mirror of
https://github.com/Ocelot-Social-Community/Ocelot-Social.git
synced 2025-12-13 07:46:06 +00:00
Implement join/leave button on group profile
This commit is contained in:
parent
aac951e7a7
commit
330bdd4df5
@ -19,7 +19,6 @@ import { followUserMutation, unfollowUserMutation } from '~/graphql/User'
|
|||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'HcFollowButton',
|
name: 'HcFollowButton',
|
||||||
|
|
||||||
props: {
|
props: {
|
||||||
followId: { type: String, default: null },
|
followId: { type: String, default: null },
|
||||||
isFollowed: { type: Boolean, default: false },
|
isFollowed: { type: Boolean, default: false },
|
||||||
91
webapp/components/Button/JoinLeaveButton.vue
Normal file
91
webapp/components/Button/JoinLeaveButton.vue
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
<template>
|
||||||
|
<base-button
|
||||||
|
class="track-button"
|
||||||
|
:disabled="disabled"
|
||||||
|
:loading="loading"
|
||||||
|
:icon="icon"
|
||||||
|
:filled="isMember && !hovered"
|
||||||
|
:danger="isMember && hovered"
|
||||||
|
@mouseenter.native="onHover"
|
||||||
|
@mouseleave.native="hovered = false"
|
||||||
|
@click.prevent="toggle"
|
||||||
|
>
|
||||||
|
{{ label }}
|
||||||
|
</base-button>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { joinGroupMutation } from '~/graphql/groups'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'JoinLeaveButton',
|
||||||
|
props: {
|
||||||
|
groupId: { type: String, required: true },
|
||||||
|
userId: { type: String, required: true },
|
||||||
|
isMember: { type: Boolean, required: true },
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
disabled: false,
|
||||||
|
loading: false,
|
||||||
|
hovered: false,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
icon() {
|
||||||
|
if (this.isMember && this.hovered) {
|
||||||
|
return 'close'
|
||||||
|
} else {
|
||||||
|
return this.isMember ? 'check' : 'plus'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
label() {
|
||||||
|
if (this.isMember) {
|
||||||
|
return this.$t('group.joinLeaveButton.iAmMember')
|
||||||
|
} else {
|
||||||
|
return this.$t('group.joinLeaveButton.join')
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
isMember() {
|
||||||
|
this.loading = false
|
||||||
|
this.hovered = false
|
||||||
|
},
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
onHover() {
|
||||||
|
if (!this.disabled && !this.loading) {
|
||||||
|
this.hovered = true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async toggle() {
|
||||||
|
const join = !this.isMember
|
||||||
|
const mutation = join ? joinGroupMutation : null // Wolle: implement "leaveGroupMutation"
|
||||||
|
|
||||||
|
this.hovered = false
|
||||||
|
const optimisticResult = { joinedByCurrentUser: join }
|
||||||
|
this.$emit('optimistic', optimisticResult)
|
||||||
|
|
||||||
|
try {
|
||||||
|
const { data } = await this.$apollo.mutate({
|
||||||
|
mutation,
|
||||||
|
variables: { groupId: this.groupId, userId: this.userId },
|
||||||
|
})
|
||||||
|
const joinedGroup = join ? data.JoinGroup : { myRoleInGroup: null } // Wolle: implement "leaveGroupMutation"
|
||||||
|
this.$emit('update', joinedGroup)
|
||||||
|
} catch (error) {
|
||||||
|
optimisticResult.joinedByCurrentUser = !join
|
||||||
|
this.$emit('optimistic', optimisticResult)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.track-button {
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -373,6 +373,10 @@
|
|||||||
"group": {
|
"group": {
|
||||||
"foundation": "Gründung",
|
"foundation": "Gründung",
|
||||||
"goal": "Ziel:",
|
"goal": "Ziel:",
|
||||||
|
"joinLeaveButton": {
|
||||||
|
"iAmMember": "Bin Mitglied",
|
||||||
|
"join": "Beitreten"
|
||||||
|
},
|
||||||
"membersCount": "Mitglieder",
|
"membersCount": "Mitglieder",
|
||||||
"membersListTitle": "Gruppenmitglieder"
|
"membersListTitle": "Gruppenmitglieder"
|
||||||
},
|
},
|
||||||
|
|||||||
@ -373,6 +373,10 @@
|
|||||||
"group": {
|
"group": {
|
||||||
"foundation": "Foundation",
|
"foundation": "Foundation",
|
||||||
"goal": "Goal:",
|
"goal": "Goal:",
|
||||||
|
"joinLeaveButton": {
|
||||||
|
"iAmMember": "I'm a member",
|
||||||
|
"join": "Join"
|
||||||
|
},
|
||||||
"membersCount": "Members",
|
"membersCount": "Members",
|
||||||
"membersListTitle": "Group Members"
|
"membersListTitle": "Group Members"
|
||||||
},
|
},
|
||||||
|
|||||||
@ -300,6 +300,10 @@
|
|||||||
"group": {
|
"group": {
|
||||||
"foundation": null,
|
"foundation": null,
|
||||||
"goal": null,
|
"goal": null,
|
||||||
|
"joinLeaveButton": {
|
||||||
|
"iAmMember": null,
|
||||||
|
"join": null
|
||||||
|
},
|
||||||
"membersCount": null,
|
"membersCount": null,
|
||||||
"membersListTitle": null
|
"membersListTitle": null
|
||||||
},
|
},
|
||||||
|
|||||||
@ -289,6 +289,10 @@
|
|||||||
"group": {
|
"group": {
|
||||||
"foundation": null,
|
"foundation": null,
|
||||||
"goal": null,
|
"goal": null,
|
||||||
|
"joinLeaveButton": {
|
||||||
|
"iAmMember": null,
|
||||||
|
"join": null
|
||||||
|
},
|
||||||
"membersCount": null,
|
"membersCount": null,
|
||||||
"membersListTitle": null
|
"membersListTitle": null
|
||||||
},
|
},
|
||||||
|
|||||||
@ -297,6 +297,10 @@
|
|||||||
"group": {
|
"group": {
|
||||||
"foundation": null,
|
"foundation": null,
|
||||||
"goal": null,
|
"goal": null,
|
||||||
|
"joinLeaveButton": {
|
||||||
|
"iAmMember": null,
|
||||||
|
"join": null
|
||||||
|
},
|
||||||
"membersCount": null,
|
"membersCount": null,
|
||||||
"membersListTitle": null
|
"membersListTitle": null
|
||||||
},
|
},
|
||||||
|
|||||||
@ -85,6 +85,10 @@
|
|||||||
"group": {
|
"group": {
|
||||||
"foundation": null,
|
"foundation": null,
|
||||||
"goal": null,
|
"goal": null,
|
||||||
|
"joinLeaveButton": {
|
||||||
|
"iAmMember": null,
|
||||||
|
"join": null
|
||||||
|
},
|
||||||
"membersCount": null,
|
"membersCount": null,
|
||||||
"membersListTitle": null
|
"membersListTitle": null
|
||||||
},
|
},
|
||||||
|
|||||||
@ -169,6 +169,10 @@
|
|||||||
"group": {
|
"group": {
|
||||||
"foundation": null,
|
"foundation": null,
|
||||||
"goal": null,
|
"goal": null,
|
||||||
|
"joinLeaveButton": {
|
||||||
|
"iAmMember": null,
|
||||||
|
"join": null
|
||||||
|
},
|
||||||
"membersCount": null,
|
"membersCount": null,
|
||||||
"membersListTitle": null
|
"membersListTitle": null
|
||||||
},
|
},
|
||||||
|
|||||||
@ -335,6 +335,10 @@
|
|||||||
"group": {
|
"group": {
|
||||||
"foundation": null,
|
"foundation": null,
|
||||||
"goal": null,
|
"goal": null,
|
||||||
|
"joinLeaveButton": {
|
||||||
|
"iAmMember": null,
|
||||||
|
"join": null
|
||||||
|
},
|
||||||
"membersCount": null,
|
"membersCount": null,
|
||||||
"membersListTitle": null
|
"membersListTitle": null
|
||||||
},
|
},
|
||||||
|
|||||||
@ -314,6 +314,10 @@
|
|||||||
"group": {
|
"group": {
|
||||||
"foundation": null,
|
"foundation": null,
|
||||||
"goal": null,
|
"goal": null,
|
||||||
|
"joinLeaveButton": {
|
||||||
|
"iAmMember": null,
|
||||||
|
"join": null
|
||||||
|
},
|
||||||
"membersCount": null,
|
"membersCount": null,
|
||||||
"membersListTitle": null
|
"membersListTitle": null
|
||||||
},
|
},
|
||||||
|
|||||||
@ -49,7 +49,11 @@
|
|||||||
<ds-flex-item>
|
<ds-flex-item>
|
||||||
<client-only>
|
<client-only>
|
||||||
<ds-number :label="$t('group.membersCount')">
|
<ds-number :label="$t('group.membersCount')">
|
||||||
<count-to slot="count" :start-val="0" :end-val="groupMembers.length" />
|
<count-to
|
||||||
|
slot="count"
|
||||||
|
:start-val="membersCountStartValue"
|
||||||
|
:end-val="groupMembers.length"
|
||||||
|
/>
|
||||||
</ds-number>
|
</ds-number>
|
||||||
</client-only>
|
</client-only>
|
||||||
</ds-flex-item>
|
</ds-flex-item>
|
||||||
@ -72,7 +76,7 @@
|
|||||||
</client-only>
|
</client-only>
|
||||||
</ds-flex-item> -->
|
</ds-flex-item> -->
|
||||||
</ds-flex>
|
</ds-flex>
|
||||||
<div v-if="!isGroupMember" class="action-buttons">
|
<div class="action-buttons">
|
||||||
<!-- <base-button v-if="user.isBlocked" @click="unblockUser(user)">
|
<!-- <base-button v-if="user.isBlocked" @click="unblockUser(user)">
|
||||||
{{ $t('settings.blocked-users.unblock') }}
|
{{ $t('settings.blocked-users.unblock') }}
|
||||||
</base-button>
|
</base-button>
|
||||||
@ -86,6 +90,15 @@
|
|||||||
@optimistic="optimisticFollow"
|
@optimistic="optimisticFollow"
|
||||||
@update="updateFollow"
|
@update="updateFollow"
|
||||||
/> -->
|
/> -->
|
||||||
|
<join-leave-button
|
||||||
|
:groupId="group ? group.id : ''"
|
||||||
|
:userId="currentUser.id"
|
||||||
|
:isMember="isGroupMember"
|
||||||
|
@optimistic="optimisticJoinLeave"
|
||||||
|
@update="updateJoinLeave"
|
||||||
|
/>
|
||||||
|
<!-- implement:
|
||||||
|
v-if="!user.isMuted && !user.isBlocked" -->
|
||||||
</div>
|
</div>
|
||||||
<template v-if="group.about">
|
<template v-if="group.about">
|
||||||
<hr />
|
<hr />
|
||||||
@ -200,8 +213,9 @@ import AvatarUploader from '~/components/Uploader/AvatarUploader'
|
|||||||
// import ContentMenu from '~/components/ContentMenu/ContentMenu'
|
// import ContentMenu from '~/components/ContentMenu/ContentMenu'
|
||||||
import CountTo from '~/components/CountTo.vue'
|
import CountTo from '~/components/CountTo.vue'
|
||||||
import Empty from '~/components/Empty/Empty'
|
import Empty from '~/components/Empty/Empty'
|
||||||
// import FollowButton from '~/components/FollowButton.vue'
|
// import FollowButton from '~/components/Button/FollowButton'
|
||||||
// import FollowList from '~/components/features/ProfileList/FollowList'
|
// import FollowList from '~/components/features/ProfileList/FollowList'
|
||||||
|
import JoinLeaveButton from '~/components/Button/JoinLeaveButton'
|
||||||
import MasonryGrid from '~/components/MasonryGrid/MasonryGrid.vue'
|
import MasonryGrid from '~/components/MasonryGrid/MasonryGrid.vue'
|
||||||
import MasonryGridItem from '~/components/MasonryGrid/MasonryGridItem.vue'
|
import MasonryGridItem from '~/components/MasonryGrid/MasonryGridItem.vue'
|
||||||
import PostTeaser from '~/components/PostTeaser/PostTeaser.vue'
|
import PostTeaser from '~/components/PostTeaser/PostTeaser.vue'
|
||||||
@ -226,6 +240,7 @@ export default {
|
|||||||
Empty,
|
Empty,
|
||||||
// FollowButton,
|
// FollowButton,
|
||||||
// FollowList,
|
// FollowList,
|
||||||
|
JoinLeaveButton,
|
||||||
PostTeaser,
|
PostTeaser,
|
||||||
ProfileAvatar,
|
ProfileAvatar,
|
||||||
ProfileList,
|
ProfileList,
|
||||||
@ -253,22 +268,26 @@ export default {
|
|||||||
// followedByCountStartValue: 0,
|
// followedByCountStartValue: 0,
|
||||||
// followedByCount: 7,
|
// followedByCount: 7,
|
||||||
// followingCount: 7,
|
// followingCount: 7,
|
||||||
membersCount: Infinity,
|
membersCountStartValue: 0,
|
||||||
|
membersCountToLoad: Infinity,
|
||||||
updateGroupMutation,
|
updateGroupMutation,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
currentUser() {
|
||||||
|
return this.$store.getters['auth/user']
|
||||||
|
},
|
||||||
group() {
|
group() {
|
||||||
return this.Group ? this.Group[0] : {}
|
return this.Group[0] ? this.Group[0] : {}
|
||||||
},
|
},
|
||||||
groupMembers() {
|
groupMembers() {
|
||||||
return this.GroupMembers ? this.GroupMembers : []
|
return this.GroupMembers ? this.GroupMembers : []
|
||||||
},
|
},
|
||||||
isGroupOwner() {
|
isGroupOwner() {
|
||||||
return this.group.myRole === 'owner'
|
return this.group ? this.group.myRole === 'owner' : false
|
||||||
},
|
},
|
||||||
isGroupMember() {
|
isGroupMember() {
|
||||||
return this.group.myRole
|
return this.group ? !!this.group.myRole : false
|
||||||
},
|
},
|
||||||
groupName() {
|
groupName() {
|
||||||
const { name } = this.group || {}
|
const { name } = this.group || {}
|
||||||
@ -405,8 +424,32 @@ export default {
|
|||||||
// this.user.followedByCurrentUser = followedByCurrentUser
|
// this.user.followedByCurrentUser = followedByCurrentUser
|
||||||
// this.user.followedBy = followedBy
|
// this.user.followedBy = followedBy
|
||||||
// },
|
// },
|
||||||
|
optimisticJoinLeave({ joinedByCurrentUser }) {
|
||||||
|
/*
|
||||||
|
* Note: "membersCountStartValue" is updated to avoid counting from 0 when join/leave
|
||||||
|
*/
|
||||||
|
this.membersCountStartValue = this.GroupMembers.length
|
||||||
|
if (joinedByCurrentUser) {
|
||||||
|
// this.membersCountToLoad++
|
||||||
|
this.GroupMembers = [this.currentUser, ...this.GroupMembers]
|
||||||
|
} else {
|
||||||
|
// this.membersCountToLoad--
|
||||||
|
this.GroupMembers = this.GroupMembers.filter((user) => user.id !== this.currentUser.id)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
updateJoinLeave({ myRoleInGroup }) {
|
||||||
|
this.Group = [{ ...this.Group[0], myRole: myRoleInGroup }] // if we assign it directly "this.group" will not be updated
|
||||||
|
const currentUserInGroupMembers = this.GroupMembers.find(
|
||||||
|
(user) => user.id === this.currentUser.id,
|
||||||
|
)
|
||||||
|
if (currentUserInGroupMembers) {
|
||||||
|
currentUserInGroupMembers.myRoleInGroup = myRoleInGroup
|
||||||
|
} else {
|
||||||
|
this.$apollo.queries.GroupMembers.refetch()
|
||||||
|
}
|
||||||
|
},
|
||||||
fetchAllMembers() {
|
fetchAllMembers() {
|
||||||
this.membersCount = Infinity
|
this.membersCountToLoad = Infinity
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
apollo: {
|
apollo: {
|
||||||
|
|||||||
@ -172,7 +172,7 @@
|
|||||||
import uniqBy from 'lodash/uniqBy'
|
import uniqBy from 'lodash/uniqBy'
|
||||||
import postListActions from '~/mixins/postListActions'
|
import postListActions from '~/mixins/postListActions'
|
||||||
import PostTeaser from '~/components/PostTeaser/PostTeaser.vue'
|
import PostTeaser from '~/components/PostTeaser/PostTeaser.vue'
|
||||||
import HcFollowButton from '~/components/FollowButton.vue'
|
import HcFollowButton from '~/components/Button/FollowButton'
|
||||||
import HcCountTo from '~/components/CountTo.vue'
|
import HcCountTo from '~/components/CountTo.vue'
|
||||||
import HcBadges from '~/components/Badges.vue'
|
import HcBadges from '~/components/Badges.vue'
|
||||||
import FollowList, { followListVisibleCount } from '~/components/features/ProfileList/FollowList'
|
import FollowList, { followListVisibleCount } from '~/components/features/ProfileList/FollowList'
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user