대화 내용 내보내기 구현. For CSV

This commit is contained in:
leejinho 2020-03-04 11:26:03 +09:00
parent 921af8f5bb
commit e41f44ca38
9 changed files with 209 additions and 16 deletions

View File

@ -0,0 +1,40 @@
import { DeviceType } from '@ucap-webmessenger/core';
import {
APIRequest,
APIEncoder,
ParameterUtil,
APIFormDataEncoder
} from '@ucap-webmessenger/api';
import { FileDownloadItem } from '../../../../ucap-webmessenger-api/src/lib/models/file-download-item';
export interface EventDownloadRequest extends APIRequest {
userSeq: number;
deviceType: DeviceType;
token: string;
roomSeq: string;
}
const eventDownloadEncodeMap = {
userSeq: 'userSeq',
deviceType: 'deviceType',
token: 'tokenKey',
roomSeq: 'roomSeq'
};
export const encodeEventDownload: APIEncoder<EventDownloadRequest> = (
req: EventDownloadRequest
) => {
const extraParams: any = {};
extraParams.roomSeq = Number(req.roomSeq);
return ParameterUtil.encode(eventDownloadEncodeMap, req, extraParams);
};
export const encodeFormDataEventDownload: APIFormDataEncoder<EventDownloadRequest> = (
req: EventDownloadRequest
) => {
const extraParams: any = {};
extraParams.roomSeq = Number(req.roomSeq);
return ParameterUtil.encodeFormData(eventDownloadEncodeMap, req, extraParams);
};

View File

@ -47,4 +47,7 @@ export interface Urls {
/** 공지 조회 */
retrieveNoticeList: string;
/** Event Download */
eventDownload: string;
}

View File

@ -7,7 +7,7 @@ import {
HttpEventType
} from '@angular/common/http';
import { Observable } from 'rxjs';
import { Observable, Subject } from 'rxjs';
import { map, filter } from 'rxjs/operators';
import { _MODULE_CONFIG } from '../config/token';
@ -97,6 +97,10 @@ import {
encodeRetrieveNotice,
decodeRetrieveNotice
} from '../apis/notice';
import {
EventDownloadRequest,
encodeFormDataEventDownload
} from '../apis/event-download';
@Injectable({
providedIn: 'root'
@ -357,4 +361,27 @@ export class MessageApiService {
})
.pipe(map(res => decodeRetrieveNotice(res)));
}
/** Event Download for Room */
public eventDownload(req: EventDownloadRequest): Observable<Blob> {
const httpReq = new HttpRequest(
'POST',
this.urls.eventDownload,
encodeFormDataEventDownload(req),
{ reportProgress: true, responseType: 'blob' }
);
return this.httpClient.request(httpReq).pipe(
filter(event => {
if (event instanceof HttpResponse) {
return true;
} else if (HttpEventType.DownloadProgress === event.type) {
}
return false;
}),
map((event: HttpResponse<any>) => {
return event.body;
})
);
}
}

View File

@ -4,6 +4,7 @@
export * from './lib/apis/del';
export * from './lib/apis/detail';
export * from './lib/apis/edit-reservation-ex';
export * from './lib/apis/event-download';
export * from './lib/apis/my-message';
export * from './lib/apis/notice';
export * from './lib/apis/retrieve';

View File

@ -310,6 +310,13 @@
>
{{ 'chat.searchEventByText' | translate }}
</button>
<button
mat-menu-item
*ngIf="getShowContextMenu('CHAT_EXPORT')"
(click)="onClickContextMenu('CHAT_EXPORT')"
>
{{ 'chat.eventDownload' | translate }}
</button>
<button
mat-menu-item
*ngIf="getShowContextMenu('OPEN_ROOM_USER')"

View File

@ -8,7 +8,8 @@ import {
EventEmitter,
Inject,
ChangeDetectorRef,
ChangeDetectionStrategy
ChangeDetectionStrategy,
NgZone
} from '@angular/core';
import {
ucapAnimations,
@ -73,7 +74,7 @@ import {
RoomType,
UserInfoShort
} from '@ucap-webmessenger/protocol-room';
import { take, map, catchError, tap } from 'rxjs/operators';
import { take, map, catchError, tap, finalize } from 'rxjs/operators';
import {
FormComponent as UCapUiChatFormComponent,
MessagesComponent as UCapUiChatMessagesComponent,
@ -101,7 +102,7 @@ import {
FileViewerDialogData,
FileViewerDialogResult
} from '@app/layouts/common/dialogs/file-viewer.dialog.component';
import { FileUtil, StickerFilesInfo } from '@ucap-webmessenger/core';
import { FileUtil, StickerFilesInfo, MimeUtil } from '@ucap-webmessenger/core';
import { StatusCode } from '@ucap-webmessenger/api';
import {
@ -137,6 +138,11 @@ import {
} from '../dialogs/conference/conference-detail.dialog.component';
import { ConferenceService } from '@ucap-webmessenger/api-prompt';
import { AuthResponse } from '@ucap-webmessenger/protocol-query';
import {
MessageApiService,
EventDownloadRequest
} from '@ucap-webmessenger/api-message';
import moment from 'moment';
@Component({
selector: 'app-layout-messenger-messages',
@ -256,7 +262,9 @@ export class MessagesComponent implements OnInit, OnDestroy, AfterViewInit {
private snackBarService: SnackBarService,
@Inject(UCAP_NATIVE_SERVICE) private nativeService: NativeService,
private appFileService: AppFileService,
private logger: NGXLogger
private messageApiService: MessageApiService,
private logger: NGXLogger,
private ngZone: NgZone
) {
this.sessionVerInfo = this.sessionStorageService.get<VersionInfo2Response>(
KEY_VER_INFO
@ -578,6 +586,20 @@ export class MessagesComponent implements OnInit, OnDestroy, AfterViewInit {
) {
return false;
}
} else if (['CHAT_EXPORT'].some(v => v === menuType)) {
if (
!this.roomInfoSubject.value ||
!this.roomInfoSubject.value.roomType ||
[
RoomType.Allim,
RoomType.Bot,
RoomType.Link,
RoomType.Allim_Elephant,
RoomType.Allim_TMS
].some(v => v === this.roomInfoSubject.value.roomType)
) {
return false;
}
}
return true;
@ -1549,6 +1571,11 @@ export class MessagesComponent implements OnInit, OnDestroy, AfterViewInit {
this.onShowToggleSearchArea();
}
break;
case 'CHAT_EXPORT':
{
this.onExportChatEvent();
}
break;
case 'OPEN_ROOM_USER':
{
this.store.dispatch(
@ -1938,6 +1965,90 @@ export class MessagesComponent implements OnInit, OnDestroy, AfterViewInit {
}
}
/** About Chat Export */
onExportChatEvent() {
let roomName = this.roomInfoSubject.value.roomName;
if (!roomName || roomName.trim().length === 0) {
roomName = this.getRoomNameByRoomUser(this._roomUserInfos);
}
const date = moment().format('YYYYMMDDHHmmss');
const fileName = `${roomName}_${date}${this.roomInfoSubject.value.roomSeq}.csv`;
const fileTalkDownloadError = (reason: any) => {
this.logger.warn(reason);
this.snackBarService.openFromComponent<
AlertSnackbarComponent,
AlertSnackbarData
>(AlertSnackbarComponent, {
data: {
html: this.translateService.instant('common.file.errors.failToSave'),
buttonText: this.translateService.instant('common.file.errors.label')
}
});
};
this.messageApiService
.eventDownload({
userSeq: this.loginResSubject.value.userSeq,
deviceType: this.environmentsInfo.deviceType,
token: this.loginResSubject.value.tokenString,
roomSeq: this.roomInfoSubject.value.roomSeq
})
.pipe(
take(1),
map(rawBlob => {
const mimeType = MimeUtil.getMimeFromExtension(
FileUtil.getExtension(fileName)
);
const blob = rawBlob.slice(0, rawBlob.size, mimeType);
FileUtil.fromBlobToBuffer(blob)
.then(buffer => {
this.nativeService
.saveFile(buffer, fileName, mimeType)
.then(filePath => {
if (!!filePath) {
const snackBarRef = this.snackBarService.open(
this.translateService.instant(
'common.file.results.savedToPath',
{
path: filePath
}
),
this.translateService.instant('common.file.open'),
{
duration: 3000,
verticalPosition: 'bottom',
horizontalPosition: 'center'
}
);
snackBarRef.onAction().subscribe(() => {
snackBarRef.dismiss();
this.ngZone.runOutsideAngular(() => {
this.nativeService
.openTargetItem(filePath)
.catch(reason => {
this.logger.warn(reason);
});
});
});
} else {
fileTalkDownloadError('fail');
}
})
.catch(reason => {
fileTalkDownloadError(reason);
});
})
.catch(reason => {
fileTalkDownloadError(reason);
});
}),
finalize(() => {}),
catchError(error => of(error))
)
.subscribe();
}
/** About Translation */
onShowToggleTranslation() {
this.isShowTranslation = !this.isShowTranslation;

View File

@ -197,6 +197,7 @@
"newChat": "New Chat",
"startChat": "Chat",
"openRoom": "Open room",
"eventDownload": "export chat",
"listOfRoomMember": "List of room member",
"settingsOfRoom": "Settings of room",
"turnOnRoomAlert": "Turn on room alert",

View File

@ -197,6 +197,7 @@
"newChat": "새로운 대화",
"startChat": "대화하기",
"openRoom": "대화방 열기",
"eventDownload": "대화 내용 내보내기",
"listOfRoomMember": "대화 참여자 목록",
"settingsOfRoom": "대화방 설정",
"turnOnRoomAlert": "대화방 알람 켜기",
@ -364,16 +365,16 @@
}
},
"conference": {
"detailView": "상세 보기",
"videoConferenceTypeNow": "[화상회의] 개설",
"videoConferenceTypeNew": "[화상회의] 예약",
"videoConferenceTypeUpdate": "[화상회의] 수정",
"videoConferenceTypeDelete": "[화상회의] 삭제",
"videoConferenceRegister": "개설자",
"videoConferenceAttendee": "참여자",
"videoConferenceDate": "날짜",
"videoConferenceRoom": "회의실",
"videoConferenceEnjoy": "참석하기"
"detailView": "상세 보기",
"videoConferenceTypeNow": "[화상회의] 개설",
"videoConferenceTypeNew": "[화상회의] 예약",
"videoConferenceTypeUpdate": "[화상회의] 수정",
"videoConferenceTypeDelete": "[화상회의] 삭제",
"videoConferenceRegister": "개설자",
"videoConferenceAttendee": "참여자",
"videoConferenceDate": "날짜",
"videoConferenceRoom": "회의실",
"videoConferenceEnjoy": "참석하기"
},
"update": {
"label": "업데이트"

View File

@ -167,7 +167,9 @@ export const messageApiUrls: MessageApiUrls = {
retrieveUnreadCount: '/uCapMsg/msg/retrieveUnreadCount.do',
retrieveNoticeList: '/uCapMsg/notice/retrieveNoticeList.do'
retrieveNoticeList: '/uCapMsg/notice/retrieveNoticeList.do',
eventDownload: '/uCapMsg/event/download'
};
export const promptUrls: PromptUrls = {
sendCall: '/uCapPrompt/api/call/clicktocall',