Merge branch 'master' into new-org
This commit is contained in:
commit
62af089e67
BIN
config/build/win/bin/config.dat
Normal file
BIN
config/build/win/bin/config.dat
Normal file
Binary file not shown.
|
@ -59,6 +59,10 @@
|
||||||
{
|
{
|
||||||
"from": "./config/build/win/bin/AeroAdmin.exe",
|
"from": "./config/build/win/bin/AeroAdmin.exe",
|
||||||
"to": "./bin/AeroAdmin.exe"
|
"to": "./bin/AeroAdmin.exe"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"from": "./config/build/win/bin/config.dat",
|
||||||
|
"to": "./bin/config.dat"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
|
@ -27,7 +27,8 @@ export enum ElectronBrowserWindowChannel {
|
||||||
Close = 'close',
|
Close = 'close',
|
||||||
Closed = 'closed',
|
Closed = 'closed',
|
||||||
ReadyToShow = 'ready-to-show',
|
ReadyToShow = 'ready-to-show',
|
||||||
Focus = 'focus'
|
Focus = 'focus',
|
||||||
|
Blur = 'blur'
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum ElectronWebContentsChannel {
|
export enum ElectronWebContentsChannel {
|
||||||
|
|
|
@ -14,8 +14,9 @@ import {
|
||||||
ElectronWebContentsChannel
|
ElectronWebContentsChannel
|
||||||
} from '@ucap-webmessenger/electron-core';
|
} from '@ucap-webmessenger/electron-core';
|
||||||
|
|
||||||
import { appStorage } from '../lib/storage';
|
|
||||||
import { now } from '../util/now';
|
import { now } from '../util/now';
|
||||||
|
import { Storage } from '../lib/storage';
|
||||||
|
import { WindowStateChannel } from '@ucap-webmessenger/native-electron';
|
||||||
|
|
||||||
export class AppWindow {
|
export class AppWindow {
|
||||||
private window: BrowserWindow | null = null;
|
private window: BrowserWindow | null = null;
|
||||||
|
@ -33,7 +34,7 @@ export class AppWindow {
|
||||||
private defaultWidth = 1024;
|
private defaultWidth = 1024;
|
||||||
private defaultHeight = 768;
|
private defaultHeight = 768;
|
||||||
|
|
||||||
public constructor(private appIconPath: string) {
|
public constructor(private appIconPath: string, appStorage: Storage) {
|
||||||
const savedWindowState = windowStateKeeper({
|
const savedWindowState = windowStateKeeper({
|
||||||
defaultWidth: this.defaultWidth,
|
defaultWidth: this.defaultWidth,
|
||||||
defaultHeight: this.defaultHeight
|
defaultHeight: this.defaultHeight
|
||||||
|
@ -60,6 +61,7 @@ export class AppWindow {
|
||||||
},
|
},
|
||||||
acceptFirstMouse: true,
|
acceptFirstMouse: true,
|
||||||
icon: this.appIconPath,
|
icon: this.appIconPath,
|
||||||
|
fullscreenable: false,
|
||||||
show: false
|
show: false
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -84,6 +86,20 @@ export class AppWindow {
|
||||||
event.returnValue = true;
|
event.returnValue = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// windows Focus or Blur state detacted.
|
||||||
|
this.window.on(ElectronBrowserWindowChannel.Focus, () => {
|
||||||
|
this.window.webContents.send(
|
||||||
|
WindowStateChannel.FocuseChanged,
|
||||||
|
ElectronBrowserWindowChannel.Focus
|
||||||
|
);
|
||||||
|
});
|
||||||
|
this.window.on(ElectronBrowserWindowChannel.Blur, () => {
|
||||||
|
this.window.webContents.send(
|
||||||
|
WindowStateChannel.FocuseChanged,
|
||||||
|
ElectronBrowserWindowChannel.Blur
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
// on macOS, when the user closes the window we really just hide it. This
|
// on macOS, when the user closes the window we really just hide it. This
|
||||||
// lets us activate quickly and keep all our interesting logic in the
|
// lets us activate quickly and keep all our interesting logic in the
|
||||||
// renderer.
|
// renderer.
|
||||||
|
@ -122,11 +138,14 @@ export class AppWindow {
|
||||||
// can be tidied up once https://github.com/electron/electron/issues/12971
|
// can be tidied up once https://github.com/electron/electron/issues/12971
|
||||||
// has been confirmed as resolved
|
// has been confirmed as resolved
|
||||||
this.window.once(ElectronBrowserWindowChannel.ReadyToShow, () => {
|
this.window.once(ElectronBrowserWindowChannel.ReadyToShow, () => {
|
||||||
if (appStorage.startupHideWindow) {
|
this.window.close();
|
||||||
|
setTimeout(() => {
|
||||||
|
if (!!appStorage && appStorage.startupHideWindow) {
|
||||||
this.window.close();
|
this.window.close();
|
||||||
} else {
|
} else {
|
||||||
this.window.show();
|
this.window.show();
|
||||||
}
|
}
|
||||||
|
}, 500);
|
||||||
this.window.on(ElectronBrowserWindowChannel.Unmaximize, () => {
|
this.window.on(ElectronBrowserWindowChannel.Unmaximize, () => {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
const bounds = this.window.getBounds();
|
const bounds = this.window.getBounds();
|
||||||
|
|
|
@ -61,7 +61,7 @@ import {
|
||||||
import log from 'electron-log';
|
import log from 'electron-log';
|
||||||
|
|
||||||
import { RendererUpdater } from './lib/renderer-updater';
|
import { RendererUpdater } from './lib/renderer-updater';
|
||||||
import { appStorage } from './lib/storage';
|
import { Storage } from './lib/storage';
|
||||||
|
|
||||||
require('v8-compile-cache');
|
require('v8-compile-cache');
|
||||||
|
|
||||||
|
@ -108,6 +108,8 @@ let updateWindowService: ElectronUpdateWindowService | null;
|
||||||
|
|
||||||
tmp.setGracefulCleanup();
|
tmp.setGracefulCleanup();
|
||||||
|
|
||||||
|
let appStorage: Storage;
|
||||||
|
|
||||||
function handleUncaughtException(error: Error) {
|
function handleUncaughtException(error: Error) {
|
||||||
preventQuit = true;
|
preventQuit = true;
|
||||||
|
|
||||||
|
@ -174,7 +176,12 @@ if (isDuplicateInstance) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function createWindow() {
|
function createWindow() {
|
||||||
const window = new AppWindow(appIconPath);
|
try {
|
||||||
|
appStorage = new Storage();
|
||||||
|
} catch (e) {
|
||||||
|
log.error('[appStorage = new Storage()]]', e);
|
||||||
|
}
|
||||||
|
const window = new AppWindow(appIconPath, appStorage);
|
||||||
|
|
||||||
if (__DEV__) {
|
if (__DEV__) {
|
||||||
// const {
|
// const {
|
||||||
|
@ -212,7 +219,8 @@ function createWindow() {
|
||||||
});
|
});
|
||||||
|
|
||||||
window.onDidLoad(() => {
|
window.onDidLoad(() => {
|
||||||
if (!appStorage.startupHideWindow) {
|
if (!!appStorage && !appStorage.startupHideWindow) {
|
||||||
|
// not used?
|
||||||
window.show();
|
window.show();
|
||||||
} else {
|
} else {
|
||||||
window.hide();
|
window.hide();
|
||||||
|
@ -440,8 +448,10 @@ ipcMain.on(
|
||||||
ipcMain.on(
|
ipcMain.on(
|
||||||
MessengerChannel.ClearAppStorage,
|
MessengerChannel.ClearAppStorage,
|
||||||
(event: IpcMainEvent, ...args: any[]) => {
|
(event: IpcMainEvent, ...args: any[]) => {
|
||||||
|
if (!!!!appStorage) {
|
||||||
appStorage.reset();
|
appStorage.reset();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
ipcMain.on(
|
ipcMain.on(
|
||||||
|
@ -478,6 +488,7 @@ ipcMain.on(
|
||||||
(event: IpcMainEvent, ...args: any[]) => {
|
(event: IpcMainEvent, ...args: any[]) => {
|
||||||
const isStartupHideWindow = args[0] as boolean;
|
const isStartupHideWindow = args[0] as boolean;
|
||||||
|
|
||||||
|
if (!!!!appStorage) {
|
||||||
appStorage.startupHideWindow = isStartupHideWindow;
|
appStorage.startupHideWindow = isStartupHideWindow;
|
||||||
log.info(
|
log.info(
|
||||||
'StartupHideWindow is changed from ',
|
'StartupHideWindow is changed from ',
|
||||||
|
@ -485,6 +496,7 @@ ipcMain.on(
|
||||||
' to ',
|
' to ',
|
||||||
appStorage.startupHideWindow
|
appStorage.startupHideWindow
|
||||||
);
|
);
|
||||||
|
}
|
||||||
event.returnValue = true;
|
event.returnValue = true;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -494,7 +506,7 @@ ipcMain.on(
|
||||||
(event: IpcMainEvent, ...args: any[]) => {
|
(event: IpcMainEvent, ...args: any[]) => {
|
||||||
const downloadPath = args[0] as string;
|
const downloadPath = args[0] as string;
|
||||||
|
|
||||||
if (!!downloadPath && downloadPath.length > 0) {
|
if (!!appStorage && !!downloadPath && downloadPath.length > 0) {
|
||||||
appStorage.downloadPath = downloadPath;
|
appStorage.downloadPath = downloadPath;
|
||||||
log.info('downloadPath is changed to ', appStorage.downloadPath);
|
log.info('downloadPath is changed to ', appStorage.downloadPath);
|
||||||
|
|
||||||
|
@ -565,9 +577,9 @@ ipcMain.on(
|
||||||
|
|
||||||
let basePath = path.join(
|
let basePath = path.join(
|
||||||
app.getPath('documents'),
|
app.getPath('documents'),
|
||||||
appStorage.constDefaultDownloadFolder
|
!!appStorage ? appStorage.constDefaultDownloadFolder : ''
|
||||||
);
|
);
|
||||||
if (!!appStorage.downloadPath) {
|
if (!!appStorage && !!appStorage.downloadPath) {
|
||||||
basePath = appStorage.downloadPath;
|
basePath = appStorage.downloadPath;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
|
@ -607,7 +619,7 @@ ipcMain.on(
|
||||||
const make: boolean = args[1];
|
const make: boolean = args[1];
|
||||||
if (!folderItem) {
|
if (!folderItem) {
|
||||||
let basePath = app.getPath('downloads');
|
let basePath = app.getPath('downloads');
|
||||||
if (!!appStorage.downloadPath) {
|
if (!!appStorage && !!appStorage.downloadPath) {
|
||||||
try {
|
try {
|
||||||
basePath = appStorage.downloadPath;
|
basePath = appStorage.downloadPath;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
@ -788,6 +800,10 @@ ipcMain.on(
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (!appWindow.isVisible()) {
|
||||||
|
appWindow.browserWindow.minimize();
|
||||||
|
}
|
||||||
|
|
||||||
appWindow.browserWindow.flashFrame(true);
|
appWindow.browserWindow.flashFrame(true);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -821,6 +837,9 @@ ipcMain.on(ClipboardChannel.Read, (event: IpcMainEvent, ...args: any[]) => {
|
||||||
ipcMain.on(AppChannel.Exit, (event: IpcMainEvent, ...args: any[]) => {
|
ipcMain.on(AppChannel.Exit, (event: IpcMainEvent, ...args: any[]) => {
|
||||||
appExit();
|
appExit();
|
||||||
});
|
});
|
||||||
|
ipcMain.on(AppChannel.Logging, (event: IpcMainEvent, ...args: any[]) => {
|
||||||
|
log.error('[G]', args[0]);
|
||||||
|
});
|
||||||
|
|
||||||
ipcMain.on(ExternalChannel.OpenUrl, (event: IpcMainEvent, ...args: any[]) => {
|
ipcMain.on(ExternalChannel.OpenUrl, (event: IpcMainEvent, ...args: any[]) => {
|
||||||
const targetUrl = args[0];
|
const targetUrl = args[0];
|
||||||
|
|
|
@ -11,6 +11,7 @@ export class Storage {
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.store = new ElectronStore({
|
this.store = new ElectronStore({
|
||||||
|
cwd: path.join(__dirname, '..', '..', '..', '/bin/'),
|
||||||
schema: {
|
schema: {
|
||||||
options: {
|
options: {
|
||||||
type: 'object',
|
type: 'object',
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "ucap-webmessenger",
|
"name": "ucap-webmessenger",
|
||||||
"version": "1.0.4",
|
"version": "1.0.13",
|
||||||
"author": {
|
"author": {
|
||||||
"name": "LG CNS",
|
"name": "LG CNS",
|
||||||
"email": "lgucap@lgcns.com"
|
"email": "lgucap@lgcns.com"
|
||||||
|
@ -45,7 +45,7 @@
|
||||||
"@angular/core": "^8.2.14",
|
"@angular/core": "^8.2.14",
|
||||||
"auto-launch": "^5.0.5",
|
"auto-launch": "^5.0.5",
|
||||||
"electron-log": "^3.0.9",
|
"electron-log": "^3.0.9",
|
||||||
"electron-store": "^5.1.0",
|
"electron-store": "^5.1.1",
|
||||||
"electron-updater": "^4.2.0",
|
"electron-updater": "^4.2.0",
|
||||||
"electron-window-state": "^5.0.3",
|
"electron-window-state": "^5.0.3",
|
||||||
"file-type": "^14.1.2",
|
"file-type": "^14.1.2",
|
||||||
|
|
|
@ -192,6 +192,14 @@ export const decodeUrlInfoDaesang: APIDecoder<DaesangUrlInfoResponse> = (
|
||||||
url: arr.length > 1 ? arr[1] : arr[0]
|
url: arr.length > 1 ? arr[1] : arr[0]
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
if (!!res.WebLinkERP) {
|
||||||
|
const arr = res.WebLinkERP.split(',');
|
||||||
|
webLink.push({
|
||||||
|
key: WebLinkType.Erp,
|
||||||
|
title: arr.length > 1 ? arr[0] : '',
|
||||||
|
url: arr.length > 1 ? arr[1] : arr[0]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
statusCode: res.StatusCode,
|
statusCode: res.StatusCode,
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
import { HttpParameterCodec } from '@angular/common/http';
|
||||||
|
|
||||||
|
export class HttpUrlEncodingCodec implements HttpParameterCodec {
|
||||||
|
encodeKey(k: string): string {
|
||||||
|
return this.standardEncoding(k);
|
||||||
|
}
|
||||||
|
encodeValue(v: string): string {
|
||||||
|
return this.standardEncoding(v);
|
||||||
|
}
|
||||||
|
decodeKey(k: string): string {
|
||||||
|
return decodeURIComponent(k);
|
||||||
|
}
|
||||||
|
decodeValue(v: string) {
|
||||||
|
return decodeURIComponent(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
standardEncoding(v: string): string {
|
||||||
|
return encodeURIComponent(v);
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,6 +3,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export * from './lib/apis/api';
|
export * from './lib/apis/api';
|
||||||
|
export * from './lib/apis/httpUrlEncodingCodec';
|
||||||
|
|
||||||
export * from './lib/types/message-status-code.type';
|
export * from './lib/types/message-status-code.type';
|
||||||
export * from './lib/types/status-code.type';
|
export * from './lib/types/status-code.type';
|
||||||
|
|
|
@ -50,6 +50,7 @@ import { AppMessengerLayoutModule } from './layouts/messenger/messenger.layout.m
|
||||||
import { AppNativeLayoutModule } from './layouts/native/native.layout.module';
|
import { AppNativeLayoutModule } from './layouts/native/native.layout.module';
|
||||||
|
|
||||||
import { environment } from '../environments/environment';
|
import { environment } from '../environments/environment';
|
||||||
|
import { ERRORHANDLER } from './error-handler';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [
|
imports: [
|
||||||
|
@ -105,7 +106,7 @@ import { environment } from '../environments/environment';
|
||||||
level: NgxLoggerLevel.DEBUG
|
level: NgxLoggerLevel.DEBUG
|
||||||
})
|
})
|
||||||
],
|
],
|
||||||
providers: [...GUARDS],
|
providers: [...GUARDS, ERRORHANDLER],
|
||||||
declarations: [AppComponent],
|
declarations: [AppComponent],
|
||||||
bootstrap: [AppComponent],
|
bootstrap: [AppComponent],
|
||||||
entryComponents: []
|
entryComponents: []
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
import { ErrorHandler, Injectable, Injector, NgZone } from '@angular/core';
|
||||||
|
import { NativeService, UCAP_NATIVE_SERVICE } from '@ucap-webmessenger/native';
|
||||||
|
import { error } from 'console';
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root'
|
||||||
|
})
|
||||||
|
export class AppGlobalErrorhandler implements ErrorHandler {
|
||||||
|
constructor(private injector: Injector, private zone: NgZone) {}
|
||||||
|
|
||||||
|
// tslint:disable-next-line: no-shadowed-variable
|
||||||
|
handleError(error: Error) {
|
||||||
|
let nativeLogging: any;
|
||||||
|
try {
|
||||||
|
const nativeService: NativeService = this.injector.get(
|
||||||
|
UCAP_NATIVE_SERVICE
|
||||||
|
);
|
||||||
|
nativeService.appLogging(error.stack);
|
||||||
|
nativeLogging = 'SUCCESS';
|
||||||
|
} catch (e) {
|
||||||
|
nativeLogging = e;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.groupCollapsed('App Global Error Logging');
|
||||||
|
console.log('App log', error);
|
||||||
|
console.log('Native Logging', nativeLogging);
|
||||||
|
console.groupEnd();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
import { AppGlobalErrorhandler } from './global.errorhandler';
|
||||||
|
import { ErrorHandler } from '@angular/core';
|
||||||
|
|
||||||
|
export const ERRORHANDLER = [
|
||||||
|
{ provide: ErrorHandler, useClass: AppGlobalErrorhandler }
|
||||||
|
];
|
|
@ -49,7 +49,7 @@ export class AppAutoLoginGuard implements CanActivate {
|
||||||
|
|
||||||
if (
|
if (
|
||||||
!!appUserInfo &&
|
!!appUserInfo &&
|
||||||
appUserInfo.settings.general.autoLogin &&
|
!!appUserInfo.settings.general.autoLogin &&
|
||||||
!(!!personLogout && !!personLogout.personLogout)
|
!(!!personLogout && !!personLogout.personLogout)
|
||||||
) {
|
) {
|
||||||
this.store.dispatch(
|
this.store.dispatch(
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
<ucap-file-viewer
|
<ucap-file-viewer
|
||||||
[fileInfo]="fileInfo"
|
[fileInfo]="fileInfo"
|
||||||
[fileDownloadUrl]="fileDownloadUrl"
|
[fileDownloadUrl]="fileDownloadUrl"
|
||||||
|
[imageOnly]="imageOnly"
|
||||||
|
[imageOnlyData]="imageOnlyData"
|
||||||
(download)="onDownload($event)"
|
(download)="onDownload($event)"
|
||||||
|
(saveAs)="onSaveAs($event)"
|
||||||
(closed)="onClosedViewer()"
|
(closed)="onClosedViewer()"
|
||||||
></ucap-file-viewer>
|
></ucap-file-viewer>
|
||||||
|
|
|
@ -7,6 +7,9 @@ import { DeviceType } from '@ucap-webmessenger/core';
|
||||||
import { FileDownloadItem } from '@ucap-webmessenger/api';
|
import { FileDownloadItem } from '@ucap-webmessenger/api';
|
||||||
import { CommonApiService } from '@ucap-webmessenger/api-common';
|
import { CommonApiService } from '@ucap-webmessenger/api-common';
|
||||||
import { AppFileService } from '@app/services/file.service';
|
import { AppFileService } from '@app/services/file.service';
|
||||||
|
import { ImageOnlyDataInfo, SnackBarService } from '@ucap-webmessenger/ui';
|
||||||
|
import { UCAP_NATIVE_SERVICE, NativeService } from '@ucap-webmessenger/native';
|
||||||
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
|
|
||||||
export interface FileViewerDialogData {
|
export interface FileViewerDialogData {
|
||||||
fileInfo: FileEventJson;
|
fileInfo: FileEventJson;
|
||||||
|
@ -14,6 +17,8 @@ export interface FileViewerDialogData {
|
||||||
userSeq: number;
|
userSeq: number;
|
||||||
deviceType: DeviceType;
|
deviceType: DeviceType;
|
||||||
token: string;
|
token: string;
|
||||||
|
imageOnly?: boolean;
|
||||||
|
imageOnlyData?: ImageOnlyDataInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface FileViewerDialogResult {}
|
export interface FileViewerDialogResult {}
|
||||||
|
@ -32,6 +37,9 @@ export class FileViewerDialogComponent implements OnInit, OnDestroy {
|
||||||
|
|
||||||
fileDownloadUrl: string;
|
fileDownloadUrl: string;
|
||||||
|
|
||||||
|
imageOnly = false;
|
||||||
|
imageOnlyData: ImageOnlyDataInfo;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
public dialogRef: MatDialogRef<
|
public dialogRef: MatDialogRef<
|
||||||
FileViewerDialogData,
|
FileViewerDialogData,
|
||||||
|
@ -40,6 +48,9 @@ export class FileViewerDialogComponent implements OnInit, OnDestroy {
|
||||||
@Inject(MAT_DIALOG_DATA) public data: FileViewerDialogData,
|
@Inject(MAT_DIALOG_DATA) public data: FileViewerDialogData,
|
||||||
private commonApiService: CommonApiService,
|
private commonApiService: CommonApiService,
|
||||||
private appFileService: AppFileService,
|
private appFileService: AppFileService,
|
||||||
|
private translateService: TranslateService,
|
||||||
|
private snackBarService: SnackBarService,
|
||||||
|
@Inject(UCAP_NATIVE_SERVICE) private nativeService: NativeService,
|
||||||
private logger: NGXLogger
|
private logger: NGXLogger
|
||||||
) {
|
) {
|
||||||
this.fileInfo = data.fileInfo;
|
this.fileInfo = data.fileInfo;
|
||||||
|
@ -47,7 +58,17 @@ export class FileViewerDialogComponent implements OnInit, OnDestroy {
|
||||||
this.userSeq = data.userSeq;
|
this.userSeq = data.userSeq;
|
||||||
this.deviceType = data.deviceType;
|
this.deviceType = data.deviceType;
|
||||||
this.token = data.token;
|
this.token = data.token;
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
if (!!this.data.imageOnly) {
|
||||||
|
this.imageOnly = this.data.imageOnly;
|
||||||
|
this.imageOnlyData = this.data.imageOnlyData;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!!this.imageOnly) {
|
||||||
|
this.fileDownloadUrl = this.imageOnlyData.imageUrl;
|
||||||
|
} else {
|
||||||
this.fileDownloadUrl = this.commonApiService.urlForFileTalkDownload(
|
this.fileDownloadUrl = this.commonApiService.urlForFileTalkDownload(
|
||||||
{
|
{
|
||||||
userSeq: this.userSeq,
|
userSeq: this.userSeq,
|
||||||
|
@ -58,8 +79,7 @@ export class FileViewerDialogComponent implements OnInit, OnDestroy {
|
||||||
this.downloadUrl
|
this.downloadUrl
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
ngOnInit() {}
|
|
||||||
|
|
||||||
ngOnDestroy(): void {}
|
ngOnDestroy(): void {}
|
||||||
|
|
||||||
|
@ -76,6 +96,47 @@ export class FileViewerDialogComponent implements OnInit, OnDestroy {
|
||||||
fileDownloadUrl: this.downloadUrl
|
fileDownloadUrl: this.downloadUrl
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
onSaveAs(fileDownloadItem: FileDownloadItem): void {
|
||||||
|
this.nativeService
|
||||||
|
.selectSaveFilePath(this.fileInfo.fileName)
|
||||||
|
.then(result => {
|
||||||
|
if (!result) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result.canceled) {
|
||||||
|
// this.snackBarService.open(
|
||||||
|
// this.translateService.instant('common.file.results.canceled'),
|
||||||
|
// this.translateService.instant('common.file.errors.label'),
|
||||||
|
// {
|
||||||
|
// duration: 1000
|
||||||
|
// }
|
||||||
|
// );
|
||||||
|
} else {
|
||||||
|
this.saveFile(fileDownloadItem, result.filePath);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(reason => {
|
||||||
|
this.snackBarService.open(
|
||||||
|
this.translateService.instant('common.file.errors.failToSpecifyPath'),
|
||||||
|
this.translateService.instant('common.file.errors.label')
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
saveFile(fileDownloadItem: FileDownloadItem, savePath?: string) {
|
||||||
|
this.appFileService.fileTalkDownlod({
|
||||||
|
req: {
|
||||||
|
userSeq: this.userSeq,
|
||||||
|
deviceType: this.deviceType,
|
||||||
|
token: this.token,
|
||||||
|
attachmentsSeq: this.fileInfo.attachmentSeq,
|
||||||
|
fileDownloadItem
|
||||||
|
},
|
||||||
|
fileName: this.fileInfo.fileName,
|
||||||
|
savePath
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
onClosedViewer(): void {
|
onClosedViewer(): void {
|
||||||
this.dialogRef.close();
|
this.dialogRef.close();
|
||||||
|
|
|
@ -20,7 +20,8 @@ import { Subscription, combineLatest, Observable } from 'rxjs';
|
||||||
import {
|
import {
|
||||||
RoomInfo,
|
RoomInfo,
|
||||||
UserInfoShort,
|
UserInfoShort,
|
||||||
UserInfo as RoomUserInfo
|
UserInfo as RoomUserInfo,
|
||||||
|
RoomType
|
||||||
} from '@ucap-webmessenger/protocol-room';
|
} from '@ucap-webmessenger/protocol-room';
|
||||||
import * as AppStore from '@app/store';
|
import * as AppStore from '@app/store';
|
||||||
import * as ChatStore from '@app/store/messenger/chat';
|
import * as ChatStore from '@app/store/messenger/chat';
|
||||||
|
@ -288,11 +289,16 @@ export class ChatComponent implements OnInit, OnDestroy, AfterViewChecked {
|
||||||
value => roomInfo.roomSeq === value.roomSeq
|
value => roomInfo.roomSeq === value.roomSeq
|
||||||
);
|
);
|
||||||
if (-1 < i) {
|
if (-1 < i) {
|
||||||
|
if (roomInfo.roomType === RoomType.Single) {
|
||||||
|
// Ignore type of joinRoom for Single Room.
|
||||||
|
return this.roomUserShortList[i].userInfos;
|
||||||
|
} else {
|
||||||
return this.roomUserShortList[i].userInfos.filter(
|
return this.roomUserShortList[i].userInfos.filter(
|
||||||
user => user.isJoinRoom
|
user => user.isJoinRoom
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
|
@ -318,6 +318,7 @@ export class MessagesComponent implements OnInit, OnDestroy, AfterViewInit {
|
||||||
.pipe(select(AppStore.MessengerSelector.RoomSelector.selectUserinfolist))
|
.pipe(select(AppStore.MessengerSelector.RoomSelector.selectUserinfolist))
|
||||||
.subscribe(userInfoList => {
|
.subscribe(userInfoList => {
|
||||||
this.userInfoListSubject.next(userInfoList);
|
this.userInfoListSubject.next(userInfoList);
|
||||||
|
this.changeDetectorRef.detectChanges();
|
||||||
});
|
});
|
||||||
|
|
||||||
this.eventListProcessing$ = this.store.pipe(
|
this.eventListProcessing$ = this.store.pipe(
|
||||||
|
@ -1585,7 +1586,32 @@ export class MessagesComponent implements OnInit, OnDestroy, AfterViewInit {
|
||||||
break;
|
break;
|
||||||
case 'ADD_MEMBER':
|
case 'ADD_MEMBER':
|
||||||
{
|
{
|
||||||
const curRoomUser = this.userInfoListSubject.value.filter(
|
const userInfoList = this.userInfoListSubject.value;
|
||||||
|
if (
|
||||||
|
!!userInfoList &&
|
||||||
|
userInfoList.length >=
|
||||||
|
environment.productConfig.CommonSetting.maxChatRoomUser
|
||||||
|
) {
|
||||||
|
this.dialogService.open<
|
||||||
|
AlertDialogComponent,
|
||||||
|
AlertDialogData,
|
||||||
|
AlertDialogResult
|
||||||
|
>(AlertDialogComponent, {
|
||||||
|
data: {
|
||||||
|
title: this.translateService.instant('chat.errors.label'),
|
||||||
|
html: this.translateService.instant(
|
||||||
|
'chat.errors.maxCountOfRoomMemberWith',
|
||||||
|
{
|
||||||
|
maxCount:
|
||||||
|
environment.productConfig.CommonSetting.maxChatRoomUser
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const curRoomUser = userInfoList.filter(
|
||||||
user =>
|
user =>
|
||||||
user.seq !== this.loginResSubject.value.userSeq && user.isJoinRoom
|
user.seq !== this.loginResSubject.value.userSeq && user.isJoinRoom
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
<div fxLayout="column" class="rightDrawer-userlist">
|
<div fxLayout="column" class="rightDrawer-userlist">
|
||||||
<div class="search-list">
|
<div class="search-list">
|
||||||
<perfect-scrollbar class="room-user-scrollbar">
|
<cdk-virtual-scroll-viewport itemSize="60" perfectScrollbar fxFlexFill>
|
||||||
<ucap-profile-user-list-item
|
<ucap-profile-user-list-item
|
||||||
*ngFor="let userInfo of userInfoList"
|
*cdkVirtualFor="let userInfo of userInfoList"
|
||||||
[userInfo]="userInfo"
|
[userInfo]="userInfo"
|
||||||
[presence]="getStatusBulkInfo(userInfo) | async"
|
[presence]="getStatusBulkInfo(userInfo) | async"
|
||||||
[sessionVerinfo]="sessionVerinfo"
|
[sessionVerinfo]="sessionVerinfo"
|
||||||
|
@ -10,11 +10,9 @@
|
||||||
(openProfile)="onClickOpenProfile(userInfo.seq)"
|
(openProfile)="onClickOpenProfile(userInfo.seq)"
|
||||||
>
|
>
|
||||||
</ucap-profile-user-list-item>
|
</ucap-profile-user-list-item>
|
||||||
</perfect-scrollbar>
|
</cdk-virtual-scroll-viewport>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div class="btn-box">
|
||||||
class="btn-box"
|
|
||||||
>
|
|
||||||
<button mat-flat-button class="mat-primary" (click)="onClickAddMember()">
|
<button mat-flat-button class="mat-primary" (click)="onClickAddMember()">
|
||||||
{{ 'chat.addMemberToRoom' | translate }}
|
{{ 'chat.addMemberToRoom' | translate }}
|
||||||
</button>
|
</button>
|
||||||
|
|
|
@ -6,7 +6,7 @@ import {
|
||||||
EventEmitter,
|
EventEmitter,
|
||||||
ViewChild
|
ViewChild
|
||||||
} from '@angular/core';
|
} from '@angular/core';
|
||||||
import { Subscription } from 'rxjs';
|
import { Subscription, combineLatest } from 'rxjs';
|
||||||
import { Store, select } from '@ngrx/store';
|
import { Store, select } from '@ngrx/store';
|
||||||
import { tap, map, take } from 'rxjs/operators';
|
import { tap, map, take } from 'rxjs/operators';
|
||||||
|
|
||||||
|
@ -21,7 +21,10 @@ import {
|
||||||
DialogService,
|
DialogService,
|
||||||
ConfirmDialogComponent,
|
ConfirmDialogComponent,
|
||||||
ConfirmDialogResult,
|
ConfirmDialogResult,
|
||||||
ConfirmDialogData
|
ConfirmDialogData,
|
||||||
|
AlertDialogComponent,
|
||||||
|
AlertDialogData,
|
||||||
|
AlertDialogResult
|
||||||
} from '@ucap-webmessenger/ui';
|
} from '@ucap-webmessenger/ui';
|
||||||
import {
|
import {
|
||||||
SelectGroupDialogComponent,
|
SelectGroupDialogComponent,
|
||||||
|
@ -43,6 +46,7 @@ import { LoginResponse } from '@ucap-webmessenger/protocol-authentication';
|
||||||
import { MatDialog } from '@angular/material/dialog';
|
import { MatDialog } from '@angular/material/dialog';
|
||||||
import { MatMenuTrigger } from '@angular/material/menu';
|
import { MatMenuTrigger } from '@angular/material/menu';
|
||||||
import { TranslateService } from '@ngx-translate/core';
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
|
import { environment } from 'projects/ucap-webmessenger-app/src/environments/environment.dev';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-layout-chat-right-drawer-room-user-list',
|
selector: 'app-layout-chat-right-drawer-room-user-list',
|
||||||
|
@ -82,16 +86,22 @@ export class RoomUserListComponent implements OnInit, OnDestroy {
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.userInfoListSubscription = this.store
|
this.userInfoListSubscription = combineLatest([
|
||||||
.pipe(
|
this.store.pipe(
|
||||||
select(AppStore.MessengerSelector.RoomSelector.selectUserinfolist),
|
select(AppStore.MessengerSelector.RoomSelector.selectUserinfolist)
|
||||||
tap(userInfoList => {
|
),
|
||||||
|
this.store.pipe(select(AppStore.MessengerSelector.RoomSelector.roomInfo))
|
||||||
|
]).subscribe(([userInfoList, roomInfo]) => {
|
||||||
this.userInfoList = userInfoList
|
this.userInfoList = userInfoList
|
||||||
.filter(userInfo => userInfo.isJoinRoom === true)
|
.filter(userInfo => {
|
||||||
.sort((a, b) => (a.name < b.name ? -1 : a.name > b.name ? 1 : 0));
|
if (roomInfo.roomType === RoomType.Single) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return userInfo.isJoinRoom === true;
|
||||||
|
}
|
||||||
})
|
})
|
||||||
)
|
.sort((a, b) => (a.name < b.name ? -1 : a.name > b.name ? 1 : 0));
|
||||||
.subscribe();
|
});
|
||||||
|
|
||||||
this.roomInfoSubscription = this.store
|
this.roomInfoSubscription = this.store
|
||||||
.pipe(
|
.pipe(
|
||||||
|
@ -139,6 +149,29 @@ export class RoomUserListComponent implements OnInit, OnDestroy {
|
||||||
}
|
}
|
||||||
|
|
||||||
async onClickAddMember() {
|
async onClickAddMember() {
|
||||||
|
if (
|
||||||
|
!!this.userInfoList &&
|
||||||
|
this.userInfoList.length >=
|
||||||
|
environment.productConfig.CommonSetting.maxChatRoomUser
|
||||||
|
) {
|
||||||
|
this.dialogService.open<
|
||||||
|
AlertDialogComponent,
|
||||||
|
AlertDialogData,
|
||||||
|
AlertDialogResult
|
||||||
|
>(AlertDialogComponent, {
|
||||||
|
data: {
|
||||||
|
title: this.translateService.instant('chat.errors.label'),
|
||||||
|
html: this.translateService.instant(
|
||||||
|
'chat.errors.maxCountOfRoomMemberWith',
|
||||||
|
{
|
||||||
|
maxCount: environment.productConfig.CommonSetting.maxChatRoomUser
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const curRoomUser = this.userInfoList.filter(
|
const curRoomUser = this.userInfoList.filter(
|
||||||
user => user.seq !== this.loginRes.userSeq && user.isJoinRoom
|
user => user.seq !== this.loginRes.userSeq && user.isJoinRoom
|
||||||
);
|
);
|
||||||
|
|
|
@ -255,15 +255,55 @@
|
||||||
[selected]="getChipsRemoveYn(userInfo)"
|
[selected]="getChipsRemoveYn(userInfo)"
|
||||||
(removed)="onClickDeleteUser(userInfo)"
|
(removed)="onClickDeleteUser(userInfo)"
|
||||||
>
|
>
|
||||||
{{ userInfo.name }}
|
{{ userInfo | ucapTranslate: 'name' }}
|
||||||
<mat-icon matChipRemove *ngIf="getChipsRemoveYn(userInfo)"
|
<mat-icon matChipRemove *ngIf="getChipsRemoveYn(userInfo)"
|
||||||
>clear</mat-icon
|
>clear</mat-icon
|
||||||
>
|
>
|
||||||
</mat-chip>
|
</mat-chip>
|
||||||
</mat-chip-list>
|
</mat-chip-list>
|
||||||
</div>
|
</div>
|
||||||
|
<ng-container
|
||||||
|
*ngIf="
|
||||||
|
data.type === UserSelectDialogType.NewChat;
|
||||||
|
then newchatcount;
|
||||||
|
else defaultcount
|
||||||
|
"
|
||||||
|
></ng-container>
|
||||||
|
<ng-template #newchatcount>
|
||||||
|
<span
|
||||||
|
[ngClass]="
|
||||||
|
selectedUserList.length >=
|
||||||
|
environment.productConfig.CommonSetting.maxChatRoomUser
|
||||||
|
? 'text-warn-color'
|
||||||
|
: ''
|
||||||
|
"
|
||||||
|
>
|
||||||
|
{{ selectedUserList.length }} /
|
||||||
|
{{ environment.productConfig.CommonSetting.maxChatRoomUser - 1 }}
|
||||||
|
{{ 'common.units.persons' | translate }}
|
||||||
|
</span>
|
||||||
|
<span
|
||||||
|
class="text-warn-color"
|
||||||
|
style="float: right;"
|
||||||
|
*ngIf="
|
||||||
|
selectedUserList.length >=
|
||||||
|
environment.productConfig.CommonSetting.maxChatRoomUser
|
||||||
|
"
|
||||||
|
>
|
||||||
|
({{
|
||||||
|
'chat.errors.maxCountOfRoomMemberWith'
|
||||||
|
| translate
|
||||||
|
: {
|
||||||
|
maxCount:
|
||||||
|
environment.productConfig.CommonSetting.maxChatRoomUser - 1
|
||||||
|
}
|
||||||
|
}})
|
||||||
|
</span>
|
||||||
|
</ng-template>
|
||||||
|
<ng-template #defaultcount>
|
||||||
<span>
|
<span>
|
||||||
{{ selectedUserList.length }}
|
{{ selectedUserList.length }}
|
||||||
{{ 'common.units.persons' | translate }}
|
{{ 'common.units.persons' | translate }}
|
||||||
</span>
|
</span>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
|
</ng-template>
|
||||||
|
|
|
@ -134,6 +134,7 @@ export class CreateChatDialogComponent implements OnInit, OnDestroy {
|
||||||
currentTabIndex: number;
|
currentTabIndex: number;
|
||||||
|
|
||||||
UserSelectDialogType = UserSelectDialogType;
|
UserSelectDialogType = UserSelectDialogType;
|
||||||
|
environment = environment;
|
||||||
|
|
||||||
loginRes: LoginResponse;
|
loginRes: LoginResponse;
|
||||||
loginResSubscription: Subscription;
|
loginResSubscription: Subscription;
|
||||||
|
@ -740,8 +741,12 @@ export class CreateChatDialogComponent implements OnInit, OnDestroy {
|
||||||
if (this.selectedUserList.length === 0 && !this.selectedRoom) {
|
if (this.selectedUserList.length === 0 && !this.selectedRoom) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
} else if (this.data.type === UserSelectDialogType.NewChat) {
|
||||||
|
return (
|
||||||
|
this.selectedUserList.length >=
|
||||||
|
this.environment.productConfig.CommonSetting.maxChatRoomUser
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,9 @@
|
||||||
[openProfileOptions]="data.openProfileOptions"
|
[openProfileOptions]="data.openProfileOptions"
|
||||||
[useBuddyToggleButton]="useBuddyToggleButton"
|
[useBuddyToggleButton]="useBuddyToggleButton"
|
||||||
[authInfo]="authInfo"
|
[authInfo]="authInfo"
|
||||||
|
[enableElephantButton]="getEnableElephantButton()"
|
||||||
|
(profileImageView)="onClickProfileImageView()"
|
||||||
|
(sendElephant)="onClickSendElephant()"
|
||||||
(openChat)="onClickChat($event)"
|
(openChat)="onClickChat($event)"
|
||||||
(sendMessage)="onClickSendMessage($event)"
|
(sendMessage)="onClickSendMessage($event)"
|
||||||
(sendCall)="onClickSendClickToCall($event)"
|
(sendCall)="onClickSendClickToCall($event)"
|
||||||
|
|
|
@ -4,9 +4,13 @@ import {
|
||||||
KEY_LOGIN_RES_INFO,
|
KEY_LOGIN_RES_INFO,
|
||||||
KEY_VER_INFO,
|
KEY_VER_INFO,
|
||||||
KEY_AUTH_INFO,
|
KEY_AUTH_INFO,
|
||||||
MainMenu
|
MainMenu,
|
||||||
|
KEY_URL_INFO
|
||||||
} from '@app/types';
|
} from '@app/types';
|
||||||
import { SessionStorageService } from '@ucap-webmessenger/web-storage';
|
import {
|
||||||
|
SessionStorageService,
|
||||||
|
LocalStorageService
|
||||||
|
} from '@ucap-webmessenger/web-storage';
|
||||||
|
|
||||||
import { Store, select } from '@ngrx/store';
|
import { Store, select } from '@ngrx/store';
|
||||||
import * as AppStore from '@app/store';
|
import * as AppStore from '@app/store';
|
||||||
|
@ -30,7 +34,8 @@ import {
|
||||||
SnackBarService,
|
SnackBarService,
|
||||||
AlertDialogComponent,
|
AlertDialogComponent,
|
||||||
AlertDialogResult,
|
AlertDialogResult,
|
||||||
AlertDialogData
|
AlertDialogData,
|
||||||
|
ImageOnlyDataInfo
|
||||||
} from '@ucap-webmessenger/ui';
|
} from '@ucap-webmessenger/ui';
|
||||||
import { VersionInfo2Response } from '@ucap-webmessenger/api-public';
|
import { VersionInfo2Response } from '@ucap-webmessenger/api-public';
|
||||||
import { LoginResponse } from '@ucap-webmessenger/protocol-authentication';
|
import { LoginResponse } from '@ucap-webmessenger/protocol-authentication';
|
||||||
|
@ -57,11 +62,20 @@ import {
|
||||||
ConferenceService
|
ConferenceService
|
||||||
} from '@ucap-webmessenger/api-prompt';
|
} from '@ucap-webmessenger/api-prompt';
|
||||||
import { NGXLogger } from 'ngx-logger';
|
import { NGXLogger } from 'ngx-logger';
|
||||||
import { SmsUtils } from '@ucap-webmessenger/daesang';
|
import { SmsUtils, WebLinkType } from '@ucap-webmessenger/daesang';
|
||||||
import { NativeService, UCAP_NATIVE_SERVICE } from '@ucap-webmessenger/native';
|
import { NativeService, UCAP_NATIVE_SERVICE } from '@ucap-webmessenger/native';
|
||||||
import { environment } from '../../../../../environments/environment';
|
import { environment } from '../../../../../environments/environment';
|
||||||
import { TranslateService } from '@ngx-translate/core';
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
import { UserInfoUpdateType } from '@ucap-webmessenger/protocol-info';
|
import { UserInfoUpdateType } from '@ucap-webmessenger/protocol-info';
|
||||||
|
import {
|
||||||
|
FileViewerDialogComponent,
|
||||||
|
FileViewerDialogData,
|
||||||
|
FileViewerDialogResult
|
||||||
|
} from '@app/layouts/common/dialogs/file-viewer.dialog.component';
|
||||||
|
import { FileEventJson } from '@ucap-webmessenger/protocol-event';
|
||||||
|
import { FileType } from '@ucap-webmessenger/protocol-file';
|
||||||
|
import { DaesangUrlInfoResponse } from '@ucap-webmessenger/api-external';
|
||||||
|
import { AppUserInfo, KEY_APP_USER_INFO } from '@app/types/app-user-info.type';
|
||||||
|
|
||||||
export interface ProfileDialogData {
|
export interface ProfileDialogData {
|
||||||
userInfo: UserInfo | UserInfoSS | UserInfoF | UserInfoDN;
|
userInfo: UserInfo | UserInfoSS | UserInfoF | UserInfoDN;
|
||||||
|
@ -99,6 +113,7 @@ export class ProfileDialogComponent implements OnInit, OnDestroy {
|
||||||
@Inject(UCAP_NATIVE_SERVICE) private nativeService: NativeService,
|
@Inject(UCAP_NATIVE_SERVICE) private nativeService: NativeService,
|
||||||
@Inject(MAT_DIALOG_DATA) public data: ProfileDialogData,
|
@Inject(MAT_DIALOG_DATA) public data: ProfileDialogData,
|
||||||
private dialogService: DialogService,
|
private dialogService: DialogService,
|
||||||
|
private localStorageService: LocalStorageService,
|
||||||
private sessionStorageService: SessionStorageService,
|
private sessionStorageService: SessionStorageService,
|
||||||
private commonApiService: CommonApiService,
|
private commonApiService: CommonApiService,
|
||||||
private conferenceService: ConferenceService,
|
private conferenceService: ConferenceService,
|
||||||
|
@ -464,6 +479,93 @@ export class ProfileDialogComponent implements OnInit, OnDestroy {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onClickProfileImageView() {
|
||||||
|
if (!this.loginRes || !this.loginRes.userInfo.profileImageFile) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const imageOnlyData: ImageOnlyDataInfo = {
|
||||||
|
imageUrl: this.userInfo.profileImageFile,
|
||||||
|
imageRootUrl: this.sessionVerinfo.profileRoot,
|
||||||
|
defaultImage: 'assets/images/no_image.png',
|
||||||
|
fileName: this.userInfo.name
|
||||||
|
};
|
||||||
|
|
||||||
|
this.dialogService.open<
|
||||||
|
FileViewerDialogComponent,
|
||||||
|
FileViewerDialogData,
|
||||||
|
FileViewerDialogResult
|
||||||
|
>(FileViewerDialogComponent, {
|
||||||
|
position: {
|
||||||
|
top: '50px'
|
||||||
|
},
|
||||||
|
maxWidth: '100vw',
|
||||||
|
maxHeight: '100vh',
|
||||||
|
height: 'calc(100% - 50px)',
|
||||||
|
width: '100%',
|
||||||
|
panelClass: 'app-dialog-full',
|
||||||
|
data: {
|
||||||
|
imageOnly: true,
|
||||||
|
imageOnlyData,
|
||||||
|
fileInfo: {},
|
||||||
|
downloadUrl: this.sessionVerinfo.downloadUrl,
|
||||||
|
deviceType: this.environmentsInfo.deviceType,
|
||||||
|
token: this.loginRes.tokenString,
|
||||||
|
userSeq: this.loginRes.userSeq
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
getEnableElephantButton() {
|
||||||
|
if (!this.loginRes) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const myEmployeeNum = this.loginRes.userInfo.employeeNum;
|
||||||
|
const profEmployeeNum = this.userInfo.employeeNum;
|
||||||
|
const trgtEmployeeCode = '10'; // only 10
|
||||||
|
if (
|
||||||
|
!this.isMe &&
|
||||||
|
!!myEmployeeNum &&
|
||||||
|
!!profEmployeeNum &&
|
||||||
|
myEmployeeNum.slice(0, 2) === trgtEmployeeCode &&
|
||||||
|
profEmployeeNum.slice(0, 2) === trgtEmployeeCode
|
||||||
|
) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
onClickSendElephant() {
|
||||||
|
const urlInfo: DaesangUrlInfoResponse = this.sessionStorageService.get<
|
||||||
|
DaesangUrlInfoResponse
|
||||||
|
>(KEY_URL_INFO);
|
||||||
|
|
||||||
|
if (!!urlInfo && !!urlInfo.webLink) {
|
||||||
|
const links = urlInfo.webLink.filter(
|
||||||
|
link => link.key === WebLinkType.Elephant
|
||||||
|
);
|
||||||
|
if (!!links && links.length > 0) {
|
||||||
|
const appUserInfo = this.localStorageService.encGet<AppUserInfo>(
|
||||||
|
KEY_APP_USER_INFO,
|
||||||
|
environment.customConfig.appKey
|
||||||
|
);
|
||||||
|
|
||||||
|
let elephantUrl = links[0].url
|
||||||
|
.replace(
|
||||||
|
/(\(%USER_PASS%\))/g,
|
||||||
|
encodeURIComponent(appUserInfo.loginPw)
|
||||||
|
) // exchange USER_PASS params
|
||||||
|
.replace('kind%3D3', 'kind%3D2'); // change value of 'kind'
|
||||||
|
elephantUrl += '%26empno%3D' + this.userInfo.employeeNum + ','; // add parameter of 'empno'
|
||||||
|
|
||||||
|
console.log(elephantUrl);
|
||||||
|
|
||||||
|
this.nativeService.openDefaultBrowser(elephantUrl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
onUpdateIntro(intro: string) {
|
onUpdateIntro(intro: string) {
|
||||||
this.store.dispatch(
|
this.store.dispatch(
|
||||||
AuthenticationStore.infoUser({
|
AuthenticationStore.infoUser({
|
||||||
|
|
|
@ -124,13 +124,6 @@
|
||||||
</div>
|
</div>
|
||||||
</mat-card-content>
|
</mat-card-content>
|
||||||
<mat-card-actions class="button-form flex-row">
|
<mat-card-actions class="button-form flex-row">
|
||||||
<!-- <button
|
|
||||||
mat-stroked-button
|
|
||||||
(click)="onClickClearSettingAndLogout()"
|
|
||||||
class="mat-primary"
|
|
||||||
>
|
|
||||||
Clear Setting & Logout
|
|
||||||
</button> -->
|
|
||||||
<button
|
<button
|
||||||
mat-stroked-button
|
mat-stroked-button
|
||||||
(click)="onClickChoice(false)"
|
(click)="onClickChoice(false)"
|
||||||
|
|
|
@ -1,20 +1,12 @@
|
||||||
import { Component, OnInit, Inject, Renderer2, OnDestroy } from '@angular/core';
|
import { Component, OnInit, Inject, Renderer2, OnDestroy } from '@angular/core';
|
||||||
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
|
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
|
||||||
import {
|
import { KEY_LOGIN_RES_INFO, KEY_VER_INFO } from '@app/types';
|
||||||
KEY_LOGIN_RES_INFO,
|
|
||||||
KEY_VER_INFO,
|
|
||||||
KEY_LOGIN_INFO,
|
|
||||||
KEY_URL_INFO,
|
|
||||||
KEY_AUTH_INFO,
|
|
||||||
KEY_LOGOUT_INFO
|
|
||||||
} from '@app/types';
|
|
||||||
import {
|
import {
|
||||||
SessionStorageService,
|
SessionStorageService,
|
||||||
LocalStorageService
|
LocalStorageService
|
||||||
} from '@ucap-webmessenger/web-storage';
|
} from '@ucap-webmessenger/web-storage';
|
||||||
|
|
||||||
import { Store } from '@ngrx/store';
|
import { Store } from '@ngrx/store';
|
||||||
import * as AuthenticationStore from '@app/store/account/authentication';
|
|
||||||
|
|
||||||
import clone from 'clone';
|
import clone from 'clone';
|
||||||
|
|
||||||
|
@ -210,17 +202,4 @@ export class MessengerSettingsDialogComponent implements OnInit, OnDestroy {
|
||||||
|
|
||||||
return modSettings;
|
return modSettings;
|
||||||
}
|
}
|
||||||
|
|
||||||
onClickClearSettingAndLogout() {
|
|
||||||
this.localStorageService.remove(KEY_APP_USER_INFO);
|
|
||||||
this.sessionStorageService.remove(KEY_LOGIN_RES_INFO);
|
|
||||||
this.sessionStorageService.remove(KEY_VER_INFO);
|
|
||||||
this.sessionStorageService.remove(KEY_LOGIN_INFO);
|
|
||||||
this.sessionStorageService.remove(KEY_URL_INFO);
|
|
||||||
this.sessionStorageService.remove(KEY_AUTH_INFO);
|
|
||||||
this.sessionStorageService.remove(KEY_LOGOUT_INFO);
|
|
||||||
this.nativeService.clearAppStorage();
|
|
||||||
this.dialogService.closeAll();
|
|
||||||
this.store.dispatch(AuthenticationStore.loginRedirect());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -103,6 +103,15 @@
|
||||||
>
|
>
|
||||||
<span class="weblink Personal-news">NEWS</span>
|
<span class="weblink Personal-news">NEWS</span>
|
||||||
</button>
|
</button>
|
||||||
|
<button
|
||||||
|
mat-icon-button
|
||||||
|
*ngSwitchCase="WebLinkType.Erp"
|
||||||
|
class="button"
|
||||||
|
[matTooltip]="link.title"
|
||||||
|
(click)="onClickWebLink(link)"
|
||||||
|
>
|
||||||
|
<span class="weblink erp">ERP</span>
|
||||||
|
</button>
|
||||||
<button
|
<button
|
||||||
mat-icon-button
|
mat-icon-button
|
||||||
*ngSwitchCase="WebLinkType.Mail"
|
*ngSwitchCase="WebLinkType.Mail"
|
||||||
|
@ -447,10 +456,13 @@
|
||||||
</mat-menu>
|
</mat-menu>
|
||||||
|
|
||||||
<mat-menu #informationMenu="matMenu">
|
<mat-menu #informationMenu="matMenu">
|
||||||
<ng-template matMenuContent>
|
<ng-template matMenuContent let-isShowClearBtn="false">
|
||||||
<div class="version-info-container menu-item">
|
<div class="version-info-container menu-item">
|
||||||
<div class="version-info-now" (click)="$event.stopPropagation()">
|
<div class="version-info-now" (click)="$event.stopPropagation()">
|
||||||
<span class="version-info-item">
|
<span
|
||||||
|
class="version-info-item"
|
||||||
|
(auxclick)="isShowClearBtn = !isShowClearBtn"
|
||||||
|
>
|
||||||
{{ 'information.installedVersion' | translate }}:<span
|
{{ 'information.installedVersion' | translate }}:<span
|
||||||
class="info-content"
|
class="info-content"
|
||||||
>{{ appVersion }}</span
|
>{{ appVersion }}</span
|
||||||
|
@ -491,5 +503,14 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div *ngIf="isShowClearBtn" class="version-info-container menu-item">
|
||||||
|
<button
|
||||||
|
mat-flat-button
|
||||||
|
class="mat-primary"
|
||||||
|
(click)="onClickClearSettingAndLogout($event)"
|
||||||
|
>
|
||||||
|
Clear setting & Logout
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
</mat-menu>
|
</mat-menu>
|
||||||
|
|
|
@ -95,7 +95,8 @@
|
||||||
&.dsp {
|
&.dsp {
|
||||||
text-indent: 0;
|
text-indent: 0;
|
||||||
}
|
}
|
||||||
&.sms {
|
&.sms,
|
||||||
|
&.erp {
|
||||||
text-indent: 0;
|
text-indent: 0;
|
||||||
letter-spacing: -1px;
|
letter-spacing: -1px;
|
||||||
}
|
}
|
||||||
|
@ -110,6 +111,9 @@
|
||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
letter-spacing: -1px;
|
letter-spacing: -1px;
|
||||||
}
|
}
|
||||||
|
&.elephant {
|
||||||
|
background-position: 50% 90%;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&.app-layout-native-title-bar-logout,
|
&.app-layout-native-title-bar-logout,
|
||||||
|
@ -212,7 +216,7 @@
|
||||||
background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='20' viewBox='0 0 24 24' fill='none' stroke='#{$color}' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' class='feather feather-video'%3E%3Cpolygon points='23 7 16 12 23 17 23 7'%3E%3C/polygon%3E%3Crect x='1' y='5' width='15' height='14' rx='2' ry='2'%3E%3C/rect%3E%3C/svg%3E");
|
background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='20' viewBox='0 0 24 24' fill='none' stroke='#{$color}' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' class='feather feather-video'%3E%3Cpolygon points='23 7 16 12 23 17 23 7'%3E%3C/polygon%3E%3Crect x='1' y='5' width='15' height='14' rx='2' ry='2'%3E%3C/rect%3E%3C/svg%3E");
|
||||||
}
|
}
|
||||||
.elephant {
|
.elephant {
|
||||||
background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='20' viewBox='0 0 24 24' fill='#{$color}' stroke='none' xml:space='preserve'%3E%3Cpath d='M19.1,5c-1,0-2,0.4-2.7,1.1c-1.2-1-2.9-1.5-4.7-1.5c-1.7,0-3.3,0.5-4.5,1.4C6.6,5.3,5.7,5,4.8,5C2.6,5,0.9,6.7,0.9,8.8 c0,1.1,1.1,4.6,2.7,5.7c0.3,0.2,0.7,0.3,1.1,0.3c0.2,0,0.4,0,0.6-0.1c0.5-0.2,0.9-0.4,1.3-0.6c0.6,0.6,1.3,1,2.1,1.4l0.8,1.2 c0.3,0.5,0.5,1.1,0.6,1.7H9.2c-0.7,0-1.2,0.6-1.2,1.2s0.6,1.2,1.2,1.2h0.4c2.5,0,4.6-1.7,5.2-4.1l0.4-1.4c0.7-0.4,1.4-0.8,1.9-1.3 c0.4,0.3,0.9,0.5,1.5,0.8c0.2,0.1,0.4,0.1,0.6,0.1c0.4,0,0.7-0.1,1.1-0.3c1.6-1.1,2.7-4.6,2.7-5.7C22.9,6.7,21.2,5,19.1,5z M5,14.1 c-0.3,0.1-0.7,0.1-1-0.2C2.7,13,1.7,9.8,1.7,8.8c0-1.7,1.4-3.1,3.1-3.1c0.7,0,1.4,0.3,2,0.7C6.4,6.8,6.1,7.1,5.8,7.5 C5.5,7.3,5.1,7.2,4.8,7.2c-1.2,0-2.1,1-2.1,2.1c0,0.6,0.6,2.5,1.5,3.1c0.2,0.1,0.4,0.2,0.6,0.2c0.1,0,0.3,0,0.4-0.1 c0.1,0,0.2-0.1,0.3-0.1c0.2,0.4,0.4,0.8,0.7,1.1C5.8,13.8,5.4,13.9,5,14.1z M5.1,11.8c-0.1,0-0.2,0.1-0.3,0.1 c-0.1,0-0.2,0.1-0.4-0.1c-0.6-0.4-1.2-2-1.2-2.5c0-0.8,0.6-1.4,1.4-1.4C5,7.9,5.2,8,5.4,8.1c-0.3,0.7-0.5,1.4-0.5,2.2 C4.9,10.8,5,11.3,5.1,11.8z M14.7,14.8c-0.1,0-0.2,0.1-0.2,0.2l-0.4,1.6c-0.5,2.1-2.4,3.5-4.5,3.5H9.2c-0.3,0-0.5-0.2-0.5-0.5 c0-0.3,0.2-0.5,0.5-0.5h1.1c0.3,0,0.5-0.2,0.5-0.5c0-0.8-0.2-1.6-0.7-2.3L9.3,15c0-0.1-0.1-0.1-0.2-0.1c-0.8-0.3-1.5-0.8-2.1-1.3 c0,0,0-0.1-0.1-0.1c0,0-0.1-0.1-0.1-0.1c-0.4-0.4-0.7-0.9-0.9-1.4c0,0,0-0.1,0-0.1c-0.2-0.5-0.3-1-0.3-1.5c0-2.8,2.7-5,6.1-5 s6.1,2.3,6.1,5C17.9,12.2,16.7,13.9,14.7,14.8z M18.2,8.3c0.3-0.2,0.6-0.4,0.9-0.4c0.8,0,1.4,0.6,1.4,1.4c0,0.5-0.5,2.1-1.2,2.5 C19.2,12,19.1,12,19,11.9c-0.2-0.1-0.4-0.2-0.6-0.3c0.1-0.4,0.2-0.9,0.2-1.3C18.6,9.6,18.5,8.9,18.2,8.3z M19.8,13.9 c-0.3,0.2-0.7,0.3-1,0.2c-0.5-0.2-0.9-0.4-1.3-0.7c0.3-0.3,0.5-0.7,0.7-1.1c0.2,0.1,0.4,0.2,0.6,0.3c0.1,0.1,0.3,0.1,0.4,0.1 c0.2,0,0.4-0.1,0.6-0.2c0.9-0.6,1.5-2.5,1.5-3.1c0-1.2-1-2.1-2.1-2.1c-0.5,0-0.9,0.2-1.3,0.4c-0.2-0.4-0.5-0.7-0.9-1.1 c0.6-0.6,1.3-0.9,2.1-0.9c1.7,0,3.1,1.4,3.1,3.1C22.2,9.8,21.1,13,19.8,13.9z'/%3E%3Cpath d='M11.5,16.5h1c0.3,0,0.5-0.2,0.5-0.5s-0.2-0.5-0.5-0.5h-1c-0.3,0-0.5,0.2-0.5,0.5S11.2,16.5,11.5,16.5z'/%3E%3Cpath d='M13,17.6H11c-0.3,0-0.5,0.2-0.5,0.5s0.2,0.5,0.5,0.5H13c0.3,0,0.5-0.2,0.5-0.5S13.3,17.6,13,17.6z'/%3E%3Cpath d='M17,12.4c0,0.5-0.4,0.8-0.8,0.8c-0.5,0-0.8-0.4-0.8-0.8s0.4-0.8,0.8-0.8C16.7,11.6,17,12,17,12.4z'/%3E%3Cpath d='M8.5,12.4c0,0.5-0.4,0.8-0.8,0.8c-0.5,0-0.8-0.4-0.8-0.8s0.4-0.8,0.8-0.8C8.1,11.6,8.5,12,8.5,12.4z'/%3E%3C/svg%3E");
|
background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='20' viewBox='0 0 24 24' fill='none' stroke='#{$color}' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' %3E%3Ctitle%3Eelephant%3C/title%3E%3Cpath d='M24,14a17.76,17.76,0,0,0-.54-3.76c-.09-.34-.18-.65-.27-.91s-.08-.23-.13-.35-.09-.23-.14-.34a10.08,10.08,0,0,0-.69-1.3A10.22,10.22,0,0,0,20.86,5.6c-.17-.17-.35-.33-.53-.49l-.57-.46a9.45,9.45,0,0,0-1.56-.93,2.52,2.52,0,0,0-.34-.15,7.07,7.07,0,0,0-.69-.27A9.49,9.49,0,0,0,4.81,10.89V11s0,.06,0,.09h0a.36.36,0,0,1,0,.1h0s0,.06,0,.09h0l0,.08h0l0,.07h0l0,0h0l0,0h0l0,0A1.18,1.18,0,0,1,4,11a1.56,1.56,0,0,1-.11-1A3.62,3.62,0,0,1,4.24,9L1,7.57H1A5.89,5.89,0,0,0,.25,9.09c0,.13-.07.26-.1.39A5.12,5.12,0,0,0,0,10.56,4.3,4.3,0,0,0,.67,13l.22.32,0,.07.23.28,0,0a2.61,2.61,0,0,0,.23.24l.05.05.25.22,0,0,.23.17.06,0,.25.16,0,0a1.27,1.27,0,0,0,.23.12l0,0,.25.11.05,0,.22.09h.05l.24.07.05,0,.21.05h0l.22,0H4l.2,0h0l.2,0h.8l.11.37c.07.17.13.33.2.49l.23.48a9.69,9.69,0,0,0,.82,1.29l.33.42.33.37A10,10,0,0,0,8.49,19.8c.22.17.46.34.7.49a11.25,11.25,0,0,0,1.53.82.48.48,0,0,0,.14.05H11l.11,0h0l.09,0h0A.16.16,0,0,0,11.3,21v0a.2.2,0,0,0,0-.08v0a.29.29,0,0,0,0-.09h0s0,0,0-.08h0v0h0v-.88a2.87,2.87,0,0,1,2.87-2.86h0a3,3,0,0,1,.85.12l.26.1a2.62,2.62,0,0,1,.49.27l.22.16a2.85,2.85,0,0,1,1,2.21v.68h0v.37l0,.06h0a.1.1,0,0,0,0,.05v0l0,0v0l0,0,0,0h.19l.08,0a9.24,9.24,0,0,0,1.41-.7,7.83,7.83,0,0,0,.67-.45,7,7,0,0,0,.92-.8,2.61,2.61,0,0,0,.27-.3,4.94,4.94,0,0,0,.49-.64l.22-.35a5.07,5.07,0,0,0,.34-.75c.05-.13.09-.26.13-.4l.13.55a2,2,0,0,1,0,.24v.07l0,.16v.08l0,.16V18l0,.17v0c0,.06,0,.11,0,.17v.06s0,.08,0,.12v.06s0,.08,0,.11v.05l0,.14v0l0,.1v0a.14.14,0,0,1,0,.06l0,0a.08.08,0,0,0,0,.05l0,0s0,0,0,0h.07l0,0h0l.05-.05,0,0a.86.86,0,0,0,.07-.1A8.15,8.15,0,0,0,24,15Q24,14.5,24,14ZM9,9.07A.73.73,0,0,1,9,7.61.73.73,0,1,1,9,9.07Zm8,4.28a3.66,3.66,0,0,1-2.35,1.28,1.88,1.88,0,0,1-1.41-.72A5.81,5.81,0,0,1,12,10.21c.05-.9.54-3.07,4-3.77a2.18,2.18,0,0,1,.44,0h0a2.46,2.46,0,0,1,2.21,1.75C19.21,9.79,18.59,11.73,17,13.35Z' transform='translate(0 -2.82)' style='fill:%23fff'/%3E%3C/svg%3E");
|
||||||
}
|
}
|
||||||
.mail {
|
.mail {
|
||||||
background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='20' viewBox='0 0 24 24' fill='none' stroke='#{$color}' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' %3E%3Cpath d='M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z'%3E%3C/path%3E%3Cpolyline points='22,6 12,13 2,6'%3E%3C/polyline%3E%3C/svg%3E");
|
background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='20' viewBox='0 0 24 24' fill='none' stroke='#{$color}' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' %3E%3Cpath d='M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z'%3E%3C/path%3E%3Cpolyline points='22,6 12,13 2,6'%3E%3C/polyline%3E%3C/svg%3E");
|
||||||
|
|
|
@ -34,7 +34,10 @@ import {
|
||||||
KEY_LOGIN_INFO,
|
KEY_LOGIN_INFO,
|
||||||
KEY_VER_INFO,
|
KEY_VER_INFO,
|
||||||
EnvironmentsInfo,
|
EnvironmentsInfo,
|
||||||
KEY_ENVIRONMENTS_INFO
|
KEY_ENVIRONMENTS_INFO,
|
||||||
|
KEY_LOGIN_RES_INFO,
|
||||||
|
KEY_LOGOUT_INFO,
|
||||||
|
KEY_AUTH_INFO
|
||||||
} from '@app/types';
|
} from '@app/types';
|
||||||
import {
|
import {
|
||||||
WebLink,
|
WebLink,
|
||||||
|
@ -62,7 +65,12 @@ import {
|
||||||
ProfileDialogResult,
|
ProfileDialogResult,
|
||||||
ProfileDialogData
|
ProfileDialogData
|
||||||
} from '@app/layouts/messenger/dialogs/profile/profile.dialog.component';
|
} from '@app/layouts/messenger/dialogs/profile/profile.dialog.component';
|
||||||
import { DialogService } from '@ucap-webmessenger/ui';
|
import {
|
||||||
|
DialogService,
|
||||||
|
ConfirmDialogComponent,
|
||||||
|
ConfirmDialogData,
|
||||||
|
ConfirmDialogResult
|
||||||
|
} from '@ucap-webmessenger/ui';
|
||||||
import { DOCUMENT } from '@angular/common';
|
import { DOCUMENT } from '@angular/common';
|
||||||
import { MatMenu, MatMenuTrigger } from '@angular/material/menu';
|
import { MatMenu, MatMenuTrigger } from '@angular/material/menu';
|
||||||
import { StatusCode, StatusType, WindowUtil } from '@ucap-webmessenger/core';
|
import { StatusCode, StatusType, WindowUtil } from '@ucap-webmessenger/core';
|
||||||
|
@ -110,6 +118,8 @@ export class TopBarComponent implements OnInit, OnDestroy {
|
||||||
webLinkBadgeMail = 0;
|
webLinkBadgeMail = 0;
|
||||||
webLinkBadgePayment = 0;
|
webLinkBadgePayment = 0;
|
||||||
|
|
||||||
|
webLinkbadgeEmailCountInterval: any;
|
||||||
|
|
||||||
appVersion: string;
|
appVersion: string;
|
||||||
|
|
||||||
WebLinkType = WebLinkType;
|
WebLinkType = WebLinkType;
|
||||||
|
@ -215,6 +225,10 @@ export class TopBarComponent implements OnInit, OnDestroy {
|
||||||
this.zoomSubscription.unsubscribe();
|
this.zoomSubscription.unsubscribe();
|
||||||
this.zoomSubscription = undefined;
|
this.zoomSubscription = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!!this.webLinkbadgeEmailCountInterval) {
|
||||||
|
clearInterval(this.webLinkbadgeEmailCountInterval);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
initWebLink(loginRes: LoginResponse): void {
|
initWebLink(loginRes: LoginResponse): void {
|
||||||
|
@ -246,9 +260,9 @@ export class TopBarComponent implements OnInit, OnDestroy {
|
||||||
);
|
);
|
||||||
|
|
||||||
const WebLinkMailCnt = link[0];
|
const WebLinkMailCnt = link[0];
|
||||||
const loginPw = appUserInfo.loginPw;
|
const loginPw = encodeURIComponent(appUserInfo.loginPw);
|
||||||
const loginPw2 = this.loginInfo.loginPw;
|
const loginPw2 = this.loginInfo.loginPw;
|
||||||
const loginId = this.loginInfo.loginId;
|
const loginId = encodeURIComponent(this.loginInfo.loginId);
|
||||||
const token = loginRes.tokenString;
|
const token = loginRes.tokenString;
|
||||||
|
|
||||||
const url = WebLinkMailCnt.url
|
const url = WebLinkMailCnt.url
|
||||||
|
@ -264,6 +278,19 @@ export class TopBarComponent implements OnInit, OnDestroy {
|
||||||
catchError(error => of(this.logger.log(error)))
|
catchError(error => of(this.logger.log(error)))
|
||||||
)
|
)
|
||||||
.subscribe();
|
.subscribe();
|
||||||
|
// interval
|
||||||
|
if (!this.webLinkbadgeEmailCountInterval) {
|
||||||
|
this.webLinkbadgeEmailCountInterval = setInterval(() => {
|
||||||
|
this.daesangApiService
|
||||||
|
.retrieveMailCount(url)
|
||||||
|
.pipe(
|
||||||
|
take(1),
|
||||||
|
map(res => (this.webLinkBadgeMail = res.count)),
|
||||||
|
catchError(error => of(this.logger.log(error)))
|
||||||
|
)
|
||||||
|
.subscribe();
|
||||||
|
}, 5 * 60 * 1000);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (urlInfo.webLinkAllowedList.indexOf(WebLinkType.Payment) > -1) {
|
if (urlInfo.webLinkAllowedList.indexOf(WebLinkType.Payment) > -1) {
|
||||||
|
@ -278,9 +305,9 @@ export class TopBarComponent implements OnInit, OnDestroy {
|
||||||
);
|
);
|
||||||
|
|
||||||
const WebLinkPaymentCnt = link[0];
|
const WebLinkPaymentCnt = link[0];
|
||||||
const loginPw = appUserInfo.loginPw;
|
const loginPw = encodeURIComponent(appUserInfo.loginPw);
|
||||||
const loginPw2 = this.loginInfo.loginPw;
|
const loginPw2 = this.loginInfo.loginPw;
|
||||||
const loginId = this.loginInfo.loginId;
|
const loginId = encodeURIComponent(this.loginInfo.loginId);
|
||||||
const token = loginRes.tokenString;
|
const token = loginRes.tokenString;
|
||||||
|
|
||||||
const url = WebLinkPaymentCnt.url
|
const url = WebLinkPaymentCnt.url
|
||||||
|
@ -406,65 +433,74 @@ export class TopBarComponent implements OnInit, OnDestroy {
|
||||||
environment.customConfig.appKey
|
environment.customConfig.appKey
|
||||||
);
|
);
|
||||||
|
|
||||||
const loginPw = appUserInfo.loginPw;
|
const loginPw = encodeURIComponent(appUserInfo.loginPw);
|
||||||
const loginPw2 = this.loginInfo.loginPw;
|
const loginPw2 = this.loginInfo.loginPw;
|
||||||
const loginId = this.loginInfo.loginId;
|
const loginId = encodeURIComponent(this.loginInfo.loginId);
|
||||||
const token = this.loginRes.tokenString;
|
const token = this.loginRes.tokenString;
|
||||||
|
const erpPw = this.daesangCipherService.encryptForSapErp(
|
||||||
|
'aes256-daesang-key!!',
|
||||||
|
this.loginRes.userInfo.employeeNum
|
||||||
|
);
|
||||||
|
|
||||||
const url = link.url
|
const url = link.url
|
||||||
.replace(/(\(%USER_TOKEN%\))/g, token)
|
.replace(/(\(%USER_TOKEN%\))/g, token)
|
||||||
.replace(/(\(%USER_ID%\))/g, loginId)
|
.replace(/(\(%USER_ID%\))/g, loginId)
|
||||||
.replace(/(\(%USER_PASS%\))/g, loginPw);
|
.replace(/(\(%USER_PASS%\))/g, loginPw)
|
||||||
|
.replace(/(\(%ENC_PASSWD%\))/g, erpPw);
|
||||||
|
|
||||||
let width = 1024;
|
let width = 1024;
|
||||||
let height = 768;
|
let height = 768;
|
||||||
let openType = 'INNER-POPUP';
|
let openType = 'INNER-POPUP';
|
||||||
switch (link.key) {
|
switch (link.key) {
|
||||||
case WebLinkType.Sms:
|
// /** SMS URL */
|
||||||
/** SMS URL */
|
// case WebLinkType.Sms:
|
||||||
{
|
// {
|
||||||
width = 685;
|
// width = 685;
|
||||||
height = 640;
|
// height = 640;
|
||||||
}
|
// }
|
||||||
break;
|
// break;
|
||||||
// case WebLinkType.Itsvcdesk:
|
|
||||||
// /** IT서비스데스크 URL */
|
// /** IT서비스데스크 URL */
|
||||||
|
// case WebLinkType.Itsvcdesk:
|
||||||
// {
|
// {
|
||||||
// width = 1400;
|
// width = 1400;
|
||||||
// height = 1000;
|
// height = 1000;
|
||||||
// }
|
// }
|
||||||
// break;
|
// break;
|
||||||
case WebLinkType.Conf:
|
|
||||||
/** 화상회의 URL */
|
/** 화상회의 URL */
|
||||||
|
case WebLinkType.Conf:
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case WebLinkType.Itsvcdesk:
|
/** SMS URL */
|
||||||
|
case WebLinkType.Sms:
|
||||||
/** IT서비스데스크 URL */
|
/** IT서비스데스크 URL */
|
||||||
case WebLinkType.Dsp:
|
case WebLinkType.Itsvcdesk:
|
||||||
/** DSP URL */
|
/** DSP URL */
|
||||||
case WebLinkType.Webhard:
|
case WebLinkType.Dsp:
|
||||||
/** 웹하드 URL */
|
/** 웹하드 URL */
|
||||||
case WebLinkType.Ep:
|
case WebLinkType.Webhard:
|
||||||
/** EP URL */
|
/** EP URL */
|
||||||
case WebLinkType.Sop:
|
case WebLinkType.Ep:
|
||||||
/** S&OP회의 URL */
|
/** S&OP회의 URL */
|
||||||
case WebLinkType.Som:
|
case WebLinkType.Sop:
|
||||||
/** S&OM회의 URL */
|
/** S&OM회의 URL */
|
||||||
case WebLinkType.Elephant:
|
case WebLinkType.Som:
|
||||||
/** 코끼리 URL */
|
/** 코끼리 URL */
|
||||||
case WebLinkType.UrgntNews:
|
case WebLinkType.Elephant:
|
||||||
/** 개인속보 URL */
|
/** 개인속보 URL */
|
||||||
case WebLinkType.MailCnt:
|
case WebLinkType.UrgntNews:
|
||||||
/** 메일Count URL */
|
/** 메일Count URL */
|
||||||
case WebLinkType.Mail:
|
case WebLinkType.MailCnt:
|
||||||
/** 메일 링크 URL */
|
/** 메일 링크 URL */
|
||||||
case WebLinkType.PaymentCnt:
|
case WebLinkType.Mail:
|
||||||
/** 결재Count URL */
|
/** 결재Count URL */
|
||||||
case WebLinkType.Payment:
|
case WebLinkType.PaymentCnt:
|
||||||
/** 결재링크 URL */
|
/** 결재링크 URL */
|
||||||
case WebLinkType.ChgPassword:
|
case WebLinkType.Payment:
|
||||||
|
/** Erp URL */
|
||||||
|
case WebLinkType.Erp:
|
||||||
/** 비밀번호변경 URL ; PC 메신저만 해당 비밀번호 만료시 */
|
/** 비밀번호변경 URL ; PC 메신저만 해당 비밀번호 만료시 */
|
||||||
|
case WebLinkType.ChgPassword:
|
||||||
{
|
{
|
||||||
openType = 'DEFAULT-BROWSER';
|
openType = 'DEFAULT-BROWSER';
|
||||||
}
|
}
|
||||||
|
@ -692,4 +728,31 @@ export class TopBarComponent implements OnInit, OnDestroy {
|
||||||
matDialogRef.removePanelClass('hideDialog');
|
matDialogRef.removePanelClass('hideDialog');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async onClickClearSettingAndLogout() {
|
||||||
|
const result = await this.dialogService.open<
|
||||||
|
ConfirmDialogComponent,
|
||||||
|
ConfirmDialogData,
|
||||||
|
ConfirmDialogResult
|
||||||
|
>(ConfirmDialogComponent, {
|
||||||
|
width: '400px',
|
||||||
|
data: {
|
||||||
|
title: 'Clear & Logout?',
|
||||||
|
html: 'Clear General Setting And Logout?'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!!result && !!result.choice && result.choice) {
|
||||||
|
this.localStorageService.remove(KEY_APP_USER_INFO);
|
||||||
|
this.sessionStorageService.remove(KEY_LOGIN_RES_INFO);
|
||||||
|
this.sessionStorageService.remove(KEY_VER_INFO);
|
||||||
|
this.sessionStorageService.remove(KEY_LOGIN_INFO);
|
||||||
|
this.sessionStorageService.remove(KEY_URL_INFO);
|
||||||
|
this.sessionStorageService.remove(KEY_AUTH_INFO);
|
||||||
|
this.sessionStorageService.remove(KEY_LOGOUT_INFO);
|
||||||
|
this.nativeService.clearAppStorage();
|
||||||
|
this.dialogService.closeAll();
|
||||||
|
this.store.dispatch(AuthenticationStore.loginRedirect());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,15 +53,16 @@
|
||||||
</div>
|
</div>
|
||||||
-->
|
-->
|
||||||
<ucap-account-login
|
<ucap-account-login
|
||||||
[companyList]="companyList$ | async"
|
[companyList]="companyList"
|
||||||
[curCompanyCode]="fixedCompany"
|
[curCompanyCode]="fixedCompany"
|
||||||
[notiText]="fixedNotiBtnText"
|
[notiText]="fixedNotiBtnText"
|
||||||
[loginBtnEnable]="loginBtnEnable"
|
[loginBtnEnable]="loginBtnEnable"
|
||||||
[loginBtnText]="loginBtnText"
|
[loginBtnText]="loginBtnText"
|
||||||
[companyCode]="appUserInfo?.companyCode"
|
[companyCode]="appUserInfo?.companyCode"
|
||||||
[loginId]="appUserInfo?.loginId"
|
[loginId]="appUserInfo?.loginId"
|
||||||
|
[loginPw]="loginPw"
|
||||||
[rememberMe]="appUserInfo?.rememberMe"
|
[rememberMe]="appUserInfo?.rememberMe"
|
||||||
[autoLogin]="appUserInfo?.settings?.general?.autoLogin"
|
[autoLogin]="autologin"
|
||||||
[useRememberMe]="useRememberMe"
|
[useRememberMe]="useRememberMe"
|
||||||
[useAutoLogin]="useAutoLogin"
|
[useAutoLogin]="useAutoLogin"
|
||||||
(login)="onLogin($event)"
|
(login)="onLogin($event)"
|
||||||
|
|
|
@ -1,15 +1,19 @@
|
||||||
import { Component, OnInit, OnDestroy, Inject } from '@angular/core';
|
import { Component, OnInit, OnDestroy, Inject, NgZone } from '@angular/core';
|
||||||
|
|
||||||
import { Store, select } from '@ngrx/store';
|
import { Store, select } from '@ngrx/store';
|
||||||
|
|
||||||
import { Company } from '@ucap-webmessenger/api-external';
|
import {
|
||||||
|
Company,
|
||||||
|
ExternalApiService,
|
||||||
|
CompanyListRequest
|
||||||
|
} from '@ucap-webmessenger/api-external';
|
||||||
import { ServerErrorCode, ProtocolService } from '@ucap-webmessenger/protocol';
|
import { ServerErrorCode, ProtocolService } from '@ucap-webmessenger/protocol';
|
||||||
|
|
||||||
import * as AppStore from '@app/store';
|
import * as AppStore from '@app/store';
|
||||||
import * as AuthenticationStore from '@app/store/account/authentication';
|
import * as AuthenticationStore from '@app/store/account/authentication';
|
||||||
import * as CompanyStore from '@app/store/setting/company';
|
import * as CompanyStore from '@app/store/setting/company';
|
||||||
import { Observable, Subscription } from 'rxjs';
|
import { Observable, Subscription, of } from 'rxjs';
|
||||||
import { map } from 'rxjs/operators';
|
import { map, take, catchError } from 'rxjs/operators';
|
||||||
import {
|
import {
|
||||||
DialogService,
|
DialogService,
|
||||||
AlertDialogComponent,
|
AlertDialogComponent,
|
||||||
|
@ -34,6 +38,7 @@ import { AppAuthenticationService } from '@app/services/authentication.service';
|
||||||
import { logoutInitialize } from '@app/store/account/authentication';
|
import { logoutInitialize } from '@app/store/account/authentication';
|
||||||
import { TranslateService } from '@ngx-translate/core';
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
import { NativeService, UCAP_NATIVE_SERVICE } from '@ucap-webmessenger/native';
|
import { NativeService, UCAP_NATIVE_SERVICE } from '@ucap-webmessenger/native';
|
||||||
|
import { StatusCode } from '@ucap-webmessenger/api';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-page-account-login',
|
selector: 'app-page-account-login',
|
||||||
|
@ -44,7 +49,8 @@ export class LoginPageComponent implements OnInit, OnDestroy {
|
||||||
fixedCompany: string;
|
fixedCompany: string;
|
||||||
fixedNotiBtnText: string;
|
fixedNotiBtnText: string;
|
||||||
|
|
||||||
companyList$: Observable<Company[]>;
|
companyList: Company[];
|
||||||
|
companyListSubscription: Subscription;
|
||||||
|
|
||||||
loginFailureCount: Subscription;
|
loginFailureCount: Subscription;
|
||||||
|
|
||||||
|
@ -57,6 +63,8 @@ export class LoginPageComponent implements OnInit, OnDestroy {
|
||||||
waitingTime: number;
|
waitingTime: number;
|
||||||
|
|
||||||
appUserInfo: AppUserInfo;
|
appUserInfo: AppUserInfo;
|
||||||
|
loginPw: string;
|
||||||
|
autologin: boolean;
|
||||||
useRememberMe: boolean;
|
useRememberMe: boolean;
|
||||||
useAutoLogin: boolean;
|
useAutoLogin: boolean;
|
||||||
|
|
||||||
|
@ -85,7 +93,9 @@ export class LoginPageComponent implements OnInit, OnDestroy {
|
||||||
private protocolService: ProtocolService,
|
private protocolService: ProtocolService,
|
||||||
private localStorageService: LocalStorageService,
|
private localStorageService: LocalStorageService,
|
||||||
private sessionStorageService: SessionStorageService,
|
private sessionStorageService: SessionStorageService,
|
||||||
private appAuthenticationService: AppAuthenticationService
|
private externalApiService: ExternalApiService,
|
||||||
|
private appAuthenticationService: AppAuthenticationService,
|
||||||
|
private ngZone: NgZone
|
||||||
) {
|
) {
|
||||||
this.useRememberMe =
|
this.useRememberMe =
|
||||||
environment.productConfig.authentication.rememberMe.use;
|
environment.productConfig.authentication.rememberMe.use;
|
||||||
|
@ -95,6 +105,9 @@ export class LoginPageComponent implements OnInit, OnDestroy {
|
||||||
KEY_APP_USER_INFO,
|
KEY_APP_USER_INFO,
|
||||||
environment.customConfig.appKey
|
environment.customConfig.appKey
|
||||||
);
|
);
|
||||||
|
if (!!this.appUserInfo) {
|
||||||
|
this.autologin = this.appUserInfo.settings.general.autoLogin || false;
|
||||||
|
}
|
||||||
|
|
||||||
this.rotateInfomationIndex =
|
this.rotateInfomationIndex =
|
||||||
new Date().getTime() % this.rotateInfomation.length;
|
new Date().getTime() % this.rotateInfomation.length;
|
||||||
|
@ -113,15 +126,36 @@ export class LoginPageComponent implements OnInit, OnDestroy {
|
||||||
this.defatulLoginBtnText = this.translateService.instant('accounts.login');
|
this.defatulLoginBtnText = this.translateService.instant('accounts.login');
|
||||||
this.defatulWaitingTime = 5 * 60; // sec
|
this.defatulWaitingTime = 5 * 60; // sec
|
||||||
|
|
||||||
this.store.dispatch(
|
this.externalApiService
|
||||||
CompanyStore.companyList({
|
.companyList({
|
||||||
companyGroupCode: environment.companyConfig.companyGroupCode
|
companyGroupCode: environment.companyConfig.companyGroupCode
|
||||||
|
} as CompanyListRequest)
|
||||||
|
.pipe(
|
||||||
|
take(1),
|
||||||
|
map(res => {
|
||||||
|
if (res.statusCode === StatusCode.Success) {
|
||||||
|
this.store.dispatch(CompanyStore.companyListSuccess(res));
|
||||||
|
} else {
|
||||||
|
this.store.dispatch(
|
||||||
|
CompanyStore.companyListFailure({ error: 'Failed' })
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
catchError(error => {
|
||||||
|
console.log('network disconnected', error);
|
||||||
|
return of();
|
||||||
})
|
})
|
||||||
);
|
)
|
||||||
|
.subscribe();
|
||||||
|
|
||||||
this.companyList$ = this.store.pipe(
|
this.companyListSubscription = this.store
|
||||||
select(AppStore.SettingSelector.CompanySelector.companyList)
|
.pipe(
|
||||||
);
|
select(AppStore.SettingSelector.CompanySelector.companyList),
|
||||||
|
map(companyList => {
|
||||||
|
this.companyList = companyList;
|
||||||
|
})
|
||||||
|
)
|
||||||
|
.subscribe();
|
||||||
|
|
||||||
this.loginFailureCount = this.store
|
this.loginFailureCount = this.store
|
||||||
.pipe(
|
.pipe(
|
||||||
|
@ -189,6 +223,56 @@ export class LoginPageComponent implements OnInit, OnDestroy {
|
||||||
this.nativeService.idleStateStop();
|
this.nativeService.idleStateStop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** CASE :: 자동로그인 실패 (비밀번호 변경에 따른 실패, 네트워크 절체) */
|
||||||
|
if (!!personLogout && !!personLogout.autoLogin) {
|
||||||
|
switch (personLogout.autoLogin.state) {
|
||||||
|
case 'IDPW_FAIL':
|
||||||
|
{
|
||||||
|
this.ngZone.run(() => {
|
||||||
|
this.dialogService.open<
|
||||||
|
AlertDialogComponent,
|
||||||
|
AlertDialogData,
|
||||||
|
AlertDialogResult
|
||||||
|
>(AlertDialogComponent, {
|
||||||
|
width: '360px',
|
||||||
|
data: {
|
||||||
|
title: '',
|
||||||
|
html: this.translateService.instant(
|
||||||
|
'accounts.errors.loginFailedIdPw'
|
||||||
|
)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'NETWORK_FAIL':
|
||||||
|
{
|
||||||
|
this.loginPw = this.appUserInfo.loginPw;
|
||||||
|
this.autologin = true;
|
||||||
|
|
||||||
|
this.ngZone.run(() => {
|
||||||
|
this.dialogService.open<
|
||||||
|
AlertDialogComponent,
|
||||||
|
AlertDialogData,
|
||||||
|
AlertDialogResult
|
||||||
|
>(AlertDialogComponent, {
|
||||||
|
width: '360px',
|
||||||
|
data: {
|
||||||
|
title: this.translateService.instant(
|
||||||
|
'accounts.errors.loginFailed'
|
||||||
|
),
|
||||||
|
html: this.translateService.instant(
|
||||||
|
'accounts.errors.networkFailedAndRetry'
|
||||||
|
)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** CASE :: 중복 로그인, Remote 로그아웃 */
|
||||||
if (!!personLogout && !!personLogout.reasonCode) {
|
if (!!personLogout && !!personLogout.reasonCode) {
|
||||||
let msg = this.translateService.instant('accounts.results.doLogout');
|
let msg = this.translateService.instant('accounts.results.doLogout');
|
||||||
switch (personLogout.reasonCode) {
|
switch (personLogout.reasonCode) {
|
||||||
|
@ -234,6 +318,9 @@ export class LoginPageComponent implements OnInit, OnDestroy {
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnDestroy(): void {
|
ngOnDestroy(): void {
|
||||||
|
if (!!this.companyListSubscription) {
|
||||||
|
this.companyListSubscription.unsubscribe();
|
||||||
|
}
|
||||||
if (!!this.loginFailureCount) {
|
if (!!this.loginFailureCount) {
|
||||||
this.loginFailureCount.unsubscribe();
|
this.loginFailureCount.unsubscribe();
|
||||||
}
|
}
|
||||||
|
@ -268,11 +355,70 @@ export class LoginPageComponent implements OnInit, OnDestroy {
|
||||||
autoLogin: boolean;
|
autoLogin: boolean;
|
||||||
notValid: () => void;
|
notValid: () => void;
|
||||||
}) {
|
}) {
|
||||||
|
this.sessionStorageService.remove(KEY_LOGOUT_INFO);
|
||||||
|
|
||||||
this.loginBtnEnable = false;
|
this.loginBtnEnable = false;
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.loginBtnEnable = true;
|
this.loginBtnEnable = true;
|
||||||
}, 30 * 1000);
|
}, 30 * 1000);
|
||||||
|
|
||||||
|
if (!this.companyList) {
|
||||||
|
this.externalApiService
|
||||||
|
.companyList({
|
||||||
|
companyGroupCode: environment.companyConfig.companyGroupCode
|
||||||
|
} as CompanyListRequest)
|
||||||
|
.pipe(
|
||||||
|
take(1),
|
||||||
|
map(res => {
|
||||||
|
if (res.statusCode === StatusCode.Success) {
|
||||||
|
this.store.dispatch(CompanyStore.companyListSuccess(res));
|
||||||
|
// Recursion function > onLogin
|
||||||
|
this.onLogin(value);
|
||||||
|
} else {
|
||||||
|
this.ngZone.run(() => {
|
||||||
|
this.dialogService.open<
|
||||||
|
AlertDialogComponent,
|
||||||
|
AlertDialogData,
|
||||||
|
AlertDialogResult
|
||||||
|
>(AlertDialogComponent, {
|
||||||
|
width: '360px',
|
||||||
|
data: {
|
||||||
|
title: this.translateService.instant(
|
||||||
|
'accounts.errors.loginFailed'
|
||||||
|
),
|
||||||
|
html: this.translateService.instant(
|
||||||
|
'accounts.errors.networkFailedAndRetry'
|
||||||
|
)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.loginBtnEnable = true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
catchError(error => {
|
||||||
|
this.ngZone.run(() => {
|
||||||
|
this.dialogService.open<
|
||||||
|
AlertDialogComponent,
|
||||||
|
AlertDialogData,
|
||||||
|
AlertDialogResult
|
||||||
|
>(AlertDialogComponent, {
|
||||||
|
width: '360px',
|
||||||
|
data: {
|
||||||
|
title: this.translateService.instant(
|
||||||
|
'accounts.errors.loginFailed'
|
||||||
|
),
|
||||||
|
html: this.translateService.instant(
|
||||||
|
'accounts.errors.networkFailedAndRetry'
|
||||||
|
)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.loginBtnEnable = true;
|
||||||
|
});
|
||||||
|
return of();
|
||||||
|
})
|
||||||
|
)
|
||||||
|
.subscribe();
|
||||||
|
} else {
|
||||||
this.store.dispatch(
|
this.store.dispatch(
|
||||||
AuthenticationStore.webLogin({
|
AuthenticationStore.webLogin({
|
||||||
loginInfo: {
|
loginInfo: {
|
||||||
|
@ -286,6 +432,7 @@ export class LoginPageComponent implements OnInit, OnDestroy {
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
onClickNoti() {
|
onClickNoti() {
|
||||||
// For Daesang,,
|
// For Daesang,,
|
||||||
|
|
|
@ -79,6 +79,12 @@ export class AppAuthenticationService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (!!environment.productConfig.defaultSettings.general.autoLaunch) {
|
||||||
|
this.nativeService.changeAutoLaunch(
|
||||||
|
environment.productConfig.defaultSettings.general.autoLaunch
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
appUserInfo = {
|
appUserInfo = {
|
||||||
|
@ -118,6 +124,7 @@ export class AppAuthenticationService {
|
||||||
environment.customConfig.appKey
|
environment.customConfig.appKey
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (!!appUserInfo) {
|
||||||
appUserInfo = {
|
appUserInfo = {
|
||||||
...appUserInfo,
|
...appUserInfo,
|
||||||
settings: {
|
settings: {
|
||||||
|
@ -136,3 +143,4 @@ export class AppAuthenticationService {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import { delGroupSuccess, buddy2 } from './../store/messenger/sync/actions';
|
|
||||||
import { Injectable, Inject } from '@angular/core';
|
import { Injectable, Inject } from '@angular/core';
|
||||||
|
|
||||||
import { tap, withLatestFrom, take } from 'rxjs/operators';
|
import { tap, withLatestFrom } from 'rxjs/operators';
|
||||||
|
|
||||||
import { Store, select } from '@ngrx/store';
|
import { Store, select } from '@ngrx/store';
|
||||||
|
|
||||||
|
@ -95,7 +94,11 @@ import {
|
||||||
NotificationType,
|
NotificationType,
|
||||||
WindowState
|
WindowState
|
||||||
} from '@ucap-webmessenger/native';
|
} from '@ucap-webmessenger/native';
|
||||||
import { StringUtil, DialogService } from '@ucap-webmessenger/ui';
|
import {
|
||||||
|
StringUtil,
|
||||||
|
DialogService,
|
||||||
|
TranslateService as UcapTranslateService
|
||||||
|
} from '@ucap-webmessenger/ui';
|
||||||
import {
|
import {
|
||||||
UmgProtocolService,
|
UmgProtocolService,
|
||||||
SSVC_TYPE_UMG_NOTI,
|
SSVC_TYPE_UMG_NOTI,
|
||||||
|
@ -110,10 +113,10 @@ import {
|
||||||
import { AppUserInfo, KEY_APP_USER_INFO } from '@app/types/app-user-info.type';
|
import { AppUserInfo, KEY_APP_USER_INFO } from '@app/types/app-user-info.type';
|
||||||
|
|
||||||
import { environment } from '../../environments/environment';
|
import { environment } from '../../environments/environment';
|
||||||
import { NotificationMethod } from '@ucap-webmessenger/core';
|
import { NotificationMethod, LocaleCode } from '@ucap-webmessenger/core';
|
||||||
import { Dictionary } from '@ngrx/entity';
|
import { Dictionary } from '@ngrx/entity';
|
||||||
import { MessageType } from '@ucap-webmessenger/api-message';
|
import { MessageType } from '@ucap-webmessenger/api-message';
|
||||||
import { LogoutInfo, KEY_LOGOUT_INFO } from '@app/types';
|
import { LogoutInfo, KEY_LOGOUT_INFO, KEY_VER_INFO } from '@app/types';
|
||||||
import { TranslateService } from '@ngx-translate/core';
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
import { deleteMessageSuccess } from '@app/store/messenger/message';
|
import { deleteMessageSuccess } from '@app/store/messenger/message';
|
||||||
import { ServerErrorCode } from '@ucap-webmessenger/protocol';
|
import { ServerErrorCode } from '@ucap-webmessenger/protocol';
|
||||||
|
@ -130,6 +133,11 @@ import {
|
||||||
ChatSetting
|
ChatSetting
|
||||||
} from '@ucap-webmessenger/ui-settings';
|
} from '@ucap-webmessenger/ui-settings';
|
||||||
import clone from 'clone';
|
import clone from 'clone';
|
||||||
|
import { ElectronBrowserWindowChannel } from '@ucap-webmessenger/electron-core';
|
||||||
|
import { UserInfo, RoomUserData } from '@ucap-webmessenger/protocol-sync';
|
||||||
|
import { VersionInfo2Response } from '@ucap-webmessenger/api-public';
|
||||||
|
import { QueryProtocolService } from '@ucap-webmessenger/protocol-query';
|
||||||
|
import { UserInfoListState } from '@app/store/messenger/room';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class AppNotificationService {
|
export class AppNotificationService {
|
||||||
|
@ -140,8 +148,10 @@ export class AppNotificationService {
|
||||||
private roomProtocolService: RoomProtocolService,
|
private roomProtocolService: RoomProtocolService,
|
||||||
private groupProtocolService: GroupProtocolService,
|
private groupProtocolService: GroupProtocolService,
|
||||||
private buddyProtocolService: BuddyProtocolService,
|
private buddyProtocolService: BuddyProtocolService,
|
||||||
|
private queryProtocolService: QueryProtocolService,
|
||||||
private statusProtocolService: StatusProtocolService,
|
private statusProtocolService: StatusProtocolService,
|
||||||
private translateService: TranslateService,
|
private translateService: TranslateService,
|
||||||
|
private ucapTranslateService: UcapTranslateService,
|
||||||
private optionProtocolService: OptionProtocolService,
|
private optionProtocolService: OptionProtocolService,
|
||||||
private umgProtocolService: UmgProtocolService,
|
private umgProtocolService: UmgProtocolService,
|
||||||
private localStorageService: LocalStorageService,
|
private localStorageService: LocalStorageService,
|
||||||
|
@ -204,14 +214,44 @@ export class AppNotificationService {
|
||||||
this.store.pipe(
|
this.store.pipe(
|
||||||
select((state: any) => state.messenger.room.roomInfo as RoomInfo)
|
select((state: any) => state.messenger.room.roomInfo as RoomInfo)
|
||||||
),
|
),
|
||||||
|
this.store.pipe(
|
||||||
|
select(
|
||||||
|
(state: any) =>
|
||||||
|
state.messenger.room.userInfoList.entities as Dictionary<
|
||||||
|
UserInfoListState
|
||||||
|
>
|
||||||
|
)
|
||||||
|
),
|
||||||
this.store.pipe(
|
this.store.pipe(
|
||||||
select(
|
select(
|
||||||
(state: any) =>
|
(state: any) =>
|
||||||
state.messenger.sync.room.entities as Dictionary<RoomInfo>
|
state.messenger.sync.room.entities as Dictionary<RoomInfo>
|
||||||
)
|
)
|
||||||
|
),
|
||||||
|
this.store.pipe(
|
||||||
|
select(
|
||||||
|
(state: any) =>
|
||||||
|
state.messenger.sync.buddy2.entities as Dictionary<UserInfo>
|
||||||
|
)
|
||||||
|
),
|
||||||
|
this.store.pipe(
|
||||||
|
select(
|
||||||
|
(state: any) =>
|
||||||
|
state.messenger.sync.roomUserShort.entities as Dictionary<
|
||||||
|
RoomUserData
|
||||||
|
>
|
||||||
|
)
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
tap(([notiOrRes, curRoomInfo, roomList]) => {
|
tap(
|
||||||
|
([
|
||||||
|
notiOrRes,
|
||||||
|
curRoomInfo,
|
||||||
|
curRoomUserInfo,
|
||||||
|
roomList,
|
||||||
|
buddyList,
|
||||||
|
roomUserShorts
|
||||||
|
]) => {
|
||||||
switch (notiOrRes.SSVC_TYPE) {
|
switch (notiOrRes.SSVC_TYPE) {
|
||||||
case SSVC_TYPE_EVENT_SEND_RES:
|
case SSVC_TYPE_EVENT_SEND_RES:
|
||||||
case SSVC_TYPE_EVENT_SEND_NOTI:
|
case SSVC_TYPE_EVENT_SEND_NOTI:
|
||||||
|
@ -232,14 +272,6 @@ export class AppNotificationService {
|
||||||
if (notiOrRes.SSVC_TYPE === SSVC_TYPE_EVENT_SEND_NOTI) {
|
if (notiOrRes.SSVC_TYPE === SSVC_TYPE_EVENT_SEND_NOTI) {
|
||||||
let doNoti = true;
|
let doNoti = true;
|
||||||
|
|
||||||
// 방별 알림이 꺼져 있으면 노티 안함.
|
|
||||||
if (
|
|
||||||
!!roomList[noti.roomSeq] &&
|
|
||||||
!roomList[noti.roomSeq].receiveAlarm
|
|
||||||
) {
|
|
||||||
doNoti = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const windowState = this.nativeService.getWindowState();
|
const windowState = this.nativeService.getWindowState();
|
||||||
|
|
||||||
// 현재 열려 있는 방일경우 노티 안함.
|
// 현재 열려 있는 방일경우 노티 안함.
|
||||||
|
@ -248,8 +280,27 @@ export class AppNotificationService {
|
||||||
!!curRoomInfo.roomSeq &&
|
!!curRoomInfo.roomSeq &&
|
||||||
curRoomInfo.roomSeq === noti.roomSeq &&
|
curRoomInfo.roomSeq === noti.roomSeq &&
|
||||||
!!windowState &&
|
!!windowState &&
|
||||||
windowState !== WindowState.Minimized &&
|
windowState.windowState !== WindowState.Minimized &&
|
||||||
windowState !== WindowState.Hidden
|
windowState.windowState !== WindowState.Hidden
|
||||||
|
) {
|
||||||
|
doNoti = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// // 포커스 아웃일때 무조건 노티.
|
||||||
|
// // Case 1 : 단순 포커스 아웃.
|
||||||
|
// // Case 2 : hidden 시 포커스 인 상태이지만 위에서 필터링 됨.
|
||||||
|
// console.log(windowState);
|
||||||
|
// if (
|
||||||
|
// windowState.windowFocusState !==
|
||||||
|
// ElectronBrowserWindowChannel.Focus
|
||||||
|
// ) {
|
||||||
|
// doNoti = true;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// 방별 알림이 꺼져 있으면 노티 안함. > 우선순위 최상위.
|
||||||
|
if (
|
||||||
|
!!roomList[noti.roomSeq] &&
|
||||||
|
!roomList[noti.roomSeq].receiveAlarm
|
||||||
) {
|
) {
|
||||||
doNoti = false;
|
doNoti = false;
|
||||||
}
|
}
|
||||||
|
@ -296,6 +347,76 @@ export class AppNotificationService {
|
||||||
appUserInfo.settings.notification
|
appUserInfo.settings.notification
|
||||||
.alertExposureTime * 1000
|
.alertExposureTime * 1000
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Sender Info setting
|
||||||
|
// STEP 1 >> In buddy group.
|
||||||
|
let senderInfo: any = buddyList[noti.SENDER_SEQ];
|
||||||
|
|
||||||
|
// STEP 2 >> In Current Room Users.
|
||||||
|
if (!senderInfo) {
|
||||||
|
senderInfo = curRoomUserInfo[noti.SENDER_SEQ];
|
||||||
|
}
|
||||||
|
|
||||||
|
// STEP 3 >> In All Room Users.
|
||||||
|
if (!senderInfo) {
|
||||||
|
for (const key in roomUserShorts) {
|
||||||
|
if (key === undefined) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (roomUserShorts.hasOwnProperty(key)) {
|
||||||
|
const element = roomUserShorts[key];
|
||||||
|
const filteredUserInfos = element.userInfos.filter(
|
||||||
|
info => info.seq === noti.SENDER_SEQ
|
||||||
|
);
|
||||||
|
|
||||||
|
if (
|
||||||
|
!!filteredUserInfos &&
|
||||||
|
filteredUserInfos.length > 0
|
||||||
|
) {
|
||||||
|
senderInfo = filteredUserInfos[0];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sender Info setting.
|
||||||
|
if (!!senderInfo) {
|
||||||
|
// name set
|
||||||
|
let name = senderInfo.name;
|
||||||
|
let grade = senderInfo.grade;
|
||||||
|
|
||||||
|
switch (
|
||||||
|
this.ucapTranslateService.currentLang.toUpperCase()
|
||||||
|
) {
|
||||||
|
case LocaleCode.English:
|
||||||
|
name = senderInfo.nameEn;
|
||||||
|
grade = senderInfo.gradeEn;
|
||||||
|
break;
|
||||||
|
case LocaleCode.Chinese:
|
||||||
|
name = senderInfo.nameCn;
|
||||||
|
grade = senderInfo.gradeCn;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
notiReq.title = this.translateService.instant(
|
||||||
|
'notification.titleChatEventArrivedByUser',
|
||||||
|
{
|
||||||
|
userInfo: !!grade ? `${name} ${grade}` : name
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// Image set.
|
||||||
|
if (!!senderInfo.profileImageFile) {
|
||||||
|
const sessionVerinfo = this.sessionStorageService.get<
|
||||||
|
VersionInfo2Response
|
||||||
|
>(KEY_VER_INFO);
|
||||||
|
notiReq.image = `${sessionVerinfo.profileRoot}${senderInfo.profileImageFile}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// express noti popup
|
||||||
this.nativeService.notify(notiReq);
|
this.nativeService.notify(notiReq);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -347,7 +468,8 @@ export class AppNotificationService {
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
|
)
|
||||||
)
|
)
|
||||||
.subscribe();
|
.subscribe();
|
||||||
this.infoProtocolService.notification$
|
this.infoProtocolService.notification$
|
||||||
|
|
|
@ -76,7 +76,11 @@ import {
|
||||||
ServiceProtocolService,
|
ServiceProtocolService,
|
||||||
UserPasswordSetResponse
|
UserPasswordSetResponse
|
||||||
} from '@ucap-webmessenger/protocol-service';
|
} from '@ucap-webmessenger/protocol-service';
|
||||||
import { DaesangUrlInfoResponse } from '@ucap-webmessenger/api-external';
|
import {
|
||||||
|
DaesangUrlInfoResponse,
|
||||||
|
ExternalApiService,
|
||||||
|
CompanyListRequest
|
||||||
|
} from '@ucap-webmessenger/api-external';
|
||||||
import { AppUserInfo, KEY_APP_USER_INFO } from '@app/types/app-user-info.type';
|
import { AppUserInfo, KEY_APP_USER_INFO } from '@app/types/app-user-info.type';
|
||||||
import { DaesangCipherService, WebLinkType } from '@ucap-webmessenger/daesang';
|
import { DaesangCipherService, WebLinkType } from '@ucap-webmessenger/daesang';
|
||||||
import { TranslateService } from '@ngx-translate/core';
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
|
@ -84,10 +88,15 @@ import {
|
||||||
InfoProtocolService,
|
InfoProtocolService,
|
||||||
UserResponse
|
UserResponse
|
||||||
} from '@ucap-webmessenger/protocol-info';
|
} from '@ucap-webmessenger/protocol-info';
|
||||||
|
import { StatusCode } from '@ucap-webmessenger/api';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class Effects {
|
export class Effects {
|
||||||
webLogin$ = createEffect(() =>
|
retryCount = 0;
|
||||||
|
retryInterval = 3000; // ms
|
||||||
|
maxRetryCount = (1 * 60 * 1000) / this.retryInterval; // 20 count due to 1 min.
|
||||||
|
webLogin$ = createEffect(
|
||||||
|
() =>
|
||||||
this.actions$.pipe(
|
this.actions$.pipe(
|
||||||
ofType(webLogin),
|
ofType(webLogin),
|
||||||
map(action => action),
|
map(action => action),
|
||||||
|
@ -96,8 +105,10 @@ export class Effects {
|
||||||
loginInfo: LoginInfo;
|
loginInfo: LoginInfo;
|
||||||
rememberMe: boolean;
|
rememberMe: boolean;
|
||||||
autoLogin: boolean;
|
autoLogin: boolean;
|
||||||
}) =>
|
}) => {
|
||||||
this.piService
|
const selfParam = params;
|
||||||
|
|
||||||
|
return this.piService
|
||||||
.login2({
|
.login2({
|
||||||
loginId: params.loginInfo.loginId,
|
loginId: params.loginInfo.loginId,
|
||||||
loginPw: params.loginInfo.loginPw,
|
loginPw: params.loginInfo.loginPw,
|
||||||
|
@ -106,22 +117,101 @@ export class Effects {
|
||||||
.pipe(
|
.pipe(
|
||||||
map((res: Login2Response) => {
|
map((res: Login2Response) => {
|
||||||
if ('success' !== res.status.toLowerCase()) {
|
if ('success' !== res.status.toLowerCase()) {
|
||||||
|
if (!!params.autoLogin) {
|
||||||
|
// auto login Failure.
|
||||||
|
// clear setting for autologin.
|
||||||
|
// this.localStorageService.remove(KEY_APP_USER_INFO);
|
||||||
|
const appUserInfo = this.localStorageService.encGet<
|
||||||
|
AppUserInfo
|
||||||
|
>(KEY_APP_USER_INFO, environment.customConfig.appKey);
|
||||||
|
appUserInfo.settings.general.autoLogin = false;
|
||||||
|
this.localStorageService.encSet<AppUserInfo>(
|
||||||
|
KEY_APP_USER_INFO,
|
||||||
|
appUserInfo,
|
||||||
|
environment.customConfig.appKey
|
||||||
|
);
|
||||||
|
|
||||||
|
// Logout reason setting.
|
||||||
|
this.sessionStorageService.set<LogoutInfo>(
|
||||||
|
KEY_LOGOUT_INFO,
|
||||||
|
{
|
||||||
|
personLogout: true,
|
||||||
|
autoLogin: {
|
||||||
|
state: 'IDPW_FAIL'
|
||||||
|
}
|
||||||
|
} as LogoutInfo
|
||||||
|
);
|
||||||
|
|
||||||
|
this.router.navigateByUrl('/account/login');
|
||||||
|
} else {
|
||||||
this.store.dispatch(increaseLoginFailCount({}));
|
this.store.dispatch(increaseLoginFailCount({}));
|
||||||
return webLoginFailure({ error: 'Failed' });
|
this.store.dispatch(webLoginFailure({ error: 'Failed' }));
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
this.store.dispatch(initialLoginFailCount({}));
|
this.store.dispatch(initialLoginFailCount({}));
|
||||||
return webLoginSuccess({
|
this.store.dispatch(
|
||||||
|
webLoginSuccess({
|
||||||
loginInfo: params.loginInfo,
|
loginInfo: params.loginInfo,
|
||||||
rememberMe: params.rememberMe,
|
rememberMe: params.rememberMe,
|
||||||
autoLogin: params.autoLogin,
|
autoLogin: params.autoLogin,
|
||||||
login2Response: res
|
login2Response: res
|
||||||
});
|
})
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
catchError(error => of(webLoginFailure({ error })))
|
catchError(error => {
|
||||||
)
|
if (!!selfParam.autoLogin) {
|
||||||
)
|
if (this.maxRetryCount > this.retryCount) {
|
||||||
|
this.store.dispatch(logoutInitialize());
|
||||||
|
setTimeout(() => {
|
||||||
|
// this.store.dispatch(webLogin(selfParam));
|
||||||
|
this.router.navigateByUrl('/account/login');
|
||||||
|
}, this.retryInterval);
|
||||||
|
|
||||||
|
this.retryCount++;
|
||||||
|
console.log('retry', this.retryCount, this.maxRetryCount);
|
||||||
|
return of(webLoginFailure({ error }));
|
||||||
|
} else {
|
||||||
|
console.log(
|
||||||
|
'retry End',
|
||||||
|
this.retryCount,
|
||||||
|
this.maxRetryCount
|
||||||
|
);
|
||||||
|
|
||||||
|
// clear setting for autologin.
|
||||||
|
const appUserInfo = this.localStorageService.encGet<
|
||||||
|
AppUserInfo
|
||||||
|
>(KEY_APP_USER_INFO, environment.customConfig.appKey);
|
||||||
|
appUserInfo.settings.general.autoLogin = false;
|
||||||
|
this.localStorageService.encSet<AppUserInfo>(
|
||||||
|
KEY_APP_USER_INFO,
|
||||||
|
appUserInfo,
|
||||||
|
environment.customConfig.appKey
|
||||||
|
);
|
||||||
|
|
||||||
|
// Logout reason setting.
|
||||||
|
this.sessionStorageService.set<LogoutInfo>(
|
||||||
|
KEY_LOGOUT_INFO,
|
||||||
|
{
|
||||||
|
personLogout: true,
|
||||||
|
autoLogin: {
|
||||||
|
state: 'NETWORK_FAIL'
|
||||||
|
}
|
||||||
|
} as LogoutInfo
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.router.navigateByUrl('/account/login');
|
||||||
|
|
||||||
|
console.log('not retry');
|
||||||
|
return of(webLoginFailure({ error }));
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
),
|
||||||
|
{ dispatch: false }
|
||||||
);
|
);
|
||||||
|
|
||||||
webLoginSuccess$ = createEffect(
|
webLoginSuccess$ = createEffect(
|
||||||
|
@ -500,6 +590,7 @@ export class Effects {
|
||||||
private sessionStorageService: SessionStorageService,
|
private sessionStorageService: SessionStorageService,
|
||||||
private piService: PiService,
|
private piService: PiService,
|
||||||
private appAuthenticationService: AppAuthenticationService,
|
private appAuthenticationService: AppAuthenticationService,
|
||||||
|
private externalApiService: ExternalApiService,
|
||||||
private protocolService: ProtocolService,
|
private protocolService: ProtocolService,
|
||||||
private authenticationProtocolService: AuthenticationProtocolService,
|
private authenticationProtocolService: AuthenticationProtocolService,
|
||||||
private infoProtocolService: InfoProtocolService,
|
private infoProtocolService: InfoProtocolService,
|
||||||
|
|
|
@ -925,30 +925,6 @@ export class Effects {
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// not opened room :: unread count increased
|
|
||||||
if (
|
|
||||||
action.SVC_TYPE === SVC_TYPE_EVENT &&
|
|
||||||
action.SSVC_TYPE === SSVC_TYPE_EVENT_SEND_RES
|
|
||||||
) {
|
|
||||||
/**
|
|
||||||
* 다른 디바이스에서 대화를 송신 할경우 RES 가 noti 로 유입될 수 있다.
|
|
||||||
* 이때 unread count 를 중가하지 않는다.
|
|
||||||
*/
|
|
||||||
} else {
|
|
||||||
if (!roomInfo || roomInfo.roomSeq !== action.roomSeq) {
|
|
||||||
if (!!trgtRoomInfos && !!trgtRoomInfos[action.roomSeq]) {
|
|
||||||
const noReadCnt = trgtRoomInfos[action.roomSeq].noReadCnt;
|
|
||||||
this.store.dispatch(
|
|
||||||
SyncStore.updateUnreadCount({
|
|
||||||
roomSeq: action.roomSeq,
|
|
||||||
noReadCnt: noReadCnt + 1
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (action.info.type === EventType.File) {
|
if (action.info.type === EventType.File) {
|
||||||
// File 정보 수집.
|
// File 정보 수집.
|
||||||
|
@ -962,6 +938,34 @@ export class Effects {
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
// not opened room :: unread count increased
|
||||||
|
if (
|
||||||
|
action.SVC_TYPE === SVC_TYPE_EVENT &&
|
||||||
|
action.SSVC_TYPE === SSVC_TYPE_EVENT_SEND_RES
|
||||||
|
) {
|
||||||
|
/**
|
||||||
|
* 다른 디바이스에서 대화를 송신 할경우 RES 가 noti 로 유입될 수 있다.
|
||||||
|
* 이때 unread count 를 중가하지 않는다.
|
||||||
|
*/
|
||||||
|
} else {
|
||||||
|
if (
|
||||||
|
!!trgtRoomInfos &&
|
||||||
|
!!trgtRoomInfos[action.roomSeq] &&
|
||||||
|
action.info.type !== EventType.Join &&
|
||||||
|
action.info.type !== EventType.Exit &&
|
||||||
|
action.info.type !== EventType.ForcedExit
|
||||||
|
) {
|
||||||
|
const noReadCnt = trgtRoomInfos[action.roomSeq].noReadCnt;
|
||||||
|
this.store.dispatch(
|
||||||
|
SyncStore.updateUnreadCount({
|
||||||
|
roomSeq: action.roomSeq,
|
||||||
|
noReadCnt: noReadCnt + 1
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 대화 > 리스트 :: finalEventMessage refresh
|
// 대화 > 리스트 :: finalEventMessage refresh
|
||||||
this.store.dispatch(ChatStore.newEventMessage(action));
|
this.store.dispatch(ChatStore.newEventMessage(action));
|
||||||
|
|
|
@ -188,3 +188,8 @@ export const exitFailure = createAction(
|
||||||
'[Messenger::Room] Exit Failure',
|
'[Messenger::Room] Exit Failure',
|
||||||
props<{ error: any }>()
|
props<{ error: any }>()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
export const syncRoomRefreshByInvite = createAction(
|
||||||
|
'[Messenger::Room] Sync Room Refresh by invite',
|
||||||
|
props<InfoRequest>()
|
||||||
|
);
|
||||||
|
|
|
@ -5,6 +5,8 @@ import { Actions, createEffect, ofType } from '@ngrx/effects';
|
||||||
import { Store, select } from '@ngrx/store';
|
import { Store, select } from '@ngrx/store';
|
||||||
|
|
||||||
import { NGXLogger } from 'ngx-logger';
|
import { NGXLogger } from 'ngx-logger';
|
||||||
|
import { environment } from '../../../../environments/environment';
|
||||||
|
|
||||||
import { of } from 'rxjs';
|
import { of } from 'rxjs';
|
||||||
import {
|
import {
|
||||||
tap,
|
tap,
|
||||||
|
@ -68,7 +70,8 @@ import {
|
||||||
exitForcingFailure,
|
exitForcingFailure,
|
||||||
exitForcingSuccess,
|
exitForcingSuccess,
|
||||||
exitNotificationOthers,
|
exitNotificationOthers,
|
||||||
clearRoomUser
|
clearRoomUser,
|
||||||
|
syncRoomRefreshByInvite
|
||||||
} from './actions';
|
} from './actions';
|
||||||
import { SessionStorageService } from '@ucap-webmessenger/web-storage';
|
import { SessionStorageService } from '@ucap-webmessenger/web-storage';
|
||||||
import { LoginInfo, KEY_LOGIN_INFO, KEY_VER_INFO } from '@app/types';
|
import { LoginInfo, KEY_LOGIN_INFO, KEY_VER_INFO } from '@app/types';
|
||||||
|
@ -79,6 +82,8 @@ import {
|
||||||
AlertDialogData,
|
AlertDialogData,
|
||||||
AlertDialogResult
|
AlertDialogResult
|
||||||
} from '@ucap-webmessenger/ui';
|
} from '@ucap-webmessenger/ui';
|
||||||
|
import { ActivatedRouteSnapshot } from '@angular/router';
|
||||||
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class Effects {
|
export class Effects {
|
||||||
|
@ -285,6 +290,29 @@ export class Effects {
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
exhaustMap(([action, roomInfo]) => {
|
exhaustMap(([action, roomInfo]) => {
|
||||||
|
if (
|
||||||
|
environment.productConfig.CommonSetting.maxChatRoomUser <
|
||||||
|
action.req.userSeqs.length
|
||||||
|
) {
|
||||||
|
this.dialogService.open<
|
||||||
|
AlertDialogComponent,
|
||||||
|
AlertDialogData,
|
||||||
|
AlertDialogResult
|
||||||
|
>(AlertDialogComponent, {
|
||||||
|
data: {
|
||||||
|
title: this.translateService.instant('chat.errors.label'),
|
||||||
|
html: this.translateService.instant(
|
||||||
|
'chat.errors.maxCountOfRoomMemberWith',
|
||||||
|
{
|
||||||
|
maxCount:
|
||||||
|
environment.productConfig.CommonSetting.maxChatRoomUser
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return of(inviteFailure({ error: 'over size room users !!' }));
|
||||||
|
}
|
||||||
|
|
||||||
if (roomInfo.roomType === RoomType.Single) {
|
if (roomInfo.roomType === RoomType.Single) {
|
||||||
// Re Open
|
// Re Open
|
||||||
return this.roomProtocolService.open(action.req).pipe(
|
return this.roomProtocolService.open(action.req).pipe(
|
||||||
|
@ -371,10 +399,11 @@ export class Effects {
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
tap(([action, roomInfo]) => {
|
tap(([action, roomInfo]) => {
|
||||||
if (!!roomInfo && roomInfo.roomSeq === action.noti.roomSeq) {
|
|
||||||
const loginInfo = this.sessionStorageService.get<LoginInfo>(
|
const loginInfo = this.sessionStorageService.get<LoginInfo>(
|
||||||
KEY_LOGIN_INFO
|
KEY_LOGIN_INFO
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (!!roomInfo && roomInfo.roomSeq === action.noti.roomSeq) {
|
||||||
this.store.dispatch(
|
this.store.dispatch(
|
||||||
info({
|
info({
|
||||||
roomSeq: action.noti.roomSeq,
|
roomSeq: action.noti.roomSeq,
|
||||||
|
@ -383,6 +412,15 @@ export class Effects {
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// room list refresh for exist.
|
||||||
|
this.store.dispatch(
|
||||||
|
syncRoomRefreshByInvite({
|
||||||
|
roomSeq: action.noti.roomSeq,
|
||||||
|
isDetail: true,
|
||||||
|
localeCode: loginInfo.localeCode
|
||||||
|
})
|
||||||
|
);
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
@ -454,6 +492,7 @@ export class Effects {
|
||||||
private store: Store<any>,
|
private store: Store<any>,
|
||||||
private roomProtocolService: RoomProtocolService,
|
private roomProtocolService: RoomProtocolService,
|
||||||
private sessionStorageService: SessionStorageService,
|
private sessionStorageService: SessionStorageService,
|
||||||
|
private translateService: TranslateService,
|
||||||
private dialogService: DialogService,
|
private dialogService: DialogService,
|
||||||
private logger: NGXLogger
|
private logger: NGXLogger
|
||||||
) {}
|
) {}
|
||||||
|
|
|
@ -72,6 +72,7 @@ export const reducer = createReducer(
|
||||||
|
|
||||||
on(updateSuccess, (state, action) => {
|
on(updateSuccess, (state, action) => {
|
||||||
const curRoomInfo = state.roomInfo;
|
const curRoomInfo = state.roomInfo;
|
||||||
|
|
||||||
if (!curRoomInfo) {
|
if (!curRoomInfo) {
|
||||||
return { ...state };
|
return { ...state };
|
||||||
}
|
}
|
||||||
|
|
|
@ -540,6 +540,62 @@ export class Effects {
|
||||||
},
|
},
|
||||||
{ dispatch: false }
|
{ dispatch: false }
|
||||||
);
|
);
|
||||||
|
syncRoomRefreshByInvite$ = createEffect(
|
||||||
|
() => {
|
||||||
|
let roomInfo: RoomInfo;
|
||||||
|
let userInfoShortList: UserInfoShort[];
|
||||||
|
let userInfoList: RoomUserInfo[];
|
||||||
|
|
||||||
|
return this.actions$.pipe(
|
||||||
|
ofType(RoomStore.syncRoomRefreshByInvite),
|
||||||
|
tap(() => {
|
||||||
|
roomInfo = null;
|
||||||
|
userInfoShortList = [];
|
||||||
|
userInfoList = [];
|
||||||
|
}),
|
||||||
|
withLatestFrom(
|
||||||
|
this.store.pipe(
|
||||||
|
select((state: any) => state.messenger.sync.room.ids as string[])
|
||||||
|
)
|
||||||
|
),
|
||||||
|
switchMap(([req, roomSeqList]) => {
|
||||||
|
const index = roomSeqList.findIndex(
|
||||||
|
(roomSeq, i) => roomSeq === req.roomSeq
|
||||||
|
);
|
||||||
|
if (index > -1) {
|
||||||
|
return this.roomProtocolService.info(req).pipe(
|
||||||
|
map(res => {
|
||||||
|
switch (res.SSVC_TYPE) {
|
||||||
|
case SSVC_TYPE_ROOM_INFO_ROOM:
|
||||||
|
roomInfo = (res as InfoData).roomInfo;
|
||||||
|
break;
|
||||||
|
case SSVC_TYPE_ROOM_INFO_USER:
|
||||||
|
userInfoShortList.push(...(res as UserShortData).userInfos);
|
||||||
|
break;
|
||||||
|
case SSVC_TYPE_ROOM_INFO_USER2:
|
||||||
|
userInfoList.push(...(res as UserData).userInfos);
|
||||||
|
break;
|
||||||
|
case SSVC_TYPE_ROOM_INFO_RES:
|
||||||
|
this.store.dispatch(
|
||||||
|
refreshRoomSuccess({
|
||||||
|
roomInfo,
|
||||||
|
userInfoShortList,
|
||||||
|
userInfoList
|
||||||
|
})
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
catchError(error => of(refreshRoomFailure({ error })))
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return of();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
|
},
|
||||||
|
{ dispatch: false }
|
||||||
|
);
|
||||||
|
|
||||||
// 대화상대 초대 성공 후 처리.
|
// 대화상대 초대 성공 후 처리.
|
||||||
inviteSuccess$ = createEffect(() =>
|
inviteSuccess$ = createEffect(() =>
|
||||||
|
|
|
@ -105,6 +105,11 @@ export const reducer = createReducer(
|
||||||
on(clearRoomUsers, (state, action) => {
|
on(clearRoomUsers, (state, action) => {
|
||||||
const roomInfo = state.room.entities[action.roomSeq];
|
const roomInfo = state.room.entities[action.roomSeq];
|
||||||
|
|
||||||
|
if (!roomInfo) {
|
||||||
|
// 방에 초대만 되고 대화가 발생하지 않아 방정보가 없을때, 방에서 강퇴된다면 roomInfo 가 없을 수 있다.
|
||||||
|
return { ...state };
|
||||||
|
}
|
||||||
|
|
||||||
const roomUserList: RoomUserDetailData = {
|
const roomUserList: RoomUserDetailData = {
|
||||||
...state.roomUser.entities[action.roomSeq]
|
...state.roomUser.entities[action.roomSeq]
|
||||||
};
|
};
|
||||||
|
|
|
@ -2,8 +2,17 @@ export const KEY_LOGOUT_INFO = 'ucap::LOGOUT_INFO';
|
||||||
|
|
||||||
export interface LogoutInfo {
|
export interface LogoutInfo {
|
||||||
personLogout: boolean;
|
personLogout: boolean;
|
||||||
|
|
||||||
|
/** 중복로그인, Remote 로그아웃 시에 사용. */
|
||||||
reasonCode?: number;
|
reasonCode?: number;
|
||||||
ip?: string;
|
ip?: string; // 중복로그인시 사용.
|
||||||
mac?: string;
|
mac?: string; // 중복로그인시 사용.
|
||||||
forceType?: string;
|
forceType?: string; // remote 로그아웃 시 사용.
|
||||||
|
|
||||||
|
/** 자동로그인 실패시. */
|
||||||
|
autoLogin?: {
|
||||||
|
state: string;
|
||||||
|
id?: string;
|
||||||
|
pw?: string;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,7 +45,9 @@
|
||||||
"failToChangePassword": "Failed to change password.",
|
"failToChangePassword": "Failed to change password.",
|
||||||
"loginFailed": "Failed to login",
|
"loginFailed": "Failed to login",
|
||||||
"loginFailedIdPw": "Username or password do not match.",
|
"loginFailedIdPw": "Username or password do not match.",
|
||||||
"loginFailOverTry": "Password error count exceeded. <br/> Check your password <br/> Please try again later."
|
"loginFailOverTry": "Password error count exceeded. <br/> Check your password <br/> Please try again later.",
|
||||||
|
"networkFailedAndExit": "Please exit the program due to a network problem. <br/> Please check the network and try again.",
|
||||||
|
"networkFailedAndRetry": "Cannot run due to network problem. <br/> Please check the network and try again."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"profile": {
|
"profile": {
|
||||||
|
@ -57,6 +59,7 @@
|
||||||
"removeBuddy": "Remove a buddy",
|
"removeBuddy": "Remove a buddy",
|
||||||
"remoteSupport": "Remote support",
|
"remoteSupport": "Remote support",
|
||||||
"fieldCompany": "Company",
|
"fieldCompany": "Company",
|
||||||
|
"fieldEmployeeNumber": "Employee Number",
|
||||||
"fieldResponsibilities": "Responsibilities",
|
"fieldResponsibilities": "Responsibilities",
|
||||||
"fieldWorkplace": "Workplace",
|
"fieldWorkplace": "Workplace",
|
||||||
"fieldJob": "Job",
|
"fieldJob": "Job",
|
||||||
|
@ -388,7 +391,9 @@
|
||||||
"label": "Update"
|
"label": "Update"
|
||||||
},
|
},
|
||||||
"notification": {
|
"notification": {
|
||||||
|
"titleChatEventArrivedByUser": "A Message of chat from {{userInfo}}.",
|
||||||
"titleChatEventArrived": "A message of chat has arrived.",
|
"titleChatEventArrived": "A message of chat has arrived.",
|
||||||
|
"titleMessageArrivedByUser": "A Message from {{userInfo}}.",
|
||||||
"titleMessageArrived": "A message has arrived."
|
"titleMessageArrived": "A message has arrived."
|
||||||
},
|
},
|
||||||
"common": {
|
"common": {
|
||||||
|
|
|
@ -45,7 +45,9 @@
|
||||||
"failToChangePassword": "비밀번호 변경에 실패하였습니다.",
|
"failToChangePassword": "비밀번호 변경에 실패하였습니다.",
|
||||||
"loginFailed": "로그인에 실패하였습니다.",
|
"loginFailed": "로그인에 실패하였습니다.",
|
||||||
"loginFailedIdPw": "아이디 또는 패스워드가<br/>일치하지 않습니다.",
|
"loginFailedIdPw": "아이디 또는 패스워드가<br/>일치하지 않습니다.",
|
||||||
"loginFailOverTry": "비밀번호 오류 횟수 초과입니다.<br/>비밀번호를 확인하신 후<br/>잠시 후 다시 시작해 주세요."
|
"loginFailOverTry": "비밀번호 오류 횟수 초과입니다.<br/>비밀번호를 확인하신 후<br/>잠시 후 다시 시작해 주세요.",
|
||||||
|
"networkFailedAndExit": "네트워크 문제로 프로그램을 종료합니다.<br/>네트워크 확인후 다시 시도해 주세요.",
|
||||||
|
"networkFailedAndRetry": "네트워크 문제로 실행할 수 없습니다.<br/>네트워크 확인후 다시 시도해 주세요."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"profile": {
|
"profile": {
|
||||||
|
@ -57,6 +59,7 @@
|
||||||
"removeBuddy": "동료삭제",
|
"removeBuddy": "동료삭제",
|
||||||
"remoteSupport": "원격 지원",
|
"remoteSupport": "원격 지원",
|
||||||
"fieldCompany": "회사",
|
"fieldCompany": "회사",
|
||||||
|
"fieldEmployeeNumber": "사번",
|
||||||
"fieldResponsibilities": "담당업무",
|
"fieldResponsibilities": "담당업무",
|
||||||
"fieldWorkplace": "근무지",
|
"fieldWorkplace": "근무지",
|
||||||
"fieldJob": "직무",
|
"fieldJob": "직무",
|
||||||
|
@ -388,7 +391,9 @@
|
||||||
"label": "업데이트"
|
"label": "업데이트"
|
||||||
},
|
},
|
||||||
"notification": {
|
"notification": {
|
||||||
|
"titleChatEventArrivedByUser": "{{userInfo}} 님의 메세지.",
|
||||||
"titleChatEventArrived": "메세지가 도착했습니다.",
|
"titleChatEventArrived": "메세지가 도착했습니다.",
|
||||||
|
"titleMessageArrivedByUser": "{{userInfo}} 님의 쪽지.",
|
||||||
"titleMessageArrived": "쪽지가 도착했습니다."
|
"titleMessageArrived": "쪽지가 도착했습니다."
|
||||||
},
|
},
|
||||||
"common": {
|
"common": {
|
||||||
|
|
BIN
projects/ucap-webmessenger-app/src/assets/images/no_image.png
Normal file
BIN
projects/ucap-webmessenger-app/src/assets/images/no_image.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.4 KiB |
|
@ -50,7 +50,7 @@ export class DaesangCipherService {
|
||||||
* const dec = this.daesangCipherService.decryptForSapErp('aes256-daesang-key!!',enc);
|
* const dec = this.daesangCipherService.decryptForSapErp('aes256-daesang-key!!',enc);
|
||||||
* console.log('dec', dec);
|
* console.log('dec', dec);
|
||||||
*/
|
*/
|
||||||
encryptForSapErp(pvUserKey: string, employeeNum: number): string {
|
encryptForSapErp(pvUserKey: string, employeeNum: string): string {
|
||||||
// const txt = '20200221090321_asdfghjk'; // 1QgLAiLqJ6Uo6bE4Qk1o3Yd6mfqxXSnmqXX%2FXLL7DoA%3D
|
// const txt = '20200221090321_asdfghjk'; // 1QgLAiLqJ6Uo6bE4Qk1o3Yd6mfqxXSnmqXX%2FXLL7DoA%3D
|
||||||
// const txt = '20200221101444_asdfghjk'; // Lz1TIdGTQQMui%2BBHMdj8fatYYhXbwJEL%2BJ91C7jUWEs%3D
|
// const txt = '20200221101444_asdfghjk'; // Lz1TIdGTQQMui%2BBHMdj8fatYYhXbwJEL%2BJ91C7jUWEs%3D
|
||||||
const str = moment().format('YYYYMMDDHHmmss') + '_' + employeeNum;
|
const str = moment().format('YYYYMMDDHHmmss') + '_' + employeeNum;
|
||||||
|
|
|
@ -28,5 +28,7 @@ export enum WebLinkType {
|
||||||
/** 결재링크 URL */
|
/** 결재링크 URL */
|
||||||
Payment = 'WebLinkPayment',
|
Payment = 'WebLinkPayment',
|
||||||
/** 비밀번호변경 URL ; PC 메신저만 해당 비밀번호 만료시 */
|
/** 비밀번호변경 URL ; PC 메신저만 해당 비밀번호 만료시 */
|
||||||
ChgPassword = 'WebLinkChgPassword'
|
ChgPassword = 'WebLinkChgPassword',
|
||||||
|
/** Erp */
|
||||||
|
Erp = 'WebLinkERP'
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,12 +39,12 @@ export class SmsUtils {
|
||||||
openSendSms(token: string, employeeNum?: string) {
|
openSendSms(token: string, employeeNum?: string) {
|
||||||
const url = this.url.replace(/(\(%USER_TOKEN%\))/g, token);
|
const url = this.url.replace(/(\(%USER_TOKEN%\))/g, token);
|
||||||
|
|
||||||
// this.nativeService.openDefaultBrowser(url);
|
this.nativeService.openDefaultBrowser(url + `&ruser=${employeeNum},`);
|
||||||
WindowUtil.popupOpen(
|
// WindowUtil.popupOpen(
|
||||||
url + `&ruser=${employeeNum},`,
|
// url + `&ruser=${employeeNum},`,
|
||||||
'DaesangSMS',
|
// 'DaesangSMS',
|
||||||
685,
|
// 685,
|
||||||
640
|
// 640
|
||||||
);
|
// );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,7 @@ import { TranslateLoaderService } from '../translate/browser-loader';
|
||||||
import { NotificationService } from '../notification/notification.service';
|
import { NotificationService } from '../notification/notification.service';
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { FileUtil, StatusCode } from '@ucap-webmessenger/core';
|
import { FileUtil, StatusCode } from '@ucap-webmessenger/core';
|
||||||
|
import { ElectronBrowserWindowChannel } from '@ucap-webmessenger/electron-core';
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root'
|
providedIn: 'root'
|
||||||
|
@ -229,11 +230,22 @@ export class BrowserNativeService extends NativeService {
|
||||||
windowMinimize(): void {}
|
windowMinimize(): void {}
|
||||||
|
|
||||||
windowMaximize(): void {}
|
windowMaximize(): void {}
|
||||||
getWindowState(): WindowState {
|
getWindowState(): {
|
||||||
return WindowState.Normal;
|
windowState: WindowState;
|
||||||
|
windowFocusState:
|
||||||
|
| ElectronBrowserWindowChannel.Focus
|
||||||
|
| ElectronBrowserWindowChannel.Blur;
|
||||||
|
} {
|
||||||
|
return {
|
||||||
|
windowState: WindowState.Normal,
|
||||||
|
windowFocusState: ElectronBrowserWindowChannel.Focus
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
appExit(): void {}
|
appExit(): void {}
|
||||||
|
appLogging(error: any): void {
|
||||||
|
console.error('[G]', error);
|
||||||
|
}
|
||||||
|
|
||||||
zoomTo(factor: number): Promise<number> {
|
zoomTo(factor: number): Promise<number> {
|
||||||
return new Promise<number>((resolve, reject) => {
|
return new Promise<number>((resolve, reject) => {
|
||||||
|
|
|
@ -31,6 +31,7 @@ import { Injectable } from '@angular/core';
|
||||||
import { TranslateLoaderService } from '../translate/electron-loader';
|
import { TranslateLoaderService } from '../translate/electron-loader';
|
||||||
import { TranslateLoader } from '@ngx-translate/core';
|
import { TranslateLoader } from '@ngx-translate/core';
|
||||||
import { StatusCode } from '@ucap-webmessenger/core';
|
import { StatusCode } from '@ucap-webmessenger/core';
|
||||||
|
import { ElectronBrowserWindowChannel } from '@ucap-webmessenger/electron-core';
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root'
|
providedIn: 'root'
|
||||||
|
@ -65,6 +66,10 @@ export class ElectronNativeService implements NativeService {
|
||||||
private backgroundCheckForUpdatesSubject: Subject<UpdateInfo> | null = null;
|
private backgroundCheckForUpdatesSubject: Subject<UpdateInfo> | null = null;
|
||||||
private backgroundCheckForUpdates$: Observable<UpdateInfo> | null = null;
|
private backgroundCheckForUpdates$: Observable<UpdateInfo> | null = null;
|
||||||
|
|
||||||
|
private windowFocusState:
|
||||||
|
| ElectronBrowserWindowChannel.Focus
|
||||||
|
| ElectronBrowserWindowChannel.Blur;
|
||||||
|
|
||||||
type(): NativeType {
|
type(): NativeType {
|
||||||
return NativeType.Electron;
|
return NativeType.Electron;
|
||||||
}
|
}
|
||||||
|
@ -395,25 +400,37 @@ export class ElectronNativeService implements NativeService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getWindowState(): WindowState {
|
getWindowState(): {
|
||||||
|
windowState: WindowState;
|
||||||
|
windowFocusState:
|
||||||
|
| ElectronBrowserWindowChannel.Focus
|
||||||
|
| ElectronBrowserWindowChannel.Blur;
|
||||||
|
} {
|
||||||
|
let windowState = WindowState.Normal;
|
||||||
if (!remote.getCurrentWindow().isVisible()) {
|
if (!remote.getCurrentWindow().isVisible()) {
|
||||||
return WindowState.Hidden;
|
windowState = WindowState.Hidden;
|
||||||
} else if (remote.getCurrentWindow().isMinimized()) {
|
} else if (remote.getCurrentWindow().isMinimized()) {
|
||||||
return WindowState.Minimized;
|
windowState = WindowState.Minimized;
|
||||||
} else if (remote.getCurrentWindow().isNormal()) {
|
} else if (remote.getCurrentWindow().isNormal()) {
|
||||||
return WindowState.Normal;
|
windowState = WindowState.Normal;
|
||||||
} else if (remote.getCurrentWindow().isMaximized()) {
|
} else if (remote.getCurrentWindow().isMaximized()) {
|
||||||
return WindowState.Maximized;
|
windowState = WindowState.Maximized;
|
||||||
} else if (remote.getCurrentWindow().isFullScreen()) {
|
} else if (remote.getCurrentWindow().isFullScreen()) {
|
||||||
return WindowState.FullScreen;
|
windowState = WindowState.FullScreen;
|
||||||
} else {
|
|
||||||
return WindowState.Normal;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
windowState,
|
||||||
|
windowFocusState: this.windowFocusState
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
appExit(): void {
|
appExit(): void {
|
||||||
this.ipcRenderer.send(AppChannel.Exit);
|
this.ipcRenderer.send(AppChannel.Exit);
|
||||||
}
|
}
|
||||||
|
appLogging(error: any): void {
|
||||||
|
this.ipcRenderer.send(AppChannel.Logging, error);
|
||||||
|
}
|
||||||
|
|
||||||
zoomTo(factor: number): Promise<number> {
|
zoomTo(factor: number): Promise<number> {
|
||||||
return new Promise<number>((resolve, reject) => {
|
return new Promise<number>((resolve, reject) => {
|
||||||
|
@ -529,5 +546,17 @@ export class ElectronNativeService implements NativeService {
|
||||||
this.shell = (window as any).require('electron').shell;
|
this.shell = (window as any).require('electron').shell;
|
||||||
this.webFrame = (window as any).require('electron').webFrame;
|
this.webFrame = (window as any).require('electron').webFrame;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.ipcRenderer.on(
|
||||||
|
WindowStateChannel.FocuseChanged,
|
||||||
|
(
|
||||||
|
event: any,
|
||||||
|
status:
|
||||||
|
| ElectronBrowserWindowChannel.Focus
|
||||||
|
| ElectronBrowserWindowChannel.Blur
|
||||||
|
) => {
|
||||||
|
this.windowFocusState = status;
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,7 +46,8 @@ export enum ProcessChannel {
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum WindowStateChannel {
|
export enum WindowStateChannel {
|
||||||
Changed = 'UCAP::windowState::windowStateChanged'
|
Changed = 'UCAP::windowState::windowStateChanged',
|
||||||
|
FocuseChanged = 'UCAP::windowState::windowFocusStateChanged'
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum IdleStateChannel {
|
export enum IdleStateChannel {
|
||||||
|
@ -61,7 +62,8 @@ export enum ClipboardChannel {
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum AppChannel {
|
export enum AppChannel {
|
||||||
Exit = 'UCAP::app::exit'
|
Exit = 'UCAP::app::exit',
|
||||||
|
Logging = 'UCAP::app::logging'
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum ExternalChannel {
|
export enum ExternalChannel {
|
||||||
|
|
|
@ -7,6 +7,7 @@ import { TranslateLoader } from '@ngx-translate/core';
|
||||||
import { StatusCode } from '@ucap-webmessenger/core';
|
import { StatusCode } from '@ucap-webmessenger/core';
|
||||||
import { UpdateInfo, UpdateCheckConfig } from '../models/update-info';
|
import { UpdateInfo, UpdateCheckConfig } from '../models/update-info';
|
||||||
import { NativeType } from '../types/native.type';
|
import { NativeType } from '../types/native.type';
|
||||||
|
import { ElectronBrowserWindowChannel } from '@ucap-webmessenger/electron-core';
|
||||||
|
|
||||||
export type NativePathName =
|
export type NativePathName =
|
||||||
| 'home'
|
| 'home'
|
||||||
|
@ -73,9 +74,15 @@ export abstract class NativeService {
|
||||||
abstract windowClose(): void;
|
abstract windowClose(): void;
|
||||||
abstract windowMinimize(): void;
|
abstract windowMinimize(): void;
|
||||||
abstract windowMaximize(): void;
|
abstract windowMaximize(): void;
|
||||||
abstract getWindowState(): WindowState;
|
abstract getWindowState(): {
|
||||||
|
windowState: WindowState;
|
||||||
|
windowFocusState:
|
||||||
|
| ElectronBrowserWindowChannel.Focus
|
||||||
|
| ElectronBrowserWindowChannel.Blur;
|
||||||
|
};
|
||||||
abstract zoomTo(factor: number): Promise<number>;
|
abstract zoomTo(factor: number): Promise<number>;
|
||||||
abstract appExit(): void;
|
abstract appExit(): void;
|
||||||
|
abstract appLogging(error: any): void;
|
||||||
|
|
||||||
abstract idleStateChanged(): Observable<WindowIdle>;
|
abstract idleStateChanged(): Observable<WindowIdle>;
|
||||||
abstract idleStateStop(): void;
|
abstract idleStateStop(): void;
|
||||||
|
|
|
@ -1,6 +1,12 @@
|
||||||
import { ParameterUtil, APIEncoder, APIDecoder } from '@ucap-webmessenger/api';
|
import {
|
||||||
|
ParameterUtil,
|
||||||
|
APIEncoder,
|
||||||
|
APIDecoder,
|
||||||
|
HttpUrlEncodingCodec
|
||||||
|
} from '@ucap-webmessenger/api';
|
||||||
|
|
||||||
import { PIRequest, PIResponse } from './pi';
|
import { PIRequest, PIResponse } from './pi';
|
||||||
|
import { HttpParams, HttpParameterCodec } from '@angular/common/http';
|
||||||
|
|
||||||
export interface Login2Request extends PIRequest {
|
export interface Login2Request extends PIRequest {
|
||||||
companyCode: string;
|
companyCode: string;
|
||||||
|
@ -26,7 +32,14 @@ const login2EncodeMap = {
|
||||||
};
|
};
|
||||||
|
|
||||||
export const encodeLogin2: APIEncoder<Login2Request> = (req: Login2Request) => {
|
export const encodeLogin2: APIEncoder<Login2Request> = (req: Login2Request) => {
|
||||||
return ParameterUtil.encode(login2EncodeMap, req);
|
let parameter: HttpParams = new HttpParams({
|
||||||
|
encoder: new HttpUrlEncodingCodec()
|
||||||
|
});
|
||||||
|
parameter = parameter.append('companyCd', req.companyCode);
|
||||||
|
parameter = parameter.append('loginId', req.loginId);
|
||||||
|
parameter = parameter.append('loginPw', req.loginPw);
|
||||||
|
return parameter;
|
||||||
|
// return ParameterUtil.encodeForm(login2EncodeMap, req);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const decodeLogin2: APIDecoder<Login2Response> = (res: any) => {
|
export const decodeLogin2: APIDecoder<Login2Response> = (res: any) => {
|
||||||
|
|
|
@ -22,7 +22,7 @@ export interface UserSeqRequest extends ProtocolRequest {
|
||||||
// 기관코드(s)
|
// 기관코드(s)
|
||||||
companyCode: string;
|
companyCode: string;
|
||||||
// 상세정보여부(s)
|
// 상세정보여부(s)
|
||||||
isDetail: boolean;
|
detailType: string;
|
||||||
// 발신자회사코드(s)
|
// 발신자회사코드(s)
|
||||||
senderCompanyCode: string;
|
senderCompanyCode: string;
|
||||||
// 발신자임직원유형(s)
|
// 발신자임직원유형(s)
|
||||||
|
@ -51,7 +51,7 @@ export const encodeUserSeq: ProtocolEncoder<UserSeqRequest> = (
|
||||||
{ type: PacketBodyValue.String, value: req.divCd },
|
{ type: PacketBodyValue.String, value: req.divCd },
|
||||||
{ type: PacketBodyValue.String, value: req.loginIds.join(',') },
|
{ type: PacketBodyValue.String, value: req.loginIds.join(',') },
|
||||||
{ type: PacketBodyValue.String, value: req.companyCode },
|
{ type: PacketBodyValue.String, value: req.companyCode },
|
||||||
{ type: PacketBodyValue.String, value: req.isDetail ? 'Y' : 'N' },
|
{ type: PacketBodyValue.String, value: req.detailType },
|
||||||
{ type: PacketBodyValue.String, value: req.senderCompanyCode },
|
{ type: PacketBodyValue.String, value: req.senderCompanyCode },
|
||||||
{ type: PacketBodyValue.String, value: req.senderEmployeeType }
|
{ type: PacketBodyValue.String, value: req.senderEmployeeType }
|
||||||
);
|
);
|
||||||
|
|
|
@ -39,6 +39,8 @@ export class LoginComponent implements OnInit {
|
||||||
@Input()
|
@Input()
|
||||||
loginId: string;
|
loginId: string;
|
||||||
@Input()
|
@Input()
|
||||||
|
loginPw?: string;
|
||||||
|
@Input()
|
||||||
rememberMe: boolean;
|
rememberMe: boolean;
|
||||||
@Input()
|
@Input()
|
||||||
autoLogin: boolean;
|
autoLogin: boolean;
|
||||||
|
@ -85,6 +87,9 @@ export class LoginComponent implements OnInit {
|
||||||
}
|
}
|
||||||
const loginPwValidators: ValidatorFn[] = [Validators.required];
|
const loginPwValidators: ValidatorFn[] = [Validators.required];
|
||||||
this.loginPwFormControl.setValidators(loginPwValidators);
|
this.loginPwFormControl.setValidators(loginPwValidators);
|
||||||
|
if (!!this.loginPw) {
|
||||||
|
this.loginPwFormControl.setValue(this.loginPw);
|
||||||
|
}
|
||||||
|
|
||||||
this.loginForm = this.formBuilder.group({
|
this.loginForm = this.formBuilder.group({
|
||||||
companyCodeFormControl: this.companyCodeFormControl,
|
companyCodeFormControl: this.companyCodeFormControl,
|
||||||
|
|
|
@ -98,9 +98,7 @@
|
||||||
|
|
||||||
<div class="message-main-container">
|
<div class="message-main-container">
|
||||||
<div class="message-main">
|
<div class="message-main">
|
||||||
<div class="chat-name">
|
<div class="chat-name">{{ senderName }} {{ senderGrade }}</div>
|
||||||
{{ senderName }}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="bubble">
|
<div class="bubble">
|
||||||
<ng-container
|
<ng-container
|
||||||
|
|
|
@ -51,6 +51,9 @@ export class MessageBoxComponent implements OnInit, AfterViewInit {
|
||||||
@Input()
|
@Input()
|
||||||
senderName: string;
|
senderName: string;
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
senderGrade: string;
|
||||||
|
|
||||||
@Input()
|
@Input()
|
||||||
profileImageRoot: string;
|
profileImageRoot: string;
|
||||||
|
|
||||||
|
|
|
@ -11,9 +11,12 @@
|
||||||
<span class="bg-accent-dark">{{ 'chat.sentDate' | translate }}</span>
|
<span class="bg-accent-dark">{{ 'chat.sentDate' | translate }}</span>
|
||||||
{{ message.sentMessageJson.postDate | ucapDate: 'YYYY.MM.DD a hh:mm' }}
|
{{ message.sentMessageJson.postDate | ucapDate: 'YYYY.MM.DD a hh:mm' }}
|
||||||
</li>
|
</li>
|
||||||
<li class="event-content">
|
<li
|
||||||
{{ message.sentMessageJson.content }}
|
class="event-content"
|
||||||
</li>
|
[innerHTML]="
|
||||||
|
message.sentMessageJson.content | ucapSafeHtml | linefeedtohtml | linky
|
||||||
|
"
|
||||||
|
></li>
|
||||||
</ul>
|
</ul>
|
||||||
<!-- <div class="btn-box">
|
<!-- <div class="btn-box">
|
||||||
<button mat-button (click)="onClickSave()">상세보기</button>
|
<button mat-button (click)="onClickSave()">상세보기</button>
|
||||||
|
|
|
@ -1,16 +1,45 @@
|
||||||
import { Component, OnInit, Input } from '@angular/core';
|
import {
|
||||||
|
Component,
|
||||||
|
OnInit,
|
||||||
|
Input,
|
||||||
|
AfterViewInit,
|
||||||
|
ElementRef,
|
||||||
|
Inject
|
||||||
|
} from '@angular/core';
|
||||||
import { Info, AllimEventJson } from '@ucap-webmessenger/protocol-event';
|
import { Info, AllimEventJson } from '@ucap-webmessenger/protocol-event';
|
||||||
|
import { UCAP_NATIVE_SERVICE, NativeService } from '@ucap-webmessenger/native';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'ucap-chat-message-box-allim',
|
selector: 'ucap-chat-message-box-allim',
|
||||||
templateUrl: './allim.component.html',
|
templateUrl: './allim.component.html',
|
||||||
styleUrls: ['./allim.component.scss']
|
styleUrls: ['./allim.component.scss']
|
||||||
})
|
})
|
||||||
export class AllimComponent implements OnInit {
|
export class AllimComponent implements OnInit, AfterViewInit {
|
||||||
@Input()
|
@Input()
|
||||||
message: Info<AllimEventJson>;
|
message: Info<AllimEventJson>;
|
||||||
|
|
||||||
constructor() {}
|
constructor(
|
||||||
|
private elementRef: ElementRef,
|
||||||
|
@Inject(UCAP_NATIVE_SERVICE) private nativeService: NativeService
|
||||||
|
) {}
|
||||||
|
|
||||||
ngOnInit() {}
|
ngOnInit() {}
|
||||||
|
|
||||||
|
ngAfterViewInit(): void {
|
||||||
|
if (
|
||||||
|
!!this.elementRef.nativeElement &&
|
||||||
|
!!this.elementRef.nativeElement.querySelector('a')
|
||||||
|
) {
|
||||||
|
const elements = this.elementRef.nativeElement.querySelectorAll('a');
|
||||||
|
elements.forEach(element => {
|
||||||
|
element.addEventListener('click', this.onClickEvent.bind(this));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onClickEvent(event: MouseEvent) {
|
||||||
|
this.nativeService.openDefaultBrowser(
|
||||||
|
(event.target as HTMLAnchorElement).text
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,6 +66,7 @@
|
||||||
"
|
"
|
||||||
[dateChanged]="getDateSplitter(message)"
|
[dateChanged]="getDateSplitter(message)"
|
||||||
[senderName]="getUserName(message.senderSeq)"
|
[senderName]="getUserName(message.senderSeq)"
|
||||||
|
[senderGrade]="getUserGrade(message.senderSeq)"
|
||||||
[profileImageRoot]="profileImageRoot"
|
[profileImageRoot]="profileImageRoot"
|
||||||
[profileImage]="getUserProfile(message.senderSeq)"
|
[profileImage]="getUserProfile(message.senderSeq)"
|
||||||
[roomInfo]="roomInfo"
|
[roomInfo]="roomInfo"
|
||||||
|
|
|
@ -322,6 +322,19 @@ export class MessagesComponent implements OnInit, OnDestroy {
|
||||||
}
|
}
|
||||||
return '(알수없는 사용자)';
|
return '(알수없는 사용자)';
|
||||||
}
|
}
|
||||||
|
getUserGrade(seq: number): string {
|
||||||
|
if (!this.userInfos) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
const userInfo: UserInfo[] = this.userInfos.filter(
|
||||||
|
user => user.seq === seq
|
||||||
|
);
|
||||||
|
if (!!userInfo && userInfo.length > 0) {
|
||||||
|
return userInfo[0].grade;
|
||||||
|
}
|
||||||
|
return '';
|
||||||
|
}
|
||||||
getUserProfile(seq: number): string {
|
getUserProfile(seq: number): string {
|
||||||
if (!this.userInfos) {
|
if (!this.userInfos) {
|
||||||
return '';
|
return '';
|
||||||
|
|
|
@ -1,7 +1,11 @@
|
||||||
<mat-card class="example-card profile mat-elevation-z">
|
<mat-card class="example-card profile mat-elevation-z">
|
||||||
<mat-card-header>
|
<mat-card-header>
|
||||||
<div class="profile-img">
|
<div class="profile-img">
|
||||||
<div class="profile-img-mask">
|
<div
|
||||||
|
class="profile-img-mask"
|
||||||
|
(click)="onClickProfileImageView()"
|
||||||
|
style="cursor: pointer;"
|
||||||
|
>
|
||||||
<img
|
<img
|
||||||
ucapImage
|
ucapImage
|
||||||
[base]="profileImageRoot"
|
[base]="profileImageRoot"
|
||||||
|
@ -24,7 +28,26 @@
|
||||||
>
|
>
|
||||||
<i class="mid mdi-camera"></i>
|
<i class="mid mdi-camera"></i>
|
||||||
</button>
|
</button>
|
||||||
|
<!-- <button
|
||||||
|
mat-mini-fab
|
||||||
|
class="mat-elevation-z6 icon-button btn-elephant"
|
||||||
|
*ngIf="!!enableElephantButton"
|
||||||
|
matTooltip="칭찬 코끼리 보내기"
|
||||||
|
(click)="onClickSendElephant()"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
viewBox="0 0 30 30"
|
||||||
|
stroke-width="1.5"
|
||||||
|
stroke="#357abc"
|
||||||
|
fill="#98d7e2"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M29,17.3a21.32,21.32,0,0,0-.63-4.39A10.59,10.59,0,0,0,28,11.85c0-.14-.1-.27-.15-.41l-.16-.39a13,13,0,0,0-.81-1.52,11.29,11.29,0,0,0-1.59-2c-.2-.2-.4-.4-.62-.58s-.43-.36-.66-.53a10.83,10.83,0,0,0-1.82-1.09l-.39-.18c-.26-.11-.53-.21-.81-.31A11.06,11.06,0,0,0,6.62,13.71l0,.09v0s0,.07,0,.1v0a.52.52,0,0,0,0,.11h0a.43.43,0,0,1,0,.11h0a.32.32,0,0,1,0,.09v0s0,.05,0,.08h0a.1.1,0,0,1,0,0h0l-.05,0h0l0,0a1.42,1.42,0,0,1-.56-.62,1.84,1.84,0,0,1-.13-1.17A4,4,0,0,1,6,11.55L2.14,9.83h0a6.75,6.75,0,0,0-.84,1.78c-.05.14-.09.29-.13.45A6.18,6.18,0,0,0,1,13.31a5,5,0,0,0,.78,2.84c.08.13.17.26.26.38l.06.08c.09.11.17.22.27.33l0,0,.26.28.07.06.28.25,0,0a2.48,2.48,0,0,0,.26.19l.06,0,.3.19.05,0,.27.14.06,0,.29.13.06,0,.25.09,0,0,.29.09h.06l.24.06h0l.26.05h0l.23,0h0l.23,0h.94l.13.43c.07.19.15.38.23.57s.17.38.27.56a11.26,11.26,0,0,0,1,1.51c.13.16.25.32.39.48a5.34,5.34,0,0,0,.39.44A11.78,11.78,0,0,0,10.9,24.1c.27.2.54.39.83.57a11.72,11.72,0,0,0,1.78,1l.16.06h.19l.13,0h0l.1-.06h0a.39.39,0,0,0,.08-.1h0l.05-.11v0l0-.1h0s0-.06,0-.09v-.08h0v-1a3.27,3.27,0,0,1,.41-1.59,3.36,3.36,0,0,1,2.94-1.76h0a3.31,3.31,0,0,1,1,.16l.3.11a3.15,3.15,0,0,1,.57.31,2.48,2.48,0,0,1,.26.19A3.34,3.34,0,0,1,21,24.08v.79h0v.29l0,0v0a.43.43,0,0,1,0,0v0a.25.25,0,0,0,0,.07h0a.21.21,0,0,0,0,.06v0l0,0,0,0,0,0,0,0,0,0h.18l.09,0a11,11,0,0,0,1.65-.82c.27-.16.53-.34.78-.52a10.65,10.65,0,0,0,1.07-.93c.11-.12.22-.23.32-.35a7.25,7.25,0,0,0,.58-.76l.24-.4a6.43,6.43,0,0,0,.41-.88l.15-.46.15.64c0,.09,0,.18.05.27v.09l0,.18v.1l0,.19V22l0,.2v.05l0,.2v.07c0,.05,0,.09,0,.14v.07a.69.69,0,0,1,0,.13V23a.94.94,0,0,1,0,.16v0a.56.56,0,0,0,0,.12v0l0,.08v0l0,.06,0,0a.1.1,0,0,0,.05,0h.07l.05,0s0,0,0,0a.12.12,0,0,0,.05,0l0,0a.52.52,0,0,0,.08-.11A9.41,9.41,0,0,0,29,18.52C29,18.12,29,17.71,29,17.3ZM10.55,11.59a.86.86,0,1,1,0-1.71.85.85,0,0,1,.85.85A.86.86,0,0,1,10.55,11.59Zm9.79,4.79A5.27,5.27,0,0,1,17,18.07a2.67,2.67,0,0,1-2-.95,7.21,7.21,0,0,1-1.69-4.84c.07-1.18.76-4,5.58-4.94a4.18,4.18,0,0,1,.61,0v0a3.43,3.43,0,0,1,3.11,2.29C23.5,11.73,22.63,14.27,20.34,16.38Z"
|
||||||
|
transform="translate(-1 -4.29)"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</button> -->
|
||||||
<span
|
<span
|
||||||
*ngIf="getWorkstatus(userInfo).length > 0"
|
*ngIf="getWorkstatus(userInfo).length > 0"
|
||||||
class="work-status"
|
class="work-status"
|
||||||
|
@ -180,6 +203,12 @@
|
||||||
<dt class="division">{{ 'profile.fieldCompany' | translate }}</dt>
|
<dt class="division">{{ 'profile.fieldCompany' | translate }}</dt>
|
||||||
<dd>{{ userInfo.companyName | ucapStringEmptycheck }}</dd>
|
<dd>{{ userInfo.companyName | ucapStringEmptycheck }}</dd>
|
||||||
</li>
|
</li>
|
||||||
|
<li class="employeeNum">
|
||||||
|
<dt class="division">
|
||||||
|
{{ 'profile.fieldEmployeeNumber' | translate }}
|
||||||
|
</dt>
|
||||||
|
<dd>{{ userInfo.employeeNum | slice: 2 }}</dd>
|
||||||
|
</li>
|
||||||
<li class="deptName">
|
<li class="deptName">
|
||||||
<dt class="division">{{ 'search.fieldDeptartment' | translate }}</dt>
|
<dt class="division">{{ 'search.fieldDeptartment' | translate }}</dt>
|
||||||
<dd>{{ userInfo | ucapTranslate: 'deptName' }}</dd>
|
<dd>{{ userInfo | ucapTranslate: 'deptName' }}</dd>
|
||||||
|
@ -379,6 +408,31 @@
|
||||||
}}</span>
|
}}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- <div class="button-text-item" *ngIf="!!enableElephantButton">
|
||||||
|
<button
|
||||||
|
mat-mini-fab
|
||||||
|
class="mat-elevation-z bg-accent-darkest"
|
||||||
|
*ngIf="!isMe"
|
||||||
|
matTooltip="칭찬 코끼리"
|
||||||
|
matTooltipPosition="above"
|
||||||
|
(click)="onClickSendElephant()"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
viewBox="0 0 30 30"
|
||||||
|
stroke-width="1.5"
|
||||||
|
stroke="#357abc"
|
||||||
|
fill="#98d7e2"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M29,17.3a21.32,21.32,0,0,0-.63-4.39A10.59,10.59,0,0,0,28,11.85c0-.14-.1-.27-.15-.41l-.16-.39a13,13,0,0,0-.81-1.52,11.29,11.29,0,0,0-1.59-2c-.2-.2-.4-.4-.62-.58s-.43-.36-.66-.53a10.83,10.83,0,0,0-1.82-1.09l-.39-.18c-.26-.11-.53-.21-.81-.31A11.06,11.06,0,0,0,6.62,13.71l0,.09v0s0,.07,0,.1v0a.52.52,0,0,0,0,.11h0a.43.43,0,0,1,0,.11h0a.32.32,0,0,1,0,.09v0s0,.05,0,.08h0a.1.1,0,0,1,0,0h0l-.05,0h0l0,0a1.42,1.42,0,0,1-.56-.62,1.84,1.84,0,0,1-.13-1.17A4,4,0,0,1,6,11.55L2.14,9.83h0a6.75,6.75,0,0,0-.84,1.78c-.05.14-.09.29-.13.45A6.18,6.18,0,0,0,1,13.31a5,5,0,0,0,.78,2.84c.08.13.17.26.26.38l.06.08c.09.11.17.22.27.33l0,0,.26.28.07.06.28.25,0,0a2.48,2.48,0,0,0,.26.19l.06,0,.3.19.05,0,.27.14.06,0,.29.13.06,0,.25.09,0,0,.29.09h.06l.24.06h0l.26.05h0l.23,0h0l.23,0h.94l.13.43c.07.19.15.38.23.57s.17.38.27.56a11.26,11.26,0,0,0,1,1.51c.13.16.25.32.39.48a5.34,5.34,0,0,0,.39.44A11.78,11.78,0,0,0,10.9,24.1c.27.2.54.39.83.57a11.72,11.72,0,0,0,1.78,1l.16.06h.19l.13,0h0l.1-.06h0a.39.39,0,0,0,.08-.1h0l.05-.11v0l0-.1h0s0-.06,0-.09v-.08h0v-1a3.27,3.27,0,0,1,.41-1.59,3.36,3.36,0,0,1,2.94-1.76h0a3.31,3.31,0,0,1,1,.16l.3.11a3.15,3.15,0,0,1,.57.31,2.48,2.48,0,0,1,.26.19A3.34,3.34,0,0,1,21,24.08v.79h0v.29l0,0v0a.43.43,0,0,1,0,0v0a.25.25,0,0,0,0,.07h0a.21.21,0,0,0,0,.06v0l0,0,0,0,0,0,0,0,0,0h.18l.09,0a11,11,0,0,0,1.65-.82c.27-.16.53-.34.78-.52a10.65,10.65,0,0,0,1.07-.93c.11-.12.22-.23.32-.35a7.25,7.25,0,0,0,.58-.76l.24-.4a6.43,6.43,0,0,0,.41-.88l.15-.46.15.64c0,.09,0,.18.05.27v.09l0,.18v.1l0,.19V22l0,.2v.05l0,.2v.07c0,.05,0,.09,0,.14v.07a.69.69,0,0,1,0,.13V23a.94.94,0,0,1,0,.16v0a.56.56,0,0,0,0,.12v0l0,.08v0l0,.06,0,0a.1.1,0,0,0,.05,0h.07l.05,0s0,0,0,0a.12.12,0,0,0,.05,0l0,0a.52.52,0,0,0,.08-.11A9.41,9.41,0,0,0,29,18.52C29,18.12,29,17.71,29,17.3ZM10.55,11.59a.86.86,0,1,1,0-1.71.85.85,0,0,1,.85.85A.86.86,0,0,1,10.55,11.59Zm9.79,4.79A5.27,5.27,0,0,1,17,18.07a2.67,2.67,0,0,1-2-.95,7.21,7.21,0,0,1-1.69-4.84c.07-1.18.76-4,5.58-4.94a4.18,4.18,0,0,1,.61,0v0a3.43,3.43,0,0,1,3.11,2.29C23.5,11.73,22.63,14.27,20.34,16.38Z"
|
||||||
|
transform="translate(-1 -4.29)"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
<span class="button-text">칭찬 코끼리</span>
|
||||||
|
</div> -->
|
||||||
|
|
||||||
<div class="button-text-item" *ngIf="!isMe">
|
<div class="button-text-item" *ngIf="!isMe">
|
||||||
<button
|
<button
|
||||||
mat-mini-fab
|
mat-mini-fab
|
||||||
|
|
|
@ -74,6 +74,7 @@ $login-max-height: 800px;
|
||||||
|
|
||||||
.work-status {
|
.work-status {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
|
margin-left: 20px;
|
||||||
height: 24px;
|
height: 24px;
|
||||||
border: 1px solid #ffffff;
|
border: 1px solid #ffffff;
|
||||||
padding: 4px 14px;
|
padding: 4px 14px;
|
||||||
|
@ -227,6 +228,26 @@ $login-max-height: 800px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.btn-elephant {
|
||||||
|
position: absolute;
|
||||||
|
background-color: #ffffff !important;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
left: 60px;
|
||||||
|
top: 46px;
|
||||||
|
svg {
|
||||||
|
width: 30px;
|
||||||
|
height: 30px;
|
||||||
|
}
|
||||||
|
&:hover {
|
||||||
|
background-color: #98d7e2 !important;
|
||||||
|
opacity: 1;
|
||||||
|
svg {
|
||||||
|
fill: #ffffff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.userInfo-call {
|
.userInfo-call {
|
||||||
position: relative;
|
position: relative;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
|
@ -44,7 +44,11 @@ export class ProfileComponent implements OnInit {
|
||||||
useBuddyToggleButton: boolean;
|
useBuddyToggleButton: boolean;
|
||||||
@Input()
|
@Input()
|
||||||
authInfo: AuthResponse;
|
authInfo: AuthResponse;
|
||||||
|
@Input()
|
||||||
|
enableElephantButton: boolean; // 칭찬코끼리 버튼 활성화 대상 여부.
|
||||||
|
|
||||||
|
@Output()
|
||||||
|
profileImageView = new EventEmitter<void>();
|
||||||
@Output()
|
@Output()
|
||||||
openChat = new EventEmitter<UserInfoSS>();
|
openChat = new EventEmitter<UserInfoSS>();
|
||||||
@Output()
|
@Output()
|
||||||
|
@ -70,6 +74,8 @@ export class ProfileComponent implements OnInit {
|
||||||
@Output()
|
@Output()
|
||||||
updateIntro = new EventEmitter<string>();
|
updateIntro = new EventEmitter<string>();
|
||||||
@Output()
|
@Output()
|
||||||
|
sendElephant = new EventEmitter();
|
||||||
|
@Output()
|
||||||
close = new EventEmitter();
|
close = new EventEmitter();
|
||||||
|
|
||||||
@ViewChild('profileImageFileInput', { static: false })
|
@ViewChild('profileImageFileInput', { static: false })
|
||||||
|
@ -86,6 +92,14 @@ export class ProfileComponent implements OnInit {
|
||||||
|
|
||||||
ngOnInit() {}
|
ngOnInit() {}
|
||||||
|
|
||||||
|
onClickProfileImageView() {
|
||||||
|
this.profileImageView.emit();
|
||||||
|
}
|
||||||
|
|
||||||
|
onClickSendElephant() {
|
||||||
|
this.sendElephant.emit();
|
||||||
|
}
|
||||||
|
|
||||||
onClickOpenChat() {
|
onClickOpenChat() {
|
||||||
this.openChat.emit(this.userInfo);
|
this.openChat.emit(this.userInfo);
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,10 @@
|
||||||
*ngSwitchCase="FileViewerType.Image"
|
*ngSwitchCase="FileViewerType.Image"
|
||||||
[fileInfo]="fileInfo"
|
[fileInfo]="fileInfo"
|
||||||
[fileDownloadUrl]="fileDownloadUrl"
|
[fileDownloadUrl]="fileDownloadUrl"
|
||||||
|
[imageOnly]="imageOnly"
|
||||||
|
[imageOnlyData]="imageOnlyData"
|
||||||
(download)="onDownload($event)"
|
(download)="onDownload($event)"
|
||||||
|
(saveAs)="onSaveAs($event)"
|
||||||
(closed)="onClosedViewer()"
|
(closed)="onClosedViewer()"
|
||||||
></ucap-image-viewer>
|
></ucap-image-viewer>
|
||||||
<ucap-sound-viewer
|
<ucap-sound-viewer
|
||||||
|
@ -28,6 +31,7 @@
|
||||||
[fileInfo]="fileInfo"
|
[fileInfo]="fileInfo"
|
||||||
[fileDownloadUrl]="fileDownloadUrl"
|
[fileDownloadUrl]="fileDownloadUrl"
|
||||||
(download)="onDownload($event)"
|
(download)="onDownload($event)"
|
||||||
|
(saveAs)="onSaveAs($event)"
|
||||||
(closed)="onClosedViewer()"
|
(closed)="onClosedViewer()"
|
||||||
></ucap-video-viewer>
|
></ucap-video-viewer>
|
||||||
<ucap-binary-viewer
|
<ucap-binary-viewer
|
||||||
|
@ -35,6 +39,7 @@
|
||||||
[fileInfo]="fileInfo"
|
[fileInfo]="fileInfo"
|
||||||
[fileDownloadUrl]="fileDownloadUrl"
|
[fileDownloadUrl]="fileDownloadUrl"
|
||||||
(download)="onDownload($event)"
|
(download)="onDownload($event)"
|
||||||
|
(saveAs)="onSaveAs($event)"
|
||||||
(closed)="onClosedViewer()"
|
(closed)="onClosedViewer()"
|
||||||
></ucap-binary-viewer>
|
></ucap-binary-viewer>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -4,6 +4,7 @@ import { FileEventJson } from '@ucap-webmessenger/protocol-event';
|
||||||
import { FileViewerType } from '../types/file-viewer.type';
|
import { FileViewerType } from '../types/file-viewer.type';
|
||||||
import { FileType } from '@ucap-webmessenger/protocol-file';
|
import { FileType } from '@ucap-webmessenger/protocol-file';
|
||||||
import { FileDownloadItem } from '@ucap-webmessenger/api';
|
import { FileDownloadItem } from '@ucap-webmessenger/api';
|
||||||
|
import { ImageOnlyDataInfo } from '../models/image-only-data-info';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'ucap-file-viewer',
|
selector: 'ucap-file-viewer',
|
||||||
|
@ -18,8 +19,15 @@ export class FileViewerComponent implements OnInit {
|
||||||
@Input()
|
@Input()
|
||||||
fileDownloadUrl: string;
|
fileDownloadUrl: string;
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
imageOnly = false;
|
||||||
|
@Input()
|
||||||
|
imageOnlyData?: ImageOnlyDataInfo;
|
||||||
|
|
||||||
@Output()
|
@Output()
|
||||||
download = new EventEmitter<FileDownloadItem>();
|
download = new EventEmitter<FileDownloadItem>();
|
||||||
|
@Output()
|
||||||
|
saveAs = new EventEmitter<FileDownloadItem>();
|
||||||
|
|
||||||
@Output()
|
@Output()
|
||||||
closed = new EventEmitter<void>();
|
closed = new EventEmitter<void>();
|
||||||
|
@ -31,6 +39,10 @@ export class FileViewerComponent implements OnInit {
|
||||||
ngOnInit() {}
|
ngOnInit() {}
|
||||||
|
|
||||||
detectFileViewerType(fileInfo: FileEventJson): FileViewerType {
|
detectFileViewerType(fileInfo: FileEventJson): FileViewerType {
|
||||||
|
if (!!this.imageOnly) {
|
||||||
|
return FileViewerType.Image;
|
||||||
|
}
|
||||||
|
|
||||||
switch (fileInfo.fileType) {
|
switch (fileInfo.fileType) {
|
||||||
case FileType.Image:
|
case FileType.Image:
|
||||||
return FileViewerType.Image;
|
return FileViewerType.Image;
|
||||||
|
@ -48,6 +60,9 @@ export class FileViewerComponent implements OnInit {
|
||||||
onDownload(fileDownloadItem: FileDownloadItem): void {
|
onDownload(fileDownloadItem: FileDownloadItem): void {
|
||||||
this.download.emit(fileDownloadItem);
|
this.download.emit(fileDownloadItem);
|
||||||
}
|
}
|
||||||
|
onSaveAs(fileDownloadItem: FileDownloadItem): void {
|
||||||
|
this.saveAs.emit(fileDownloadItem);
|
||||||
|
}
|
||||||
|
|
||||||
onClosedViewer(): void {
|
onClosedViewer(): void {
|
||||||
this.closed.emit();
|
this.closed.emit();
|
||||||
|
|
|
@ -44,6 +44,31 @@
|
||||||
/>
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
|
<button
|
||||||
|
mat-icon-button
|
||||||
|
class="ucap-image-viewer-action"
|
||||||
|
matTooltip="{{ 'common.file.saveAs' | translate }}"
|
||||||
|
matTooltipPosition="below"
|
||||||
|
aria-label=""
|
||||||
|
(click)="onClickSaveAs()"
|
||||||
|
>
|
||||||
|
<!--<mat-icon>get_app</mat-icon>-->
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="21"
|
||||||
|
height="21"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
stroke-width="2"
|
||||||
|
stroke-linecap="butt"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M3 15v4c0 1.1.9 2 2 2h14a2 2 0 0 0 2-2v-4M17 9l-5 5-5-5M12 12.8V2.5"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
<span class="stroke-bar"></span>
|
<span class="stroke-bar"></span>
|
||||||
<button
|
<button
|
||||||
mat-icon-button
|
mat-icon-button
|
||||||
|
@ -94,7 +119,7 @@
|
||||||
<div class="guide-msg">
|
<div class="guide-msg">
|
||||||
{{ 'common.file.errors.noPreview' | translate }}
|
{{ 'common.file.errors.noPreview' | translate }}
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div class="btn-group">
|
||||||
<button
|
<button
|
||||||
colori
|
colori
|
||||||
mat-raised-button
|
mat-raised-button
|
||||||
|
@ -103,6 +128,14 @@
|
||||||
>
|
>
|
||||||
{{ 'common.file.download' | translate }}
|
{{ 'common.file.download' | translate }}
|
||||||
</button>
|
</button>
|
||||||
|
<button
|
||||||
|
colori
|
||||||
|
mat-raised-button
|
||||||
|
aria-label=""
|
||||||
|
(click)="onClickSaveAs()"
|
||||||
|
>
|
||||||
|
{{ 'common.file.saveAs' | translate }}
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -60,5 +60,10 @@
|
||||||
margin: 30px;
|
margin: 30px;
|
||||||
color: #ffffff;
|
color: #ffffff;
|
||||||
}
|
}
|
||||||
|
.btn-group {
|
||||||
|
button {
|
||||||
|
margin: 0 5px;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,8 @@ export class BinaryViewerComponent implements OnInit {
|
||||||
|
|
||||||
@Output()
|
@Output()
|
||||||
download = new EventEmitter<FileDownloadItem>();
|
download = new EventEmitter<FileDownloadItem>();
|
||||||
|
@Output()
|
||||||
|
saveAs = new EventEmitter<FileDownloadItem>();
|
||||||
|
|
||||||
@Output()
|
@Output()
|
||||||
closed = new EventEmitter<void>();
|
closed = new EventEmitter<void>();
|
||||||
|
@ -33,6 +35,11 @@ export class BinaryViewerComponent implements OnInit {
|
||||||
this.download.emit(this.fileDownloadItem);
|
this.download.emit(this.fileDownloadItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onClickSaveAs(): void {
|
||||||
|
this.fileDownloadItem = new FileDownloadItem();
|
||||||
|
this.saveAs.emit(this.fileDownloadItem);
|
||||||
|
}
|
||||||
|
|
||||||
onClickClose(): void {
|
onClickClose(): void {
|
||||||
this.closed.emit();
|
this.closed.emit();
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,10 +17,21 @@
|
||||||
<circle cx="8.5" cy="8.5" r="1.5" />
|
<circle cx="8.5" cy="8.5" r="1.5" />
|
||||||
<path d="M20.4 14.5L16 10 4 20" />
|
<path d="M20.4 14.5L16 10 4 20" />
|
||||||
</svg>
|
</svg>
|
||||||
<span class="ucap-image-viewer-title">{{ fileInfo.fileName }}</span>
|
<span class="ucap-image-viewer-title">
|
||||||
|
<ng-container
|
||||||
|
*ngIf="imageOnly; then imageOnlyName; else defaultName"
|
||||||
|
></ng-container>
|
||||||
|
<ng-template #imageOnlyName>
|
||||||
|
{{ imageOnlyData.fileName }}
|
||||||
|
</ng-template>
|
||||||
|
<ng-template #defaultName>
|
||||||
|
{{ fileInfo.fileName }}
|
||||||
|
</ng-template>
|
||||||
|
</span>
|
||||||
<span class="ucap-image-viewer-spacer"></span>
|
<span class="ucap-image-viewer-spacer"></span>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
|
*ngIf="!imageOnly"
|
||||||
mat-icon-button
|
mat-icon-button
|
||||||
class="ucap-image-viewer-action"
|
class="ucap-image-viewer-action"
|
||||||
matTooltip="{{ 'common.messages.zoomReset' | translate }}"
|
matTooltip="{{ 'common.messages.zoomReset' | translate }}"
|
||||||
|
@ -47,6 +58,7 @@
|
||||||
</svg>
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
|
*ngIf="!imageOnly"
|
||||||
mat-icon-button
|
mat-icon-button
|
||||||
class="ucap-image-viewer-action"
|
class="ucap-image-viewer-action"
|
||||||
matTooltip="{{ 'common.messages.zoomOut' | translate }}"
|
matTooltip="{{ 'common.messages.zoomOut' | translate }}"
|
||||||
|
@ -72,6 +84,7 @@
|
||||||
</svg>
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
|
*ngIf="!imageOnly"
|
||||||
mat-icon-button
|
mat-icon-button
|
||||||
class="ucap-image-viewer-action"
|
class="ucap-image-viewer-action"
|
||||||
matTooltip="{{ 'common.messages.zoomIn' | translate }}"
|
matTooltip="{{ 'common.messages.zoomIn' | translate }}"
|
||||||
|
@ -98,6 +111,7 @@
|
||||||
</svg>
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
|
*ngIf="!imageOnly"
|
||||||
mat-icon-button
|
mat-icon-button
|
||||||
class="ucap-image-viewer-action"
|
class="ucap-image-viewer-action"
|
||||||
matTooltip="{{ 'common.file.download' | translate }}"
|
matTooltip="{{ 'common.file.download' | translate }}"
|
||||||
|
@ -122,6 +136,32 @@
|
||||||
/>
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
|
<button
|
||||||
|
*ngIf="!imageOnly"
|
||||||
|
mat-icon-button
|
||||||
|
class="ucap-image-viewer-action"
|
||||||
|
matTooltip="{{ 'common.file.saveAs' | translate }}"
|
||||||
|
matTooltipPosition="below"
|
||||||
|
aria-label=""
|
||||||
|
(click)="onClickSaveAs()"
|
||||||
|
>
|
||||||
|
<!--<mat-icon>get_app</mat-icon>-->
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="21"
|
||||||
|
height="21"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
stroke-width="2"
|
||||||
|
stroke-linecap="butt"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M3 15v4c0 1.1.9 2 2 2h14a2 2 0 0 0 2-2v-4M17 9l-5 5-5-5M12 12.8V2.5"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
<span class="stroke-bar"></span>
|
<span class="stroke-bar"></span>
|
||||||
<button
|
<button
|
||||||
mat-icon-button
|
mat-icon-button
|
||||||
|
@ -166,6 +206,20 @@
|
||||||
fxFlexFill
|
fxFlexFill
|
||||||
fxLayoutAlign="center center"
|
fxLayoutAlign="center center"
|
||||||
>
|
>
|
||||||
|
<ng-container
|
||||||
|
*ngIf="imageOnly; then imageOnlyImg; else defaultImg"
|
||||||
|
></ng-container>
|
||||||
|
<ng-template #imageOnlyImg>
|
||||||
|
<img
|
||||||
|
ucapImage
|
||||||
|
[base]="imageOnlyData.imageRootUrl"
|
||||||
|
[path]="imageOnlyData.imageUrl"
|
||||||
|
[default]="imageOnlyData.defaultImage"
|
||||||
|
style="cursor: pointer; width: auto;"
|
||||||
|
(click)="onClickClose()"
|
||||||
|
/>
|
||||||
|
</ng-template>
|
||||||
|
<ng-template #defaultImg>
|
||||||
<img
|
<img
|
||||||
#downloadImage
|
#downloadImage
|
||||||
*ngIf="fileDownloadUrl"
|
*ngIf="fileDownloadUrl"
|
||||||
|
@ -174,6 +228,7 @@
|
||||||
[style.height]="imageHeight + 'px'"
|
[style.height]="imageHeight + 'px'"
|
||||||
(load)="onLoadFileDownloadUrl(downloadImage)"
|
(load)="onLoadFileDownloadUrl(downloadImage)"
|
||||||
/>
|
/>
|
||||||
|
</ng-template>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -13,6 +13,7 @@ import {
|
||||||
import { ucapAnimations } from '../../animations';
|
import { ucapAnimations } from '../../animations';
|
||||||
import { FileEventJson } from '@ucap-webmessenger/protocol-event';
|
import { FileEventJson } from '@ucap-webmessenger/protocol-event';
|
||||||
import { FileDownloadItem } from '@ucap-webmessenger/api';
|
import { FileDownloadItem } from '@ucap-webmessenger/api';
|
||||||
|
import { ImageOnlyDataInfo } from '../../models/image-only-data-info';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'ucap-image-viewer',
|
selector: 'ucap-image-viewer',
|
||||||
|
@ -28,11 +29,18 @@ export class ImageViewerComponent implements OnInit {
|
||||||
@Input()
|
@Input()
|
||||||
fileDownloadUrl: string;
|
fileDownloadUrl: string;
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
imageOnly = false;
|
||||||
|
@Input()
|
||||||
|
imageOnlyData?: ImageOnlyDataInfo;
|
||||||
|
|
||||||
@Output()
|
@Output()
|
||||||
closed = new EventEmitter<void>();
|
closed = new EventEmitter<void>();
|
||||||
|
|
||||||
@Output()
|
@Output()
|
||||||
download = new EventEmitter<FileDownloadItem>();
|
download = new EventEmitter<FileDownloadItem>();
|
||||||
|
@Output()
|
||||||
|
saveAs = new EventEmitter<FileDownloadItem>();
|
||||||
|
|
||||||
@ViewChild('imageContainer', { static: false })
|
@ViewChild('imageContainer', { static: false })
|
||||||
imageContainer: ElementRef<HTMLElement>;
|
imageContainer: ElementRef<HTMLElement>;
|
||||||
|
@ -67,6 +75,11 @@ export class ImageViewerComponent implements OnInit {
|
||||||
this.download.emit(this.fileDownloadItem);
|
this.download.emit(this.fileDownloadItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onClickSaveAs(): void {
|
||||||
|
this.fileDownloadItem = new FileDownloadItem();
|
||||||
|
this.saveAs.emit(this.fileDownloadItem);
|
||||||
|
}
|
||||||
|
|
||||||
onClickClose(): void {
|
onClickClose(): void {
|
||||||
this.closed.emit();
|
this.closed.emit();
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,31 @@
|
||||||
/>
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
|
<button
|
||||||
|
mat-icon-button
|
||||||
|
class="ucap-image-viewer-action"
|
||||||
|
matTooltip="{{ 'common.file.saveAs' | translate }}"
|
||||||
|
matTooltipPosition="below"
|
||||||
|
aria-label=""
|
||||||
|
(click)="onClickSaveAs()"
|
||||||
|
>
|
||||||
|
<!--<mat-icon>get_app</mat-icon>-->
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="21"
|
||||||
|
height="21"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
stroke-width="2"
|
||||||
|
stroke-linecap="butt"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M3 15v4c0 1.1.9 2 2 2h14a2 2 0 0 0 2-2v-4M17 9l-5 5-5-5M12 12.8V2.5"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
<span class="stroke-bar"></span>
|
<span class="stroke-bar"></span>
|
||||||
<button
|
<button
|
||||||
mat-icon-button
|
mat-icon-button
|
||||||
|
|
|
@ -27,6 +27,8 @@ export class SoundViewerComponent implements OnInit {
|
||||||
|
|
||||||
@Output()
|
@Output()
|
||||||
download = new EventEmitter<FileDownloadItem>();
|
download = new EventEmitter<FileDownloadItem>();
|
||||||
|
@Output()
|
||||||
|
saveAs = new EventEmitter<FileDownloadItem>();
|
||||||
|
|
||||||
@Output()
|
@Output()
|
||||||
closed = new EventEmitter<void>();
|
closed = new EventEmitter<void>();
|
||||||
|
@ -95,6 +97,11 @@ export class SoundViewerComponent implements OnInit {
|
||||||
this.download.emit(this.fileDownloadItem);
|
this.download.emit(this.fileDownloadItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onClickSaveAs(): void {
|
||||||
|
this.fileDownloadItem = new FileDownloadItem();
|
||||||
|
this.saveAs.emit(this.fileDownloadItem);
|
||||||
|
}
|
||||||
|
|
||||||
onClickClose(): void {
|
onClickClose(): void {
|
||||||
this.closed.emit();
|
this.closed.emit();
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,6 +49,31 @@
|
||||||
/>
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
|
<button
|
||||||
|
mat-icon-button
|
||||||
|
class="ucap-image-viewer-action"
|
||||||
|
matTooltip="{{ 'common.file.saveAs' | translate }}"
|
||||||
|
matTooltipPosition="below"
|
||||||
|
aria-label=""
|
||||||
|
(click)="onClickSaveAs()"
|
||||||
|
>
|
||||||
|
<!--<mat-icon>get_app</mat-icon>-->
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="21"
|
||||||
|
height="21"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
stroke-width="2"
|
||||||
|
stroke-linecap="butt"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M3 15v4c0 1.1.9 2 2 2h14a2 2 0 0 0 2-2v-4M17 9l-5 5-5-5M12 12.8V2.5"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
<span class="stroke-bar"></span>
|
<span class="stroke-bar"></span>
|
||||||
<button
|
<button
|
||||||
mat-icon-button
|
mat-icon-button
|
||||||
|
|
|
@ -30,6 +30,8 @@ export class VideoViewerComponent implements OnInit {
|
||||||
|
|
||||||
@Output()
|
@Output()
|
||||||
download = new EventEmitter<FileDownloadItem>();
|
download = new EventEmitter<FileDownloadItem>();
|
||||||
|
@Output()
|
||||||
|
saveAs = new EventEmitter<FileDownloadItem>();
|
||||||
|
|
||||||
@Output()
|
@Output()
|
||||||
closed = new EventEmitter<void>();
|
closed = new EventEmitter<void>();
|
||||||
|
@ -116,6 +118,11 @@ export class VideoViewerComponent implements OnInit {
|
||||||
this.download.emit(this.fileDownloadItem);
|
this.download.emit(this.fileDownloadItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onClickSaveAs(): void {
|
||||||
|
this.fileDownloadItem = new FileDownloadItem();
|
||||||
|
this.saveAs.emit(this.fileDownloadItem);
|
||||||
|
}
|
||||||
|
|
||||||
onClickClose(): void {
|
onClickClose(): void {
|
||||||
this.closed.emit();
|
this.closed.emit();
|
||||||
}
|
}
|
||||||
|
|
|
@ -125,7 +125,7 @@
|
||||||
</th>
|
</th>
|
||||||
<td mat-cell *matCellDef="let element" class="lineNumber">
|
<td mat-cell *matCellDef="let element" class="lineNumber">
|
||||||
<div class="lineNumber">
|
<div class="lineNumber">
|
||||||
{{ element.lineNumber }}
|
{{ element.lineNumber | ucapStringFormatterPhone }}
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
@ -140,7 +140,7 @@
|
||||||
</th>
|
</th>
|
||||||
<td mat-cell *matCellDef="let element" class="hpNumber">
|
<td mat-cell *matCellDef="let element" class="hpNumber">
|
||||||
<div class="hpNumber">
|
<div class="hpNumber">
|
||||||
{{ element.hpNumber }}
|
{{ element.hpNumber | ucapStringFormatterPhone }}
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
export interface ImageOnlyDataInfo {
|
||||||
|
imageUrl: string;
|
||||||
|
imageRootUrl: string;
|
||||||
|
defaultImage: string;
|
||||||
|
fileName: string;
|
||||||
|
}
|
|
@ -30,6 +30,8 @@ export * from './lib/directives/click-outside.directive';
|
||||||
export * from './lib/directives/file-upload-for.directive';
|
export * from './lib/directives/file-upload-for.directive';
|
||||||
export * from './lib/directives/image.directive';
|
export * from './lib/directives/image.directive';
|
||||||
|
|
||||||
|
export * from './lib/models/image-only-data-info';
|
||||||
|
|
||||||
export * from './lib/services/bottom-sheet.service';
|
export * from './lib/services/bottom-sheet.service';
|
||||||
export * from './lib/services/clipboard.service';
|
export * from './lib/services/clipboard.service';
|
||||||
export * from './lib/services/dialog.service';
|
export * from './lib/services/dialog.service';
|
||||||
|
|
Loading…
Reference in New Issue
Block a user