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

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 {
Component,
OnInit,
@ -32,7 +33,11 @@ import * as ChatStore from '@app/store/messenger/chat';
import * as RoomStore from '@app/store/messenger/room';
import { LoginResponse } from '@ucap-webmessenger/protocol-authentication';
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 { tap, take } from 'rxjs/operators';
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 { MatMenuTrigger } from '@angular/material';
import { CommonApiService } from '@ucap-webmessenger/api-common';
import {
DeleteMessageDialogComponent,
DeleteMessageDialogData,
DeleteMessageDialogResult
} from '@app/layouts/messenger/dialogs/message/delete-message.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';
CreateChatDialogComponent,
CreateChatDialogData,
CreateChatDialogResult
} from '../dialogs/chat/create-chat.dialog.component';
@Component({
selector: 'app-layout-messenger-messages',
@ -320,16 +314,48 @@ export class MessagesComponent implements OnInit, OnDestroy, AfterViewChecked {
case 'REPLAY':
{
const result = await this.dialogService.open<
RelayMessageDialogComponent,
RelayMessageDialogData,
RelayMessageDialogResult
>(RelayMessageDialogComponent, {
width: '220px',
CreateChatDialogComponent,
CreateChatDialogData,
CreateChatDialogResult
>(CreateChatDialogComponent, {
width: '600px',
height: '500px',
data: {
title: 'Logout',
message: 'Logout ?'
type: UserSelectDialogType.MessageForward,
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;
case 'REPLAY_TO_ME':

View File

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

View File

@ -1,7 +1,17 @@
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 { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material';
import {
MatDialogRef,
MAT_DIALOG_DATA,
MatTabChangeEvent
} from '@angular/material';
import { NGXLogger } from 'ngx-logger';
import { Observable, combineLatest, Subscription, of } from 'rxjs';
import { map, tap, catchError } from 'rxjs/operators';
@ -44,11 +54,14 @@ export interface CreateChatDialogData {
title: string;
/** CASE :: EditMember */
group?: GroupDetailData;
/** CASE :: EventForward */
ignoreRoom?: RoomInfo[];
}
export interface CreateChatDialogResult {
choice: boolean;
selectedUserList?: (UserInfo | UserInfoSS | UserInfoF | UserInfoDN)[];
selectedRoom?: RoomInfo;
groupName?: string;
oldGroup?: GroupDetailData;
}
@ -101,6 +114,8 @@ export class CreateChatDialogComponent implements OnInit, OnDestroy {
// 수집 데이터
selectedUserList: (UserInfo | UserInfoSS | UserInfoF | UserInfoDN)[] = [];
isShowSelectedUserList = true;
selectedRoom: RoomInfo;
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: {
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 를 판단. */
getCheckedUser(userInfo: UserInfo | UserInfoSS | UserInfoF | UserInfoDN) {
if (!!this.selectedUserList && this.selectedUserList.length > 0) {
@ -334,6 +368,22 @@ export class CreateChatDialogComponent implements OnInit, OnDestroy {
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) {
this.selectedUserList = this.selectedUserList.filter(
@ -346,6 +396,7 @@ export class CreateChatDialogComponent implements OnInit, OnDestroy {
this.dialogRef.close({
choice,
selectedUserList: this.selectedUserList,
selectedRoom: this.selectedRoom,
groupName:
this.data.type === UserSelectDialogType.NewGroup
? this.inputForm.get('groupName').value

View File

@ -72,6 +72,29 @@ export const sendNotification = createAction(
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(
'[Messenger::Event] read',
props<ReadRequest>()

View File

@ -29,6 +29,7 @@ import {
} from '@ucap-webmessenger/protocol-event';
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 {
@ -51,12 +52,20 @@ import {
delFailure,
delInfoList,
cancel,
cancelFailure
cancelFailure,
forward,
forwardFailure,
forwardAfterRoomOpen
} from './actions';
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 { Dictionary } from '@ngrx/entity';
import { openSuccess, openFailure } from '../room';
@Injectable()
export class Effects {
@ -220,6 +229,67 @@ export class Effects {
{ 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(
() => {
return this.actions$.pipe(
@ -360,6 +430,7 @@ export class Effects {
private actions$: Actions,
private store: Store<any>,
private eventProtocolService: EventProtocolService,
private roomProtocolService: RoomProtocolService,
private sessionStorageService: SessionStorageService,
private logger: NGXLogger
) {}

View File

@ -16,7 +16,7 @@
<div class="num" *ngIf="roomInfo.roomType === RoomType.Multi">
{{ roomInfo.joinUserCount }}명
</div>
<div *ngIf="!roomInfo.receiveAlarm">
<div *ngIf="!checkable && !roomInfo.receiveAlarm">
<mat-icon>notifications_off</mat-icon>
</div>
</div>
@ -25,6 +25,15 @@
<div class="date">{{ roomInfo.finalEventDate }}</div>
</dd>
<dd *ngIf="checkable">
<mat-checkbox
#checkbox
[checked]="isChecked"
(change)="onChangeCheck(checkbox.checked, roomInfo)"
(click)="$event.stopPropagation()"
>
</mat-checkbox>
</dd>
</dl>
<!-- <span class="noti">1</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 {
RoomInfo,
UserInfoShort,
@ -7,13 +14,9 @@ import {
} from '@ucap-webmessenger/protocol-room';
import { NGXLogger } from 'ngx-logger';
import { VersionInfo2Response } from '@ucap-webmessenger/api-public';
import { EventType } from '@ucap-webmessenger/protocol-event';
import { FileInfo, StickerInfo } from '@ucap-webmessenger/ui-chat';
import { FileType } from '@ucap-webmessenger/protocol-file';
import {
LoginResponse,
UserInfo
} from '@ucap-webmessenger/protocol-authentication';
import { LoginResponse } from '@ucap-webmessenger/protocol-authentication';
import { FormsModule } from '@angular/forms';
import { MatCheckbox } from '@angular/material';
@Component({
selector: 'ucap-room-list-item',
@ -29,6 +32,18 @@ export class ListItemComponent implements OnInit {
roomUserInfo: (RoomUserInfo | UserInfoShort)[];
@Input()
sessionVerinfo: VersionInfo2Response;
@Input()
checkable = false;
@Input()
isChecked = false;
@Input()
multiCheckable = true;
@Output()
checkRoom = new EventEmitter<{
isChecked: boolean;
roomInfo: RoomInfo;
}>();
imagePath: string;
defaultPath = 'assets/images/img_nophoto_50.png';
@ -95,4 +110,21 @@ export class ListItemComponent implements OnInit {
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 { MatInputModule } from '@angular/material/input';
import { ListItemComponent } from './components/list-item.component';
import { MatBadgeModule } from '@angular/material';
import { MatBadgeModule, MatCheckboxModule } from '@angular/material';
import { UCapUiModule } from '@ucap-webmessenger/ui';
@ -26,6 +26,7 @@ const SERVICES = [];
MatIconModule,
MatInputModule,
MatBadgeModule,
MatCheckboxModule,
UCapUiModule
],