src/app/modules/groups/components/group-members/group-members.component.ts
OnInit
OnDestroy
selector | app-group-members |
styleUrls | ./group-members.component.scss |
templateUrl | ./group-members.component.html |
Properties |
Methods |
Inputs |
constructor(router: Router, activatedRoute: ActivatedRoute, resourceService: ResourceService, groupsService: GroupsService, toasterService: ToasterService, userService: UserService)
|
|||||||||||||||||||||
Parameters :
|
config | |
Type : IGroupMemberConfig
|
|
Default value : {
showMemberCount: false,
showSearchBox: false,
showAddMemberButton: false,
showMemberMenu: false
}
|
|
groupData | |
Type : IGroupCard
|
|
members | |
Type : IGroupMember[]
|
|
Default value : []
|
|
addMember |
addMember()
|
Returns :
void
|
addTelemetry | ||||||||||||
addTelemetry(id, extra?, edata?)
|
||||||||||||
Parameters :
Returns :
void
|
dismissRole | ||||
dismissRole(data)
|
||||
Parameters :
Returns :
void
|
getMenuData | ||||||
getMenuData(event, member)
|
||||||
Parameters :
Returns :
void
|
getUpdatedGroupData |
getUpdatedGroupData()
|
Returns :
void
|
hideMemberMenu |
hideMemberMenu()
|
Returns :
void
|
ngOnDestroy |
ngOnDestroy()
|
Returns :
void
|
ngOnInit |
ngOnInit()
|
Returns :
void
|
onActionConfirm | ||||||
onActionConfirm(event: any)
|
||||||
Parameters :
Returns :
void
|
onModalClose |
onModalClose()
|
Returns :
void
|
openModal | ||||||
openModal(action: string)
|
||||||
Parameters :
Returns :
void
|
promoteMember | ||||
promoteMember(data)
|
||||
Parameters :
Returns :
void
|
removeMember | ||||
removeMember(data)
|
||||
Parameters :
Returns :
void
|
resetValue |
resetValue()
|
Returns :
void
|
search | ||||||
search(searchKey: string)
|
||||||
Parameters :
Returns :
void
|
showAddMember |
showAddMember()
|
Returns :
boolean
|
Public ADD_MEMBER |
Default value : ADD_MEMBER
|
currentUser |
groupId |
memberAction |
Type : string
|
memberCardConfig |
Type : object
|
Default value : { size: 'small', isBold: false, isSelectable: false, view: 'horizontal' }
|
memberListToShow |
Type : IGroupMember[]
|
Default value : []
|
Public resourceService |
Type : ResourceService
|
searchInputBox |
Type : ElementRef
|
Decorators :
@ViewChild('searchInputBox')
|
searchQuery |
Type : string
|
Default value : ''
|
selectedMember |
Type : IGroupMember
|
showKebabMenu |
Default value : false
|
showLoader |
Default value : false
|
showModal |
Default value : false
|
showSearchResults |
Default value : false
|
Private unsubscribe$ |
Default value : new Subject<void>()
|
import { UserService } from '@sunbird/core';
import { Component, ElementRef, Input, OnDestroy, OnInit, ViewChild } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { GroupMemberRole, GroupEntityStatus } from '@project-sunbird/client-services/models/group';
import { ResourceService, ToasterService } from '@sunbird/shared';
import * as _ from 'lodash-es';
import { fromEvent, Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { GROUP_DETAILS, IGroupMember, IGroupMemberConfig, MY_GROUPS, IGroupCard } from '../../interfaces';
import { GroupsService } from '../../services';
import { ADD_MEMBER } from '../../interfaces/telemetryConstants';
@Component({
selector: 'app-group-members',
templateUrl: './group-members.component.html',
styleUrls: ['./group-members.component.scss']
})
export class GroupMembersComponent implements OnInit, OnDestroy {
@ViewChild('searchInputBox') searchInputBox: ElementRef;
@Input() config: IGroupMemberConfig = {
showMemberCount: false,
showSearchBox: false,
showAddMemberButton: false,
showMemberMenu: false
};
@Input() members: IGroupMember[] = [];
@Input() groupData: IGroupCard;
currentUser;
showKebabMenu = false;
showModal = false;
showSearchResults = false;
memberListToShow: IGroupMember[] = [];
memberAction: string;
searchQuery = '';
selectedMember: IGroupMember;
private unsubscribe$ = new Subject<void>();
groupId;
showLoader = false;
memberCardConfig = { size: 'small', isBold: false, isSelectable: false, view: 'horizontal' };
public ADD_MEMBER = ADD_MEMBER;
constructor(
private router: Router,
private activatedRoute: ActivatedRoute,
public resourceService: ResourceService,
private groupsService: GroupsService,
private toasterService: ToasterService,
private userService: UserService
) { }
ngOnInit() {
this.showLoader = false;
this.groupId = _.get(this.activatedRoute, 'snapshot.params.groupId');
this.memberListToShow = _.cloneDeep(this.members);
this.hideMemberMenu();
fromEvent(document, 'click')
.pipe(takeUntil(this.unsubscribe$))
.subscribe(item => {
if (this.showKebabMenu) {
this.showKebabMenu = false;
this.addTelemetry('member-card-menu-close');
}
});
this.groupsService.membersList.subscribe(members => {
this.memberListToShow = members;
this.hideMemberMenu();
});
this.groupsService.showMenu.subscribe(data => {
this.showKebabMenu = data === 'member';
});
this.groupsService.updateEvent.pipe(takeUntil(this.unsubscribe$)).subscribe((status: GroupEntityStatus) => {
this.groupData.active = this.groupsService.updateGroupStatus(this.groupData, status);
});
}
hideMemberMenu() {
/* istanbul ignore else */
if (!this.config.showMemberMenu) {
this.memberListToShow.forEach(item => item.isMenu = false);
}
}
getMenuData(event, member) {
this.showKebabMenu = !this.showKebabMenu;
this.groupsService.emitMenuVisibility('member');
this.showKebabMenu ? this.addTelemetry('member-card-menu-show') : this.addTelemetry('member-card-menu-close');
this.selectedMember = member;
event.event.stopImmediatePropagation();
}
search(searchKey: string) {
searchKey = _.toLower(searchKey).trim();
if (searchKey.trim().length) {
this.showSearchResults = true;
this.memberListToShow = this.members.filter(item => _.toLower(item.title).includes(searchKey));
this.addTelemetry('group-member-search-input', { query: searchKey });
} else {
this.showSearchResults = false;
this.memberListToShow = _.cloneDeep(this.members);
}
}
openModal(action: string) {
this.showModal = !this.showModal;
this.memberAction = action;
}
addMember() {
this.router.navigate([`${MY_GROUPS}/${GROUP_DETAILS}`, _.get(this.groupData, 'id') || this.groupId, 'add-member-to-group']);
}
onModalClose() {
this.showModal = false;
// Handle Telemetry
}
getUpdatedGroupData() {
const groupId = _.get(this.groupData, 'id') || _.get(this.activatedRoute.snapshot, 'params.groupId');
this.groupsService.getGroupById(groupId, true, true).pipe(takeUntil(this.unsubscribe$)).subscribe(groupData => {
const user = _.find(_.get(groupData, 'members'), (m) => _.get(m, 'userId') === this.userService.userid);
if (!user || _.get(groupData, 'status') === 'inactive') {
this.groupsService.goBack();
}
this.groupsService.groupData = groupData;
this.groupData = groupData;
this.members = this.groupsService.addFieldsToMember(_.get(this.groupData, 'members'));
this.memberListToShow = _.cloneDeep(this.members);
this.showLoader = false;
}, err => {
this.showLoader = false;
this.toasterService.error(this.resourceService.messages.emsg.m002);
this.groupsService.goBack();
});
}
onActionConfirm(event: any) {
/* istanbul ignore else */
if (event.action) {
switch (event.action) {
case 'promoteAsAdmin':
this.promoteMember(event.data);
break;
case 'removeFromGroup':
this.removeMember(event.data);
break;
case 'dismissAsAdmin':
this.dismissRole(event.data);
break;
}
}
}
promoteMember(data) {
this.showLoader = true;
const memberReq = {
members: [{
userId: _.get(data, 'userId'),
role: GroupMemberRole.ADMIN
}]
};
this.groupsService.updateMembers(this.groupId, memberReq).pipe(takeUntil(this.unsubscribe$)).subscribe(res => {
this.showLoader = false;
this.getUpdatedGroupData();
this.toasterService.success(_.replace(this.resourceService.messages.smsg.promoteAsAdmin, '{memberName}', _.get(data, 'name')));
}, error => {
this.showLoader = false;
this.toasterService.error(_.replace(this.resourceService.messages.emsg.promoteAsAdmin, '{memberName}', _.get(data, 'name')));
});
}
removeMember(data) {
this.showLoader = true;
this.groupsService.removeMembers(this.groupId, [_.get(data, 'userId')]).pipe(takeUntil(this.unsubscribe$)).subscribe(res => {
this.showLoader = false;
this.getUpdatedGroupData();
this.toasterService.success(_.replace(this.resourceService.messages.smsg.removeMember, '{memberName}', _.get(data, 'name')));
}, error => {
this.showLoader = false;
this.toasterService.error(this.resourceService.messages.emsg.removeMember);
});
}
dismissRole(data) {
this.showLoader = true;
const req = {
members: [{
userId: _.get(data, 'userId'),
role: GroupMemberRole.MEMBER
}]
};
this.groupsService.updateMembers(this.groupId, req).pipe(takeUntil(this.unsubscribe$)).subscribe(res => {
this.showLoader = false;
this.getUpdatedGroupData();
this.toasterService.success(_.replace(this.resourceService.messages.smsg.dissmissAsAdmin, '{memberName}', _.get(data, 'name')));
}, error => {
this.showLoader = false;
this.toasterService.error(this.resourceService.messages.emsg.dissmissAsAdmin);
});
}
/**
* @description - To set the telemetry Intract event data
* @param {} edata? - it's an object to specify the type and subtype of edata
*/
addTelemetry(id, extra?, edata?) {
this.groupsService.addTelemetry({id, extra, edata}, this.activatedRoute.snapshot, [], this.groupId);
}
showAddMember () {
if (!this.groupData.active || !this.config.showAddMemberButton) {
return false;
}
return (this.groupData['isAdmin'] && !this.showSearchResults);
}
ngOnDestroy() {
this.unsubscribe$.next();
this.unsubscribe$.complete();
}
resetValue() {
this.searchInputBox.nativeElement.value = '';
this.search('');
}
}
<div class="flex-dc d-flex p-8 py-24 sb-bg-color-white br-4 sb-groups-members-card">
<div class="title mb-16 font-weight-bold px-8">
{{resourceService?.frmelmnts?.lbl?.members}}
<span *ngIf="config?.showMemberCount" class="badge">{{groupData?.members?.length}}</span>
</div>
<div class="sb-library-cards">
<div class="px-8" *ngIf="config?.showSearchBox">
<div class="sb-search-box no-btn mb-16">
<div class="input-div relative">
<i class="search icon" aria-hidden="true"></i>
<label for="search-within-group" class="hide">{{resourceService?.frmelmnts?.lbl?.searchWithinGroup}}</label>
<input class="sb-search-input" id="search-within-group" type="text" #searchInputBox (input)="search(searchInputBox.value)"
[placeholder]="resourceService?.frmelmnts?.lbl?.searchWithinGroup"/>
<i class="icon close mt-4" (click)="resetValue();"></i>
</div>
<button class="sb-btn sb-btn-normal">{{resourceService?.frmelmnts?.lbl?.search}}</button>
</div>
</div>
<div *ngIf="showAddMember()" tabindex="0" (click)="addMember();addTelemetry('add-member-btn', '', { type: ADD_MEMBER})">
<div class="cursor-pointer mb-8 fnormal px-8">
<img alt="admin" src="./assets/images/add-member-1.png" width="32">
{{resourceService?.frmelmnts?.lbl?.addMember}}
</div>
<div class="devided-line m-8"></div>
</div>
<div class="d-flex flex-dc" *ngIf="memberListToShow?.length && !showLoader">
<div *ngFor="let member of memberListToShow" class="relative">
<sb-member-card [title]="member?.title" [identifier]="member?.identifier" [config]="memberCardConfig"
[isAdmin]="member?.isAdmin" [isMenu]="member?.isMenu && groupData?.active" [indexOfMember]="member?.indexOfMember"
[initial]="member?.initial" (menuClick)="getMenuData($event, member)">
</sb-member-card>
<div class="kabab-menu-dropdown-content"
*ngIf="showKebabMenu && selectedMember?.identifier === member?.identifier">
<div class="list mb-8" tabindex="0" (click)="openModal('promoteAsAdmin')" *ngIf="!member?.isAdmin">
<span>{{resourceService?.frmelmnts?.btn?.makeAdmin}}</span>
</div>
<div class="list mb-8" tabindex="0" (click)="openModal('dismissAsAdmin')" *ngIf="member?.isAdmin && !member?.isCreator">
<span>{{resourceService?.frmelmnts?.btn?.dismissAdmin}}</span>
</div>
<div class="list sb-color-error" tabindex="0" (click)="openModal('removeFromGroup')" *ngIf="!member?.isCreator">
<span>{{resourceService?.frmelmnts?.btn?.removeMember}}</span>
</div>
</div>
</div>
</div>
<div class="d-flex flex-dc" *ngIf="showLoader"><!--showLoader && !memberListToShow?.length -->
<div *ngFor="let item of [0,1,2,3]">
<sb-member-card [isLoading]="true" [config]="memberCardConfig"></sb-member-card>
</div>
</div>
<!--No Group member except admin-->
<div class="d-flex flex-dc flex-jc-center flex-ai-center text-center my-24"
*ngIf="memberListToShow?.length < 2 && !showSearchResults">
<img width="197" alt="" src="./assets/images/add-member@2x.svg">
</div>
<!--No search results -->
<div class="member-no-result pt-32" *ngIf="showSearchResults && !memberListToShow?.length">
<div class="d-flex flex-dc flex-jc-center flex-ai-center text-center">
<img alt="" height="165" width="206" src="./assets/images/group-search-empty.svg">
<div class="mt-16 no-result-text">
{{resourceService?.frmelmnts?.lbl?.NoSerchGroupMemberResults}}
</div>
<div class="my-8 no-result-desc hide">
<div>{{resourceService?.frmelmnts?.lbl?.checkYourSpelling}}</div>
<div>{{resourceService?.frmelmnts?.lbl?.similarButDiffName}}</div>
</div>
</div>
</div>
</div>
</div>
<app-member-actions *ngIf="showModal" [action]="memberAction" [member]="selectedMember" (modalClose)="onModalClose()"
(actionConfirm)="onActionConfirm($event)"></app-member-actions>
./group-members.component.scss
@use "@project-sunbird/sb-styles/assets/mixins/mixins" as *;
@use "pages/kabab-menu" as *;
.devided-line {
border-bottom: calculateRem(0.5px) solid var(--gray-100);
}
.member-no-result {
.no-result-text {
font-size: calculateRem(14px);
}
.no-result-desc {
font-size: calculateRem(12px);
color: var(--gray-200);
}
}