쪽지 미리보기 중간 적용.

This commit is contained in:
leejinho 2019-11-26 17:54:37 +09:00
parent 664a92781f
commit e0c1e181f7
20 changed files with 544 additions and 63 deletions

View File

@ -6,7 +6,9 @@ import {
} from '@ucap-webmessenger/api';
import { DeviceType } from '@ucap-webmessenger/core';
import { MessageType } from '../types/message.type';
import { CategoryType } from '../types/category.type';
import { MessageDetailInfo } from '../models/message-list';
import { DetailContent } from '../models/detail-content';
import { DetailReceiver } from '../models/detail-receiver';
export interface DetailRequest extends APIRequest {
userSeq: number;
@ -18,32 +20,11 @@ export interface DetailRequest extends APIRequest {
}
export interface DetailResponse extends MessageAPIResponse {
msgInfo: {
msgId: number;
category: CategoryType;
title: string;
titleYn: boolean;
};
msgInfo: MessageDetailInfo;
content: {
type: MessageType;
sendUserSeq: number;
sendUserName: string;
reservationTime: string | null;
sendYn: boolean;
regDate: string;
attachmentYn: boolean;
smsYn: boolean;
fileAllow: string;
}[];
contents: DetailContent[];
recvList: {
userSeq: number;
userName: string;
cancelYn: boolean;
readDate: string;
readYn: boolean;
}[];
recvList: DetailReceiver[];
}
export const encodeDetail: APIJsonEncoder<DetailRequest> = (
@ -53,15 +34,50 @@ export const encodeDetail: APIJsonEncoder<DetailRequest> = (
};
export const decodeDetail: APIDecoder<DetailResponse> = (res: any) => {
let msgInfo: MessageDetailInfo = null;
const contents: DetailContent[] = [];
const recvList: DetailReceiver[] = [];
if (!!res.msgInfo) {
// msgInfo
msgInfo = {
...res.msgInfo,
titleYn: res.msgInfo.titleYn === 'Y' ? true : false,
attachmentYn: res.msgInfo.attachmentYn === 'Y' ? true : false,
smsYn: res.msgInfo.smsYn === 'Y' ? true : false
};
// contents
if (!!res.msgInfo.content && res.msgInfo.content.length > 0) {
for (const content of res.msgInfo.content) {
contents.push({
...content,
activeYn: content.activeYn === 'Y' ? true : false
});
}
}
// receiver
if (!!res.recvList && res.recvList.length > 0) {
for (const recv of res.recvList) {
recvList.push({
...recv,
cancelYn: recv.cancelYn === 'Y' ? true : false,
readYn: recv.readYn === 'Y' ? true : false
});
}
}
}
return {
responseCode: res.responseCode,
responseMsg: res.responseMsg,
msgInfo: null,
content: [],
recvList: []
msgInfo,
contents,
recvList
} as DetailResponse;
};

View File

@ -0,0 +1,21 @@
import { ContentType } from '../types/content.type';
export interface DetailContent {
// text default
activeYn: boolean;
resSeq: number;
resUrl: string;
resContent: string;
resType: ContentType;
resSize: number;
// attach file default
companyCode?: string;
synapKey?: string;
// image default
resResolution?: string;
thumbnailNm?: string;
thumbnailSeq?: number;
thumbnailUrl?: string;
}

View File

@ -0,0 +1,7 @@
export interface DetailReceiver {
userSeq: number;
userName: string;
cancelYn: boolean;
readDate: string;
readYn: boolean;
}

View File

@ -32,3 +32,10 @@ export interface MessageList {
/** 읽음여부 */
readYn?: boolean;
}
export interface MessageDetailInfo extends MessageList {
sendUserSeq: number;
sendUserName: string;
smsYn?: boolean;
fileAllow?: string;
}

View File

@ -1,8 +1,13 @@
import { Injectable, Inject } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import {
HttpClient,
HttpHeaders,
HttpRequest,
HttpResponse
} from '@angular/common/http';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { map, filter } from 'rxjs/operators';
import { _MODULE_CONFIG } from '../config/token';
import { ModuleConfig } from '../config/module-config';
@ -203,16 +208,47 @@ export class MessageApiService {
}
public retrieveResourceFile(
req: RetrieveResourceFileRequest
): Observable<RetrieveResourceFileResponse> {
return this.httpClient
.post<any>(
this.urls.retrieveResourceFile,
encodeRetrieveResourceFile(req),
{
headers: this.headers
): Observable<Blob> {
const httpReq = new HttpRequest(
'POST',
this.urls.retrieveResourceFile,
encodeRetrieveResourceFile(req),
{
headers: this.headers,
responseType: 'blob'
}
);
return this.httpClient.request(httpReq).pipe(
filter(event => {
if (event instanceof HttpResponse) {
return true;
}
)
.pipe(map(res => decodeRetrieveResourceFile(res)));
return false;
}),
map((event: HttpResponse<any>) => {
return event.body;
})
);
// return this.httpClient
// .post<any>(
// this.urls.retrieveResourceFile,
// encodeRetrieveResourceFile(req),
// {
// headers: this.headers
// }
// )
// .pipe(map(res => decodeRetrieveResourceFile(res)));
}
public urlForFileMessageDownload(req: RetrieveResourceFileRequest): string {
const httpReq = new HttpRequest(
'POST',
this.urls.retrieveResourceFile,
encodeRetrieveResourceFile(req),
{
headers: this.headers
}
);
return httpReq.urlWithParams;
}
/** del */

View File

@ -13,6 +13,8 @@ export * from './lib/services/message-api.service';
export * from './lib/ucap-message-api.module';
export * from './lib/models/detail-receiver';
export * from './lib/models/detail-content';
export * from './lib/models/message-list';
export * from './lib/types/category.type';

View File

@ -89,7 +89,16 @@
<mat-tab [aria-label]="MainMenu.Message">
<ng-template mat-tab-label>
<!--<mat-icon>device_hub</mat-icon>-->
<div class="icon-item" matTooltip="Message" matTooltipPosition="after">
<div
class="icon-item"
[matBadgeHidden]="badgeMessageUnReadCount <= 0"
[matBadge]="badgeMessageUnReadCount"
matBadgeDescription="확인하지 않은 메시지가 있습니다."
matBadgeColor="accent"
matBadgePosition="above after"
matTooltip="Message"
matTooltipPosition="after"
>
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
@ -191,6 +200,7 @@
>
<app-layout-chat-left-sidenav-message
[isVisible]="currentTabLable === MainMenu.Message"
(doRefreshUnReadCount)="getMessageUnreadCount()"
></app-layout-chat-left-sidenav-message>
</div>
<div

View File

@ -16,7 +16,7 @@ import {
CreateChatDialogData,
CreateChatDialogResult
} from '@app/layouts/messenger/dialogs/chat/create-chat.dialog.component';
import { Observable, Subscription } from 'rxjs';
import { Observable, Subscription, of } from 'rxjs';
import { Store, select } from '@ngrx/store';
import * as AppStore from '@app/store';
@ -35,6 +35,11 @@ import { SessionStorageService } from '@ucap-webmessenger/web-storage';
import { KEY_LOGIN_RES_INFO } from '@app/types/login-res-info.type';
import { VersionInfo2Response } from '@ucap-webmessenger/api-public';
import { KEY_VER_INFO } from '@app/types/ver-info.type';
import { MessageApiService } from '@ucap-webmessenger/api-message';
import { DeviceType } from '@ucap-webmessenger/core';
import { UnreadCountRequest } from 'projects/ucap-webmessenger-api-message/src/lib/apis/unread-count';
import { map, catchError } from 'rxjs/operators';
import { MessageStatusCode } from '@ucap-webmessenger/api';
export enum MainMenu {
Group = 'GROUP',
@ -62,6 +67,9 @@ export class LeftSideComponent implements OnInit, OnDestroy {
badgeChatUnReadCount: number;
badgeChatUnReadCountSubscription: Subscription;
badgeMessageUnReadCount: number;
badgeMessageUnReadCountSubscription: Subscription;
badgeMessageInterval: any;
/** 조직도에서 부서원 선택 */
selectedUserList: (UserInfo | UserInfoSS | UserInfoF | UserInfoDN)[] = [];
@ -79,6 +87,7 @@ export class LeftSideComponent implements OnInit, OnDestroy {
private store: Store<any>,
private dialogService: DialogService,
private sessionStorageService: SessionStorageService,
private messageApiService: MessageApiService,
private logger: NGXLogger
) {
this.loginRes = this.sessionStorageService.get<LoginResponse>(
@ -98,6 +107,12 @@ export class LeftSideComponent implements OnInit, OnDestroy {
this.badgeChatUnReadCount = count;
});
this.getMessageUnreadCount();
this.badgeMessageInterval = setInterval(
() => this.getMessageUnreadCount(),
5 * 60 * 1000
);
this.setFabInitial(MainMenu.Group);
this.currentTabLable = MainMenu.Group;
}
@ -106,6 +121,13 @@ export class LeftSideComponent implements OnInit, OnDestroy {
if (!!this.badgeChatUnReadCountSubscription) {
this.badgeChatUnReadCountSubscription.unsubscribe();
}
if (!!this.badgeMessageUnReadCountSubscription) {
this.badgeMessageUnReadCountSubscription.unsubscribe();
}
if (!!this.badgeMessageInterval) {
clearInterval(this.badgeMessageInterval);
}
this.logger.debug('-----------------------LeftSideComponent ngOnDestroy');
}
@ -314,4 +336,23 @@ export class LeftSideComponent implements OnInit, OnDestroy {
break;
}
}
getMessageUnreadCount(): void {
this.badgeMessageUnReadCountSubscription = this.messageApiService
.retrieveUnreadCount({
userSeq: this.loginRes.userSeq,
deviceType: DeviceType.PC,
tokenKey: this.loginRes.tokenString
} as UnreadCountRequest)
.pipe(
map(res => {
if (res.responseCode === MessageStatusCode.Success) {
this.badgeMessageUnReadCount = res.unreadCount;
} else {
}
}),
catchError(error => of(this.logger.error(error)))
)
.subscribe();
}
}

View File

@ -50,7 +50,11 @@
수신
</ng-template>
<div *ngFor="let message of messageList">
<div
*ngFor="let message of messageList"
(click)="onClickDetail(message)"
class="message-item"
>
<dl>
<dt>
<mat-icon
@ -82,7 +86,11 @@
발신
</ng-template>
<div *ngFor="let message of messageList">
<div
*ngFor="let message of messageList"
(click)="onClickDetail(message)"
class="message-item"
>
<dl>
<dt>
<mat-icon
@ -114,7 +122,11 @@
예약
</ng-template>
<div *ngFor="let message of messageList">
<div
*ngFor="let message of messageList"
(click)="onClickDetail(message)"
class="message-item"
>
<dl>
<dt>
<mat-icon
@ -147,7 +159,10 @@
<div class="search-sub">
<form [formGroup]="fgSearchType" class="w-100-p">
<mat-form-field>
<mat-select formControlName="searchMessageType" (selectionChange)="onChangeSelection($event)">
<mat-select
formControlName="searchMessageType"
(selectionChange)="onChangeSelection($event)"
>
<mat-option [value]="MessageType.All">전체</mat-option>
<mat-option [value]="MessageType.Receive">수신</mat-option>
<mat-option [value]="MessageType.Send">발신</mat-option>
@ -171,7 +186,11 @@
</mat-radio-group>
</form>
</div>
<div *ngFor="let message of messageList">
<div
*ngFor="let message of messageList"
(click)="onClickDetail(message)"
class="message-item"
>
<dl>
<dt>
<mat-icon

View File

@ -65,3 +65,7 @@
.mat-tab-label-active {
opacity: 1;
}
.message-item {
cursor: pointer;
}

View File

@ -11,6 +11,7 @@ import {
import { Subscription, of } from 'rxjs';
import { Store, select } from '@ngrx/store';
import { tap, map, catchError } from 'rxjs/operators';
import { NGXLogger } from 'ngx-logger';
import * as AppStore from '@app/store';
@ -27,7 +28,8 @@ import {
RetrieveRequest,
MessageList,
RetrieveSearchRequest,
MessageSearchType
MessageSearchType,
DetailRequest
} from '@ucap-webmessenger/api-message';
import { DeviceType } from '@ucap-webmessenger/core';
import { MessageStatusCode } from '@ucap-webmessenger/api';
@ -38,6 +40,11 @@ import {
MatSelectChange,
MatRadioChange
} from '@angular/material';
import {
MessageDetailDialogComponent,
MessageDetailDialogResult,
MessageDetailDialogData
} from '../../dialogs/message/message-detail.dialog.component';
@Component({
selector: 'app-layout-chat-left-sidenav-message',
@ -49,6 +56,9 @@ export class MessageBoxComponent
@Input()
isVisible = false;
@Output()
doRefreshUnReadCount = new EventEmitter();
@ViewChild('tabs', { static: false }) tabs: MatTabGroup;
isInitTabs = false;
@ -85,7 +95,8 @@ export class MessageBoxComponent
private formBuilder: FormBuilder,
private sessionStorageService: SessionStorageService,
private dialogService: DialogService,
private messageApiService: MessageApiService
private messageApiService: MessageApiService,
private logger: NGXLogger
) {
this.loginRes = this.sessionStorageService.get<LoginResponse>(
KEY_LOGIN_RES_INFO
@ -210,7 +221,6 @@ export class MessageBoxComponent
} as RetrieveSearchRequest)
.pipe(
map(res => {
console.log(res);
if (res.responseCode === MessageStatusCode.Success) {
this.currentTotalCount = res.totalCount;
this.currentPage = res.pageCount;
@ -219,7 +229,7 @@ export class MessageBoxComponent
} else {
}
}),
catchError(error => of(console.log(error)))
catchError(error => of(this.logger.error(error)))
)
.subscribe();
}
@ -244,7 +254,6 @@ export class MessageBoxComponent
} as RetrieveRequest)
.pipe(
map(res => {
console.log(res);
if (res.responseCode === MessageStatusCode.Success) {
this.currentTotalCount = res.totalCount;
this.currentPage = res.pageCount;
@ -253,7 +262,7 @@ export class MessageBoxComponent
} else {
}
}),
catchError(error => of(console.log(error)))
catchError(error => of(this.logger.error(error)))
)
.subscribe();
}
@ -271,7 +280,6 @@ export class MessageBoxComponent
} as RetrieveRequest)
.pipe(
map(res => {
console.log(res);
if (res.responseCode === MessageStatusCode.Success) {
this.currentTotalCount = res.totalCount;
this.currentPage = res.pageCount;
@ -280,7 +288,7 @@ export class MessageBoxComponent
} else {
}
}),
catchError(error => of(console.log(error)))
catchError(error => of(this.logger.error(error)))
)
.subscribe();
}
@ -298,7 +306,6 @@ export class MessageBoxComponent
} as RetrieveRequest)
.pipe(
map(res => {
console.log(res);
if (res.responseCode === MessageStatusCode.Success) {
this.currentTotalCount = res.totalCount;
this.currentPage = res.pageCount;
@ -307,11 +314,51 @@ export class MessageBoxComponent
} else {
}
}),
catchError(error => of(console.log(error)))
catchError(error => of(this.logger.error(error)))
)
.subscribe();
}
break;
}
}
onClickDetail(message: MessageList) {
this.messageApiService
.detailMessage({
userSeq: this.loginRes.userSeq,
deviceType: DeviceType.PC,
tokenKey: this.loginRes.tokenString,
type: message.type,
msgId: message.msgId
} as DetailRequest)
.pipe(
map(async res => {
if (res.responseCode === MessageStatusCode.Success) {
// Badge Refresh in case Receive Message..
if (res.msgInfo.type === MessageType.Receive) {
this.doRefreshUnReadCount.emit();
}
// detail view..
const result = await this.dialogService.open<
MessageDetailDialogComponent,
MessageDetailDialogData,
MessageDetailDialogResult
>(MessageDetailDialogComponent, {
width: '600px',
data: {
detail: res,
loginRes: this.loginRes
}
});
// if (!!result && !!result.choice && result.choice) {
// }
} else {
}
}),
catchError(error => of(this.logger.error(error)))
)
.subscribe();
}
}

View File

@ -1,11 +1,13 @@
import { DIALOGS as CHAT_DIALOGS } from './chat';
import { DIALOGS as GROUP_DIALOGS } from './group';
import { DIALOGS as MESSAGE_DIALOGS } from './message';
import { DIALOGS as PROFILE_DIALOGS } from './profile';
import { DIALOGS as SETTINGS_DIALOGS } from './settings';
export const DIALOGS = [
...CHAT_DIALOGS,
...GROUP_DIALOGS,
...MESSAGE_DIALOGS,
...PROFILE_DIALOGS,
...SETTINGS_DIALOGS
];

View File

@ -0,0 +1,3 @@
import { MessageDetailDialogComponent } from './message-detail.dialog.component';
export const DIALOGS = [MessageDetailDialogComponent];

View File

@ -0,0 +1,82 @@
<mat-card class="confirm-card mat-elevation-z">
<mat-card-header>
<mat-card-title>
<ng-container [ngSwitch]="messageInfo.type">
<span *ngSwitchCase="MessageType.Receive">받은 쪽지</span>
<span *ngSwitchCase="MessageType.Send">보낸 쪽지</span>
<span *ngSwitchCase="MessageType.Reservation">예약 쪽지</span>
</ng-container>
</mat-card-title>
</mat-card-header>
<mat-card-content>
<div fxFlex fxLayout="column" fxLayoutAlign=" stretch">
<div class="title">
{{ messageInfo.title }}
<span>
<button mat-icon-button aria-label="group menu" class="message-menu">
<mat-icon>more_vert</mat-icon>
</button>
</span>
</div>
<div class="info">
<ul>
<li>
<span *ngIf="messageInfo.type === MessageType.Receive" class="label"
>보낸사람</span
>
<span *ngIf="messageInfo.type !== MessageType.Receive" class="label"
>받는사람</span
>
<span>{{ messageInfo.sendUserName }}</span>
</li>
<li>
<span class="label">받은시간</span>
<span>{{
messageInfo.regDate
| dateToStringFormat: 'YYYY.MM.dd (KS) a/p HH:mm'
}}</span>
</li>
</ul>
</div>
<div class="contents">
<ul>
<li *ngFor="let cont of contents">
<pre *ngIf="cont.resType === ContentType.Text">{{
cont.resContent
}}</pre>
<img
*ngIf="cont.resType === ContentType.Image"
[src]="getThumbImage(cont)"
/>
</li>
</ul>
</div>
<div *ngIf="attachFile && attachFile.length > 0" class="attachFile">
<div>
<div class="title">
<span *ngIf="isExpiredAttachFile">기간이 만료된 파일입니다</span>
<button mat-stroked-button class="mat-primary">
모두저장
</button>
</div>
<ul>
<li *ngFor="let file of attachFile">
<div>
<span class="mdi mdi-attachment"></span>
<span>{{ file.resContent }}</span>
<span>{{ file.resSize | ucapBytes }}</span>
<span class="mdi mdi-download"></span>
</div>
</li>
</ul>
</div>
</div>
</div>
</mat-card-content>
<mat-card-actions class="button-farm flex-row">
<button mat-stroked-button (click)="onClickConfirm()" class="mat-primary">
Confirm
</button>
</mat-card-actions>
</mat-card>

View File

@ -0,0 +1,18 @@
::ng-deep .mat-card-header-tex {
margin: 0;
}
.confirm-card {
min-width: 500px;
.mat-card-content {
}
.button-farm {
text-align: right;
.mat-primary {
margin-left: 4px;
}
}
}
::ng-deep .mat-mini-fab .mat-button-wrapper {
padding: 0;
}

View File

@ -0,0 +1,24 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { MessageDetailDialogComponent } from './message-detail.dialog.component';
describe('app::layouts::messenger::MessageDetailDialogComponent', () => {
let component: MessageDetailDialogComponent;
let fixture: ComponentFixture<MessageDetailDialogComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [MessageDetailDialogComponent]
}).compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(MessageDetailDialogComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,142 @@
import { Component, OnInit, Inject, ViewChild } from '@angular/core';
import {
MatDialogRef,
MAT_DIALOG_DATA,
MatSelectionList,
MatSelectionListChange
} from '@angular/material';
import { Observable, combineLatest, of } from 'rxjs';
import { Store, select } from '@ngrx/store';
import { map, catchError, take } from 'rxjs/operators';
import * as AppStore from '@app/store';
import * as SyncStore from '@app/store/messenger/sync';
import {
DialogService,
ConfirmDialogComponent,
ConfirmDialogData,
ConfirmDialogResult
} from '@ucap-webmessenger/ui';
import { GroupDetailData, UserInfo } from '@ucap-webmessenger/protocol-sync';
import {
DetailResponse,
MessageType,
MessageList,
DetailContent,
DetailReceiver,
ContentType,
MessageDetailInfo,
MessageApiService,
RetrieveResourceFileRequest
} from '@ucap-webmessenger/api-message';
import { DeviceType } from '@ucap-webmessenger/core';
import { LoginResponse } from '@ucap-webmessenger/protocol-authentication';
import { NGXLogger } from 'ngx-logger';
export interface MessageDetailDialogData {
detail: DetailResponse;
loginRes: LoginResponse;
}
// tslint:disable-next-line: no-empty-interface
export interface MessageDetailDialogResult {}
@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;
constructor(
public dialogRef: MatDialogRef<
MessageDetailDialogData,
MessageDetailDialogResult
>,
@Inject(MAT_DIALOG_DATA) public data: MessageDetailDialogData,
private messageApiService: MessageApiService,
private logger: NGXLogger,
private store: Store<any>,
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);
}
});
}
this.receivers = this.messageDetail.recvList;
}
getThumbImage(content: DetailContent): string {
console.log(
JSON.stringify({
userSeq: this.data.loginRes.userSeq,
deviceType: DeviceType.PC,
tokenKey: this.data.loginRes.tokenString,
type: this.messageInfo.type,
msgId: this.messageInfo.msgId,
resUrl: content.thumbnailUrl
})
);
if (content.resType === ContentType.Image) {
// // return this.messageApiService.urlForFileMessageDownload({
// // 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);
// 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 => {
// console.log(rawBlob);
// return URL.createObjectURL(rawBlob);
// })
// )
// .subscribe();
} else {
return '';
}
}
onClickConfirm(): void {
this.dialogRef.close({});
}
}

View File

@ -78,7 +78,7 @@ export class MainPageComponent implements OnInit, OnDestroy {
this.idleStateChangedSubscription = this.nativeService
.idleStateChanged()
.subscribe(action => {
console.log(action);
this.logger.debug(action);
let statusType: StatusCode;
if (action === 'IDLE') {

View File

@ -22,10 +22,10 @@
</ul>
<ul *ngIf="!expired && fileInfo && fileInfo.attachmentSeq">
<li>
<button mat-button (click)="onClickSave()">Save</button>
<button mat-button (click)="onClickSave()">저장</button>
</li>
<li>
<button mat-button (click)="onClickSaveAs()">Save As</button>
<button mat-button (click)="onClickSaveAs()">다른이름으로 저장</button>
</li>
</ul>
</div>

View File

@ -24,10 +24,10 @@
</ul>
<ul *ngIf="!expired && fileInfo && fileInfo.attachmentSeq">
<li>
<button mat-button (click)="onClickSave()">Save</button>
<button mat-button (click)="onClickSave()">저장</button>
</li>
<li>
<button mat-button (click)="onClickSaveAs()">Save As</button>
<button mat-button (click)="onClickSaveAs()">다른이름으로 저장</button>
</li>
</ul>
</div>