mirror of https://github.com/nextcloud/contacts
Fix circle leave and visible/member checks
Signed-off-by: John Molakvoæ (skjnldsv) <skjnldsv@protonmail.com>
This commit is contained in:
parent
0538d6a7cf
commit
21c5e699ff
|
@ -76,8 +76,8 @@
|
|||
</ActionButton>
|
||||
</template>
|
||||
|
||||
<AppNavigationCounter v-if="circle.members.length > 0" slot="counter">
|
||||
{{ circle.members.length }}
|
||||
<AppNavigationCounter v-if="memberCount > 0" slot="counter">
|
||||
{{ memberCount }}
|
||||
</AppNavigationCounter>
|
||||
</AppNavigationItem>
|
||||
</template>
|
||||
|
@ -121,7 +121,7 @@ export default {
|
|||
|
||||
data() {
|
||||
return {
|
||||
loading: false
|
||||
loading: false,
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -145,6 +145,10 @@ export default {
|
|||
}
|
||||
return t('contacts', 'Join circle')
|
||||
},
|
||||
|
||||
memberCount() {
|
||||
return this.circle?.members?.length || 0
|
||||
},
|
||||
},
|
||||
|
||||
methods: {
|
||||
|
@ -162,7 +166,21 @@ export default {
|
|||
|
||||
},
|
||||
|
||||
leaveCircle() {
|
||||
async leaveCircle() {
|
||||
this.loading = true
|
||||
const member = this.circle.initiator
|
||||
|
||||
try {
|
||||
await this.$store.dispatch('deleteMemberFromCircle', {
|
||||
member,
|
||||
leave: true,
|
||||
})
|
||||
} catch (error) {
|
||||
console.error('Could not leave the circle', member, error)
|
||||
showError(t('contacts', 'Could not leave the circle {displayName}', this.circle))
|
||||
} finally {
|
||||
this.loading = false
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
|
|
|
@ -61,8 +61,16 @@
|
|||
:size="16"
|
||||
decorative />
|
||||
</ActionButton>
|
||||
<ActionButton v-if="canDelete" icon="icon-delete" @click="deleteMember">
|
||||
{{ deleteMemberName }}
|
||||
|
||||
<!-- Leave or delete member from circle -->
|
||||
<ActionButton v-if="isCurrentUser && !circle.isOwner" @click="deleteMember">
|
||||
{{ t('contacts', 'Leave circle') }}
|
||||
<ExitToApp slot="icon"
|
||||
:size="16"
|
||||
decorative />
|
||||
</ActionButton>
|
||||
<ActionButton v-else-if="canDelete" icon="icon-delete" @click="deleteMember">
|
||||
{{ t('contacts', 'Remove member') }}
|
||||
</ActionButton>
|
||||
</template>
|
||||
</Actions>
|
||||
|
@ -77,13 +85,14 @@ import ListItemIcon from '@nextcloud/vue/dist/Components/ListItemIcon'
|
|||
import ActionButton from '@nextcloud/vue/dist/Components/ActionButton'
|
||||
import ActionText from '@nextcloud/vue/dist/Components/ActionText'
|
||||
|
||||
import ShieldCheck from 'vue-material-design-icons/ShieldCheck'
|
||||
import ArrowLeft from 'vue-material-design-icons/ArrowLeft'
|
||||
import ExitToApp from 'vue-material-design-icons/ExitToApp'
|
||||
import ShieldCheck from 'vue-material-design-icons/ShieldCheck'
|
||||
|
||||
import RouterMixin from '../../mixins/RouterMixin'
|
||||
import Member from '../../models/member'
|
||||
import { showError } from '@nextcloud/dialogs'
|
||||
import { changeMemberLevel } from '../../services/circles'
|
||||
import { showError } from '@nextcloud/dialogs'
|
||||
import Member from '../../models/member'
|
||||
import RouterMixin from '../../mixins/RouterMixin'
|
||||
|
||||
export default {
|
||||
name: 'MemberListItem',
|
||||
|
@ -93,6 +102,7 @@ export default {
|
|||
ActionButton,
|
||||
ActionText,
|
||||
ArrowLeft,
|
||||
ExitToApp,
|
||||
ListItemIcon,
|
||||
ShieldCheck,
|
||||
},
|
||||
|
@ -115,6 +125,10 @@ export default {
|
|||
},
|
||||
|
||||
computed: {
|
||||
/**
|
||||
* Return the current circle
|
||||
* @returns {Circle}
|
||||
*/
|
||||
circle() {
|
||||
return this.$store.getters.getCircle(this.selectedCircle)
|
||||
},
|
||||
|
@ -135,12 +149,6 @@ export default {
|
|||
|| CIRCLES_MEMBER_LEVELS[MEMBER_LEVEL_MEMBER]
|
||||
},
|
||||
|
||||
deleteMemberName() {
|
||||
return this.isCurrentUser
|
||||
? t('contacts', 'Leave this circle')
|
||||
: t('contacts', 'Remove member')
|
||||
},
|
||||
|
||||
/**
|
||||
* Current user member level
|
||||
* @returns {number}
|
||||
|
@ -186,7 +194,7 @@ export default {
|
|||
},
|
||||
|
||||
/**
|
||||
* Can the current user delete members?
|
||||
* Can the current user delete members or?
|
||||
* @returns {boolean}
|
||||
*/
|
||||
canDelete() {
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
|
||||
import {
|
||||
MEMBER_LEVEL_MODERATOR, MEMBER_LEVEL_NONE, MEMBER_LEVEL_OWNER,
|
||||
CIRCLE_CONFIG_REQUEST, CIRCLE_CONFIG_INVITE, CIRCLE_CONFIG_OPEN,
|
||||
CIRCLE_CONFIG_REQUEST, CIRCLE_CONFIG_INVITE, CIRCLE_CONFIG_OPEN, CIRCLE_CONFIG_VISIBLE,
|
||||
} from './constants'
|
||||
|
||||
import Vue from 'vue'
|
||||
|
@ -33,15 +33,25 @@ import Member from './member'
|
|||
export default class Circle {
|
||||
|
||||
_data = {}
|
||||
_members = {}
|
||||
|
||||
/**
|
||||
* Creates an instance of Contact
|
||||
* Creates an instance of Circle
|
||||
*
|
||||
* @param {Object} data the vcard data as string with proper new lines
|
||||
* @param {object} circle the addressbook which the contat belongs to
|
||||
* @memberof Circle
|
||||
*/
|
||||
constructor(data) {
|
||||
this.updateData(data)
|
||||
}
|
||||
|
||||
/**
|
||||
* Update inner circle data, owner and initiator
|
||||
* @param {Object} data the vcard data as string with proper new lines
|
||||
* @memberof Circle
|
||||
*/
|
||||
updateData(data) {
|
||||
if (typeof data !== 'object') {
|
||||
throw new Error('Invalid circle')
|
||||
}
|
||||
|
@ -52,9 +62,8 @@ export default class Circle {
|
|||
}
|
||||
|
||||
this._data = data
|
||||
this._data.initiator = new Member(data.initiator)
|
||||
this._data.initiator = new Member(data.initiator, this)
|
||||
this._data.owner = new Member(data.owner)
|
||||
this._data.members = {}
|
||||
}
|
||||
|
||||
// METADATA -----------------------------------------
|
||||
|
@ -148,7 +157,7 @@ export default class Circle {
|
|||
* @returns {Member[]}
|
||||
*/
|
||||
get members() {
|
||||
return this._data.members
|
||||
return this._members
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -157,7 +166,7 @@ export default class Circle {
|
|||
* @memberof Circle
|
||||
*/
|
||||
set members(members) {
|
||||
this._data.members = members
|
||||
this._members = members
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -170,10 +179,10 @@ export default class Circle {
|
|||
}
|
||||
|
||||
const uid = member.id
|
||||
if (this._data.members[uid]) {
|
||||
console.warn('Duplicate member overrided', this._data.members[uid], member)
|
||||
if (this._members[uid]) {
|
||||
console.warn('Duplicate member overrided', this._members[uid], member)
|
||||
}
|
||||
Vue.set(this._data.members, uid, member)
|
||||
Vue.set(this._members, uid, member)
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -186,12 +195,12 @@ export default class Circle {
|
|||
}
|
||||
|
||||
const uid = member.id
|
||||
if (!this._data.members[uid]) {
|
||||
if (!this._members[uid]) {
|
||||
console.warn('The member was not in this circle. Nothing was done.', member)
|
||||
}
|
||||
|
||||
// Delete and clear memory
|
||||
Vue.delete(this._data.members, uid)
|
||||
Vue.delete(this._members, uid)
|
||||
}
|
||||
|
||||
// CONFIGS --------------------------------------------
|
||||
|
@ -229,6 +238,16 @@ export default class Circle {
|
|||
return (this._data.config & CIRCLE_CONFIG_OPEN) !== 0
|
||||
}
|
||||
|
||||
/**
|
||||
* Circle is visible to others
|
||||
* @readonly
|
||||
* @memberof Circle
|
||||
* @returns {boolean}
|
||||
*/
|
||||
get isVisible() {
|
||||
return (this._data.config & CIRCLE_CONFIG_VISIBLE) !== 0
|
||||
}
|
||||
|
||||
/**
|
||||
* Circle requires invite to be accepted by the member
|
||||
* @readonly
|
||||
|
|
|
@ -25,7 +25,6 @@
|
|||
import { MEMBER_TYPE_USER } from './constants'
|
||||
|
||||
import Circle from './circle'
|
||||
import Vue from 'vue'
|
||||
export default class Member {
|
||||
|
||||
/** @typedef Circle */
|
||||
|
|
|
@ -41,6 +41,9 @@ const mutations = {
|
|||
* @param {Circle} circle the circle to add
|
||||
*/
|
||||
addCircle(state, circle) {
|
||||
if (circle.constructor.name !== Circle.name) {
|
||||
throw new Error('circle must be a Circle type')
|
||||
}
|
||||
Vue.set(state.circles, circle.id, circle)
|
||||
},
|
||||
|
||||
|
@ -51,22 +54,12 @@ const mutations = {
|
|||
* @param {Circle} circle the circle to delete
|
||||
*/
|
||||
deleteCircle(state, circle) {
|
||||
if (!(circle.id in state.circles)) {
|
||||
console.warn('Skipping deletion of unknown circle', circle)
|
||||
}
|
||||
Vue.delete(state.circles, circle.id)
|
||||
},
|
||||
|
||||
/**
|
||||
* Rename a circle
|
||||
*
|
||||
* @param {Object} state the store mutations
|
||||
* @param {Object} data destructuring object
|
||||
* @param {Circle} data.circle the circle to rename
|
||||
* @param {string} data.newName the new name of the addressbook
|
||||
*/
|
||||
renameCircle(state, { circle, newName }) {
|
||||
circle = state.circles[circle.id]
|
||||
circle.displayName = newName
|
||||
},
|
||||
|
||||
/**
|
||||
* Append a list of members to a circle
|
||||
* and remove duplicates
|
||||
|
@ -193,14 +186,21 @@ const actions = {
|
|||
*
|
||||
* @param {Object} context the store mutations Current context
|
||||
* @param {Member} member the member to remove
|
||||
* @param {boolean} [leave=false] leave the circle instead of removing a member
|
||||
* @param {boolean} [leave=false] leave the circle instead of removing the member
|
||||
*/
|
||||
async deleteMemberFromCircle(context, { member, leave = false }) {
|
||||
console.info(leave);
|
||||
const circleId = member.circle.id
|
||||
const memberId = member.id
|
||||
|
||||
if (leave) {
|
||||
await leaveCircle(circleId)
|
||||
const circle = await leaveCircle(circleId)
|
||||
member.circle.updateData(circle)
|
||||
|
||||
// If the circle is not visible, we remove it from the list
|
||||
if (!member.circle.isVisible && !member.circle.isMember) {
|
||||
await context.commit('deleteCircle', circle)
|
||||
console.debug('Deleted circle', circleId, memberId)
|
||||
}
|
||||
} else {
|
||||
await deleteMember(circleId, memberId)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue