file upload is implemented
This commit is contained in:
parent
5b9fa9f55c
commit
086a4556f8
3
package-lock.json
generated
3
package-lock.json
generated
|
@ -14104,7 +14104,8 @@
|
|||
"tslib": {
|
||||
"version": "1.10.0",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz",
|
||||
"integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ=="
|
||||
"integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==",
|
||||
"dev": true
|
||||
},
|
||||
"tslint": {
|
||||
"version": "5.15.0",
|
||||
|
|
|
@ -6,25 +6,28 @@ import {
|
|||
APIDecoder,
|
||||
ParameterUtil,
|
||||
StatusCode,
|
||||
JsonAnalization
|
||||
JsonAnalization,
|
||||
APIFormDataEncoder
|
||||
} from '@ucap-webmessenger/api';
|
||||
import { JsonObject } from 'type-fest';
|
||||
import { FileUploadItem } from '../models/file-upload-item';
|
||||
|
||||
export interface FileTalkSaveRequest extends APIRequest {
|
||||
userSeq: string;
|
||||
userSeq: number;
|
||||
deviceType: DeviceType;
|
||||
token: string;
|
||||
file?: File;
|
||||
file: File;
|
||||
fileName?: string;
|
||||
fileUploadItem: FileUploadItem;
|
||||
thumb?: File;
|
||||
voice?: boolean;
|
||||
voiceTime?: string;
|
||||
roomId?: string;
|
||||
roomSeq?: string;
|
||||
type?: string;
|
||||
}
|
||||
|
||||
export interface FileTalkSaveResponse extends APIResponse {
|
||||
roomID?: string;
|
||||
roomSeq?: string;
|
||||
fileName?: string;
|
||||
fileExt?: string;
|
||||
fileType?: string;
|
||||
|
@ -49,19 +52,21 @@ const fileTalkSaveEncodeMap = {
|
|||
thumb: 'thumb',
|
||||
voice: 'p_voice',
|
||||
voiceTime: 'p_voice_time',
|
||||
roomId: 'p_room_id',
|
||||
roomSeq: 'p_room_id',
|
||||
type: 'p_type'
|
||||
};
|
||||
|
||||
export const encodeFileTalkSave: APIEncoder<FileTalkSaveRequest> = (
|
||||
export const encodeFileTalkSave: APIFormDataEncoder<FileTalkSaveRequest> = (
|
||||
req: FileTalkSaveRequest
|
||||
) => {
|
||||
const extraParams: any = {};
|
||||
|
||||
extraParams.userSeq = String(req.userSeq);
|
||||
if (!!req.voice) {
|
||||
extraParams.voice = req.voice ? 'Y' : 'N';
|
||||
}
|
||||
|
||||
return ParameterUtil.encode(fileTalkSaveEncodeMap, req, extraParams);
|
||||
return ParameterUtil.encodeFormData(fileTalkSaveEncodeMap, req, extraParams);
|
||||
};
|
||||
|
||||
export const decodeFileTalkSave: APIDecoder<FileTalkSaveResponse> = (
|
||||
|
@ -71,7 +76,7 @@ export const decodeFileTalkSave: APIDecoder<FileTalkSaveResponse> = (
|
|||
const json: JsonObject | Error = JsonAnalization.receiveAnalization(res);
|
||||
return {
|
||||
statusCode: json.StatusCode,
|
||||
roomID: json.RoomID,
|
||||
roomSeq: json.RoomID,
|
||||
fileName: json.FileName,
|
||||
fileExt: json.FileExt,
|
||||
fileType: json.FileType,
|
||||
|
|
|
@ -4,32 +4,43 @@ import {
|
|||
APIResponse,
|
||||
APIEncoder,
|
||||
APIDecoder,
|
||||
ParameterUtil
|
||||
ParameterUtil,
|
||||
JsonAnalization,
|
||||
StatusCode
|
||||
} from '@ucap-webmessenger/api';
|
||||
import { JsonObject } from 'type-fest';
|
||||
|
||||
export interface FileTalkShareRequest extends APIRequest {
|
||||
userSeq: string;
|
||||
deviceType: DeviceType;
|
||||
token: string;
|
||||
attachmentsSeq?: string;
|
||||
roomId?: string;
|
||||
roomSeq?: string;
|
||||
synapKey?: string;
|
||||
}
|
||||
|
||||
export interface FileTalkShareResponse extends APIResponse {
|
||||
RoomID?: string;
|
||||
FileName?: string;
|
||||
FileExt?: string;
|
||||
FileType?: string;
|
||||
ThumbURL?: string;
|
||||
AttSEQ?: string;
|
||||
AttSize?: string;
|
||||
AttRegDate?: string;
|
||||
CompanyCode?: string;
|
||||
SynapKey?: string;
|
||||
roomSeq?: string;
|
||||
fileName?: string;
|
||||
fileExt?: string;
|
||||
fileType?: string;
|
||||
thumbnailUrl?: string;
|
||||
attachmentSeq?: string;
|
||||
attachmentSize?: string;
|
||||
attachmentRegDate?: string;
|
||||
companyCode?: string;
|
||||
synapKey?: string;
|
||||
returnJson?: any;
|
||||
}
|
||||
|
||||
const fileTalkShareEncodeMap = {};
|
||||
const fileTalkShareEncodeMap = {
|
||||
userSeq: 'p_user_seq',
|
||||
deviceType: 'p_device_type',
|
||||
token: 'p_token',
|
||||
attachmentsSeq: 'p_att_seq',
|
||||
roomSeq: 'p_room_id',
|
||||
synapKey: 'p_synap_key'
|
||||
};
|
||||
|
||||
export const encodeFileTalkShare: APIEncoder<FileTalkShareRequest> = (
|
||||
req: FileTalkShareRequest
|
||||
|
@ -40,5 +51,26 @@ export const encodeFileTalkShare: APIEncoder<FileTalkShareRequest> = (
|
|||
export const decodeFileTalkShare: APIDecoder<FileTalkShareResponse> = (
|
||||
res: any
|
||||
) => {
|
||||
return {} as FileTalkShareResponse;
|
||||
try {
|
||||
const json: JsonObject | Error = JsonAnalization.receiveAnalization(res);
|
||||
return {
|
||||
statusCode: json.StatusCode,
|
||||
roomSeq: json.RoomID,
|
||||
fileName: json.FileName,
|
||||
fileExt: json.FileExt,
|
||||
fileType: json.FileType,
|
||||
thumbnailUrl: json.ThumbURL,
|
||||
attachmentSeq: json.AttSEQ,
|
||||
attachmentSize: json.AttSize,
|
||||
attachmentRegDate: json.AttRegDate,
|
||||
companyCode: json.CompanyCode,
|
||||
synapKey: json.SynapKey,
|
||||
returnJson: res
|
||||
} as FileTalkShareResponse;
|
||||
} catch (e) {
|
||||
return {
|
||||
statusCode: StatusCode.Fail,
|
||||
errorMessage: e
|
||||
} as FileTalkShareResponse;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -20,7 +20,7 @@ export interface MassTalkSaveRequest extends APIRequest {
|
|||
|
||||
export interface MassTalkSaveResponse extends APIResponse {
|
||||
eventMassSeq?: string;
|
||||
roomID?: string;
|
||||
roomSeq?: string;
|
||||
regDate?: string;
|
||||
content?: string;
|
||||
returnJson?: any;
|
||||
|
@ -51,7 +51,7 @@ export const decodeMassTalkSave: APIDecoder<MassTalkSaveResponse> = (
|
|||
content: json.Content,
|
||||
eventMassSeq: json.EventMassSeq,
|
||||
regDate: json.RegDate,
|
||||
roomID: json.RoomID,
|
||||
roomSeq: json.RoomID,
|
||||
returnJson: res
|
||||
} as MassTalkSaveResponse;
|
||||
} catch (e) {
|
||||
|
|
|
@ -4,8 +4,11 @@ import {
|
|||
APIResponse,
|
||||
APIEncoder,
|
||||
APIDecoder,
|
||||
ParameterUtil
|
||||
ParameterUtil,
|
||||
JsonAnalization,
|
||||
StatusCode
|
||||
} from '@ucap-webmessenger/api';
|
||||
import { JsonObject } from 'type-fest';
|
||||
|
||||
export interface TransMassTalkSaveRequest extends APIRequest {
|
||||
userSeq: string;
|
||||
|
@ -13,20 +16,29 @@ export interface TransMassTalkSaveRequest extends APIRequest {
|
|||
token: string;
|
||||
original?: string;
|
||||
translation?: string;
|
||||
roomId?: string;
|
||||
roomSeq?: string;
|
||||
locale: string;
|
||||
}
|
||||
|
||||
export interface TransMassTalkSaveResponse extends APIResponse {
|
||||
EventTransSEQ?: string;
|
||||
RoomID?: string;
|
||||
RegDate?: string;
|
||||
Locale?: string;
|
||||
Original?: string;
|
||||
Translation?: string;
|
||||
roomSeq?: string;
|
||||
registrationDate?: string;
|
||||
translationSeq?: string;
|
||||
locale?: string;
|
||||
original?: string;
|
||||
translation?: string;
|
||||
returnJson?: any;
|
||||
}
|
||||
|
||||
const transMassTalkSaveEncodeMap = {};
|
||||
const transMassTalkSaveEncodeMap = {
|
||||
userSeq: 'p_user_seq',
|
||||
deviceType: 'p_device_type',
|
||||
token: 'p_token',
|
||||
original: 'p_original',
|
||||
translation: 'p_translation',
|
||||
roomSeq: 'p_room_id',
|
||||
locale: 'p_locale'
|
||||
};
|
||||
|
||||
export const encodeTransMassTalkSave: APIEncoder<TransMassTalkSaveRequest> = (
|
||||
req: TransMassTalkSaveRequest
|
||||
|
@ -37,5 +49,22 @@ export const encodeTransMassTalkSave: APIEncoder<TransMassTalkSaveRequest> = (
|
|||
export const decodeTransMassTalkSave: APIDecoder<TransMassTalkSaveResponse> = (
|
||||
res: any
|
||||
) => {
|
||||
return {} as TransMassTalkSaveResponse;
|
||||
try {
|
||||
const json: JsonObject | Error = JsonAnalization.receiveAnalization(res);
|
||||
return {
|
||||
statusCode: json.StatusCode,
|
||||
translationSeq: json.EventTransSEQ,
|
||||
roomSeq: json.RoomID,
|
||||
registrationDate: json.RegDate,
|
||||
locale: json.Locale,
|
||||
original: json.Original,
|
||||
translation: json.Translation,
|
||||
returnJson: res
|
||||
} as TransMassTalkSaveResponse;
|
||||
} catch (e) {
|
||||
return {
|
||||
statusCode: StatusCode.Fail,
|
||||
errorMessage: e
|
||||
} as TransMassTalkSaveResponse;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -4,30 +4,42 @@ import {
|
|||
APIResponse,
|
||||
APIEncoder,
|
||||
APIDecoder,
|
||||
ParameterUtil
|
||||
ParameterUtil,
|
||||
JsonAnalization,
|
||||
StatusCode
|
||||
} from '@ucap-webmessenger/api';
|
||||
import { JsonObject } from 'type-fest';
|
||||
|
||||
export interface TranslationSaveRequest extends APIRequest {
|
||||
userSeq: string;
|
||||
deviceType: DeviceType;
|
||||
token: string;
|
||||
roomId?: string;
|
||||
roomSeq?: string;
|
||||
original?: string;
|
||||
srcLocale: string;
|
||||
destLocale: string;
|
||||
}
|
||||
|
||||
export interface TranslationSaveResponse extends APIResponse {
|
||||
EventTransSeq?: string;
|
||||
RoomID?: string;
|
||||
RegDate?: string;
|
||||
SrcLocale?: string;
|
||||
DestLocale?: string;
|
||||
Original?: string;
|
||||
Translation?: string;
|
||||
translationSeq?: string;
|
||||
roomSeq?: string;
|
||||
registrationDate?: string;
|
||||
srcLocale?: string;
|
||||
destLocale?: string;
|
||||
original?: string;
|
||||
translation?: string;
|
||||
returnJson?: any;
|
||||
}
|
||||
|
||||
const translationSaveEncodeMap = {};
|
||||
const translationSaveEncodeMap = {
|
||||
userSeq: 'p_user_seq',
|
||||
deviceType: 'p_device_type',
|
||||
token: 'p_token',
|
||||
roomSeq: 'p_room_id',
|
||||
original: 'p_original',
|
||||
srcLocale: 'p_src_locale',
|
||||
destLocale: 'p_dest_locale'
|
||||
};
|
||||
|
||||
export const encodeTranslationSave: APIEncoder<TranslationSaveRequest> = (
|
||||
req: TranslationSaveRequest
|
||||
|
@ -38,5 +50,23 @@ export const encodeTranslationSave: APIEncoder<TranslationSaveRequest> = (
|
|||
export const decodeTranslationSave: APIDecoder<TranslationSaveResponse> = (
|
||||
res: any
|
||||
) => {
|
||||
return {} as TranslationSaveResponse;
|
||||
try {
|
||||
const json: JsonObject | Error = JsonAnalization.receiveAnalization(res);
|
||||
return {
|
||||
statusCode: json.StatusCode,
|
||||
translationSeq: json.EventTransSEQ,
|
||||
roomSeq: json.RoomID,
|
||||
registrationDate: json.RegDate,
|
||||
srcLocale: json.SrcLocale,
|
||||
destLocale: json.DestLocale,
|
||||
original: json.Original,
|
||||
translation: json.Translation,
|
||||
returnJson: res
|
||||
} as TranslationSaveResponse;
|
||||
} catch (e) {
|
||||
return {
|
||||
statusCode: StatusCode.Fail,
|
||||
errorMessage: e
|
||||
} as TranslationSaveResponse;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -3,12 +3,11 @@ import {
|
|||
HttpClient,
|
||||
HttpEventType,
|
||||
HttpResponse,
|
||||
HttpRequest,
|
||||
HttpProgressEvent
|
||||
HttpRequest
|
||||
} from '@angular/common/http';
|
||||
|
||||
import { Observable } from 'rxjs';
|
||||
import { map } from 'rxjs/operators';
|
||||
import { map, filter } from 'rxjs/operators';
|
||||
|
||||
import { _MODULE_CONFIG } from '../types/token';
|
||||
import { ModuleConfig } from '../types/module-config';
|
||||
|
@ -115,21 +114,30 @@ export class CommonApiService {
|
|||
public fileTalkSave(
|
||||
req: FileTalkSaveRequest,
|
||||
fileTalkSaveUrl?: string
|
||||
): Observable<FileTalkSaveResponse | HttpProgressEvent> {
|
||||
): Observable<FileTalkSaveResponse> {
|
||||
const asa = encodeFileTalkSave(req);
|
||||
|
||||
const httpReq = new HttpRequest(
|
||||
'POST',
|
||||
!!fileTalkSaveUrl ? fileTalkSaveUrl : this.moduleConfig.urls.fileTalkSave,
|
||||
encodeFileTalkSave(req),
|
||||
{ reportProgress: true }
|
||||
{ reportProgress: true, responseType: 'text' as 'json' }
|
||||
);
|
||||
|
||||
const progress = req.fileUploadItem.uploadStart();
|
||||
|
||||
return this.httpClient.request(httpReq).pipe(
|
||||
map(event => {
|
||||
filter(event => {
|
||||
if (event instanceof HttpResponse) {
|
||||
return decodeFileTalkSave(event);
|
||||
return true;
|
||||
} else if (HttpEventType.UploadProgress === event.type) {
|
||||
return event;
|
||||
progress.next(Math.round((100 * event.loaded) / event.total));
|
||||
}
|
||||
return false;
|
||||
}),
|
||||
map((event: HttpResponse<any>) => {
|
||||
req.fileUploadItem.uploadComplete();
|
||||
return decodeFileTalkSave(event.body);
|
||||
})
|
||||
);
|
||||
}
|
||||
|
|
|
@ -81,7 +81,8 @@
|
|||
fxFlex="1 1 auto"
|
||||
class="chat-content"
|
||||
#messageBoxContainer
|
||||
ucapUiFileUploadFor
|
||||
ucapFileUploadFor
|
||||
[fileUploadQueue]="fileUploadQueue"
|
||||
(fileSelected)="onFileSelected($event)"
|
||||
(fileDragEnter)="onFileDragEnter($event)"
|
||||
(fileDragOver)="onFileDragOver()"
|
||||
|
@ -109,16 +110,11 @@
|
|||
</ucap-chat-messages>
|
||||
</perfect-scrollbar>
|
||||
<!-- CHAT MESSAGES -->
|
||||
<div
|
||||
*ngIf="fileDragOver || (files && 0 < files.length)"
|
||||
class="file-drop-zone-container"
|
||||
>
|
||||
<div class="file-drop-zone">
|
||||
<ucap-ui-file-upload-queue
|
||||
[(files)]="files"
|
||||
[items]="fileItems"
|
||||
></ucap-ui-file-upload-queue>
|
||||
</div>
|
||||
<div class="file-drop-zone-container">
|
||||
<ucap-file-upload-queue
|
||||
#fileUploadQueue
|
||||
class="file-drop-zone"
|
||||
></ucap-file-upload-queue>
|
||||
</div>
|
||||
</div>
|
||||
<!-- / CHAT CONTENT -->
|
||||
|
@ -128,6 +124,7 @@
|
|||
<!-- REPLY FORM -->
|
||||
<ucap-chat-form
|
||||
#chatForm
|
||||
[fileUploadQueue]="fileUploadQueue"
|
||||
(send)="onSendMessage($event)"
|
||||
(sendFiles)="onFileSelected($event)"
|
||||
></ucap-chat-form>
|
||||
|
@ -147,7 +144,7 @@
|
|||
<mat-menu
|
||||
#messageContextMenu="matMenu"
|
||||
[hasBackdrop]="false"
|
||||
(ucapUiClickOutside)="messageContextMenuTrigger.closeMenu()"
|
||||
(ucapClickOutside)="messageContextMenuTrigger.closeMenu()"
|
||||
>
|
||||
<ng-template matMenuContent let-message="message" let-loginRes="loginRes">
|
||||
<ng-container *ngIf="!isRecalledMessage(message.type)">
|
||||
|
|
|
@ -91,15 +91,16 @@
|
|||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: rgba(255, 255, 255, 0.95);
|
||||
background-color: transparent;
|
||||
|
||||
.file-drop-zone {
|
||||
position: absolute;
|
||||
background-color: rgb(180, 180, 180);
|
||||
|
||||
top: 10%;
|
||||
left: 10%;
|
||||
width: 80%;
|
||||
height: 80%;
|
||||
top: calc(100% - 200px);
|
||||
left: 20%;
|
||||
width: 60%;
|
||||
height: 200px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,10 +2,8 @@ import {
|
|||
Component,
|
||||
OnInit,
|
||||
OnDestroy,
|
||||
AfterViewChecked,
|
||||
ViewChild,
|
||||
ElementRef,
|
||||
AfterContentInit,
|
||||
AfterViewInit
|
||||
} from '@angular/core';
|
||||
import {
|
||||
|
@ -18,11 +16,12 @@ import {
|
|||
ConfirmDialogResult,
|
||||
AlertDialogComponent,
|
||||
AlertDialogData,
|
||||
AlertDialogResult
|
||||
AlertDialogResult,
|
||||
FileUploadQueueComponent
|
||||
} from '@ucap-webmessenger/ui';
|
||||
import { Store, select } from '@ngrx/store';
|
||||
import { NGXLogger } from 'ngx-logger';
|
||||
import { Observable, Subscription } from 'rxjs';
|
||||
import { Observable, Subscription, forkJoin, of } from 'rxjs';
|
||||
import {
|
||||
Info,
|
||||
EventType,
|
||||
|
@ -44,7 +43,7 @@ import {
|
|||
UserSelectDialogType
|
||||
} from '@app/types';
|
||||
import { RoomInfo, UserInfo, RoomType } from '@ucap-webmessenger/protocol-room';
|
||||
import { tap, take } from 'rxjs/operators';
|
||||
import { tap, take, map, catchError } from 'rxjs/operators';
|
||||
import {
|
||||
FileInfo,
|
||||
FormComponent as UCapUiChatFormComponent
|
||||
|
@ -52,7 +51,12 @@ import {
|
|||
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 {
|
||||
CommonApiService,
|
||||
FileUploadItem,
|
||||
FileTalkSaveRequest,
|
||||
FileTalkSaveResponse
|
||||
} from '@ucap-webmessenger/api-common';
|
||||
import {
|
||||
CreateChatDialogComponent,
|
||||
CreateChatDialogData,
|
||||
|
@ -65,6 +69,7 @@ import {
|
|||
} from '@app/layouts/common/dialogs/image-viewer.dialog.component';
|
||||
import { CONST } from '@ucap-webmessenger/core';
|
||||
import { PerfectScrollbarComponent } from 'ngx-perfect-scrollbar';
|
||||
import { StatusCode } from '@ucap-webmessenger/api';
|
||||
|
||||
@Component({
|
||||
selector: 'app-layout-messenger-messages',
|
||||
|
@ -86,6 +91,9 @@ export class MessagesComponent implements OnInit, OnDestroy, AfterViewInit {
|
|||
@ViewChild('psChatContent', { static: true })
|
||||
psChatContent: PerfectScrollbarComponent;
|
||||
|
||||
@ViewChild('fileUploadQueue', { static: true })
|
||||
fileUploadQueue: FileUploadQueueComponent;
|
||||
|
||||
environmentsInfo: EnvironmentsInfo;
|
||||
|
||||
loginRes: LoginResponse;
|
||||
|
@ -106,10 +114,6 @@ export class MessagesComponent implements OnInit, OnDestroy, AfterViewInit {
|
|||
isCopyableMessage = isCopyable;
|
||||
isRecallableMessage = isRecallable;
|
||||
|
||||
fileDragOver = false;
|
||||
files: File[];
|
||||
fileItems: DataTransferItemList;
|
||||
|
||||
/** Timer 대화방의 대화 삭제를 위한 interval */
|
||||
interval: any;
|
||||
|
||||
|
@ -185,7 +189,7 @@ export class MessagesComponent implements OnInit, OnDestroy, AfterViewInit {
|
|||
);
|
||||
|
||||
this.interval = setInterval(() => {
|
||||
if (!!this.roomInfo.isTimeRoom) {
|
||||
if (!!this.roomInfo && !!this.roomInfo.isTimeRoom) {
|
||||
this.store.dispatch(EventStore.infoIntervalClear({}));
|
||||
}
|
||||
}, 1000);
|
||||
|
@ -369,8 +373,6 @@ export class MessagesComponent implements OnInit, OnDestroy, AfterViewInit {
|
|||
|
||||
onFileDragEnter(items: DataTransferItemList) {
|
||||
this.logger.debug('onFileDragEnter', items);
|
||||
this.fileDragOver = true;
|
||||
this.fileItems = items;
|
||||
}
|
||||
|
||||
onFileDragOver() {
|
||||
|
@ -379,17 +381,64 @@ export class MessagesComponent implements OnInit, OnDestroy, AfterViewInit {
|
|||
|
||||
onFileDragLeave() {
|
||||
this.logger.debug('onFileDragLeave');
|
||||
this.fileDragOver = false;
|
||||
}
|
||||
|
||||
onFileSelected(files: File[]) {
|
||||
this.logger.debug('onFileSelected', files);
|
||||
if (!this.files) {
|
||||
this.files = [];
|
||||
}
|
||||
this.files.push(...files);
|
||||
onFileSelected(fileUploadItems: FileUploadItem[]) {
|
||||
this.logger.debug('onFileSelected', fileUploadItems);
|
||||
|
||||
this.fileDragOver = false;
|
||||
const allObservables: Observable<FileTalkSaveResponse>[] = [];
|
||||
|
||||
for (const fileUploadItem of fileUploadItems) {
|
||||
const req: FileTalkSaveRequest = {
|
||||
userSeq: this.loginRes.userSeq,
|
||||
deviceType: this.environmentsInfo.deviceType,
|
||||
token: this.loginRes.tokenString,
|
||||
roomSeq: this.roomInfo.roomSeq,
|
||||
file: fileUploadItem.file,
|
||||
fileName: fileUploadItem.file.name,
|
||||
fileUploadItem
|
||||
};
|
||||
|
||||
allObservables.push(
|
||||
this.commonApiService
|
||||
.fileTalkSave(req, this.sessionVerInfo.uploadUrl)
|
||||
.pipe(
|
||||
map(res => {
|
||||
if (!res) {
|
||||
return;
|
||||
}
|
||||
if (StatusCode.Success === res.statusCode) {
|
||||
return res;
|
||||
} else {
|
||||
throw res;
|
||||
}
|
||||
})
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
forkJoin(allObservables)
|
||||
.pipe(take(1))
|
||||
.subscribe(
|
||||
resList => {
|
||||
for (const res of resList) {
|
||||
this.store.dispatch(
|
||||
EventStore.send({
|
||||
senderSeq: this.loginRes.userSeq,
|
||||
req: {
|
||||
roomSeq: this.roomInfo.roomSeq,
|
||||
eventType: EventType.File,
|
||||
sentMessage: res.returnJson
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
||||
},
|
||||
error => {},
|
||||
() => {
|
||||
this.fileUploadQueue.onUploadComplete();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
onContextMenuMessage(params: { event: MouseEvent; message: Info }) {
|
||||
|
|
|
@ -65,7 +65,6 @@ import {
|
|||
cancel,
|
||||
cancelFailure,
|
||||
forward,
|
||||
forwardFailure,
|
||||
forwardAfterRoomOpen,
|
||||
sendMass,
|
||||
sendMassFailure,
|
||||
|
@ -418,7 +417,7 @@ export class Effects {
|
|||
send({
|
||||
senderSeq: action.senderSeq,
|
||||
req: {
|
||||
roomSeq: res.roomID,
|
||||
roomSeq: res.roomSeq,
|
||||
eventType: EventType.MassText,
|
||||
sentMessage: res.returnJson
|
||||
}
|
||||
|
|
|
@ -4,9 +4,12 @@ import {
|
|||
Output,
|
||||
EventEmitter,
|
||||
ViewChild,
|
||||
ElementRef
|
||||
ElementRef,
|
||||
Input
|
||||
} from '@angular/core';
|
||||
import { NgForm } from '@angular/forms';
|
||||
import { FileUploadItem } from '@ucap-webmessenger/api-common';
|
||||
import { FileUploadQueueComponent } from '@ucap-webmessenger/ui';
|
||||
|
||||
@Component({
|
||||
selector: 'ucap-chat-form',
|
||||
|
@ -14,11 +17,14 @@ import { NgForm } from '@angular/forms';
|
|||
styleUrls: ['./form.component.scss']
|
||||
})
|
||||
export class FormComponent implements OnInit {
|
||||
@Input()
|
||||
fileUploadQueue: FileUploadQueueComponent;
|
||||
|
||||
@Output()
|
||||
send = new EventEmitter<string>();
|
||||
|
||||
@Output()
|
||||
sendFiles = new EventEmitter<File[]>();
|
||||
sendFiles = new EventEmitter<FileUploadItem[]>();
|
||||
|
||||
@ViewChild('replyForm', { static: false })
|
||||
replyForm: NgForm;
|
||||
|
@ -53,6 +59,13 @@ export class FormComponent implements OnInit {
|
|||
for (let i = 0; i < this.fileInput.nativeElement.files.length; i++) {
|
||||
files.push(this.fileInput.nativeElement.files.item(i));
|
||||
}
|
||||
this.sendFiles.emit(files);
|
||||
|
||||
const fileUploadItems = FileUploadItem.fromFiles(files);
|
||||
|
||||
if (!!this.fileUploadQueue) {
|
||||
this.fileUploadQueue.onFileSelected(fileUploadItems);
|
||||
}
|
||||
|
||||
this.sendFiles.emit(fileUploadItems);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,41 +1,31 @@
|
|||
<div
|
||||
fxLayout="row wrap"
|
||||
fxFlex="100"
|
||||
class="ucap-ui-file-upload-queue-container"
|
||||
>
|
||||
<div fxLayout="row wrap" fxFlex="100" class="ucap-file-upload-queue-container">
|
||||
<div
|
||||
fxLayout="column"
|
||||
fxFlex="100"
|
||||
fxFlex.gt-xs="100"
|
||||
fxFlex.gt-md="25"
|
||||
*ngFor="let file of uploadFiles"
|
||||
*ngFor="let fileUploadItem of fileUploadItems"
|
||||
>
|
||||
<div fxLayout="row">
|
||||
<div>
|
||||
<mat-icon>image</mat-icon>
|
||||
</div>
|
||||
<div>{{ file.name }}</div>
|
||||
<div (click)="onClickClear(file)">
|
||||
<div>{{ fileUploadItem.file.name }}</div>
|
||||
<!-- <div (click)="onClickClear(fileUploadItem)">
|
||||
<mat-icon>clear</mat-icon>
|
||||
</div>
|
||||
</div> -->
|
||||
</div>
|
||||
<div fxLayout="row">
|
||||
<mat-progress-bar mode="determinate" value="40"> </mat-progress-bar>
|
||||
<mat-progress-bar
|
||||
mode="determinate"
|
||||
[value]="fileUploadItem.uploadingProgress$ | async"
|
||||
>
|
||||
</mat-progress-bar>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div *ngIf="uploadItems" fxLayout="column">
|
||||
<div>여기에 파일을 Drop하시면 업로드 됩니다.</div>
|
||||
<div>
|
||||
<div
|
||||
fxLayout="row"
|
||||
fxFlex="100"
|
||||
fxFlex.gt-xs="20"
|
||||
fxFlex.gt-md="25"
|
||||
*ngFor="let item of uploadItems"
|
||||
>
|
||||
<mat-icon>image</mat-icon>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
.ucap-ui-file-upload-queue-container {
|
||||
.ucap-file-upload-queue-container {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
|
|
@ -1,40 +1,108 @@
|
|||
import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
|
||||
import {
|
||||
Component,
|
||||
OnInit,
|
||||
Input,
|
||||
Output,
|
||||
EventEmitter,
|
||||
ElementRef,
|
||||
AfterViewInit
|
||||
} from '@angular/core';
|
||||
|
||||
import { NGXLogger } from 'ngx-logger';
|
||||
import { FileUploadItem } from '@ucap-webmessenger/api-common';
|
||||
|
||||
@Component({
|
||||
selector: 'ucap-ui-file-upload-queue',
|
||||
selector: 'ucap-file-upload-queue',
|
||||
templateUrl: './file-upload-queue.component.html',
|
||||
styleUrls: ['./file-upload-queue.component.scss']
|
||||
})
|
||||
export class FileUploadQueueComponent implements OnInit {
|
||||
@Output()
|
||||
filesChange = new EventEmitter<File[]>();
|
||||
export class FileUploadQueueComponent implements OnInit, AfterViewInit {
|
||||
fileUploadItems: FileUploadItem[];
|
||||
uploadItems: DataTransferItem[];
|
||||
|
||||
@Input() set files(files: File[]) {
|
||||
this.uploadFiles = files;
|
||||
this.uploadItems = undefined;
|
||||
constructor(
|
||||
private elementRef: ElementRef<HTMLElement>,
|
||||
private logger: NGXLogger
|
||||
) {}
|
||||
|
||||
ngOnInit() {}
|
||||
|
||||
ngAfterViewInit(): void {
|
||||
this.changeStyleDisplay(false);
|
||||
}
|
||||
|
||||
onDragEnter(items: DataTransferItemList): void {
|
||||
if (!items || 0 === items.length) {
|
||||
return;
|
||||
}
|
||||
uploadFiles: File[];
|
||||
|
||||
@Input() set items(items: DataTransferItemList) {
|
||||
const uploadItems: DataTransferItem[] = [];
|
||||
// tslint:disable-next-line: prefer-for-of
|
||||
for (let i = 0; i < items.length; i++) {
|
||||
uploadItems.push(items[i]);
|
||||
}
|
||||
this.uploadItems = [...uploadItems];
|
||||
this.changeStyleDisplay(true);
|
||||
}
|
||||
uploadItems: DataTransferItem[];
|
||||
|
||||
constructor(private logger: NGXLogger) {}
|
||||
onDragLeave(): void {
|
||||
this.changeStyleDisplay(false);
|
||||
}
|
||||
|
||||
ngOnInit() {}
|
||||
onDrop(fileUploadItems: FileUploadItem[]) {
|
||||
if (!fileUploadItems || 0 === fileUploadItems.length) {
|
||||
return;
|
||||
}
|
||||
this.fileUploadItems = fileUploadItems;
|
||||
this.uploadItems = undefined;
|
||||
}
|
||||
|
||||
onClickClear(file: File) {
|
||||
this.uploadFiles = this.uploadFiles.filter(f => {
|
||||
return f.name !== file.name && f.path !== file.path;
|
||||
});
|
||||
this.filesChange.emit(this.uploadFiles);
|
||||
onFileSelected(fileUploadItems: FileUploadItem[]): void {
|
||||
if (!fileUploadItems || 0 === fileUploadItems.length) {
|
||||
return;
|
||||
}
|
||||
this.fileUploadItems = fileUploadItems;
|
||||
this.uploadItems = undefined;
|
||||
this.changeStyleDisplay(true);
|
||||
}
|
||||
|
||||
onUploadComplete(): void {
|
||||
setTimeout(() => {
|
||||
this.fileUploadItems = undefined;
|
||||
this.changeStyleDisplay(false);
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
isEventInElement(event: DragEvent): boolean {
|
||||
const rect = this.elementRef.nativeElement.getBoundingClientRect();
|
||||
// const rect: DOMRect = this.elementRef.nativeElement.getBoundingClientRect();
|
||||
|
||||
if (
|
||||
event.pageX >= rect.left &&
|
||||
event.pageX <= rect.left + rect.width &&
|
||||
event.pageY >= rect.top &&
|
||||
event.pageY <= rect.top + rect.height
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private changeStyleDisplay(show: boolean): void {
|
||||
if (show || (!!this.fileUploadItems && 0 < this.fileUploadItems.length)) {
|
||||
this.elementRef.nativeElement.style.display = '';
|
||||
} else {
|
||||
this.elementRef.nativeElement.style.display = 'none';
|
||||
}
|
||||
}
|
||||
|
||||
// onClickClear(fileUploadItem: FileUploadItem) {
|
||||
// this.fileUploadItems = this.fileUploadItems.filter(f => {
|
||||
// return (
|
||||
// f.file.name !== fileUploadItem.file.name &&
|
||||
// f.file.path !== fileUploadItem.file.path
|
||||
// );
|
||||
// });
|
||||
// this.filesChange.emit(this.fileUploadItems);
|
||||
// }
|
||||
}
|
||||
|
|
|
@ -3,15 +3,22 @@ import {
|
|||
ElementRef,
|
||||
EventEmitter,
|
||||
HostListener,
|
||||
Output
|
||||
Output,
|
||||
Input,
|
||||
AfterViewInit
|
||||
} from '@angular/core';
|
||||
|
||||
import { NGXLogger } from 'ngx-logger';
|
||||
import { FileUploadQueueComponent } from '../components/file-upload-queue.component';
|
||||
import { FileUploadItem } from '@ucap-webmessenger/api-common';
|
||||
|
||||
@Directive({
|
||||
selector: 'input[ucapUiFileUploadFor], div[ucapUiFileUploadFor]'
|
||||
selector: 'input[ucapFileUploadFor], div[ucapFileUploadFor]'
|
||||
})
|
||||
export class FileUploadForDirective {
|
||||
export class FileUploadForDirective implements AfterViewInit {
|
||||
@Input()
|
||||
fileUploadQueue: FileUploadQueueComponent;
|
||||
|
||||
@Output()
|
||||
public fileDragEnter = new EventEmitter<DataTransferItemList>();
|
||||
|
||||
|
@ -22,12 +29,14 @@ export class FileUploadForDirective {
|
|||
public fileDragLeave = new EventEmitter<void>();
|
||||
|
||||
@Output()
|
||||
public fileSelected = new EventEmitter<File[]>();
|
||||
public fileSelected = new EventEmitter<FileUploadItem[]>();
|
||||
|
||||
dragOver = false;
|
||||
|
||||
constructor(private elementRef: ElementRef, private logger: NGXLogger) {}
|
||||
|
||||
ngAfterViewInit(): void {}
|
||||
|
||||
@HostListener('window:dragenter', ['$event'])
|
||||
public onDragEnter(event: DragEvent): any {
|
||||
if (!this.isFileDrag(event.dataTransfer)) {
|
||||
|
@ -37,6 +46,9 @@ export class FileUploadForDirective {
|
|||
if (!this.dragOver) {
|
||||
this.fileDragEnter.emit(event.dataTransfer.items);
|
||||
this.dragOver = true;
|
||||
if (!!this.fileUploadQueue) {
|
||||
this.fileUploadQueue.onDragEnter(event.dataTransfer.items);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -46,7 +58,7 @@ export class FileUploadForDirective {
|
|||
return;
|
||||
}
|
||||
|
||||
if (this.isEventInElement(event)) {
|
||||
if (this.fileUploadQueue.isEventInElement(event)) {
|
||||
event.dataTransfer.dropEffect = 'copy';
|
||||
} else {
|
||||
event.dataTransfer.dropEffect = 'none';
|
||||
|
@ -63,13 +75,16 @@ export class FileUploadForDirective {
|
|||
if (event && event.pageX === 0 && event.pageY === 0) {
|
||||
this.fileDragLeave.emit();
|
||||
this.dragOver = false;
|
||||
if (!!this.fileUploadQueue) {
|
||||
this.fileUploadQueue.onDragLeave();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@HostListener('change')
|
||||
public onChange(): any {
|
||||
const files = this.elementRef.nativeElement.files;
|
||||
this.fileSelected.emit(files);
|
||||
this.fileSelected.emit(FileUploadItem.fromFiles(files));
|
||||
this.elementRef.nativeElement.value = '';
|
||||
}
|
||||
|
||||
|
@ -79,11 +94,15 @@ export class FileUploadForDirective {
|
|||
return;
|
||||
}
|
||||
const files = event.dataTransfer.files;
|
||||
this.fileSelected.emit(files);
|
||||
const fileUploadItems = FileUploadItem.fromFiles(files);
|
||||
this.fileSelected.emit(fileUploadItems);
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
this.elementRef.nativeElement.value = '';
|
||||
this.dragOver = false;
|
||||
if (!!this.fileUploadQueue) {
|
||||
this.fileUploadQueue.onDrop(fileUploadItems);
|
||||
}
|
||||
}
|
||||
|
||||
private isFileDrag(dataTransfer: DataTransfer): boolean {
|
||||
|
@ -101,18 +120,4 @@ export class FileUploadForDirective {
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
private isEventInElement(event: DragEvent): boolean {
|
||||
const rect: DOMRect = this.elementRef.nativeElement.getBoundingClientRect();
|
||||
|
||||
if (
|
||||
event.pageX >= rect.left &&
|
||||
event.pageX <= rect.left + rect.width &&
|
||||
event.pageY >= rect.top &&
|
||||
event.pageY <= rect.top + rect.height
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user