mirror of
https://github.com/Ocelot-Social-Community/Ocelot-Social.git
synced 2025-12-12 23:35:58 +00:00
Start setting up frontend pinning/unpinning
- Add pin/unpin post to content menu - Update apollo cache to reactively unpin - Update apollo cache in root path to re-order Posts - Order with pinned post first - Start setting up filters, so that the pinned post is always the first post visible
This commit is contained in:
parent
36f6be9e36
commit
f871df02ae
@ -55,24 +55,46 @@ export default {
|
||||
routes() {
|
||||
let routes = []
|
||||
|
||||
if (this.isOwner && this.resourceType === 'contribution') {
|
||||
routes.push({
|
||||
name: this.$t(`post.menu.edit`),
|
||||
path: this.$router.resolve({
|
||||
name: 'post-edit-id',
|
||||
params: {
|
||||
id: this.resource.id,
|
||||
if (this.resourceType === 'contribution') {
|
||||
if (this.isOwner) {
|
||||
routes.push({
|
||||
name: this.$t(`post.menu.edit`),
|
||||
path: this.$router.resolve({
|
||||
name: 'post-edit-id',
|
||||
params: {
|
||||
id: this.resource.id,
|
||||
},
|
||||
}).href,
|
||||
icon: 'edit',
|
||||
})
|
||||
routes.push({
|
||||
name: this.$t(`post.menu.delete`),
|
||||
callback: () => {
|
||||
this.openModal('delete')
|
||||
},
|
||||
}).href,
|
||||
icon: 'edit',
|
||||
})
|
||||
routes.push({
|
||||
name: this.$t(`post.menu.delete`),
|
||||
callback: () => {
|
||||
this.openModal('delete')
|
||||
},
|
||||
icon: 'trash',
|
||||
})
|
||||
icon: 'trash',
|
||||
})
|
||||
}
|
||||
|
||||
if (this.isAdmin) {
|
||||
if (!this.resource.pinnedBy) {
|
||||
routes.push({
|
||||
name: this.$t(`post.menu.pin`),
|
||||
callback: () => {
|
||||
this.$emit('pinPost', this.resource)
|
||||
},
|
||||
icon: 'link',
|
||||
})
|
||||
} else {
|
||||
routes.push({
|
||||
name: this.$t(`post.menu.unpin`),
|
||||
callback: () => {
|
||||
this.$emit('unpinPost', this.resource)
|
||||
},
|
||||
icon: 'unlink',
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (this.isOwner && this.resourceType === 'comment') {
|
||||
@ -155,6 +177,9 @@ export default {
|
||||
isModerator() {
|
||||
return this.$store.getters['auth/isModerator']
|
||||
},
|
||||
isAdmin() {
|
||||
return this.$store.getters['auth/isAdmin']
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
openItem(route, toggleMenu) {
|
||||
@ -175,6 +200,7 @@ export default {
|
||||
},
|
||||
})
|
||||
},
|
||||
pinPost() {},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
@ -61,6 +61,8 @@
|
||||
:resource="post"
|
||||
:modalsData="menuModalsData"
|
||||
:is-owner="isAuthor"
|
||||
@pinPost="pinPost"
|
||||
@unpinPost="unpinPost"
|
||||
/>
|
||||
</div>
|
||||
</client-only>
|
||||
@ -127,6 +129,12 @@ export default {
|
||||
this.$toast.error(err.message)
|
||||
}
|
||||
},
|
||||
pinPost(post) {
|
||||
this.$emit('pinPost', post)
|
||||
},
|
||||
unpinPost(post) {
|
||||
this.$emit('unpinPost', post)
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
@ -57,6 +57,12 @@ export const postFragment = lang => gql`
|
||||
name
|
||||
icon
|
||||
}
|
||||
pinnedBy {
|
||||
id
|
||||
name
|
||||
role
|
||||
}
|
||||
pinnedAt
|
||||
}
|
||||
`
|
||||
export const commentFragment = lang => gql`
|
||||
|
||||
@ -34,6 +34,8 @@ export default () => {
|
||||
$imageUpload: Upload
|
||||
$categoryIds: [ID]
|
||||
$image: String
|
||||
$pinned: Boolean
|
||||
$unpinned: Boolean
|
||||
) {
|
||||
UpdatePost(
|
||||
id: $id
|
||||
@ -43,6 +45,8 @@ export default () => {
|
||||
imageUpload: $imageUpload
|
||||
categoryIds: $categoryIds
|
||||
image: $image
|
||||
pinned: $pinned
|
||||
unpinned: $unpinned
|
||||
) {
|
||||
id
|
||||
title
|
||||
@ -50,6 +54,11 @@ export default () => {
|
||||
content
|
||||
contentExcerpt
|
||||
language
|
||||
pinnedBy {
|
||||
id
|
||||
name
|
||||
role
|
||||
}
|
||||
}
|
||||
}
|
||||
`,
|
||||
|
||||
@ -368,7 +368,11 @@
|
||||
},
|
||||
"menu": {
|
||||
"edit": "Edit Post",
|
||||
"delete": "Delete Post"
|
||||
"delete": "Delete Post",
|
||||
"pin": "Pin post",
|
||||
"pinnedSuccessfully": "Post pinned successfully!",
|
||||
"unpin": "Unpin post",
|
||||
"unpinnedSuccessfully": "Post unpinned successfully!"
|
||||
},
|
||||
"comment": {
|
||||
"submit": "Comment",
|
||||
|
||||
@ -21,6 +21,8 @@
|
||||
:post="post"
|
||||
:width="{ base: '100%', xs: '100%', md: '50%', xl: '33%' }"
|
||||
@removePostFromList="deletePost"
|
||||
@pinPost="pinPost"
|
||||
@unpinPost="unpinPost"
|
||||
/>
|
||||
</masonry-grid-item>
|
||||
</template>
|
||||
@ -64,6 +66,7 @@ import MasonryGrid from '~/components/MasonryGrid/MasonryGrid.vue'
|
||||
import MasonryGridItem from '~/components/MasonryGrid/MasonryGridItem.vue'
|
||||
import { mapGetters } from 'vuex'
|
||||
import { filterPosts } from '~/graphql/PostQuery.js'
|
||||
import PostMutations from '~/graphql/PostMutations'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
@ -166,6 +169,37 @@ export default {
|
||||
return post.id !== deletedPost.id
|
||||
})
|
||||
},
|
||||
resetPostList() {
|
||||
this.offset = 0
|
||||
this.posts = []
|
||||
this.hasMore = true
|
||||
},
|
||||
pinPost(post) {
|
||||
this.$apollo
|
||||
.mutate({
|
||||
mutation: PostMutations().UpdatePost,
|
||||
variables: { id: post.id, title: post.title, content: post.content, pinned: true },
|
||||
})
|
||||
.then(() => {
|
||||
this.$toast.success(this.$t('post.menu.pinnedSuccessfully'))
|
||||
this.resetPostList()
|
||||
this.$apollo.queries.Post.refetch()
|
||||
})
|
||||
.catch(error => this.$toast.error(error.message))
|
||||
},
|
||||
unpinPost(post) {
|
||||
this.$apollo
|
||||
.mutate({
|
||||
mutation: PostMutations().UpdatePost,
|
||||
variables: { id: post.id, title: post.title, content: post.content, unpinned: true },
|
||||
})
|
||||
.then(() => {
|
||||
this.$toast.success(this.$t('post.menu.unpinnedSuccessfully'))
|
||||
this.resetPostList()
|
||||
this.$apollo.queries.Post.refetch()
|
||||
})
|
||||
.catch(error => this.$toast.error(error.message))
|
||||
},
|
||||
},
|
||||
apollo: {
|
||||
Post: {
|
||||
@ -176,7 +210,7 @@ export default {
|
||||
return {
|
||||
filter: this.finalFilters,
|
||||
first: this.pageSize,
|
||||
orderBy: this.sorting,
|
||||
orderBy: ['pinnedAt_asc', this.sorting],
|
||||
offset: 0,
|
||||
}
|
||||
},
|
||||
|
||||
@ -18,6 +18,8 @@
|
||||
:resource="post"
|
||||
:modalsData="menuModalsData"
|
||||
:is-owner="isAuthor(post.author ? post.author.id : null)"
|
||||
@pinPost="pinPost"
|
||||
@unpinPost="unpinPost"
|
||||
/>
|
||||
</client-only>
|
||||
<ds-space margin-bottom="small" />
|
||||
@ -77,6 +79,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapMutations } from 'vuex'
|
||||
import ContentViewer from '~/components/Editor/ContentViewer'
|
||||
import HcCategory from '~/components/Category'
|
||||
import HcHashtag from '~/components/Hashtag/Hashtag'
|
||||
@ -88,6 +91,7 @@ import HcCommentList from '~/components/CommentList/CommentList'
|
||||
import { postMenuModalsData, deletePostMutation } from '~/components/utils/PostHelpers'
|
||||
import PostQuery from '~/graphql/PostQuery'
|
||||
import HcEmotions from '~/components/Emotions/Emotions'
|
||||
import PostMutations from '~/graphql/PostMutations'
|
||||
|
||||
export default {
|
||||
name: 'PostSlug',
|
||||
@ -141,6 +145,9 @@ export default {
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
...mapMutations({
|
||||
setCurrentUser: 'auth/SET_USER',
|
||||
}),
|
||||
isAuthor(id) {
|
||||
return this.$store.getters['auth/user'].id === id
|
||||
},
|
||||
@ -156,6 +163,33 @@ export default {
|
||||
async createComment(comment) {
|
||||
this.post.comments.push(comment)
|
||||
},
|
||||
resetPostList() {
|
||||
this.offset = 0
|
||||
this.posts = []
|
||||
this.hasMore = true
|
||||
},
|
||||
pinPost(post) {
|
||||
this.$apollo
|
||||
.mutate({
|
||||
mutation: PostMutations().UpdatePost,
|
||||
variables: { id: post.id, title: post.title, content: post.content, pinned: true },
|
||||
})
|
||||
.then(() => {
|
||||
this.$toast.success(this.$t('post.menu.pinnedSuccessfully'))
|
||||
})
|
||||
.catch(error => this.$toast.error(error.message))
|
||||
},
|
||||
unpinPost(post) {
|
||||
this.$apollo
|
||||
.mutate({
|
||||
mutation: PostMutations().UpdatePost,
|
||||
variables: { id: post.id, title: post.title, content: post.content, unpinned: true },
|
||||
})
|
||||
.then(() => {
|
||||
this.$toast.success(this.$t('post.menu.unpinnedSuccessfully'))
|
||||
})
|
||||
.catch(error => this.$toast.error(error.message))
|
||||
},
|
||||
},
|
||||
apollo: {
|
||||
Post: {
|
||||
|
||||
@ -444,7 +444,7 @@ export default {
|
||||
filter: this.filter,
|
||||
first: this.pageSize,
|
||||
offset: 0,
|
||||
orderBy: 'createdAt_desc',
|
||||
orderBy: ['pinnedAt_asc', 'createdAt_desc'],
|
||||
}
|
||||
},
|
||||
update({ Post }) {
|
||||
|
||||
@ -10,23 +10,31 @@ const defaultFilter = {}
|
||||
export const state = () => {
|
||||
return {
|
||||
filter: {
|
||||
...defaultFilter,
|
||||
OR: [{ pinnedBy_in: { role_in: ['admin'] } }, {}],
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
export const mutations = {
|
||||
TOGGLE_FILTER_BY_FOLLOWED(state, currentUserId) {
|
||||
const filter = clone(state.filter)
|
||||
const id = get(filter, 'author.followedBy_some.id')
|
||||
let filter = clone(state.filter)
|
||||
const id = filter.OR.find(object => object.author)
|
||||
if (id) {
|
||||
delete filter.author
|
||||
filter.OR.forEach(object => delete object.author)
|
||||
state.filter = filter
|
||||
} else {
|
||||
state.filter = {
|
||||
...filter,
|
||||
if (isEmpty(filter.OR[-1])) filter.OR.pop()
|
||||
filter.OR.map(object => {
|
||||
for (let key in object) {
|
||||
if (object.hasOwnProperty(key)) {
|
||||
object = { key: object[key] }
|
||||
}
|
||||
}
|
||||
})
|
||||
filter.OR.unshift({
|
||||
author: { followedBy_some: { id: currentUserId } },
|
||||
}
|
||||
})
|
||||
state.filter = filter
|
||||
}
|
||||
},
|
||||
RESET_CATEGORIES(state) {
|
||||
@ -35,9 +43,20 @@ export const mutations = {
|
||||
state.filter = filter
|
||||
},
|
||||
TOGGLE_CATEGORY(state, categoryId) {
|
||||
const filter = clone(state.filter)
|
||||
update(filter, 'categories_some.id_in', categoryIds => xor(categoryIds, [categoryId]))
|
||||
if (isEmpty(get(filter, 'categories_some.id_in'))) delete filter.categories_some
|
||||
let filter = clone(state.filter)
|
||||
if (isEmpty(filter.OR[-1])) filter.OR.pop()
|
||||
filter.OR.map(object => {
|
||||
for (let key in object) {
|
||||
if (object.hasOwnProperty(key)) {
|
||||
object = { key: object[key] }
|
||||
}
|
||||
}
|
||||
})
|
||||
filter.OR.unshift({
|
||||
categories_some: { id_in: [categoryId] },
|
||||
})
|
||||
// update(filter, 'categories_some.id_in', categoryIds => xor(categoryIds, [categoryId]))
|
||||
// if (isEmpty(get(filter.OR[0], 'categories_some.id_in'))) delete filter.OR[0].categories_some
|
||||
state.filter = filter
|
||||
},
|
||||
TOGGLE_EMOTION(state, emotion) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user