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 {
|
||||
name: 'HcFollowButton',
|
||||
|
||||
props: {
|
||||
followId: { type: String, default: null },
|
||||
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": {
|
||||
"foundation": "Gründung",
|
||||
"goal": "Ziel:",
|
||||
"joinLeaveButton": {
|
||||
"iAmMember": "Bin Mitglied",
|
||||
"join": "Beitreten"
|
||||
},
|
||||
"membersCount": "Mitglieder",
|
||||
"membersListTitle": "Gruppenmitglieder"
|
||||
},
|
||||
|
||||
@ -373,6 +373,10 @@
|
||||
"group": {
|
||||
"foundation": "Foundation",
|
||||
"goal": "Goal:",
|
||||
"joinLeaveButton": {
|
||||
"iAmMember": "I'm a member",
|
||||
"join": "Join"
|
||||
},
|
||||
"membersCount": "Members",
|
||||
"membersListTitle": "Group Members"
|
||||
},
|
||||
|
||||
@ -300,6 +300,10 @@
|
||||
"group": {
|
||||
"foundation": null,
|
||||
"goal": null,
|
||||
"joinLeaveButton": {
|
||||
"iAmMember": null,
|
||||
"join": null
|
||||
},
|
||||
"membersCount": null,
|
||||
"membersListTitle": null
|
||||
},
|
||||
|
||||
@ -289,6 +289,10 @@
|
||||
"group": {
|
||||
"foundation": null,
|
||||
"goal": null,
|
||||
"joinLeaveButton": {
|
||||
"iAmMember": null,
|
||||
"join": null
|
||||
},
|
||||
"membersCount": null,
|
||||
"membersListTitle": null
|
||||
},
|
||||
|
||||
@ -297,6 +297,10 @@
|
||||
"group": {
|
||||
"foundation": null,
|
||||
"goal": null,
|
||||
"joinLeaveButton": {
|
||||
"iAmMember": null,
|
||||
"join": null
|
||||
},
|
||||
"membersCount": null,
|
||||
"membersListTitle": null
|
||||
},
|
||||
|
||||
@ -85,6 +85,10 @@
|
||||
"group": {
|
||||
"foundation": null,
|
||||
"goal": null,
|
||||
"joinLeaveButton": {
|
||||
"iAmMember": null,
|
||||
"join": null
|
||||
},
|
||||
"membersCount": null,
|
||||
"membersListTitle": null
|
||||
},
|
||||
|
||||
@ -169,6 +169,10 @@
|
||||
"group": {
|
||||
"foundation": null,
|
||||
"goal": null,
|
||||
"joinLeaveButton": {
|
||||
"iAmMember": null,
|
||||
"join": null
|
||||
},
|
||||
"membersCount": null,
|
||||
"membersListTitle": null
|
||||
},
|
||||
|
||||
@ -335,6 +335,10 @@
|
||||
"group": {
|
||||
"foundation": null,
|
||||
"goal": null,
|
||||
"joinLeaveButton": {
|
||||
"iAmMember": null,
|
||||
"join": null
|
||||
},
|
||||
"membersCount": null,
|
||||
"membersListTitle": null
|
||||
},
|
||||
|
||||
@ -314,6 +314,10 @@
|
||||
"group": {
|
||||
"foundation": null,
|
||||
"goal": null,
|
||||
"joinLeaveButton": {
|
||||
"iAmMember": null,
|
||||
"join": null
|
||||
},
|
||||
"membersCount": null,
|
||||
"membersListTitle": null
|
||||
},
|
||||
|
||||
@ -49,7 +49,11 @@
|
||||
<ds-flex-item>
|
||||
<client-only>
|
||||
<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>
|
||||
</client-only>
|
||||
</ds-flex-item>
|
||||
@ -72,7 +76,7 @@
|
||||
</client-only>
|
||||
</ds-flex-item> -->
|
||||
</ds-flex>
|
||||
<div v-if="!isGroupMember" class="action-buttons">
|
||||
<div class="action-buttons">
|
||||
<!-- <base-button v-if="user.isBlocked" @click="unblockUser(user)">
|
||||
{{ $t('settings.blocked-users.unblock') }}
|
||||
</base-button>
|
||||
@ -86,6 +90,15 @@
|
||||
@optimistic="optimisticFollow"
|
||||
@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>
|
||||
<template v-if="group.about">
|
||||
<hr />
|
||||
@ -200,8 +213,9 @@ import AvatarUploader from '~/components/Uploader/AvatarUploader'
|
||||
// import ContentMenu from '~/components/ContentMenu/ContentMenu'
|
||||
import CountTo from '~/components/CountTo.vue'
|
||||
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 JoinLeaveButton from '~/components/Button/JoinLeaveButton'
|
||||
import MasonryGrid from '~/components/MasonryGrid/MasonryGrid.vue'
|
||||
import MasonryGridItem from '~/components/MasonryGrid/MasonryGridItem.vue'
|
||||
import PostTeaser from '~/components/PostTeaser/PostTeaser.vue'
|
||||
@ -226,6 +240,7 @@ export default {
|
||||
Empty,
|
||||
// FollowButton,
|
||||
// FollowList,
|
||||
JoinLeaveButton,
|
||||
PostTeaser,
|
||||
ProfileAvatar,
|
||||
ProfileList,
|
||||
@ -253,22 +268,26 @@ export default {
|
||||
// followedByCountStartValue: 0,
|
||||
// followedByCount: 7,
|
||||
// followingCount: 7,
|
||||
membersCount: Infinity,
|
||||
membersCountStartValue: 0,
|
||||
membersCountToLoad: Infinity,
|
||||
updateGroupMutation,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
currentUser() {
|
||||
return this.$store.getters['auth/user']
|
||||
},
|
||||
group() {
|
||||
return this.Group ? this.Group[0] : {}
|
||||
return this.Group[0] ? this.Group[0] : {}
|
||||
},
|
||||
groupMembers() {
|
||||
return this.GroupMembers ? this.GroupMembers : []
|
||||
},
|
||||
isGroupOwner() {
|
||||
return this.group.myRole === 'owner'
|
||||
return this.group ? this.group.myRole === 'owner' : false
|
||||
},
|
||||
isGroupMember() {
|
||||
return this.group.myRole
|
||||
return this.group ? !!this.group.myRole : false
|
||||
},
|
||||
groupName() {
|
||||
const { name } = this.group || {}
|
||||
@ -405,8 +424,32 @@ export default {
|
||||
// this.user.followedByCurrentUser = followedByCurrentUser
|
||||
// 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() {
|
||||
this.membersCount = Infinity
|
||||
this.membersCountToLoad = Infinity
|
||||
},
|
||||
},
|
||||
apollo: {
|
||||
|
||||
@ -172,7 +172,7 @@
|
||||
import uniqBy from 'lodash/uniqBy'
|
||||
import postListActions from '~/mixins/postListActions'
|
||||
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 HcBadges from '~/components/Badges.vue'
|
||||
import FollowList, { followListVisibleCount } from '~/components/features/ProfileList/FollowList'
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user