기능추가 :: 대화방 > 대화전달

This commit is contained in:
leejh 2019-10-24 17:04:58 +09:00
parent 14ab59459f
commit 7f32caa01f
8 changed files with 259 additions and 39 deletions

View File

@ -1,3 +1,4 @@
import { forward } from './../../../store/messenger/event/actions';
import { import {
Component, Component,
OnInit, OnInit,
@ -32,7 +33,11 @@ import * as ChatStore from '@app/store/messenger/chat';
import * as RoomStore from '@app/store/messenger/room'; import * as RoomStore from '@app/store/messenger/room';
import { LoginResponse } from '@ucap-webmessenger/protocol-authentication'; import { LoginResponse } from '@ucap-webmessenger/protocol-authentication';
import { SessionStorageService } from '@ucap-webmessenger/web-storage'; import { SessionStorageService } from '@ucap-webmessenger/web-storage';
import { EnvironmentsInfo, KEY_ENVIRONMENTS_INFO } from '@app/types'; import {
EnvironmentsInfo,
KEY_ENVIRONMENTS_INFO,
UserSelectDialogType
} from '@app/types';
import { RoomInfo, UserInfo, RoomType } from '@ucap-webmessenger/protocol-room'; import { RoomInfo, UserInfo, RoomType } from '@ucap-webmessenger/protocol-room';
import { tap, take } from 'rxjs/operators'; import { tap, take } from 'rxjs/operators';
import { FileInfo } from '@ucap-webmessenger/ui-chat'; import { FileInfo } from '@ucap-webmessenger/ui-chat';
@ -40,22 +45,11 @@ import { KEY_VER_INFO } from '@app/types/ver-info.type';
import { VersionInfo2Response } from '@ucap-webmessenger/api-public'; import { VersionInfo2Response } from '@ucap-webmessenger/api-public';
import { MatMenuTrigger } from '@angular/material'; import { MatMenuTrigger } from '@angular/material';
import { CommonApiService } from '@ucap-webmessenger/api-common'; import { CommonApiService } from '@ucap-webmessenger/api-common';
import { import {
DeleteMessageDialogComponent, CreateChatDialogComponent,
DeleteMessageDialogData, CreateChatDialogData,
DeleteMessageDialogResult CreateChatDialogResult
} from '@app/layouts/messenger/dialogs/message/delete-message.dialog.component'; } from '../dialogs/chat/create-chat.dialog.component';
import {
RelayMessageDialogComponent,
RelayMessageDialogData,
RelayMessageDialogResult
} from '@app/layouts/messenger/dialogs/message/relay-message.dialog.component';
import {
RecallMessageDialogComponent,
RecallMessageDialogData,
RecallMessageDialogResult
} from '@app/layouts/messenger/dialogs/message/recall-message.dialog.component';
@Component({ @Component({
selector: 'app-layout-messenger-messages', selector: 'app-layout-messenger-messages',
@ -320,16 +314,48 @@ export class MessagesComponent implements OnInit, OnDestroy, AfterViewChecked {
case 'REPLAY': case 'REPLAY':
{ {
const result = await this.dialogService.open< const result = await this.dialogService.open<
RelayMessageDialogComponent, CreateChatDialogComponent,
RelayMessageDialogData, CreateChatDialogData,
RelayMessageDialogResult CreateChatDialogResult
>(RelayMessageDialogComponent, { >(CreateChatDialogComponent, {
width: '220px', width: '600px',
height: '500px',
data: { data: {
title: 'Logout', type: UserSelectDialogType.MessageForward,
message: 'Logout ?' title: 'MessageForward',
ignoreRoom: [this.roomInfo]
} }
}); });
if (!!result && !!result.choice && result.choice) {
const userSeqs: number[] = [];
let roomSeq = '';
if (
!!result.selectedUserList &&
result.selectedUserList.length > 0
) {
result.selectedUserList.map(user => userSeqs.push(user.seq));
}
if (!!result.selectedRoom) {
roomSeq = result.selectedRoom.roomSeq;
}
if (userSeqs.length > 0 || roomSeq.trim().length > 0) {
this.store.dispatch(
EventStore.forward({
senderSeq: this.loginRes.userSeq,
req: {
roomSeq: '-999',
eventType: message.type,
sentMessage: message.sentMessage
},
trgtUserSeqs: userSeqs,
trgtRoomSeq: roomSeq
})
);
}
}
} }
break; break;
case 'REPLAY_TO_ME': case 'REPLAY_TO_ME':

View File

@ -25,7 +25,10 @@
fxLayoutGap.xs="0" fxLayoutGap.xs="0"
> >
<div fxFlex class="container"> <div fxFlex class="container">
<mat-tab-group mat-stretch-tabs> <mat-tab-group
mat-stretch-tabs
(selectedTabChange)="onSelectedTabChange($event)"
>
<mat-tab> <mat-tab>
<ng-template mat-tab-label> <ng-template mat-tab-label>
<mat-icon>group</mat-icon> <mat-icon>group</mat-icon>
@ -98,12 +101,16 @@
[roomInfo]="room" [roomInfo]="room"
[roomUserInfo]="getRoomUserList(room)" [roomUserInfo]="getRoomUserList(room)"
[sessionVerinfo]="sessionVerinfo" [sessionVerinfo]="sessionVerinfo"
[checkable]="getCheckableRoom(room)"
[isChecked]="getCheckedRoom(room)"
[multiCheckable]="false"
(checkRoom)="onCheckRoom($event)"
> >
</ucap-room-list-item> </ucap-room-list-item>
</mat-tab> </mat-tab>
</mat-tab-group> </mat-tab-group>
</div> </div>
<div fxFlex="150px"> <div fxFlex="150px" *ngIf="isShowSelectedUserList">
<mat-chip-list aria-label="User selection"> <mat-chip-list aria-label="User selection">
<mat-chip <mat-chip
*ngFor="let userInfo of selectedUserList" *ngFor="let userInfo of selectedUserList"

View File

@ -1,7 +1,17 @@
import { UserSelectDialogType } from './../../../../types/userselect.dialog.type'; import { UserSelectDialogType } from './../../../../types/userselect.dialog.type';
import { Component, OnInit, OnDestroy, Inject } from '@angular/core'; import {
Component,
OnInit,
OnDestroy,
Inject,
EventEmitter
} from '@angular/core';
import { FormGroup, FormBuilder, Validators } from '@angular/forms'; import { FormGroup, FormBuilder, Validators } from '@angular/forms';
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material'; import {
MatDialogRef,
MAT_DIALOG_DATA,
MatTabChangeEvent
} from '@angular/material';
import { NGXLogger } from 'ngx-logger'; import { NGXLogger } from 'ngx-logger';
import { Observable, combineLatest, Subscription, of } from 'rxjs'; import { Observable, combineLatest, Subscription, of } from 'rxjs';
import { map, tap, catchError } from 'rxjs/operators'; import { map, tap, catchError } from 'rxjs/operators';
@ -44,11 +54,14 @@ export interface CreateChatDialogData {
title: string; title: string;
/** CASE :: EditMember */ /** CASE :: EditMember */
group?: GroupDetailData; group?: GroupDetailData;
/** CASE :: EventForward */
ignoreRoom?: RoomInfo[];
} }
export interface CreateChatDialogResult { export interface CreateChatDialogResult {
choice: boolean; choice: boolean;
selectedUserList?: (UserInfo | UserInfoSS | UserInfoF | UserInfoDN)[]; selectedUserList?: (UserInfo | UserInfoSS | UserInfoF | UserInfoDN)[];
selectedRoom?: RoomInfo;
groupName?: string; groupName?: string;
oldGroup?: GroupDetailData; oldGroup?: GroupDetailData;
} }
@ -101,6 +114,8 @@ export class CreateChatDialogComponent implements OnInit, OnDestroy {
// 수집 데이터 // 수집 데이터
selectedUserList: (UserInfo | UserInfoSS | UserInfoF | UserInfoDN)[] = []; selectedUserList: (UserInfo | UserInfoSS | UserInfoF | UserInfoDN)[] = [];
isShowSelectedUserList = true;
selectedRoom: RoomInfo;
inputForm: FormGroup; inputForm: FormGroup;
@ -220,6 +235,16 @@ export class CreateChatDialogComponent implements OnInit, OnDestroy {
} }
} }
onSelectedTabChange(tabChangeEvent: MatTabChangeEvent): void {
if (tabChangeEvent.index === 2) {
this.selectedUserList = [];
this.isShowSelectedUserList = false;
} else {
this.selectedRoom = null;
this.isShowSelectedUserList = true;
}
}
/** 유저검색 */ /** 유저검색 */
onKeyDownEnterOrganizationTenantSearch(params: { onKeyDownEnterOrganizationTenantSearch(params: {
companyCode: string; companyCode: string;
@ -323,6 +348,15 @@ export class CreateChatDialogComponent implements OnInit, OnDestroy {
} }
} }
/** 대화방 > 대화방 선택 :: 해당 팝업에서는 대화방을 중복 선택하지 않는다 */
onCheckRoom(params: { isChecked: boolean; roomInfo: RoomInfo }) {
if (params.isChecked) {
this.selectedRoom = params.roomInfo;
} else {
this.selectedRoom = null;
}
}
/** 그룹>부서원 리스트의 ischecked 를 판단. */ /** 그룹>부서원 리스트의 ischecked 를 판단. */
getCheckedUser(userInfo: UserInfo | UserInfoSS | UserInfoF | UserInfoDN) { getCheckedUser(userInfo: UserInfo | UserInfoSS | UserInfoF | UserInfoDN) {
if (!!this.selectedUserList && this.selectedUserList.length > 0) { if (!!this.selectedUserList && this.selectedUserList.length > 0) {
@ -334,6 +368,22 @@ export class CreateChatDialogComponent implements OnInit, OnDestroy {
return false; return false;
} }
getCheckableRoom(roomInfo: RoomInfo) {
if (!!this.data.ignoreRoom && this.data.ignoreRoom.length > 0) {
return !(
this.data.ignoreRoom.filter(room => room.roomSeq === roomInfo.roomSeq)
.length > 0
);
}
return true;
}
getCheckedRoom(roomInfo: RoomInfo) {
if (!!this.selectedRoom) {
return this.selectedRoom.roomSeq === roomInfo.roomSeq;
}
return false;
}
/** 선택된 사용자 취소 */ /** 선택된 사용자 취소 */
onClickDeleteUser(userInfo: UserInfo | UserInfoSS | UserInfoF | UserInfoDN) { onClickDeleteUser(userInfo: UserInfo | UserInfoSS | UserInfoF | UserInfoDN) {
this.selectedUserList = this.selectedUserList.filter( this.selectedUserList = this.selectedUserList.filter(
@ -346,6 +396,7 @@ export class CreateChatDialogComponent implements OnInit, OnDestroy {
this.dialogRef.close({ this.dialogRef.close({
choice, choice,
selectedUserList: this.selectedUserList, selectedUserList: this.selectedUserList,
selectedRoom: this.selectedRoom,
groupName: groupName:
this.data.type === UserSelectDialogType.NewGroup this.data.type === UserSelectDialogType.NewGroup
? this.inputForm.get('groupName').value ? this.inputForm.get('groupName').value

View File

@ -72,6 +72,29 @@ export const sendNotification = createAction(
props<{ noti: SendNotification }>() props<{ noti: SendNotification }>()
); );
export const forward = createAction(
'[Messenger::Event] forward',
props<{
senderSeq: number;
req: SendRequest;
trgtUserSeqs?: number[];
trgtRoomSeq?: string;
}>()
);
export const forwardFailure = createAction(
'[Messenger::Event] Forward Failure',
props<{ error: any }>()
);
export const forwardAfterRoomOpen = createAction(
'[Messenger::Event] forwardAfterRoomOpen',
props<{
senderSeq: number;
req: SendRequest;
trgtUserSeqs?: number[];
trgtRoomSeq?: string;
}>()
);
export const read = createAction( export const read = createAction(
'[Messenger::Event] read', '[Messenger::Event] read',
props<ReadRequest>() props<ReadRequest>()

View File

@ -29,6 +29,7 @@ import {
} from '@ucap-webmessenger/protocol-event'; } from '@ucap-webmessenger/protocol-event';
import * as ChatStore from '@app/store/messenger/chat'; import * as ChatStore from '@app/store/messenger/chat';
import * as EventStore from '@app/store/messenger/event';
import * as SyncStore from '@app/store/messenger/sync'; import * as SyncStore from '@app/store/messenger/sync';
import { import {
@ -51,12 +52,20 @@ import {
delFailure, delFailure,
delInfoList, delInfoList,
cancel, cancel,
cancelFailure cancelFailure,
forward,
forwardFailure,
forwardAfterRoomOpen
} from './actions'; } from './actions';
import { SessionStorageService } from '@ucap-webmessenger/web-storage'; import { SessionStorageService } from '@ucap-webmessenger/web-storage';
import { RoomInfo } from '@ucap-webmessenger/protocol-room'; import {
RoomInfo,
RoomProtocolService,
OpenResponse
} from '@ucap-webmessenger/protocol-room';
import { LoginInfo, KEY_LOGIN_INFO } from '@app/types'; import { LoginInfo, KEY_LOGIN_INFO } from '@app/types';
import { Dictionary } from '@ngrx/entity'; import { Dictionary } from '@ngrx/entity';
import { openSuccess, openFailure } from '../room';
@Injectable() @Injectable()
export class Effects { export class Effects {
@ -220,6 +229,67 @@ export class Effects {
{ dispatch: false } { dispatch: false }
); );
forward$ = createEffect(
() => {
return this.actions$.pipe(
ofType(forward),
map(action => {
if (!!action.trgtRoomSeq) {
this.store.dispatch(
ChatStore.selectedRoom({ roomSeq: action.trgtRoomSeq })
);
this.store.dispatch(
EventStore.send({
senderSeq: action.senderSeq,
req: {
roomSeq: action.trgtRoomSeq,
eventType: action.req.eventType,
sentMessage: action.req.sentMessage
}
})
);
} else if (!!action.trgtUserSeqs && action.trgtUserSeqs.length > 0) {
// 방오픈 후 대화전달.
this.store.dispatch(forwardAfterRoomOpen(action));
}
})
);
},
{ dispatch: false }
);
forwardAfterRoomOpen$ = createEffect(() =>
this.actions$.pipe(
ofType(forwardAfterRoomOpen),
exhaustMap(action => {
return this.roomProtocolService
.open({
divCd: 'forwardOpen',
userSeqs: action.trgtUserSeqs
})
.pipe(
map((res: OpenResponse) => {
return openSuccess({ res });
}),
map(res => {
this.store.dispatch(
EventStore.send({
senderSeq: action.senderSeq,
req: {
roomSeq: res.res.roomSeq,
eventType: action.req.eventType,
sentMessage: action.req.sentMessage
}
})
);
return res;
}),
catchError(error => of(openFailure({ error })))
);
})
)
);
newInfo$ = createEffect( newInfo$ = createEffect(
() => { () => {
return this.actions$.pipe( return this.actions$.pipe(
@ -360,6 +430,7 @@ export class Effects {
private actions$: Actions, private actions$: Actions,
private store: Store<any>, private store: Store<any>,
private eventProtocolService: EventProtocolService, private eventProtocolService: EventProtocolService,
private roomProtocolService: RoomProtocolService,
private sessionStorageService: SessionStorageService, private sessionStorageService: SessionStorageService,
private logger: NGXLogger private logger: NGXLogger
) {} ) {}

View File

@ -16,7 +16,7 @@
<div class="num" *ngIf="roomInfo.roomType === RoomType.Multi"> <div class="num" *ngIf="roomInfo.roomType === RoomType.Multi">
{{ roomInfo.joinUserCount }}명 {{ roomInfo.joinUserCount }}명
</div> </div>
<div *ngIf="!roomInfo.receiveAlarm"> <div *ngIf="!checkable && !roomInfo.receiveAlarm">
<mat-icon>notifications_off</mat-icon> <mat-icon>notifications_off</mat-icon>
</div> </div>
</div> </div>
@ -25,6 +25,15 @@
<div class="date">{{ roomInfo.finalEventDate }}</div> <div class="date">{{ roomInfo.finalEventDate }}</div>
</dd> </dd>
<dd *ngIf="checkable">
<mat-checkbox
#checkbox
[checked]="isChecked"
(change)="onChangeCheck(checkbox.checked, roomInfo)"
(click)="$event.stopPropagation()"
>
</mat-checkbox>
</dd>
</dl> </dl>
<!-- <span class="noti">1</span> --> <!-- <span class="noti">1</span> -->
<span <span

View File

@ -1,4 +1,11 @@
import { Component, OnInit, Input } from '@angular/core'; import {
Component,
OnInit,
Input,
Output,
EventEmitter,
ViewChildren
} from '@angular/core';
import { import {
RoomInfo, RoomInfo,
UserInfoShort, UserInfoShort,
@ -7,13 +14,9 @@ import {
} from '@ucap-webmessenger/protocol-room'; } from '@ucap-webmessenger/protocol-room';
import { NGXLogger } from 'ngx-logger'; import { NGXLogger } from 'ngx-logger';
import { VersionInfo2Response } from '@ucap-webmessenger/api-public'; import { VersionInfo2Response } from '@ucap-webmessenger/api-public';
import { EventType } from '@ucap-webmessenger/protocol-event'; import { LoginResponse } from '@ucap-webmessenger/protocol-authentication';
import { FileInfo, StickerInfo } from '@ucap-webmessenger/ui-chat'; import { FormsModule } from '@angular/forms';
import { FileType } from '@ucap-webmessenger/protocol-file'; import { MatCheckbox } from '@angular/material';
import {
LoginResponse,
UserInfo
} from '@ucap-webmessenger/protocol-authentication';
@Component({ @Component({
selector: 'ucap-room-list-item', selector: 'ucap-room-list-item',
@ -29,6 +32,18 @@ export class ListItemComponent implements OnInit {
roomUserInfo: (RoomUserInfo | UserInfoShort)[]; roomUserInfo: (RoomUserInfo | UserInfoShort)[];
@Input() @Input()
sessionVerinfo: VersionInfo2Response; sessionVerinfo: VersionInfo2Response;
@Input()
checkable = false;
@Input()
isChecked = false;
@Input()
multiCheckable = true;
@Output()
checkRoom = new EventEmitter<{
isChecked: boolean;
roomInfo: RoomInfo;
}>();
imagePath: string; imagePath: string;
defaultPath = 'assets/images/img_nophoto_50.png'; defaultPath = 'assets/images/img_nophoto_50.png';
@ -95,4 +110,21 @@ export class ListItemComponent implements OnInit {
return roomName; return roomName;
} }
} }
// getChecked(value: boolean, roomInfo: RoomInfo) {
// if (value && !this.multiCheckable) {
// if (this.selected === roomInfo.roomSeq) {
// return true;
// } else {
// return false;
// }
// }
// }
onChangeCheck(value: boolean, roomInfo: RoomInfo) {
this.checkRoom.emit({
isChecked: value,
roomInfo
});
}
} }

View File

@ -8,7 +8,7 @@ import { MatFormFieldModule } from '@angular/material/form-field';
import { MatIconModule } from '@angular/material/icon'; import { MatIconModule } from '@angular/material/icon';
import { MatInputModule } from '@angular/material/input'; import { MatInputModule } from '@angular/material/input';
import { ListItemComponent } from './components/list-item.component'; import { ListItemComponent } from './components/list-item.component';
import { MatBadgeModule } from '@angular/material'; import { MatBadgeModule, MatCheckboxModule } from '@angular/material';
import { UCapUiModule } from '@ucap-webmessenger/ui'; import { UCapUiModule } from '@ucap-webmessenger/ui';
@ -26,6 +26,7 @@ const SERVICES = [];
MatIconModule, MatIconModule,
MatInputModule, MatInputModule,
MatBadgeModule, MatBadgeModule,
MatCheckboxModule,
UCapUiModule UCapUiModule
], ],