Skip to content

Commit

Permalink
feat: Ability to render groups as attendees
Browse files Browse the repository at this point in the history
  • Loading branch information
Jonas Heinrich committed Aug 21, 2023
1 parent 79a24df commit 9474ee0
Show file tree
Hide file tree
Showing 6 changed files with 363 additions and 9 deletions.
17 changes: 14 additions & 3 deletions src/components/Editor/AvatarParticipationStatus.vue
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,12 @@

<template>
<div class="avatar-participation-status">
<Avatar :disable-tooltip="true"
<Avatar v-if="isGroup === true">
<template #icon>
<AccountMultiple :size="28" />
</template>
</Avatar>
<Avatar v-else :disable-tooltip="true"
:user="avatarLink"
:is-no-user="isResource" />
<template v-if="participationStatus === 'ACCEPTED' && isViewedByOrganizer">
Expand Down Expand Up @@ -125,6 +130,7 @@

<script>
import { NcAvatar as Avatar } from '@nextcloud/vue'
import AccountMultiple from 'vue-material-design-icons/AccountMultiple.vue'
import IconCheck from 'vue-material-design-icons/CheckCircle.vue'
import IconNoResponse from 'vue-material-design-icons/HelpCircle.vue'
import IconClose from 'vue-material-design-icons/CloseCircle.vue'
Expand All @@ -133,8 +139,9 @@ import IconDelegated from 'vue-material-design-icons/ArrowRightDropCircle.vue'
export default {
name: 'AvatarParticipationStatus',
components: {
Avatar,
IconCheck,
Avatar,
AccountMultiple,
IconCheck,
IconNoResponse,
IconClose,
IconDelegated,
Expand All @@ -161,6 +168,10 @@ export default {
type: Boolean,
required: true,
},
isGroup: {
type: Boolean,
required: false,
},
isSuggestion: {
type: Boolean,
default: false,
Expand Down
31 changes: 30 additions & 1 deletion src/components/Editor/Invitees/InviteesList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
:attendee="invitee"
:is-read-only="isReadOnly"
:organizer-display-name="organizerDisplayName"
:members="invitee.members"
@remove-attendee="removeAttendee" />
<NoAttendeesView v-if="isReadOnly && isListEmpty"
:message="noInviteesMessage" />
Expand Down Expand Up @@ -106,6 +107,7 @@ export default {
return {
creatingTalkRoom: false,
showFreeBusyModel: false,
dummyProperty: 0,
}
},
computed: {
Expand All @@ -117,16 +119,42 @@ export default {
},
invitees() {
return this.calendarObjectInstance.attendees.filter(attendee => {

// Assign members to group type
attendee.members = [];
if (attendee.attendeeProperty.userType === 'GROUP') {
let group = attendee
group.members = this.calendarObjectInstance.attendees.filter(attendee => {
return group.uri === attendee.member
})
}

return !['RESOURCE', 'ROOM'].includes(attendee.attendeeProperty.userType)
})
},
groups() {
return this.calendarObjectInstance.attendees.filter(attendee => {
return attendee.attendeeProperty.userType === 'GROUP'
})
},
inviteesWithoutOrganizer() {
if (!this.calendarObjectInstance.organizer) {
return this.invitees
}

return this.invitees
.filter(attendee => attendee.uri !== this.calendarObjectInstance.organizer.uri)
.filter(attendee => {
// Filter attendees which are part of an invited group
if (attendee.member) {
var isMemberOfGroup = this.groups.some(function(group) {
return attendee.member.includes(group.uri) &&
attendee.attendeeProperty.userType === 'INDIVIDUAL'
})
}

return attendee.uri !== this.calendarObjectInstance.organizer.uri &&
!isMemberOfGroup
})
},
hasOrganizer() {
return this.calendarObjectInstance.organizer !== null
Expand Down Expand Up @@ -189,6 +217,7 @@ export default {
})
},
removeAttendee(attendee) {
console.log("remove attendee ", attendee)
this.$store.commit('removeAttendee', {
calendarObjectInstance: this.calendarObjectInstance,
attendee,
Expand Down
99 changes: 94 additions & 5 deletions src/components/Editor/Invitees/InviteesListItem.vue
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,28 @@
:avatar-link="avatarLink"
:participation-status="attendee.participationStatus"
:organizer-display-name="organizerDisplayName"
:common-name="commonName" />
:common-name="commonName"
:is-group="isGroup" />
<div class="invitees-list-item__displayname">
{{ commonName }}
<span v-if="hasMembers"
class="invitees-list-item__member-count">
({{ attendee.members.length }})
</span>
</div>
<div class="invitees-list-item__actions">
<NcButton v-if="hasMembers"
class="icon-collapse"
:class="{ 'icon-collapse--open':memberListExpaneded }"
type="tertiary"
@click="toggleMemberList">
<template #icon>
<ChevronUp v-if="memberListExpaneded"
:size="20" />
<ChevronDown v-else
:size="20" />
</template>
</NcButton>
<Actions v-if="isViewedByOrganizer">
<ActionCheckbox :checked="attendee.rsvp"
@change="toggleRSVP">
Expand Down Expand Up @@ -61,14 +78,25 @@
{{ $t('calendar', 'Non-participant') }}
</ActionRadio>

<ActionButton @click="removeAttendee">
<ActionButton @click="removeAttendee(attendee)">
<template #icon>
<Delete :size="20" decorative />
</template>
{{ $t('calendar', 'Remove attendee') }}
{{ removeAttendeeText }}
</ActionButton>
</Actions>
</div>
<div v-if="hasMembers"
class="member-list"
:class="{ 'member-list--open':memberListExpaneded }">
<InviteesMemberItem v-for="member in attendee.members"
:key="member.email"
:attendee="member"
:is-read-only="isReadOnly"
:organizer-display-name="organizerDisplayName"
:members="member.members"
@remove-attendee="removeAttendee(member)" />
</div>
</div>
</template>

Expand All @@ -79,8 +107,12 @@ import {
NcActionButton as ActionButton,
NcActionRadio as ActionRadio,
NcActionCheckbox as ActionCheckbox,
NcButton,
} from '@nextcloud/vue'
import { removeMailtoPrefix } from '../../../utils/attendee.js'
import ChevronDown from 'vue-material-design-icons/ChevronDown.vue'
import ChevronUp from 'vue-material-design-icons/ChevronUp.vue'
import InviteesMemberItem from './InviteesMemberItem.vue'

import Delete from 'vue-material-design-icons/Delete.vue'

Expand All @@ -93,6 +125,10 @@ export default {
ActionRadio,
Actions,
Delete,
NcButton,
ChevronDown,
ChevronUp,
InviteesMemberItem,
},
props: {
attendee: {
Expand All @@ -108,6 +144,11 @@ export default {
required: true,
},
},
data() {
return {
memberListExpaneded: false
};
},
computed: {
/**
* @return {string}
Expand All @@ -116,6 +157,16 @@ export default {
// return this.$store.getters.getAvatarForContact(this.uri) || this.commonName
return this.commonName
},
/**
* @return {string}
*/
removeAttendeeText() {
if (this.isGroup) {
return this.$t('calendar', 'Remove group')
} else {
return this.$t('calendar', 'Remove attendee')
}
},
/**
* Common name of the organizer or the uri without the 'mailto:' prefix.
*
Expand Down Expand Up @@ -151,6 +202,12 @@ export default {
// TODO: check if also viewed by organizer
return !this.isReadOnly
},
isGroup() {
return this.attendee.attendeeProperty.userType === 'GROUP'
},
hasMembers() {
return this.attendee.members.length > 0
}
},
methods: {
/**
Expand All @@ -175,14 +232,27 @@ export default {
/**
* Removes an attendee from the event
*/
removeAttendee() {
this.$emit('remove-attendee', this.attendee)
removeAttendee(attendee) {
this.$emit('remove-attendee', attendee)
},
/**
* Toggle member list if attendee is a group
*/
toggleMemberList(e) {
this.memberListExpaneded = !this.memberListExpaneded
},
},
}
</script>

<style lang="scss" scoped>
.invitees-list-item {
flex-wrap: wrap;
}
.invitees-list-item__actions {
display: flex;
}

.invitees-list-item__displayname {
margin-bottom: 17px;
text-overflow: ellipsis;
Expand All @@ -193,4 +263,23 @@ export default {
.avatar-participation-status {
margin-top: 5px;
}

.invitees-list-item__member-count {
color: var(--color-text-maxcontrast);
font-weight: 300;
}

.member-list {
height: auto;
max-height: 0;
flex-basis: 100%;
overflow: hidden;
transition: max-height 0.3s ease;
padding-left: 15px;
}

.member-list--open {
max-height: 1000px;
transition: max-height 0.3s ease;
}
</style>
Loading

0 comments on commit 9474ee0

Please sign in to comment.