@ -28,26 +28,14 @@
v - if = "membersToShow().length > 0 && showOrganizerTools && isOrganizer"
>
Click
< span
class = "inline-block w-5 h-5 rounded-full bg-blue-100 text-blue-600 text-center"
>
< font -awesome icon = "plus" class = "text-sm" / >
< / span >
< font -awesome icon = "circle-plus" class = "text-blue-500 text-sm" / >
/
< span
class = "inline-block w-5 h-5 rounded-full bg-blue-100 text-blue-600 text-center"
>
< font -awesome icon = "minus" class = "text-sm" / >
< / span >
< font -awesome icon = "circle-minus" class = "text-rose-500 text-sm" / >
to add / remove them to / from the meeting .
< / li >
< li v-if ="membersToShow().length > 0" >
Click
< span
class = "inline-block w-5 h-5 rounded-full bg-green-100 text-green-600 text-center"
>
< font -awesome icon = "circle-user" class = "text-sm" / >
< / span >
< font -awesome icon = "circle-user" class = "text-green-600 text-sm" / >
to add them to your contacts .
< / li >
< / ul >
@ -66,6 +54,15 @@
Refresh
< span class = "text-xs" > ( { { countdownTimer } } s ) < / span >
< / button >
< button
v - if = "getPendingMembersCount() > 0"
class = "text-sm bg-gradient-to-b from-blue-100 to-blue-200 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.2)] text-blue-800 px-3 py-1.5 rounded-md"
@ click = "showAdmitAllPendingDialog"
>
< font -awesome icon = "circle-plus" class = "text-blue-500" / >
Admit Pending
< / button >
< / div >
< ul
v - if = "membersToShow().length > 0"
@ -74,16 +71,38 @@
< li
v - for = "member in membersToShow()"
: key = "member.member.memberId"
class = "border-b border-slate-300 py-1.5"
: class = " [
'border-b px-2 sm:px-3 py-1.5' ,
{
'bg-blue-50 border-t border-blue-300 -mt-[1px]' :
! member . member . admitted ,
} ,
{ 'border-slate-300' : member . member . admitted } ,
] "
>
< div class = "flex items-center gap-2 justify-between" >
< div class = "flex items-center gap-1 overflow-hidden" >
< h3 class = "font-semibold truncate" >
< h3
: class = " [
'font-semibold truncate' ,
{ 'text-slate-500' : ! member . member . admitted } ,
] "
>
< font -awesome
v - if = "member.member.memberId === members[0]?.memberId"
icon = "crown"
class = "fa-fw text-amber-400"
/ >
< font -awesome
v - if = "!member.member.admitted"
icon = "hourglass-half"
class = "fa-fw text-slate-400"
/ >
{ { member . name || unnamedMember } }
< / h3 >
< div
v - if = "!getContactFor(member.did) && member.did !== activeDid"
class = "flex items-center gap-1"
class = "flex items-center gap-1.5 ms-1 "
>
< button
class = "btn-add-contact"
@ -102,7 +121,7 @@
)
"
>
< font -awesome icon = "circle-info" class = "text-sm" / >
< font -awesome icon = "circle-info" / >
< / button >
< / div >
< / div >
@ -110,17 +129,23 @@
v - if = "
showOrganizerTools && isOrganizer && member . did !== activeDid
"
class = "flex items-center gap-1"
class = "flex items-center gap-1.5 "
>
< button
class = "btn-admission"
: class = "
member . member . admitted
? 'btn-admission-remove'
: 'btn-admission-add'
"
: title = "
member . member . admitted ? 'Remove member' : 'Admit member'
"
@ click = "checkWhetherContactBeforeAdmitting(member)"
>
< font -awesome
: icon = "member.member.admitted ? 'minus' : 'plus'"
: icon = "
member . member . admitted ? 'circle-minus' : 'circle-plus'
"
/ >
< / button >
@ -129,7 +154,7 @@
title = "Admission Info"
@ click = "informAboutAdmission()"
>
< font -awesome icon = "circle-info" class = "text-sm" / >
< font -awesome icon = "circle-info" / >
< / button >
< / span >
< / div >
@ -189,6 +214,7 @@ import { createNotifyHelpers, TIMEOUTS } from "@/utils/notify";
import {
NOTIFY_ADD_CONTACT_FIRST ,
NOTIFY_CONTINUE_WITHOUT_ADDING ,
NOTIFY_ADMIT_ALL_PENDING ,
} from "@/constants/notifications" ;
import { SOMEONE_UNNAMED } from "@/constants/entities" ;
import SetBulkVisibilityDialog from "./SetBulkVisibilityDialog.vue" ;
@ -378,17 +404,44 @@ export default class MembersList extends Vue {
}
membersToShow ( ) : DecryptedMember [ ] {
let members : DecryptedMember [ ] = [ ] ;
if ( this . isOrganizer ) {
if ( this . showOrganizerTools ) {
return this . decryptedMembers ;
members = this . decryptedMembers ;
} else {
return this . decryptedMembers . filter (
members = this . decryptedMembers . filter (
( member : DecryptedMember ) => member . member . admitted ,
) ;
}
} else {
/ / n o n - o r g a n i z e r s o n l y g e t v i s i b l e m e m b e r s f r o m s e r v e r
members = this . decryptedMembers ;
}
/ / n o n - o r g a n i z e r s o n l y g e t v i s i b l e m e m b e r s f r o m s e r v e r
return this . decryptedMembers ;
/ / S o r t m e m b e r s a c c o r d i n g t o p r i o r i t y :
/ / 1 . O r g a n i z e r a t t h e t o p
/ / 2 . N o n - a d m i t t e d m e m b e r s n e x t
/ / 3 . E v e r y o n e e l s e a f t e r
return members . sort ( ( a , b ) => {
/ / C h e c k i f e i t h e r m e m b e r i s t h e o r g a n i z e r ( f i r s t m e m b e r i n o r i g i n a l l i s t )
const aIsOrganizer = a . member . memberId === this . members [ 0 ] ? . memberId ;
const bIsOrganizer = b . member . memberId === this . members [ 0 ] ? . memberId ;
/ / O r g a n i z e r a l w a y s c o m e s f i r s t
if ( aIsOrganizer && ! bIsOrganizer ) return - 1 ;
if ( ! aIsOrganizer && bIsOrganizer ) return 1 ;
/ / I f b o t h a r e o r g a n i z e r s o r n e i t h e r a r e o r g a n i z e r s , s o r t b y a d m i s s i o n s t a t u s
if ( aIsOrganizer && bIsOrganizer ) return 0 ; / / B o t h o r g a n i z e r s , m a i n t a i n o r i g i n a l o r d e r
/ / N o n - a d m i t t e d m e m b e r s c o m e b e f o r e a d m i t t e d m e m b e r s
if ( ! a . member . admitted && b . member . admitted ) return - 1 ;
if ( a . member . admitted && ! b . member . admitted ) return 1 ;
/ / I f a d m i s s i o n s t a t u s i s t h e s a m e , m a i n t a i n o r i g i n a l o r d e r
return 0 ;
} ) ;
}
informAboutAdmission ( ) {
@ -701,6 +754,114 @@ export default class MembersList extends Vue {
this . startAutoRefresh ( ) ;
}
/ * *
* Get count of pending ( non - admitted ) members
* /
getPendingMembersCount ( ) : number {
return this . decryptedMembers . filter (
( member ) => ! member . member . admitted && member . did !== this . activeDid ,
) . length ;
}
/ * *
* Get list of pending members
* /
getPendingMembers ( ) : DecryptedMember [ ] {
return this . decryptedMembers . filter (
( member ) => ! member . member . admitted && member . did !== this . activeDid ,
) ;
}
/ * *
* Show the admit all pending members dialog
* /
showAdmitAllPendingDialog ( ) {
const pendingCount = this . getPendingMembersCount ( ) ;
if ( pendingCount === 0 ) {
this . notify . info (
"There are no pending members to admit." ,
TIMEOUTS . STANDARD ,
) ;
return ;
}
/ / P a u s e a u t o - r e f r e s h w h e n d i a l o g o p e n s
this . stopAutoRefresh ( ) ;
const dialogText = NOTIFY_ADMIT_ALL_PENDING . text . replace (
"{count}" ,
pendingCount . toString ( ) ,
) ;
this . $notify (
{
group : "modal" ,
type : "confirm" ,
title : NOTIFY_ADMIT_ALL_PENDING . title ,
text : dialogText ,
yesText : NOTIFY_ADMIT_ALL_PENDING . yesText ,
noText : NOTIFY_ADMIT_ALL_PENDING . noText ,
onYes : async ( ) => {
await this . admitAllPendingMembers ( true ) ; / / t r u e = a d d t o c o n t a c t s
/ / R e s u m e a u t o - r e f r e s h a f t e r a c t i o n
this . startAutoRefresh ( ) ;
} ,
onNo : async ( ) => {
await this . admitAllPendingMembers ( false ) ; / / f a l s e = d o n ' t a d d t o c o n t a c t s
/ / R e s u m e a u t o - r e f r e s h a f t e r a c t i o n
this . startAutoRefresh ( ) ;
} ,
onCancel : async ( ) => {
/ / D o n o t h i n g - u s e r c a n c e l l e d
/ / R e s u m e a u t o - r e f r e s h a f t e r c a n c e l l a t i o n
this . startAutoRefresh ( ) ;
} ,
} ,
TIMEOUTS . MODAL ,
) ;
}
/ * *
* Admit all pending members with optional contact addition
* /
async admitAllPendingMembers ( addToContacts : boolean ) {
const pendingMembers = this . getPendingMembers ( ) ;
if ( pendingMembers . length === 0 ) {
return ;
}
try {
/ / P r o c e s s e a c h p e n d i n g m e m b e r
for ( const member of pendingMembers ) {
/ / A d d t o c o n t a c t s i f r e q u e s t e d a n d n o t a l r e a d y a c o n t a c t
if ( addToContacts && ! this . getContactFor ( member . did ) ) {
await this . addAsContact ( member ) ;
}
/ / A d m i t t h e m e m b e r
await this . toggleAdmission ( member ) ;
}
/ / S h o w s u c c e s s m e s s a g e
const contactMessage = addToContacts ? " and added to your contacts" : "" ;
this . notify . success (
` All ${ pendingMembers . length } pending members have been admitted ${ contactMessage } . ` ,
TIMEOUTS . STANDARD ,
) ;
} catch ( error ) {
this . $logAndConsole (
"Error admitting all pending members: " + errorStringForLog ( error ) ,
true ,
) ;
this . notify . error (
"Failed to admit some members. Please try again." ,
TIMEOUTS . LONG ,
) ;
}
}
beforeDestroy ( ) {
this . stopAutoRefresh ( ) ;
}
@ -718,23 +879,26 @@ export default class MembersList extends Vue {
. btn - add - contact {
/* stylelint-disable-next-line at-rule-no-unknown */
@ apply w - 6 h - 6 flex items - center justify - center rounded - full
bg - green - 100 text - green - 600 hover : bg - green - 200 hover : text - green - 800
@ apply text - lg text - green - 600 hover : text - green - 800
transition - colors ;
}
. btn - info - contact ,
. btn - info - admission {
/* stylelint-disable-next-line at-rule-no-unknown */
@ apply w - 6 h - 6 flex items - center justify - center rounded - full
bg - slate - 100 text - slate - 400 hover : text - slate - 600
@ apply text - slate - 400 hover : text - slate - 600
transition - colors ;
}
. btn - admission {
. btn - admission - add {
/* stylelint-disable-next-line at-rule-no-unknown */
@ apply w - 6 h - 6 flex items - center justify - center rounded - full
bg - blue - 100 text - blue - 600 hover : bg - blue - 200 hover : text - blue - 800
@ apply text - lg text - blue - 500 hover : text - blue - 700
transition - colors ;
}
. btn - admission - remove {
/* stylelint-disable-next-line at-rule-no-unknown */
@ apply text - lg text - rose - 500 hover : text - rose - 700
transition - colors ;
}
< / style >