그룹 > 동료리스트 context menu > 이 그룹에서 삭제, 대화 상대, 대화 상대 이동 :: 기능 구현.

This commit is contained in:
leejinho 2019-11-21 11:46:49 +09:00
parent 7cd159efba
commit b3c649c393
6 changed files with 227 additions and 23 deletions

View File

@ -33,13 +33,13 @@
(more)="onMoreGroup($event)" (more)="onMoreGroup($event)"
> >
<ucap-profile-user-list-item <ucap-profile-user-list-item
*ucapGroupExpansionPanelItem="let userInfo" *ucapGroupExpansionPanelItem="let userInfo; let group = group"
[userInfo]="userInfo" [userInfo]="userInfo"
[presence]="getStatusBulkInfo(userInfo) | async" [presence]="getStatusBulkInfo(userInfo) | async"
[sessionVerinfo]="sessionVerinfo" [sessionVerinfo]="sessionVerinfo"
(click)="onSelectBuddy(userInfo)" (click)="onSelectBuddy(userInfo)"
(openProfile)="onClickOpenProfile($event)" (openProfile)="onClickOpenProfile($event)"
(contextmenu)="onContextMenuProfile($event, userInfo)" (contextmenu)="onContextMenuProfile($event, userInfo, group)"
class="list-item-frame" class="list-item-frame"
> >
</ucap-profile-user-list-item> </ucap-profile-user-list-item>
@ -121,7 +121,7 @@
[hasBackdrop]="false" [hasBackdrop]="false"
(ucapClickOutside)="profileContextMenuTrigger.closeMenu()" (ucapClickOutside)="profileContextMenuTrigger.closeMenu()"
> >
<ng-template matMenuContent let-userInfo="userInfo"> <ng-template matMenuContent let-userInfo="userInfo" let-group="group">
<button <button
mat-menu-item mat-menu-item
(click)="onClickProfileContextMenu('VIEW_PROFILE', userInfo)" (click)="onClickProfileContextMenu('VIEW_PROFILE', userInfo)"
@ -130,7 +130,7 @@
</button> </button>
<button <button
mat-menu-item mat-menu-item
*ngIf="getShowContextMenu(userInfo)" *ngIf="getShowContextMenu('REGISTER_FAVORITE', userInfo, group)"
(click)="onClickProfileContextMenu('REGISTER_FAVORITE', userInfo)" (click)="onClickProfileContextMenu('REGISTER_FAVORITE', userInfo)"
> >
즐겨찾기 {{ userInfo.isFavorit ? '해제' : '등록' }} 즐겨찾기 {{ userInfo.isFavorit ? '해제' : '등록' }}
@ -140,39 +140,39 @@
</button> </button>
<button <button
mat-menu-item mat-menu-item
*ngIf="getShowContextMenu(userInfo)" *ngIf="getShowContextMenu('REMOVE_FROM_GROUP', userInfo, group)"
(click)="onClickProfileContextMenu('REMOVE_FROM_GROUP', userInfo)" (click)="onClickProfileContextMenu('REMOVE_FROM_GROUP', userInfo, group)"
> >
이 그룹에서 삭제 이 그룹에서 삭제
</button> </button>
<button <button
mat-menu-item mat-menu-item
*ngIf="getShowContextMenu(userInfo)" *ngIf="getShowContextMenu('COPY_BUDDY', userInfo, group)"
(click)="onClickProfileContextMenu('COPY_BUDDY', userInfo)" (click)="onClickProfileContextMenu('COPY_BUDDY', userInfo)"
> >
대화 상대 복사 대화 상대 복사
</button> </button>
<button <button
mat-menu-item mat-menu-item
*ngIf="getShowContextMenu(userInfo)" *ngIf="getShowContextMenu('MOVE_BUDDY', userInfo, group)"
(click)="onClickProfileContextMenu('MOVE_BUDDY', userInfo)" (click)="onClickProfileContextMenu('MOVE_BUDDY', userInfo, group)"
> >
대화 상대 이동 대화 상대 이동
</button> </button>
<button <button
mat-menu-item mat-menu-item
*ngIf="getShowContextMenu(userInfo)" *ngIf="getShowContextMenu('SEND_NOTE', userInfo, group)"
(click)="onClickProfileContextMenu('SEND_NOTE', userInfo)" (click)="onClickProfileContextMenu('SEND_NOTE', userInfo)"
> >
쪽지 보내기 쪽지 보내기
</button> </button>
<button <!-- <button
mat-menu-item mat-menu-item
*ngIf="getShowContextMenu(userInfo)" *ngIf="getShowContextMenu('REGISTER_NICKNAME', userInfo, group)"
(click)="onClickProfileContextMenu('REGISTER_NICKNAME', userInfo)" (click)="onClickProfileContextMenu('REGISTER_NICKNAME', userInfo)"
> >
닉네임 설정 닉네임 설정
</button> </button> -->
</ng-template> </ng-template>
</mat-menu> </mat-menu>

View File

@ -56,6 +56,11 @@ import {
EditGroupDialogData, EditGroupDialogData,
EditGroupDialogResult EditGroupDialogResult
} from '@app/layouts/messenger/dialogs/group/edit-group.dialog.component'; } from '@app/layouts/messenger/dialogs/group/edit-group.dialog.component';
import {
SelectGroupDialogComponent,
SelectGroupDialogResult,
SelectGroupDialogData
} from '../../dialogs/group/select-group.dialog.component';
@Component({ @Component({
selector: 'app-layout-chat-left-sidenav-group', selector: 'app-layout-chat-left-sidenav-group',
@ -281,20 +286,42 @@ export class GroupComponent implements OnInit, OnDestroy {
this.searchUserInfos = []; this.searchUserInfos = [];
} }
getShowContextMenu(userInfo: UserInfo | UserInfoF) { getShowContextMenu(
menuType: string,
userInfo: UserInfo | UserInfoF,
group?: GroupDetailData
) {
if (userInfo.seq === this.loginRes.userSeq) { if (userInfo.seq === this.loginRes.userSeq) {
return false; return false;
} else {
return true;
} }
if (!group || group === undefined) {
if (
menuType === 'REGISTER_FAVORITE' ||
menuType === 'SEND_NOTE' ||
menuType === 'REGISTER_NICKNAME'
) {
// continue;
} else {
return false;
}
}
return true;
} }
onClickProfileContextMenu(menuType: string, userInfo: UserInfo | UserInfoF) { async onClickProfileContextMenu(
menuType: string,
userInfo: UserInfo | UserInfoF,
group?: GroupDetailData
) {
this.logger.debug( this.logger.debug(
'onClickProfileContextMenu', 'onClickProfileContextMenu',
'menuType', 'menuType',
menuType, menuType,
'userInfo', 'userInfo',
userInfo userInfo,
'group',
group
); );
switch (menuType) { switch (menuType) {
case 'VIEW_PROFILE': case 'VIEW_PROFILE':
@ -303,6 +330,98 @@ export class GroupComponent implements OnInit, OnDestroy {
case 'CHAT': case 'CHAT':
this.onSelectBuddy(userInfo); this.onSelectBuddy(userInfo);
break; break;
case 'REMOVE_FROM_GROUP':
{
const result = await this.dialogService.open<
ConfirmDialogComponent,
ConfirmDialogData,
ConfirmDialogResult
>(ConfirmDialogComponent, {
width: '360px',
data: {
title: 'Delete Member in Group',
html: `[${userInfo.name} ${userInfo.grade}]를 [${group.name}]그룹에서 삭제하시겠습니까?`
}
});
if (!!result && !!result.choice && result.choice) {
const trgtUserSeq = group.userSeqs.filter(
user => user !== userInfo.seq
);
this.store.dispatch(
SyncStore.updateGroupMember({
oldGroup: group,
trgtUserSeq
})
);
}
}
break;
case 'COPY_BUDDY':
{
const result = await this.dialogService.open<
SelectGroupDialogComponent,
SelectGroupDialogData,
SelectGroupDialogResult
>(SelectGroupDialogComponent, {
width: '600px',
data: {
title: 'Group Select'
}
});
if (!!result && !!result.choice && result.choice) {
if (!!result.group) {
const oldGroup: GroupDetailData = result.group;
const trgtUserSeq: number[] = [];
let exist = false;
result.group.userSeqs.map(seq => {
trgtUserSeq.push(seq);
if (seq === userInfo.seq) {
exist = true;
}
});
if (!exist) {
trgtUserSeq.push(userInfo.seq);
}
this.store.dispatch(
SyncStore.updateGroupMember({
oldGroup,
trgtUserSeq
})
);
}
}
}
break;
case 'MOVE_BUDDY':
{
const result = await this.dialogService.open<
SelectGroupDialogComponent,
SelectGroupDialogData,
SelectGroupDialogResult
>(SelectGroupDialogComponent, {
width: '600px',
data: {
title: 'Group Select'
}
});
if (!!result && !!result.choice && result.choice) {
if (!!result.group) {
this.store.dispatch(
SyncStore.moveGroupMember({
fromGroup: group,
toGroup: result.group,
trgtUserSeq: [userInfo.seq]
})
);
}
}
}
break;
case 'REGISTER_FAVORITE': case 'REGISTER_FAVORITE':
this.store.dispatch( this.store.dispatch(
SyncStore.updateBuddy({ SyncStore.updateBuddy({
@ -320,7 +439,8 @@ export class GroupComponent implements OnInit, OnDestroy {
onContextMenuProfile( onContextMenuProfile(
event: MouseEvent, event: MouseEvent,
userInfo: UserInfo | UserInfoSS | UserInfoF | UserInfoDN userInfo: UserInfo | UserInfoSS | UserInfoF | UserInfoDN,
group: GroupDetailData
) { ) {
event.preventDefault(); event.preventDefault();
event.stopPropagation(); event.stopPropagation();
@ -328,7 +448,7 @@ export class GroupComponent implements OnInit, OnDestroy {
this.profileContextMenuPosition.x = event.clientX + 'px'; this.profileContextMenuPosition.x = event.clientX + 'px';
this.profileContextMenuPosition.y = event.clientY + 'px'; this.profileContextMenuPosition.y = event.clientY + 'px';
this.profileContextMenuTrigger.menu.focusFirstItem('mouse'); this.profileContextMenuTrigger.menu.focusFirstItem('mouse');
this.profileContextMenuTrigger.menuData = { userInfo }; this.profileContextMenuTrigger.menuData = { userInfo, group };
this.profileContextMenuTrigger.openMenu(); this.profileContextMenuTrigger.openMenu();
} }

View File

@ -149,6 +149,23 @@ export const updateGroupMemberFailure = createAction(
'[Messenger::Sync] Update Group Member Failure', '[Messenger::Sync] Update Group Member Failure',
props<{ error: any }>() props<{ error: any }>()
); );
/** 그룹원 이동 */
export const moveGroupMember = createAction(
'[Messenger::Sync] Move Group Member',
props<{
fromGroup: GroupDetailData;
toGroup: GroupDetailData;
trgtUserSeq: number[];
}>()
);
export const moveGroupToFailure = createAction(
'[Messenger::Sync] Move Group Member / To',
props<{ error: any }>()
);
export const moveGroupFromFailure = createAction(
'[Messenger::Sync] Move Group Member / From',
props<{ error: any }>()
);
/** 동료 추가 */ /** 동료 추가 */
export const addBuddy = createAction( export const addBuddy = createAction(

View File

@ -48,7 +48,10 @@ import {
delGroup, delGroup,
delGroupFailure, delGroupFailure,
delGroupSuccess, delGroupSuccess,
delBuddyAndClear delBuddyAndClear,
moveGroupMember,
moveGroupFromFailure,
moveGroupToFailure
} from './actions'; } from './actions';
import { SessionStorageService } from '@ucap-webmessenger/web-storage'; import { SessionStorageService } from '@ucap-webmessenger/web-storage';
import { LoginInfo, KEY_LOGIN_INFO } from '@app/types'; import { LoginInfo, KEY_LOGIN_INFO } from '@app/types';
@ -623,6 +626,67 @@ export class Effects {
{ dispatch: false } { dispatch: false }
); );
moveGroupMember$ = createEffect(() =>
this.actions$.pipe(
ofType(moveGroupMember),
withLatestFrom(
this.store.pipe(
select(
(state: any) =>
state.messenger.sync.group2.entities as Dictionary<
GroupDetailData
>
)
),
this.store.pipe(
select((state: any) => state.messenger.sync.group2.syncDate as string)
)
),
exhaustMap(([action, groupList, syncDate]) => {
// copy to
let toTrgtUserSeqs = groupList[action.toGroup.seq].userSeqs;
action.trgtUserSeq.forEach(trgtSeq => {
if (toTrgtUserSeqs.indexOf(trgtSeq) > -1) {
// ignore
} else {
toTrgtUserSeqs = toTrgtUserSeqs.concat(trgtSeq);
}
});
return this.groupProtocolService
.update2({
groupSeq: action.toGroup.seq,
groupName: action.toGroup.name,
userSeqs: toTrgtUserSeqs
})
.pipe(
exhaustMap((resTo: GroupUpdateResponse) => {
// del from
const fromTrgtUserSeqs = groupList[action.fromGroup.seq].userSeqs;
return this.groupProtocolService
.update2({
groupSeq: action.fromGroup.seq,
groupName: action.fromGroup.name,
userSeqs: fromTrgtUserSeqs.filter(
trgtSeq => action.trgtUserSeq.indexOf(trgtSeq) < 0
)
})
.pipe(
map((resFrom: GroupUpdateResponse) => {
return group2({
syncDate
});
}),
catchError(error => of(moveGroupFromFailure({ error })))
);
}),
catchError(error => of(moveGroupToFailure({ error })))
);
})
)
);
delGroup$ = createEffect(() => delGroup$ = createEffect(() =>
this.actions$.pipe( this.actions$.pipe(
ofType(delGroup), ofType(delGroup),

View File

@ -19,10 +19,12 @@
<div class="mat-tree-node"> <div class="mat-tree-node">
<ng-container <ng-container
[ngTemplateOutlet]="expansionPanelItemTemplateRef" [ngTemplateOutlet]="expansionPanelItemTemplateRef"
[ngTemplateOutletContext]="{ $implicit: node?.userInfo }" [ngTemplateOutletContext]="{
$implicit: node?.userInfo,
group: node?.groupDetail
}"
> >
</ng-container> </ng-container>
<!--{{ node?.userInfo?.name }}-->
</div> </div>
</li> </li>
</mat-tree-node> </mat-tree-node>

View File

@ -119,6 +119,7 @@ export class ExpansionPanelComponent
item.buddyList.forEach(userInfo => { item.buddyList.forEach(userInfo => {
groupNode.children.push({ groupNode.children.push({
nodeType: NodeType.Buddy, nodeType: NodeType.Buddy,
groupDetail: item.group,
userInfo userInfo
}); });
}); });