492 lines
15 KiB
TypeScript
492 lines
15 KiB
TypeScript
import { Component, OnInit, Inject, ViewChild } from '@angular/core';
|
|
import {
|
|
MatDialogRef,
|
|
MAT_DIALOG_DATA,
|
|
MatSelectionList,
|
|
MatDrawer
|
|
} from '@angular/material';
|
|
import { map, catchError, take } from 'rxjs/operators';
|
|
|
|
import {
|
|
DialogService,
|
|
ConfirmDialogComponent,
|
|
ConfirmDialogData,
|
|
ConfirmDialogResult,
|
|
SnackBarService,
|
|
AlertDialogComponent,
|
|
AlertDialogResult,
|
|
AlertDialogData
|
|
} from '@ucap-webmessenger/ui';
|
|
import {
|
|
DetailResponse,
|
|
MessageType,
|
|
DetailContent,
|
|
DetailReceiver,
|
|
ContentType,
|
|
MessageDetailInfo,
|
|
MessageApiService,
|
|
RetrieveResourceFileRequest,
|
|
CancelRequest
|
|
} from '@ucap-webmessenger/api-message';
|
|
import { DeviceType, MimeUtil, FileUtil } from '@ucap-webmessenger/core';
|
|
import { LoginResponse } from '@ucap-webmessenger/protocol-authentication';
|
|
import { NGXLogger } from 'ngx-logger';
|
|
import { NativeService, UCAP_NATIVE_SERVICE } from '@ucap-webmessenger/native';
|
|
import { MessageStatusCode } from '@ucap-webmessenger/api';
|
|
import { of } from 'rxjs';
|
|
|
|
export interface MessageDetailDialogData {
|
|
detail: DetailResponse;
|
|
loginRes: LoginResponse;
|
|
}
|
|
|
|
export interface MessageDetailDialogResult {
|
|
returnType: string;
|
|
messageInfo?: MessageDetailInfo;
|
|
cancelUserSeqs?: number[];
|
|
}
|
|
|
|
export interface DownloadQueueForMessage extends DetailContent {
|
|
downloadType: string;
|
|
}
|
|
|
|
@Component({
|
|
selector: 'app-layout-messenger-message-detail',
|
|
templateUrl: './message-detail.dialog.component.html',
|
|
styleUrls: ['./message-detail.dialog.component.scss']
|
|
})
|
|
export class MessageDetailDialogComponent implements OnInit {
|
|
messageDetail: DetailResponse;
|
|
messageInfo: MessageDetailInfo;
|
|
contents: DetailContent[] = [];
|
|
attachFile: DetailContent[] = [];
|
|
receivers: DetailReceiver[] = [];
|
|
|
|
isExpiredAttachFile = true;
|
|
|
|
MessageType = MessageType;
|
|
ContentType = ContentType;
|
|
|
|
downloadProgress = false;
|
|
downloadQueue: DownloadQueueForMessage[] = [];
|
|
downloadFail: DownloadQueueForMessage[] = [];
|
|
|
|
@ViewChild('rightDrawer', { static: true }) rightDrawer: MatDrawer;
|
|
@ViewChild('unReadUsers', { static: false }) unReadUsers: MatSelectionList;
|
|
|
|
constructor(
|
|
public dialogRef: MatDialogRef<
|
|
MessageDetailDialogData,
|
|
MessageDetailDialogResult
|
|
>,
|
|
@Inject(MAT_DIALOG_DATA) public data: MessageDetailDialogData,
|
|
@Inject(UCAP_NATIVE_SERVICE) private nativeService: NativeService,
|
|
private messageApiService: MessageApiService,
|
|
private snackBarService: SnackBarService,
|
|
private logger: NGXLogger,
|
|
private dialogService: DialogService
|
|
) {}
|
|
|
|
ngOnInit(): void {
|
|
this.messageDetail = this.data.detail;
|
|
this.messageInfo = this.messageDetail.msgInfo;
|
|
|
|
if (
|
|
!!this.messageDetail.contents &&
|
|
this.messageDetail.contents.length > 0
|
|
) {
|
|
this.messageDetail.contents.forEach(cont => {
|
|
if (cont.resType !== ContentType.AttachFile) {
|
|
this.contents.push(cont);
|
|
} else if (cont.resType === ContentType.AttachFile) {
|
|
if (cont.activeYn) {
|
|
this.isExpiredAttachFile = false;
|
|
}
|
|
this.attachFile.push(cont);
|
|
}
|
|
});
|
|
}
|
|
|
|
// contents 내 이미지 Thumnail 파일 정보 수집.
|
|
this.getThumbImage();
|
|
|
|
this.receivers = this.messageDetail.recvList.sort((a, b) =>
|
|
a.userName < b.userName ? -1 : a.userName > b.userName ? 1 : 0
|
|
);
|
|
}
|
|
|
|
getSendReceiverNames(): string {
|
|
if (this.messageInfo.type === MessageType.Receive) {
|
|
return this.messageInfo.sendUserName;
|
|
} else {
|
|
return this.receivers.map(user => user.userName).join(',');
|
|
}
|
|
}
|
|
|
|
getReadUserCount(readYn: boolean): number {
|
|
return this.receivers.filter(user => user.readYn === readYn).length;
|
|
}
|
|
|
|
getFileStatusIcon(file: DetailContent) {
|
|
const downloading =
|
|
this.downloadQueue.filter(dq => dq.resSeq === file.resSeq).length > 0;
|
|
const error =
|
|
this.downloadFail.filter(df => df.resSeq === file.resSeq).length > 0;
|
|
|
|
if (error) {
|
|
return 'mdi-window-close';
|
|
} else if (downloading) {
|
|
return ['mdi-spin', 'mdi-loading'];
|
|
} else {
|
|
return 'mdi-attachment';
|
|
}
|
|
}
|
|
|
|
getThumbImage(): void {
|
|
this.contents.forEach(content => {
|
|
if (content.resType === ContentType.Image) {
|
|
this.messageApiService
|
|
.retrieveResourceFile({
|
|
userSeq: this.data.loginRes.userSeq,
|
|
deviceType: DeviceType.PC,
|
|
tokenKey: this.data.loginRes.tokenString,
|
|
type: this.messageInfo.type,
|
|
msgId: this.messageInfo.msgId,
|
|
resUrl: content.thumbnailUrl
|
|
} as RetrieveResourceFileRequest)
|
|
.pipe(
|
|
take(1),
|
|
map(async rawBlob => {
|
|
const reader = new FileReader();
|
|
reader.readAsDataURL(rawBlob);
|
|
reader.onloadend = () => {
|
|
content.imageSrc = reader.result;
|
|
};
|
|
})
|
|
)
|
|
.subscribe();
|
|
}
|
|
});
|
|
}
|
|
|
|
// /**
|
|
// * @deprecated
|
|
// */
|
|
// downloadAttachFile(attachFile: DetailContent): void {
|
|
// this.messageApiService
|
|
// .retrieveResourceFile({
|
|
// userSeq: this.data.loginRes.userSeq,
|
|
// deviceType: DeviceType.PC,
|
|
// tokenKey: this.data.loginRes.tokenString,
|
|
// type: this.messageInfo.type,
|
|
// msgId: this.messageInfo.msgId,
|
|
// resUrl: attachFile.resUrl
|
|
// } as RetrieveResourceFileRequest)
|
|
// .pipe(
|
|
// take(1),
|
|
// map(async rawBlob => {
|
|
// const mimeType = MimeUtil.getMimeFromExtension(
|
|
// FileUtil.getExtension(attachFile.resContent)
|
|
// );
|
|
// const blob = rawBlob.slice(0, rawBlob.size, mimeType);
|
|
|
|
// FileUtil.fromBlobToBuffer(blob)
|
|
// .then(buffer => {
|
|
// this.nativeService
|
|
// .saveFile(buffer, attachFile.resContent, mimeType)
|
|
// .then(result => {
|
|
// if (!!result) {
|
|
// if (this.downloadFail.length > 0) {
|
|
// this.downloadFail = this.downloadFail.filter(
|
|
// df => df.resSeq !== attachFile.resSeq
|
|
// );
|
|
// }
|
|
|
|
// this.snackBarService.open(
|
|
// `파일이 경로[${result}]에 저장되었습니다.`,
|
|
// '',
|
|
// {
|
|
// duration: 3000,
|
|
// verticalPosition: 'bottom'
|
|
// }
|
|
// );
|
|
// } else {
|
|
// this.snackBarService.open('파일 저장에 실패하였습니다.');
|
|
// }
|
|
// })
|
|
// .catch(reason => {
|
|
// this.snackBarService.open('파일 저장에 실패하였습니다.');
|
|
// });
|
|
// })
|
|
// .catch(reason => {
|
|
// this.logger.error('download', reason);
|
|
// });
|
|
// })
|
|
// )
|
|
// .subscribe();
|
|
// }
|
|
downloadAttachFileSingle(attachFile: DetailContent): void {
|
|
if (!this.downloadProgress) {
|
|
this.downloadProgress = true;
|
|
this.downloadQueue = [{ ...attachFile, downloadType: 'SINGLE' }];
|
|
this.downloadFail = [];
|
|
if (!!this.downloadQueue && this.downloadQueue.length > 0) {
|
|
this.downloadAttachFileByQueue();
|
|
}
|
|
} else {
|
|
if (
|
|
this.downloadQueue.filter(dq => dq.resSeq === attachFile.resSeq)
|
|
.length === 0
|
|
) {
|
|
this.downloadQueue.push({ ...attachFile, downloadType: 'SINGLE' });
|
|
}
|
|
}
|
|
}
|
|
downloadAttachFileAll(): void {
|
|
if (!this.downloadProgress) {
|
|
this.downloadProgress = true;
|
|
this.downloadQueue = [];
|
|
this.downloadFail = [];
|
|
this.attachFile.forEach(file =>
|
|
this.downloadQueue.push({ ...file, downloadType: '' })
|
|
);
|
|
if (!!this.downloadQueue && this.downloadQueue.length > 0) {
|
|
this.downloadAttachFileByQueue();
|
|
}
|
|
} else {
|
|
this.dialogService.open<
|
|
AlertDialogComponent,
|
|
AlertDialogData,
|
|
AlertDialogResult
|
|
>(AlertDialogComponent, {
|
|
data: {
|
|
title: '',
|
|
html: `다운로드가 진행중입니다.`
|
|
}
|
|
});
|
|
}
|
|
}
|
|
downloadAttachFileByQueue(): void {
|
|
const attachFile = this.downloadQueue[0];
|
|
this.messageApiService
|
|
.retrieveResourceFile({
|
|
userSeq: this.data.loginRes.userSeq,
|
|
deviceType: DeviceType.PC,
|
|
tokenKey: this.data.loginRes.tokenString,
|
|
type: this.messageInfo.type,
|
|
msgId: this.messageInfo.msgId,
|
|
resUrl: attachFile.resUrl
|
|
} as RetrieveResourceFileRequest)
|
|
.pipe(
|
|
take(1),
|
|
map(async rawBlob => {
|
|
const mimeType = MimeUtil.getMimeFromExtension(
|
|
FileUtil.getExtension(attachFile.resContent)
|
|
);
|
|
const blob = rawBlob.slice(0, rawBlob.size, mimeType);
|
|
|
|
FileUtil.fromBlobToBuffer(blob)
|
|
.then(buffer => {
|
|
this.nativeService
|
|
.saveFile(buffer, attachFile.resContent, mimeType)
|
|
.then(result => {
|
|
if (!!result) {
|
|
if (
|
|
!!attachFile.downloadType &&
|
|
attachFile.downloadType === 'SINGLE'
|
|
) {
|
|
attachFile.downloadType = result;
|
|
}
|
|
|
|
if (this.downloadQueue.length > 1) {
|
|
this.downloadQueue = this.downloadQueue.slice(1);
|
|
} else {
|
|
this.downloadQueue = [];
|
|
}
|
|
} else {
|
|
throw new Error('response Error');
|
|
}
|
|
})
|
|
.catch(reason => {
|
|
this.downloadFail.push(this.downloadQueue[0]);
|
|
|
|
if (this.downloadQueue.length > 1) {
|
|
this.downloadQueue = this.downloadQueue.slice(1);
|
|
} else {
|
|
this.downloadQueue = [];
|
|
}
|
|
});
|
|
})
|
|
.catch(reason => {
|
|
this.downloadFail.push(this.downloadQueue[0]);
|
|
|
|
if (this.downloadQueue.length > 1) {
|
|
this.downloadQueue = this.downloadQueue.slice(1);
|
|
} else {
|
|
this.downloadQueue = [];
|
|
}
|
|
})
|
|
.finally(() => {
|
|
if (this.downloadQueue.length > 0) {
|
|
// 재귀
|
|
this.downloadAttachFileByQueue();
|
|
} else {
|
|
if (this.downloadFail.length > 0) {
|
|
// 일부 혹은 전부 실패.
|
|
let errMsg = '';
|
|
if (
|
|
!!attachFile.downloadType &&
|
|
attachFile.downloadType === 'SINGLE'
|
|
) {
|
|
// single :: fail
|
|
errMsg = '파일 저장에 실패하였습니다.';
|
|
} else {
|
|
// all
|
|
errMsg = '일부 저장중 오류가 발생하였습니다.';
|
|
}
|
|
this.snackBarService.open(errMsg, '확인', {
|
|
duration: 8000,
|
|
verticalPosition: 'bottom'
|
|
});
|
|
} else {
|
|
// 성공종료.
|
|
if (
|
|
!!attachFile.downloadType &&
|
|
attachFile.downloadType.length > 0
|
|
) {
|
|
// single :: success
|
|
this.snackBarService.open(
|
|
`파일이 경로[${attachFile.downloadType}]에 저장되었습니다.`,
|
|
'',
|
|
{
|
|
duration: 3000,
|
|
verticalPosition: 'bottom'
|
|
}
|
|
);
|
|
} else {
|
|
// all
|
|
this.snackBarService.open('모두 저장하였습니다.', '', {
|
|
duration: 3000,
|
|
verticalPosition: 'bottom'
|
|
});
|
|
}
|
|
}
|
|
this.downloadProgress = false;
|
|
}
|
|
});
|
|
})
|
|
)
|
|
.subscribe();
|
|
}
|
|
|
|
async onClickMessageMenu(menuType: string) {
|
|
switch (menuType) {
|
|
case 'MESSAGE_READ':
|
|
{
|
|
this.rightDrawer.open();
|
|
}
|
|
break;
|
|
case 'MESSAGE_CANCEL':
|
|
{
|
|
const result = await this.dialogService.open<
|
|
ConfirmDialogComponent,
|
|
ConfirmDialogData,
|
|
ConfirmDialogResult
|
|
>(ConfirmDialogComponent, {
|
|
data: {
|
|
title: '발송취소',
|
|
html: `예약발송을 취소 하시겠습니까?<br/>취소하면 목록에서도 영구 삭제됩니다.`
|
|
}
|
|
});
|
|
|
|
if (!!result && !!result.choice && result.choice) {
|
|
this.dialogRef.close({
|
|
returnType: 'CANCEL_RESERVATION',
|
|
messageInfo: this.messageInfo
|
|
});
|
|
}
|
|
}
|
|
break;
|
|
case 'MESSAGE_DEL':
|
|
{
|
|
const result = await this.dialogService.open<
|
|
ConfirmDialogComponent,
|
|
ConfirmDialogData,
|
|
ConfirmDialogResult
|
|
>(ConfirmDialogComponent, {
|
|
data: {
|
|
title: '삭제',
|
|
message: '선택한 쪽지를 삭제하시겠습니까?'
|
|
}
|
|
});
|
|
|
|
if (!!result && !!result.choice && result.choice) {
|
|
this.dialogRef.close({
|
|
returnType: 'DEL',
|
|
messageInfo: this.messageInfo
|
|
});
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
async cancelSendMessageForUsers() {
|
|
if (
|
|
!!this.unReadUsers &&
|
|
this.unReadUsers.selectedOptions.selected.length > 0
|
|
) {
|
|
const result = await this.dialogService.open<
|
|
ConfirmDialogComponent,
|
|
ConfirmDialogData,
|
|
ConfirmDialogResult
|
|
>(ConfirmDialogComponent, {
|
|
data: {
|
|
title: '발송 취소',
|
|
message:
|
|
'발송 취소를 하시면 받는 사람의 쪽지함에서 쪽지가 삭제됩니다.'
|
|
}
|
|
});
|
|
|
|
if (!!result && !!result.choice && result.choice) {
|
|
const cancelUserSeqs: number[] = [];
|
|
const recvUserList: { userSeq: number }[] = [];
|
|
this.unReadUsers.selectedOptions.selected.forEach(selected => {
|
|
cancelUserSeqs.push(selected.value);
|
|
recvUserList.push({ userSeq: selected.value });
|
|
});
|
|
|
|
this.messageApiService
|
|
.cancelMessage({
|
|
userSeq: this.data.loginRes.userSeq,
|
|
deviceType: DeviceType.PC,
|
|
tokenKey: this.data.loginRes.tokenString,
|
|
type: this.messageInfo.type,
|
|
msgId: this.messageInfo.msgId,
|
|
recvUserList
|
|
} as CancelRequest)
|
|
.pipe(
|
|
map(async res => {
|
|
if (res.responseCode === MessageStatusCode.Success) {
|
|
this.receivers = this.receivers.filter(
|
|
user => cancelUserSeqs.indexOf(user.userSeq) < 0
|
|
);
|
|
this.rightDrawer.close();
|
|
} else {
|
|
this.logger.error('message cancel user Error!');
|
|
}
|
|
}),
|
|
catchError(error => of(this.logger.error(error)))
|
|
)
|
|
.subscribe();
|
|
}
|
|
}
|
|
}
|
|
|
|
onClickConfirm(): void {
|
|
this.dialogRef.close({
|
|
returnType: 'CLOSE'
|
|
});
|
|
}
|
|
}
|