This commit is contained in:
khk 2019-11-13 15:44:46 +09:00
commit ae1b3503d3
158 changed files with 3806 additions and 1276 deletions

View File

@ -1,5 +1,5 @@
{ {
"trailingComma": "es5", "trailingComma": "none",
"tabWidth": 2, "tabWidth": 2,
"singleQuote": true "singleQuote": true
} }

View File

@ -41,6 +41,8 @@
"with": "projects/ucap-webmessenger-app/src/environments/environment-browser.dev.ts" "with": "projects/ucap-webmessenger-app/src/environments/environment-browser.dev.ts"
} }
], ],
"polyfills": "projects/ucap-webmessenger-app/src/polyfills-es5.ts",
"tsConfig": "projects/ucap-webmessenger-app/tsconfig-es5.app.json",
"optimization": false, "optimization": false,
"outputHashing": "all", "outputHashing": "all",
"sourceMap": true, "sourceMap": true,
@ -70,6 +72,8 @@
"with": "projects/ucap-webmessenger-app/src/environments/environment-browser.prod.ts" "with": "projects/ucap-webmessenger-app/src/environments/environment-browser.prod.ts"
} }
], ],
"polyfills": "projects/ucap-webmessenger-app/src/polyfills-es5.ts",
"tsConfig": "projects/ucap-webmessenger-app/tsconfig-es5.app.json",
"optimization": true, "optimization": true,
"outputHashing": "all", "outputHashing": "all",
"sourceMap": false, "sourceMap": false,
@ -82,7 +86,7 @@
"budgets": [ "budgets": [
{ {
"type": "initial", "type": "initial",
"maximumWarning": "2mb", "maximumWarning": "4mb",
"maximumError": "5mb" "maximumError": "5mb"
}, },
{ {
@ -140,7 +144,7 @@
"budgets": [ "budgets": [
{ {
"type": "initial", "type": "initial",
"maximumWarning": "2mb", "maximumWarning": "4mb",
"maximumError": "5mb" "maximumError": "5mb"
}, },
{ {
@ -155,7 +159,8 @@
"serve": { "serve": {
"builder": "@angular-builders/custom-webpack:dev-server", "builder": "@angular-builders/custom-webpack:dev-server",
"options": { "options": {
"browserTarget": "ucap-webmessenger-app:build" "browserTarget": "ucap-webmessenger-app:build",
"disableHostCheck": true
}, },
"configurations": { "configurations": {
"browser-development": { "browser-development": {
@ -354,6 +359,40 @@
} }
} }
}, },
"ucap-webmessenger-api-message": {
"projectType": "library",
"root": "projects/ucap-webmessenger-api-message",
"sourceRoot": "projects/ucap-webmessenger-api-message/src",
"prefix": "ucap-api-message",
"architect": {
"build": {
"builder": "@angular-devkit/build-ng-packagr:build",
"options": {
"tsConfig": "projects/ucap-webmessenger-api-message/tsconfig.lib.json",
"project": "projects/ucap-webmessenger-api-message/ng-package.json"
}
},
"test": {
"builder": "@angular-devkit/build-angular:karma",
"options": {
"main": "projects/ucap-webmessenger-api-message/src/test.ts",
"tsConfig": "projects/ucap-webmessenger-api-message/tsconfig.spec.json",
"karmaConfig": "projects/ucap-webmessenger-api-message/karma.conf.js"
}
},
"lint": {
"builder": "@angular-devkit/build-angular:tslint",
"options": {
"tsConfig": [
"projects/ucap-webmessenger-api-message/tsconfig.lib.json",
"projects/ucap-webmessenger-api-message/tsconfig.spec.json"
],
"exclude": ["**/node_modules/**"]
}
}
}
},
"ucap-webmessenger-api": { "ucap-webmessenger-api": {
"projectType": "library", "projectType": "library",
"root": "projects/ucap-webmessenger-api", "root": "projects/ucap-webmessenger-api",

View File

@ -4,14 +4,12 @@ module.exports = (config, options) => {
const PRODUCTION = process.env.NODE_ENV === 'production'; const PRODUCTION = process.env.NODE_ENV === 'production';
const BROWSER = process.env.UCAP_ENV_RUNTIME === 'BROWSER'; const BROWSER = process.env.UCAP_ENV_RUNTIME === 'BROWSER';
console.log('BROWSER', BROWSER, config.target);
if (!BROWSER) { if (!BROWSER) {
config.target = 'electron-renderer'; config.target = 'electron-renderer';
} else { } else {
config.target = 'web'; config.target = 'web';
config.node = { config.node = {
fs: 'empty' fs: 'empty',
}; };
} }
@ -21,7 +19,7 @@ module.exports = (config, options) => {
__dirname, __dirname,
'..', '..',
'projects/ucap-webmessenger-ui/src/assets/scss' 'projects/ucap-webmessenger-ui/src/assets/scss'
) ),
}; };
return config; return config;

View File

@ -13,6 +13,6 @@ export function getEnviroments() {
__DEV__: channel === 'development', __DEV__: channel === 'development',
'process.platform': s(process.platform), 'process.platform': s(process.platform),
'process.env.NODE_ENV': s(process.env.NODE_ENV || 'development'), 'process.env.NODE_ENV': s(process.env.NODE_ENV || 'development'),
'process.env.TEST_ENV': s(process.env.TEST_ENV) 'process.env.TEST_ENV': s(process.env.TEST_ENV),
}; };
} }

View File

@ -20,18 +20,18 @@ const mainConfig: webpack.Configuration = {
__dirname, __dirname,
'..', '..',
'electron-projects/ucap-webmessenger-electron/src/index' 'electron-projects/ucap-webmessenger-electron/src/index'
) ),
}, },
target: 'electron-main', target: 'electron-main',
mode: enviroments.__DEV__ ? 'development' : 'production', mode: enviroments.__DEV__ ? 'development' : 'production',
devtool: 'source-map', devtool: 'source-map',
optimization: { optimization: {
noEmitOnErrors: true noEmitOnErrors: true,
}, },
externals, externals,
output: { output: {
filename: '[name].js', filename: '[name].js',
path: path.resolve(__dirname, '..', outputDir) path: path.resolve(__dirname, '..', outputDir),
}, },
module: { module: {
rules: [ rules: [
@ -44,7 +44,7 @@ const mainConfig: webpack.Configuration = {
'electron-projects/ucap-webmessenger-electron/src' 'electron-projects/ucap-webmessenger-electron/src'
), ),
path.resolve(__dirname, '..', 'electron-projects'), path.resolve(__dirname, '..', 'electron-projects'),
path.resolve(__dirname, '..', 'projects') path.resolve(__dirname, '..', 'projects'),
], ],
use: [ use: [
{ {
@ -55,20 +55,20 @@ const mainConfig: webpack.Configuration = {
__dirname, __dirname,
'..', '..',
'electron-projects/ucap-webmessenger-electron/tsconfig.electron.json' 'electron-projects/ucap-webmessenger-electron/tsconfig.electron.json'
) ),
} },
} },
], ],
exclude: /node_modules/ exclude: /node_modules/,
}, },
{ {
test: /\.node$/, test: /\.node$/,
loader: 'awesome-node-loader', loader: 'awesome-node-loader',
options: { options: {
name: '[name].[ext]' name: '[name].[ext]',
} },
} },
] ],
}, },
plugins: [ plugins: [
new CleanWebpackPlugin({ verbose: false }), new CleanWebpackPlugin({ verbose: false }),
@ -77,16 +77,16 @@ const mainConfig: webpack.Configuration = {
new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/), new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),
new webpack.DefinePlugin( new webpack.DefinePlugin(
Object.assign({}, enviroments, { Object.assign({}, enviroments, {
__PROCESS_KIND__: JSON.stringify('main') __PROCESS_KIND__: JSON.stringify('main'),
}) })
), ),
new CopyWebpackPlugin([ new CopyWebpackPlugin([
{ {
from: 'ucap-webmessenger-electron/resources/**/*', from: 'ucap-webmessenger-electron/resources/**/*',
to: path.resolve(__dirname, '..', 'dist'), to: path.resolve(__dirname, '..', 'dist'),
context: 'electron-projects' context: 'electron-projects',
} },
]) ]),
], ],
resolve: { resolve: {
extensions: ['.js', '.ts'], extensions: ['.js', '.ts'],
@ -101,6 +101,11 @@ const mainConfig: webpack.Configuration = {
'..', '..',
'electron-projects/ucap-webmessenger-electron-notification/src/public-api' 'electron-projects/ucap-webmessenger-electron-notification/src/public-api'
), ),
'@ucap-webmessenger/core': path.resolve(
__dirname,
'..',
'projects/ucap-webmessenger-core/src/public-api'
),
'@ucap-webmessenger/native': path.resolve( '@ucap-webmessenger/native': path.resolve(
__dirname, __dirname,
'..', '..',
@ -115,14 +120,14 @@ const mainConfig: webpack.Configuration = {
__dirname, __dirname,
'..', '..',
'electron-projects/ucap-webmessenger-electron/src/public-api' 'electron-projects/ucap-webmessenger-electron/src/public-api'
) ),
}, },
modules: [path.resolve(__dirname, '..', 'node_modules/')] modules: [path.resolve(__dirname, '..', 'node_modules/')],
}, },
node: { node: {
__dirname: false, __dirname: false,
__filename: false __filename: false,
} },
}; };
export default [mainConfig]; export default [mainConfig];

View File

@ -0,0 +1,9 @@
version: '3.1'
services:
nginx:
image: nginx:1.17.5-alpine
volumes:
- ../dist/ucap-webmessenger-app:/usr/share/nginx/html:ro
ports:
- 8099:80

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 999 B

View File

@ -241,8 +241,9 @@ ipcMain.on(
try { try {
const buffer: Buffer = args[0]; const buffer: Buffer = args[0];
const fileName: string = args[1]; const fileName: string = args[1];
const mimeType: string = args[2];
let savePath: string = path.join( let savePath: string = path.join(
!!args[2] ? args[2] : DefaultFolder.downloads(), !!args[3] ? args[3] : DefaultFolder.downloads(),
fileName fileName
); );
savePath = await FileUtil.uniqueFileName(savePath); savePath = await FileUtil.uniqueFileName(savePath);

View File

@ -19,6 +19,9 @@
"@ucap-webmessenger/electron-notification": [ "@ucap-webmessenger/electron-notification": [
"../ucap-webmessenger-electron-notification/src/public-api" "../ucap-webmessenger-electron-notification/src/public-api"
], ],
"@ucap-webmessenger/core": [
"../../projects/ucap-webmessenger-core/src/public-api"
],
"@ucap-webmessenger/native": [ "@ucap-webmessenger/native": [
"../../projects/ucap-webmessenger-native/src/public-api" "../../projects/ucap-webmessenger-native/src/public-api"
], ],

21
package-lock.json generated
View File

@ -2789,6 +2789,15 @@
"integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=",
"dev": true "dev": true
}, },
"angular-split": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/angular-split/-/angular-split-3.0.2.tgz",
"integrity": "sha512-km59k1kEgVlplo2t4t5Ob43Vx16qVXWXsl5gbsdQtqrOW7341So4CFUmCjcZgfk1swu9RBaCdSQEqzNWOe/89w==",
"dev": true,
"requires": {
"tslib": "^1.9.0"
}
},
"ansi-align": { "ansi-align": {
"version": "3.0.0", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.0.tgz", "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.0.tgz",
@ -4184,6 +4193,12 @@
} }
} }
}, },
"classlist.js": {
"version": "1.1.20150312",
"resolved": "https://registry.npmjs.org/classlist.js/-/classlist.js-1.1.20150312.tgz",
"integrity": "sha1-HXCEL3Ai8I2awIbOaeWyUPLFd4k=",
"dev": true
},
"clean-css": { "clean-css": {
"version": "4.2.1", "version": "4.2.1",
"resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.1.tgz", "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.1.tgz",
@ -15387,6 +15402,12 @@
"minimalistic-assert": "^1.0.0" "minimalistic-assert": "^1.0.0"
} }
}, },
"web-animations-js": {
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/web-animations-js/-/web-animations-js-2.3.2.tgz",
"integrity": "sha512-TOMFWtQdxzjWp8qx4DAraTWTsdhxVSiWa6NkPFSaPtZ1diKUxTn4yTix73A1euG1WbSOMMPcY51cnjTIHrGtDA==",
"dev": true
},
"webdriver-js-extender": { "webdriver-js-extender": {
"version": "2.1.0", "version": "2.1.0",
"resolved": "https://registry.npmjs.org/webdriver-js-extender/-/webdriver-js-extender-2.1.0.tgz", "resolved": "https://registry.npmjs.org/webdriver-js-extender/-/webdriver-js-extender-2.1.0.tgz",

View File

@ -7,7 +7,9 @@
"start:main": "wait-on http-get://localhost:4200/ && npm run build:main:development && electron --nolazy --inspect-brk=9229 .", "start:main": "wait-on http-get://localhost:4200/ && npm run build:main:development && electron --nolazy --inspect-brk=9229 .",
"start:renderer": "cross-env UCAP_ENV_RUNTIME=ELECTRON ng serve -c renderer-development", "start:renderer": "cross-env UCAP_ENV_RUNTIME=ELECTRON ng serve -c renderer-development",
"start:browser": "cross-env UCAP_ENV_RUNTIME=BROWSER ng serve -c browser-development -o", "start:browser": "cross-env UCAP_ENV_RUNTIME=BROWSER ng serve -c browser-development -o",
"build": "npm-run-all -p build:renderer build:main:production",
"build:renderer": "cross-env NODE_ENV=production ng build --base-href ./", "build:renderer": "cross-env NODE_ENV=production ng build --base-href ./",
"build:browser": "cross-env UCAP_ENV_RUNTIME=BROWSER ng build -c browser-development",
"build:main:development": "cross-env NODE_ENV=development TS_NODE_PROJECT='./config/tsconfig.webpack.json' parallel-webpack --config=config/main.webpack.config.ts", "build:main:development": "cross-env NODE_ENV=development TS_NODE_PROJECT='./config/tsconfig.webpack.json' parallel-webpack --config=config/main.webpack.config.ts",
"build:main:production": "cross-env NODE_ENV=production TS_NODE_PROJECT='./config/tsconfig.webpack.json' NODE_OPTIONS='--max_old_space_size=4096' parallel-webpack --config=config/main.webpack.config.ts", "build:main:production": "cross-env NODE_ENV=production TS_NODE_PROJECT='./config/tsconfig.webpack.json' NODE_OPTIONS='--max_old_space_size=4096' parallel-webpack --config=config/main.webpack.config.ts",
"test": "ng test", "test": "ng test",
@ -59,8 +61,10 @@
"@types/webpack": "^4.39.5", "@types/webpack": "^4.39.5",
"@types/webpack-merge": "^4.1.5", "@types/webpack-merge": "^4.1.5",
"@types/webpack-node-externals": "^1.6.3", "@types/webpack-node-externals": "^1.6.3",
"angular-split": "^3.0.2",
"awesome-node-loader": "^1.1.1", "awesome-node-loader": "^1.1.1",
"awesome-typescript-loader": "^5.2.1", "awesome-typescript-loader": "^5.2.1",
"classlist.js": "^1.1.20150312",
"clean-webpack-plugin": "^3.0.0", "clean-webpack-plugin": "^3.0.0",
"copy-webpack-plugin": "^5.0.4", "copy-webpack-plugin": "^5.0.4",
"codelyzer": "^5.0.0", "codelyzer": "^5.0.0",
@ -106,6 +110,7 @@
"tslint": "~5.15.0", "tslint": "~5.15.0",
"typescript": "~3.5.3", "typescript": "~3.5.3",
"wait-on": "^3.3.0", "wait-on": "^3.3.0",
"web-animations-js": "^2.3.2",
"webpack": "4.39.2", "webpack": "4.39.2",
"webpack-cli": "^3.3.7", "webpack-cli": "^3.3.7",
"webpack-node-externals": "^1.7.2", "webpack-node-externals": "^1.7.2",

View File

@ -0,0 +1,7 @@
import { ModuleConfig as CoreModuleConfig } from '@ucap-webmessenger/core';
import { Urls } from './urls';
export interface ModuleConfig extends CoreModuleConfig<Urls> {
acceptableFileExtensions: string[];
}

View File

@ -0,0 +1,12 @@
export interface Urls {
fileProfileSave: string;
fileTalkDownload: string;
fileTalkSave: string;
fileTalkShare: string;
massTalkDownload: string;
massTalkSave: string;
transMassTalkDownload: string;
transMassTalkSave: string;
translationReq: string;
translationSave: string;
}

View File

@ -3,82 +3,92 @@ import {
HttpClient, HttpClient,
HttpEventType, HttpEventType,
HttpResponse, HttpResponse,
HttpRequest HttpRequest,
} from '@angular/common/http'; } from '@angular/common/http';
import { Observable, Subject } from 'rxjs'; import { Observable, Subject } from 'rxjs';
import { map, filter } from 'rxjs/operators'; import { map, filter } from 'rxjs/operators';
import { _MODULE_CONFIG } from '../types/token';
import { ModuleConfig } from '../types/module-config';
import { import {
FileProfileSaveRequest, FileProfileSaveRequest,
FileProfileSaveResponse, FileProfileSaveResponse,
encodeFileProfileSave, encodeFileProfileSave,
decodeFileProfileSave decodeFileProfileSave,
} from '../apis/file-profile-save'; } from '../apis/file-profile-save';
import { import {
FileTalkDownloadRequest, FileTalkDownloadRequest,
encodeFileTalkDownload, encodeFileTalkDownload,
encodeFormDataFileTalkDownload encodeFormDataFileTalkDownload,
} from '../apis/file-talk-download'; } from '../apis/file-talk-download';
import { import {
FileTalkSaveRequest, FileTalkSaveRequest,
FileTalkSaveResponse, FileTalkSaveResponse,
encodeFileTalkSave, encodeFileTalkSave,
decodeFileTalkSave decodeFileTalkSave,
} from '../apis/file-talk-save'; } from '../apis/file-talk-save';
import { import {
FileTalkShareRequest, FileTalkShareRequest,
FileTalkShareResponse, FileTalkShareResponse,
encodeFileTalkShare, encodeFileTalkShare,
decodeFileTalkShare decodeFileTalkShare,
} from '../apis/file-talk-share'; } from '../apis/file-talk-share';
import { import {
MassTalkDownloadRequest, MassTalkDownloadRequest,
MassTalkDownloadResponse, MassTalkDownloadResponse,
encodeMassTalkDownload, encodeMassTalkDownload,
decodeMassTalkDownload decodeMassTalkDownload,
} from '../apis/mass-talk-download'; } from '../apis/mass-talk-download';
import { import {
MassTalkSaveRequest, MassTalkSaveRequest,
MassTalkSaveResponse, MassTalkSaveResponse,
encodeMassTalkSave, encodeMassTalkSave,
decodeMassTalkSave decodeMassTalkSave,
} from '../apis/mass-talk-save'; } from '../apis/mass-talk-save';
import { import {
TransMassTalkDownloadRequest, TransMassTalkDownloadRequest,
TransMassTalkDownloadResponse, TransMassTalkDownloadResponse,
encodeTransMassTalkDownload, encodeTransMassTalkDownload,
decodeTransMassTalkDownload decodeTransMassTalkDownload,
} from '../apis/trans-mass-talk-download'; } from '../apis/trans-mass-talk-download';
import { import {
TransMassTalkSaveRequest, TransMassTalkSaveRequest,
TransMassTalkSaveResponse, TransMassTalkSaveResponse,
encodeTransMassTalkSave, encodeTransMassTalkSave,
decodeTransMassTalkSave decodeTransMassTalkSave,
} from '../apis/trans-mass-talk-save'; } from '../apis/trans-mass-talk-save';
import { import {
TranslationReqRequest, TranslationReqRequest,
TranslationReqResponse, TranslationReqResponse,
encodeTranslationReq, encodeTranslationReq,
decodeTranslationReq decodeTranslationReq,
} from '../apis/translation-req'; } from '../apis/translation-req';
import { import {
TranslationSaveRequest, TranslationSaveRequest,
TranslationSaveResponse, TranslationSaveResponse,
encodeTranslationSave, encodeTranslationSave,
decodeTranslationSave decodeTranslationSave,
} from '../apis/translation-save'; } from '../apis/translation-save';
import { _MODULE_CONFIG } from '../config/token';
import { ModuleConfig } from '../config/module-config';
import { Urls } from '../config/urls';
import { UrlConfig } from '@ucap-webmessenger/core';
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root',
}) })
export class CommonApiService { export class CommonApiService {
readonly urls: Urls;
constructor( constructor(
@Inject(_MODULE_CONFIG) private moduleConfig: ModuleConfig, @Inject(_MODULE_CONFIG) private moduleConfig: ModuleConfig,
private httpClient: HttpClient private httpClient: HttpClient
) {} ) {
this.urls = UrlConfig.getUrls(
this.moduleConfig.hostConfig,
this.moduleConfig.urls
);
}
public fileProfileSave( public fileProfileSave(
req: FileProfileSaveRequest, req: FileProfileSaveRequest,
@ -86,12 +96,10 @@ export class CommonApiService {
): Observable<FileProfileSaveResponse> { ): Observable<FileProfileSaveResponse> {
return this.httpClient return this.httpClient
.post<any>( .post<any>(
!!fileProfileSaveUrl !!fileProfileSaveUrl ? fileProfileSaveUrl : this.urls.fileProfileSave,
? fileProfileSaveUrl
: this.moduleConfig.urls.fileProfileSave,
{}, {},
{ {
params: encodeFileProfileSave(req) params: encodeFileProfileSave(req),
} }
) )
.pipe(map(res => decodeFileProfileSave(res))); .pipe(map(res => decodeFileProfileSave(res)));
@ -103,12 +111,10 @@ export class CommonApiService {
): string { ): string {
const httpReq = new HttpRequest( const httpReq = new HttpRequest(
'GET', 'GET',
!!fileTalkDownloadUrl !!fileTalkDownloadUrl ? fileTalkDownloadUrl : this.urls.fileTalkDownload,
? fileTalkDownloadUrl
: this.moduleConfig.urls.fileTalkDownload,
{}, {},
{ {
params: encodeFileTalkDownload(req) params: encodeFileTalkDownload(req),
} }
); );
@ -121,9 +127,7 @@ export class CommonApiService {
): Observable<Blob> { ): Observable<Blob> {
const httpReq = new HttpRequest( const httpReq = new HttpRequest(
'POST', 'POST',
!!fileTalkDownloadUrl !!fileTalkDownloadUrl ? fileTalkDownloadUrl : this.urls.fileTalkDownload,
? fileTalkDownloadUrl
: this.moduleConfig.urls.fileTalkDownload,
encodeFormDataFileTalkDownload(req), encodeFormDataFileTalkDownload(req),
{ reportProgress: true, responseType: 'blob' } { reportProgress: true, responseType: 'blob' }
); );
@ -159,7 +163,7 @@ export class CommonApiService {
): Observable<FileTalkSaveResponse> { ): Observable<FileTalkSaveResponse> {
const httpReq = new HttpRequest( const httpReq = new HttpRequest(
'POST', 'POST',
!!fileTalkSaveUrl ? fileTalkSaveUrl : this.moduleConfig.urls.fileTalkSave, !!fileTalkSaveUrl ? fileTalkSaveUrl : this.urls.fileTalkSave,
encodeFileTalkSave(req), encodeFileTalkSave(req),
{ reportProgress: true, responseType: 'text' as 'json' } { reportProgress: true, responseType: 'text' as 'json' }
); );
@ -185,7 +189,10 @@ export class CommonApiService {
public acceptableExtensionForFileTalk(extensions: string[]): boolean { public acceptableExtensionForFileTalk(extensions: string[]): boolean {
for (const extension of extensions) { for (const extension of extensions) {
if ( if (
-1 === this.moduleConfig.acceptableFileExtensions.indexOf(extension.toLowerCase()) -1 ===
this.moduleConfig.acceptableFileExtensions.indexOf(
extension.toLowerCase()
)
) { ) {
return false; return false;
} }
@ -198,10 +205,10 @@ export class CommonApiService {
): Observable<FileTalkShareResponse> { ): Observable<FileTalkShareResponse> {
return this.httpClient return this.httpClient
.post<any>( .post<any>(
this.moduleConfig.urls.fileTalkShare, this.urls.fileTalkShare,
{}, {},
{ {
params: encodeFileTalkShare(req) params: encodeFileTalkShare(req),
} }
) )
.pipe(map(res => decodeFileTalkShare(res))); .pipe(map(res => decodeFileTalkShare(res)));
@ -212,11 +219,11 @@ export class CommonApiService {
): Observable<MassTalkDownloadResponse> { ): Observable<MassTalkDownloadResponse> {
return this.httpClient return this.httpClient
.post<any>( .post<any>(
this.moduleConfig.urls.massTalkDownload, this.urls.massTalkDownload,
{}, {},
{ {
params: encodeMassTalkDownload(req), params: encodeMassTalkDownload(req),
responseType: 'text' as 'json' responseType: 'text' as 'json',
} }
) )
.pipe(map(res => decodeMassTalkDownload(res))); .pipe(map(res => decodeMassTalkDownload(res)));
@ -227,11 +234,11 @@ export class CommonApiService {
): Observable<MassTalkSaveResponse> { ): Observable<MassTalkSaveResponse> {
return this.httpClient return this.httpClient
.post<any>( .post<any>(
this.moduleConfig.urls.massTalkSave, this.urls.massTalkSave,
{}, {},
{ {
params: encodeMassTalkSave(req), params: encodeMassTalkSave(req),
responseType: 'text' as 'json' responseType: 'text' as 'json',
} }
) )
.pipe(map(res => decodeMassTalkSave(res))); .pipe(map(res => decodeMassTalkSave(res)));
@ -242,10 +249,10 @@ export class CommonApiService {
): Observable<TransMassTalkDownloadResponse> { ): Observable<TransMassTalkDownloadResponse> {
return this.httpClient return this.httpClient
.post<any>( .post<any>(
this.moduleConfig.urls.transMassTalkDownload, this.urls.transMassTalkDownload,
{}, {},
{ {
params: encodeTransMassTalkDownload(req) params: encodeTransMassTalkDownload(req),
} }
) )
.pipe(map(res => decodeTransMassTalkDownload(res))); .pipe(map(res => decodeTransMassTalkDownload(res)));
@ -256,10 +263,10 @@ export class CommonApiService {
): Observable<TransMassTalkSaveResponse> { ): Observable<TransMassTalkSaveResponse> {
return this.httpClient return this.httpClient
.post<any>( .post<any>(
this.moduleConfig.urls.transMassTalkSave, this.urls.transMassTalkSave,
{}, {},
{ {
params: encodeTransMassTalkSave(req) params: encodeTransMassTalkSave(req),
} }
) )
.pipe(map(res => decodeTransMassTalkSave(res))); .pipe(map(res => decodeTransMassTalkSave(res)));
@ -270,10 +277,10 @@ export class CommonApiService {
): Observable<TranslationReqResponse> { ): Observable<TranslationReqResponse> {
return this.httpClient return this.httpClient
.post<any>( .post<any>(
this.moduleConfig.urls.translationReq, this.urls.translationReq,
{}, {},
{ {
params: encodeTranslationReq(req) params: encodeTranslationReq(req),
} }
) )
.pipe(map(res => decodeTranslationReq(res))); .pipe(map(res => decodeTranslationReq(res)));
@ -284,10 +291,10 @@ export class CommonApiService {
): Observable<TranslationSaveResponse> { ): Observable<TranslationSaveResponse> {
return this.httpClient return this.httpClient
.post<any>( .post<any>(
this.moduleConfig.urls.translationSave, this.urls.translationSave,
{}, {},
{ {
params: encodeTranslationSave(req) params: encodeTranslationSave(req),
} }
) )
.pipe(map(res => decodeTranslationSave(res))); .pipe(map(res => decodeTranslationSave(res)));

View File

@ -1,15 +0,0 @@
export interface ModuleConfig {
urls: {
fileProfileSave: string;
fileTalkDownload: string;
fileTalkSave: string;
fileTalkShare: string;
massTalkDownload: string;
massTalkSave: string;
transMassTalkDownload: string;
transMassTalkSave: string;
translationReq: string;
translationSave: string;
};
acceptableFileExtensions: string[];
}

View File

@ -1,15 +1,16 @@
import { NgModule, ModuleWithProviders } from '@angular/core'; import { NgModule, ModuleWithProviders } from '@angular/core';
import { _MODULE_CONFIG } from './types/token';
import { CommonApiService } from './services/common-api.service'; import { CommonApiService } from './services/common-api.service';
import { ModuleConfig } from './types/module-config';
import { _MODULE_CONFIG } from './config/token';
import { ModuleConfig } from './config/module-config';
const SERVICES = [CommonApiService]; const SERVICES = [CommonApiService];
@NgModule({ @NgModule({
declarations: [], declarations: [],
imports: [], imports: [],
exports: [] exports: [],
}) })
export class UCapCommonApiModule { export class UCapCommonApiModule {
public static forRoot( public static forRoot(
@ -17,7 +18,7 @@ export class UCapCommonApiModule {
): ModuleWithProviders<UCapCommonApiModule> { ): ModuleWithProviders<UCapCommonApiModule> {
return { return {
ngModule: UCapCommonApiModule, ngModule: UCapCommonApiModule,
providers: [{ provide: _MODULE_CONFIG, useValue: config }, ...SERVICES] providers: [{ provide: _MODULE_CONFIG, useValue: config }, ...SERVICES],
}; };
} }
} }

View File

@ -2,8 +2,6 @@
* Public API Surface of ucap-webmessenger-api-common * Public API Surface of ucap-webmessenger-api-common
*/ */
export * from './lib/types/module-config';
export * from './lib/apis/file-profile-save'; export * from './lib/apis/file-profile-save';
export * from './lib/apis/file-talk-download'; export * from './lib/apis/file-talk-download';
export * from './lib/apis/file-talk-save'; export * from './lib/apis/file-talk-save';
@ -21,3 +19,6 @@ export * from './lib/models/file-upload-item';
export * from './lib/services/common-api.service'; export * from './lib/services/common-api.service';
export * from './lib/ucap-common-api.module'; export * from './lib/ucap-common-api.module';
export * from './lib/config/urls';
export * from './lib/config/module-config';

View File

@ -0,0 +1,5 @@
import { ModuleConfig as CoreModuleConfig } from '@ucap-webmessenger/core';
import { Urls } from './urls';
export interface ModuleConfig extends CoreModuleConfig<Urls> {}

View File

@ -0,0 +1,6 @@
export interface Urls {
checkUserInfoEx: string;
companyList: string;
tokenUpdate: string;
urlInfo: string;
}

View File

@ -4,51 +4,61 @@ import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs'; import { Observable } from 'rxjs';
import { map } from 'rxjs/operators'; import { map } from 'rxjs/operators';
import { _MODULE_CONFIG } from '../types/token';
import { ModuleConfig } from '../types/module-config';
import { import {
CheckUserInfoExRequest, CheckUserInfoExRequest,
CheckUserInfoExResponse, CheckUserInfoExResponse,
encodeCheckUserInfoEx, encodeCheckUserInfoEx,
decodeCheckUserInfoEx decodeCheckUserInfoEx,
} from '../apis/check-user-info-ex'; } from '../apis/check-user-info-ex';
import { import {
CompanyListRequest, CompanyListRequest,
CompanyListResponse, CompanyListResponse,
encodeCompanyList, encodeCompanyList,
decodeCompanyList decodeCompanyList,
} from '../apis/company-list'; } from '../apis/company-list';
import { import {
TokenUpdateRequest, TokenUpdateRequest,
TokenUpdateResponse, TokenUpdateResponse,
encodeTokenUpdate, encodeTokenUpdate,
decodeTokenUpdate decodeTokenUpdate,
} from '../apis/token-update'; } from '../apis/token-update';
import { import {
UrlInfoResponse, UrlInfoResponse,
UrlInfoRequest, UrlInfoRequest,
encodeUrlInfo, encodeUrlInfo,
decodeUrlInfo decodeUrlInfo,
} from '../apis/url-info'; } from '../apis/url-info';
import { _MODULE_CONFIG } from '../config/token';
import { ModuleConfig } from '../config/module-config';
import { Urls } from '../config/urls';
import { UrlConfig } from '@ucap-webmessenger/core';
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root',
}) })
export class ExternalApiService { export class ExternalApiService {
readonly urls: Urls;
constructor( constructor(
@Inject(_MODULE_CONFIG) private moduleConfig: ModuleConfig, @Inject(_MODULE_CONFIG) private moduleConfig: ModuleConfig,
private httpClient: HttpClient private httpClient: HttpClient
) {} ) {
this.urls = UrlConfig.getUrls(
this.moduleConfig.hostConfig,
this.moduleConfig.urls
);
}
public checkUserInfoEx( public checkUserInfoEx(
req: CheckUserInfoExRequest req: CheckUserInfoExRequest
): Observable<CheckUserInfoExResponse> { ): Observable<CheckUserInfoExResponse> {
return this.httpClient return this.httpClient
.post<any>( .post<any>(
this.moduleConfig.urls.checkUserInfoEx, this.urls.checkUserInfoEx,
{}, {},
{ {
params: encodeCheckUserInfoEx(req) params: encodeCheckUserInfoEx(req),
} }
) )
.pipe(map(res => decodeCheckUserInfoEx(res))); .pipe(map(res => decodeCheckUserInfoEx(res)));
@ -57,10 +67,10 @@ export class ExternalApiService {
public companyList(req: CompanyListRequest): Observable<CompanyListResponse> { public companyList(req: CompanyListRequest): Observable<CompanyListResponse> {
return this.httpClient return this.httpClient
.post<any>( .post<any>(
this.moduleConfig.urls.companyList, this.urls.companyList,
{}, {},
{ {
params: encodeCompanyList(req) params: encodeCompanyList(req),
} }
) )
.pipe(map(res => decodeCompanyList(res))); .pipe(map(res => decodeCompanyList(res)));
@ -69,10 +79,10 @@ export class ExternalApiService {
public tokenUpdate(req: TokenUpdateRequest): Observable<TokenUpdateResponse> { public tokenUpdate(req: TokenUpdateRequest): Observable<TokenUpdateResponse> {
return this.httpClient return this.httpClient
.post<any>( .post<any>(
this.moduleConfig.urls.tokenUpdate, this.urls.tokenUpdate,
{}, {},
{ {
params: encodeTokenUpdate(req) params: encodeTokenUpdate(req),
} }
) )
.pipe(map(res => decodeTokenUpdate(res))); .pipe(map(res => decodeTokenUpdate(res)));
@ -81,10 +91,10 @@ export class ExternalApiService {
public urlInfo(req: UrlInfoRequest): Observable<UrlInfoResponse> { public urlInfo(req: UrlInfoRequest): Observable<UrlInfoResponse> {
return this.httpClient return this.httpClient
.post<any>( .post<any>(
this.moduleConfig.urls.urlInfo, this.urls.urlInfo,
{}, {},
{ {
params: encodeUrlInfo(req) params: encodeUrlInfo(req),
} }
) )
.pipe(map(res => decodeUrlInfo(res))); .pipe(map(res => decodeUrlInfo(res)));

View File

@ -1,8 +0,0 @@
export interface ModuleConfig {
urls: {
checkUserInfoEx: string;
companyList: string;
tokenUpdate: string;
urlInfo: string;
};
}

View File

@ -1,15 +1,16 @@
import { NgModule, ModuleWithProviders } from '@angular/core'; import { NgModule, ModuleWithProviders } from '@angular/core';
import { _MODULE_CONFIG } from './types/token';
import { ExternalApiService } from './services/external-api.service'; import { ExternalApiService } from './services/external-api.service';
import { ModuleConfig } from './types/module-config';
import { _MODULE_CONFIG } from './config/token';
import { ModuleConfig } from './config/module-config';
const SERVICES = [ExternalApiService]; const SERVICES = [ExternalApiService];
@NgModule({ @NgModule({
declarations: [], declarations: [],
imports: [], imports: [],
exports: [] exports: [],
}) })
export class UCapExternalApiModule { export class UCapExternalApiModule {
public static forRoot( public static forRoot(
@ -17,7 +18,7 @@ export class UCapExternalApiModule {
): ModuleWithProviders<UCapExternalApiModule> { ): ModuleWithProviders<UCapExternalApiModule> {
return { return {
ngModule: UCapExternalApiModule, ngModule: UCapExternalApiModule,
providers: [{ provide: _MODULE_CONFIG, useValue: config }, ...SERVICES] providers: [{ provide: _MODULE_CONFIG, useValue: config }, ...SERVICES],
}; };
} }
} }

View File

@ -2,8 +2,6 @@
* Public API Surface of ucap-webmessenger-api-public * Public API Surface of ucap-webmessenger-api-public
*/ */
export * from './lib/types/module-config';
export * from './lib/models/company'; export * from './lib/models/company';
export * from './lib/apis/check-user-info-ex'; export * from './lib/apis/check-user-info-ex';
@ -14,3 +12,6 @@ export * from './lib/apis/url-info';
export * from './lib/services/external-api.service'; export * from './lib/services/external-api.service';
export * from './lib/ucap-external-api.module'; export * from './lib/ucap-external-api.module';
export * from './lib/config/urls';
export * from './lib/config/module-config';

View File

@ -0,0 +1,24 @@
# UcapWebmessengerApiMessage
This library was generated with [Angular CLI](https://github.com/angular/angular-cli) version 8.2.11.
## Code scaffolding
Run `ng generate component component-name --project ucap-webmessenger-api-message` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module --project ucap-webmessenger-api-message`.
> Note: Don't forget to add `--project ucap-webmessenger-api-message` or else it will be added to the default project in your `angular.json` file.
## Build
Run `ng build ucap-webmessenger-api-message` to build the project. The build artifacts will be stored in the `dist/` directory.
## Publishing
After building your library with `ng build ucap-webmessenger-api-message`, go to the dist folder `cd dist/ucap-webmessenger-api-message` and run `npm publish`.
## Running unit tests
Run `ng test ucap-webmessenger-api-message` to execute the unit tests via [Karma](https://karma-runner.github.io).
## Further help
To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI README](https://github.com/angular/angular-cli/blob/master/README.md).

View File

@ -0,0 +1,32 @@
// Karma configuration file, see link for more information
// https://karma-runner.github.io/1.0/config/configuration-file.html
module.exports = function (config) {
config.set({
basePath: '',
frameworks: ['jasmine', '@angular-devkit/build-angular'],
plugins: [
require('karma-jasmine'),
require('karma-chrome-launcher'),
require('karma-jasmine-html-reporter'),
require('karma-coverage-istanbul-reporter'),
require('@angular-devkit/build-angular/plugins/karma')
],
client: {
clearContext: false // leave Jasmine Spec Runner output visible in browser
},
coverageIstanbulReporter: {
dir: require('path').join(__dirname, '../../coverage/ucap-webmessenger-api-message'),
reports: ['html', 'lcovonly', 'text-summary'],
fixWebpackSourcePaths: true
},
reporters: ['progress', 'kjhtml'],
port: 9876,
colors: true,
logLevel: config.LOG_INFO,
autoWatch: true,
browsers: ['Chrome'],
singleRun: false,
restartOnFileChange: true
});
};

View File

@ -0,0 +1,7 @@
{
"$schema": "../../node_modules/ng-packagr/ng-package.schema.json",
"dest": "../../dist/ucap-webmessenger-api-message",
"lib": {
"entryFile": "src/public-api.ts"
}
}

View File

@ -0,0 +1,8 @@
{
"name": "@ucap-webmessenger/api-message",
"version": "0.0.1",
"peerDependencies": {
"@angular/common": "^8.2.11",
"@angular/core": "^8.2.11"
}
}

View File

@ -0,0 +1,49 @@
import {
APIRequest,
APIResponse,
APIEncoder,
APIDecoder,
ParameterUtil
} from '@ucap-webmessenger/api';
import { DeviceType } from '@ucap-webmessenger/core';
import { MessageType } from '../types/message.type';
import { MessageList } from '../models/message-list';
export interface RetrieveRequest extends APIRequest {
userSeq: number;
deviceType: DeviceType;
tokenKey: string;
type: MessageType;
pageSize: number;
pageCount: number;
}
export interface RetrieveSendResponse extends APIResponse {
responseCode: string;
responseMsg: string;
totalCount: number;
messageList: MessageList[];
}
const RetrieveSendEncodeMap = {};
export const encodeRetrieve: APIEncoder<RetrieveRequest> = (
req: RetrieveRequest
) => {
return ParameterUtil.encode(RetrieveSendEncodeMap, req);
};
export const decodeRetrieveSend: APIDecoder<RetrieveSendResponse> = (
res: any
) => {
return {
statusCode: res.StatusCode,
errorMessage: res.ErrorMessage,
responseCode: res.responseCode,
responseMsg: res.responseMsg,
totalCount: res.totalCount,
messageList: []
} as RetrieveSendResponse;
};

View File

@ -0,0 +1,5 @@
import { ModuleConfig as CoreModuleConfig } from '@ucap-webmessenger/core';
import { Urls } from './urls';
export interface ModuleConfig extends CoreModuleConfig<Urls> {}

View File

@ -0,0 +1,5 @@
import { InjectionToken } from '@angular/core';
export const _MODULE_CONFIG = new InjectionToken(
'@ucap-webmessenger/api-message config of module'
);

View File

@ -0,0 +1,47 @@
export interface Urls {
/** 발신 메시지 list 조회 */
retrieveSendMessageList: string;
/** 수신 메시지 list 조회 */
retrieveRecvMessageList: string;
/** 예약 메시지 list 조회 */
retrieveReservationMessageList: string;
/** 메시지 검색 list 조회 */
retrieveSearchMessage: string;
/** 메시지 발송 */
sendNewMessage: string;
/** 메시지 상세 정보 조회 */
retrieveMessageDetail: string;
/** 메시지 읽음 */
readMessage: string;
/** 읽음 확인 */
retrieveReadCheck: string;
/** 발송 취소 */
cancelMessage: string;
/** 예약 메시지 발송 취소 */
cancelReservationMessage: string;
/** content Resource 파일 요청 */
retrieveResourceFile: string;
/** 메시지 삭제 */
deleteMessage: string;
/** My 메시지 등록 */
saveMyMessage: string;
/** My 메시지 조회 */
retrieveMyMessage: string;
/** My 메시지 삭제 */
deleteMyMessage: string;
/** My 메시지 수정 */
editMyMessage: string;
/** 예약 메시지 수정 - 썸네일 기능 완료된 경우 */
editReservationMessageEx: string;
/** 메시지 전달 - 메시지 복사 후, 발송 */
sendCopyMessage: string;
/** 읽지 않은 메시지 개수 조회 */
retrieveUnreadCount: string;
}

View File

@ -0,0 +1,30 @@
import { MessageType } from '../types/message.type';
import { CategoryType } from '../types/category.type';
import { ContentType } from '../types/content.type';
export interface MessageList {
/** 메시지 ID */
msgId: number;
/** 메시지 카테고리 */
category: CategoryType;
/** 메시지 TITLE */
title: string;
/** 메시지 제목 입력 여부 */
titleYn: boolean;
/** 메시지 TYPE */
type: MessageType;
/** 수신자의 시퀀스 */
userSeq: number;
/** 수신자 */
userName: string;
/** 수신자 수 */
userCount: number;
/** 읽은 사람 수 */
userReadCount: number;
/** 발신시간 */
regDate: Date;
/** CONTENT 타입 */
resType: ContentType;
/** 첨부파일 존재여부 */
attachmentYn: boolean;
}

View File

@ -0,0 +1,12 @@
import { TestBed } from '@angular/core/testing';
import { MessageApiService } from './message-api.service';
describe('MessageApiService', () => {
beforeEach(() => TestBed.configureTestingModule({}));
it('should be created', () => {
const service: MessageApiService = TestBed.get(MessageApiService);
expect(service).toBeTruthy();
});
});

View File

@ -0,0 +1,47 @@
import { Injectable, Inject } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { _MODULE_CONFIG } from '../config/token';
import { ModuleConfig } from '../config/module-config';
import { UrlConfig } from '@ucap-webmessenger/core';
import { Urls } from '../config/urls';
import {
RetrieveRequest,
RetrieveSendResponse,
encodeRetrieve,
decodeRetrieveSend
} from '../apis/retrieve-send';
@Injectable({
providedIn: 'root'
})
export class MessageApiService {
readonly urls: Urls;
constructor(
@Inject(_MODULE_CONFIG) private moduleConfig: ModuleConfig,
private httpClient: HttpClient
) {
this.urls = UrlConfig.getUrls(
this.moduleConfig.hostConfig,
this.moduleConfig.urls
);
}
public retrieveSendMessage(
req: RetrieveRequest
): Observable<RetrieveSendResponse> {
return this.httpClient
.post<any>(
this.urls.retrieveSendMessageList,
{},
{
params: encodeRetrieve(req)
}
)
.pipe(map(res => decodeRetrieveSend(res)));
}
}

View File

@ -0,0 +1,6 @@
export enum CategoryType {
/** 일반 */
General = 'G',
/** 공지 */
Notice = 'N'
}

View File

@ -0,0 +1,8 @@
export enum ContentType {
/** 텍스트 */
Text = 'T',
/** 이미지파일 */
Image = 'F',
/** 첨부파일 */
AttachFile = 'A'
}

View File

@ -0,0 +1,5 @@
export enum MessageType {
Send = 'S',
Receive = 'R',
Reservation = 'B'
}

View File

@ -0,0 +1,24 @@
import { NgModule, ModuleWithProviders } from '@angular/core';
import { MessageApiService } from './services/message-api.service';
import { _MODULE_CONFIG } from './config/token';
import { ModuleConfig } from './config/module-config';
const SERVICES = [MessageApiService];
@NgModule({
declarations: [],
imports: [],
exports: [],
})
export class UCapMessageApiModule {
public static forRoot(
config: ModuleConfig
): ModuleWithProviders<UCapMessageApiModule> {
return {
ngModule: UCapMessageApiModule,
providers: [{ provide: _MODULE_CONFIG, useValue: config }, ...SERVICES],
};
}
}

View File

@ -0,0 +1,17 @@
/*
* Public API Surface of ucap-webmessenger-api-message
*/
export * from './lib/apis/retrieve-send';
export * from './lib/services/message-api.service';
export * from './lib/ucap-message-api.module';
export * from './lib/models/message-list';
export * from './lib/types/category.type';
export * from './lib/types/content.type';
export * from './lib/types/message.type';
export * from './lib/config/urls';
export * from './lib/config/module-config';

View File

@ -0,0 +1,21 @@
// This file is required by karma.conf.js and loads recursively all the .spec and framework files
import 'zone.js/dist/zone';
import 'zone.js/dist/zone-testing';
import { getTestBed } from '@angular/core/testing';
import {
BrowserDynamicTestingModule,
platformBrowserDynamicTesting
} from '@angular/platform-browser-dynamic/testing';
declare const require: any;
// First, initialize the Angular testing environment.
getTestBed().initTestEnvironment(
BrowserDynamicTestingModule,
platformBrowserDynamicTesting()
);
// Then we find all the tests.
const context = require.context('./', true, /\.spec\.ts$/);
// And load the modules.
context.keys().map(context);

View File

@ -0,0 +1,26 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"outDir": "../../out-tsc/lib",
"target": "es2015",
"declaration": true,
"inlineSources": true,
"types": [],
"lib": [
"dom",
"es2018"
]
},
"angularCompilerOptions": {
"annotateForClosureCompiler": true,
"skipTemplateCodegen": true,
"strictMetadataEmit": true,
"fullTemplateTypeCheck": true,
"strictInjectionParameters": true,
"enableResourceInlining": true
},
"exclude": [
"src/test.ts",
"**/*.spec.ts"
]
}

View File

@ -0,0 +1,17 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"outDir": "../../out-tsc/spec",
"types": [
"jasmine",
"node"
]
},
"files": [
"src/test.ts"
],
"include": [
"**/*.spec.ts",
"**/*.d.ts"
]
}

View File

@ -0,0 +1,17 @@
{
"extends": "../../tslint.json",
"rules": {
"directive-selector": [
true,
"attribute",
"ucapApiMessage",
"camelCase"
],
"component-selector": [
true,
"element",
"ucap-api-message",
"kebab-case"
]
}
}

View File

@ -4,7 +4,7 @@ import {
APIResponse, APIResponse,
APIEncoder, APIEncoder,
APIDecoder, APIDecoder,
ParameterUtil ParameterUtil,
} from '@ucap-webmessenger/api'; } from '@ucap-webmessenger/api';
export interface UpdateInfoRequest extends APIRequest { export interface UpdateInfoRequest extends APIRequest {
@ -19,7 +19,7 @@ export interface UpdateInfoResponse extends APIResponse {
} }
const updateInfoEncodeMap = { const updateInfoEncodeMap = {
deviceType: 'p_device_type' deviceType: 'p_device_type',
}; };
export const encodeUpdateInfo: APIEncoder<UpdateInfoRequest> = ( export const encodeUpdateInfo: APIEncoder<UpdateInfoRequest> = (
@ -35,6 +35,6 @@ export const decodeUpdateInfo: APIDecoder<UpdateInfoResponse> = (res: any) => {
appVersion: res.AppVer, appVersion: res.AppVer,
installUrl: res.InstallURL, installUrl: res.InstallURL,
launcherAppVersion: res.LauncherAppVer, launcherAppVersion: res.LauncherAppVer,
launcherInstallUrl: res.LauncherInstallURL launcherInstallUrl: res.LauncherInstallURL,
} as UpdateInfoResponse; } as UpdateInfoResponse;
}; };

View File

@ -0,0 +1,5 @@
import { ModuleConfig as CoreModuleConfig } from '@ucap-webmessenger/core';
import { Urls } from './urls';
export interface ModuleConfig extends CoreModuleConfig<Urls> {}

View File

@ -0,0 +1,4 @@
export interface Urls {
versionInfo2: string;
updateInfo: string;
}

View File

@ -4,39 +4,49 @@ import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs'; import { Observable } from 'rxjs';
import { map } from 'rxjs/operators'; import { map } from 'rxjs/operators';
import { _MODULE_CONFIG } from '../types/token';
import { import {
VersionInfo2Request, VersionInfo2Request,
VersionInfo2Response, VersionInfo2Response,
encodeVersionInfo2, encodeVersionInfo2,
decodeVersionInfo2 decodeVersionInfo2,
} from '../apis/version-info2'; } from '../apis/version-info2';
import { import {
UpdateInfoRequest, UpdateInfoRequest,
UpdateInfoResponse, UpdateInfoResponse,
encodeUpdateInfo, encodeUpdateInfo,
decodeUpdateInfo decodeUpdateInfo,
} from '../apis/update-info'; } from '../apis/update-info';
import { ModuleConfig } from '../types/module-config';
import { _MODULE_CONFIG } from '../config/token';
import { ModuleConfig } from '../config/module-config';
import { UrlConfig } from '@ucap-webmessenger/core';
import { Urls } from '../config/urls';
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root',
}) })
export class PublicApiService { export class PublicApiService {
readonly urls: Urls;
constructor( constructor(
@Inject(_MODULE_CONFIG) private moduleConfig: ModuleConfig, @Inject(_MODULE_CONFIG) private moduleConfig: ModuleConfig,
private httpClient: HttpClient private httpClient: HttpClient
) {} ) {
this.urls = UrlConfig.getUrls(
this.moduleConfig.hostConfig,
this.moduleConfig.urls
);
}
public versionInfo2( public versionInfo2(
req: VersionInfo2Request req: VersionInfo2Request
): Observable<VersionInfo2Response> { ): Observable<VersionInfo2Response> {
return this.httpClient return this.httpClient
.post<any>( .post<any>(
this.moduleConfig.urls.versionInfo2, this.urls.versionInfo2,
{}, {},
{ {
params: encodeVersionInfo2(req) params: encodeVersionInfo2(req),
} }
) )
.pipe(map((res: any) => decodeVersionInfo2(res))); .pipe(map((res: any) => decodeVersionInfo2(res)));
@ -45,10 +55,10 @@ export class PublicApiService {
public updateInfo(req: UpdateInfoRequest): Observable<UpdateInfoResponse> { public updateInfo(req: UpdateInfoRequest): Observable<UpdateInfoResponse> {
return this.httpClient return this.httpClient
.post<any>( .post<any>(
this.moduleConfig.urls.updateInfo, this.urls.updateInfo,
{}, {},
{ {
params: encodeUpdateInfo(req) params: encodeUpdateInfo(req),
} }
) )
.pipe(map(res => decodeUpdateInfo(res))); .pipe(map(res => decodeUpdateInfo(res)));

View File

@ -1,6 +0,0 @@
export interface ModuleConfig {
urls: {
versionInfo2: string;
updateInfo: string;
};
}

View File

@ -1,15 +1,16 @@
import { NgModule, ModuleWithProviders } from '@angular/core'; import { NgModule, ModuleWithProviders } from '@angular/core';
import { _MODULE_CONFIG } from './types/token';
import { PublicApiService } from './services/public-api.service'; import { PublicApiService } from './services/public-api.service';
import { ModuleConfig } from './types/module-config';
import { _MODULE_CONFIG } from './config/token';
import { ModuleConfig } from './config/module-config';
const SERVICES = [PublicApiService]; const SERVICES = [PublicApiService];
@NgModule({ @NgModule({
declarations: [], declarations: [],
imports: [], imports: [],
exports: [] exports: [],
}) })
export class UCapPublicApiModule { export class UCapPublicApiModule {
public static forRoot( public static forRoot(
@ -17,7 +18,7 @@ export class UCapPublicApiModule {
): ModuleWithProviders<UCapPublicApiModule> { ): ModuleWithProviders<UCapPublicApiModule> {
return { return {
ngModule: UCapPublicApiModule, ngModule: UCapPublicApiModule,
providers: [{ provide: _MODULE_CONFIG, useValue: config }, ...SERVICES] providers: [{ provide: _MODULE_CONFIG, useValue: config }, ...SERVICES],
}; };
} }
} }

View File

@ -7,7 +7,9 @@ export * from './lib/apis/version-info2';
export * from './lib/services/public-api.service'; export * from './lib/services/public-api.service';
export * from './lib/types/module-config';
export * from './lib/types/sync-mode.type'; export * from './lib/types/sync-mode.type';
export * from './lib/ucap-public-api.module'; export * from './lib/ucap-public-api.module';
export * from './lib/config/urls';
export * from './lib/config/module-config';

View File

@ -1,4 +1,4 @@
export enum StatusCode { export enum StatusCode {
Success = '200', Success = '200',
Fail = '500' Fail = '500',
} }

View File

@ -1,35 +1,59 @@
import { NgModule, APP_INITIALIZER } from '@angular/core'; import { NgModule, APP_INITIALIZER, Type } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { UCAP_NATIVE_SERVICE, NativeService } from '@ucap-webmessenger/native';
import { RESOLVERS } from './resolvers'; import { RESOLVERS } from './resolvers';
import { SERVICES } from './services'; import { SERVICES } from './services';
import { AppService } from './services/app.service'; import { AppService } from './services/app.service';
import { HttpClient } from '@angular/common/http';
import { UCAP_NATIVE_SERVICE } from '@ucap-webmessenger/native';
import { environment } from '../environments/environment';
export function initializeApp(appService: AppService) { import { environment } from '../environments/environment';
import { BrowserNativeService } from '@ucap-webmessenger/native-browser';
import { ElectronNativeService } from '@ucap-webmessenger/native-electron';
export function initializeApp(
appService: AppService,
nativeService: NativeService
) {
return (): Promise<any> => { return (): Promise<any> => {
return appService.postInit(); return appService.postInit();
}; };
} }
// export function nativeServiceFactory(httpClient: HttpClient) {
// if ('browser' === environment.runtime) {
// return import('@ucap-webmessenger/native-browser').then(
// m => new m.BrowserNativeService(httpClient)
// );
// } else {
// return import('@ucap-webmessenger/native-electron').then(
// m => new m.ElectronNativeService()
// );
// }
// }
@NgModule({ @NgModule({
imports: [], imports: [],
exports: [], exports: [],
providers: [ providers: [
...SERVICES,
...RESOLVERS,
{ {
provide: UCAP_NATIVE_SERVICE, provide: UCAP_NATIVE_SERVICE,
useClass: environment.modules.native.serviceClass, // useFactory: nativeServiceFactory,
deps: [HttpClient] useClass:
'browser' === environment.runtime
? BrowserNativeService
: ElectronNativeService,
deps: [HttpClient],
}, },
...SERVICES,
...RESOLVERS,
{ {
provide: APP_INITIALIZER, provide: APP_INITIALIZER,
useFactory: initializeApp, useFactory: initializeApp,
deps: [AppService, UCAP_NATIVE_SERVICE], deps: [AppService, UCAP_NATIVE_SERVICE],
multi: true multi: true,
} },
] ],
}) })
export class AppProviderModule {} export class AppProviderModule {}

View File

@ -10,26 +10,26 @@ const routes: Routes = [
import('./pages/messenger/messenger.page.module').then( import('./pages/messenger/messenger.page.module').then(
m => m.AppMessengerPageModule m => m.AppMessengerPageModule
), ),
canActivate: [AppAuthGuard] canActivate: [AppAuthGuard],
}, },
{ {
path: 'account', path: 'account',
loadChildren: () => loadChildren: () =>
import('./pages/account/account.page.module').then( import('./pages/account/account.page.module').then(
m => m.AppAccountPageModule m => m.AppAccountPageModule
) ),
}, },
{ {
path: 'template', path: 'template',
loadChildren: () => loadChildren: () =>
import('./pages/template/template.page.module').then( import('./pages/template/template.page.module').then(
m => m.AppTemplatePageModule m => m.AppTemplatePageModule
) ),
} },
]; ];
@NgModule({ @NgModule({
imports: [RouterModule.forRoot(routes, { enableTracing: false })], imports: [RouterModule.forRoot(routes, { enableTracing: false })],
exports: [RouterModule] exports: [RouterModule],
}) })
export class AppRoutingModule {} export class AppRoutingModule {}

View File

@ -7,8 +7,16 @@ import { MatProgressBarModule } from '@angular/material/progress-bar';
import { PerfectScrollbarModule } from 'ngx-perfect-scrollbar'; import { PerfectScrollbarModule } from 'ngx-perfect-scrollbar';
import { UCapUiModule } from '@ucap-webmessenger/ui';
import { UCapUiAccountModule } from '@ucap-webmessenger/ui-account';
import { UCapWebStorageModule } from '@ucap-webmessenger/web-storage';
import { UCapUtilModule } from '@ucap-webmessenger/util';
import { UCapCommonApiModule } from '@ucap-webmessenger/api-common'; import { UCapCommonApiModule } from '@ucap-webmessenger/api-common';
import { UCapExternalApiModule } from '@ucap-webmessenger/api-external'; import { UCapExternalApiModule } from '@ucap-webmessenger/api-external';
import { UCapMessageApiModule } from '@ucap-webmessenger/api-message';
import { UCapPublicApiModule } from '@ucap-webmessenger/api-public'; import { UCapPublicApiModule } from '@ucap-webmessenger/api-public';
import { UCapPiModule } from '@ucap-webmessenger/pi'; import { UCapPiModule } from '@ucap-webmessenger/pi';
@ -25,17 +33,8 @@ import { UCapServiceProtocolModule } from '@ucap-webmessenger/protocol-service';
import { UCapStatusProtocolModule } from '@ucap-webmessenger/protocol-status'; import { UCapStatusProtocolModule } from '@ucap-webmessenger/protocol-status';
import { UCapSyncProtocolModule } from '@ucap-webmessenger/protocol-sync'; import { UCapSyncProtocolModule } from '@ucap-webmessenger/protocol-sync';
import { UCapUiModule } from '@ucap-webmessenger/ui';
import { UCapUiAccountModule } from '@ucap-webmessenger/ui-account';
import { UCapWebStorageModule } from '@ucap-webmessenger/web-storage';
import { UCapUtilModule } from '@ucap-webmessenger/util';
import { LoggerModule, NgxLoggerLevel } from 'ngx-logger'; import { LoggerModule, NgxLoggerLevel } from 'ngx-logger';
import { environment } from '../environments/environment';
import { AppProviderModule } from './app-provider.module'; import { AppProviderModule } from './app-provider.module';
import { AppRoutingModule } from './app-routing.module'; import { AppRoutingModule } from './app-routing.module';
import { AppStoreModule } from './app-store.module'; import { AppStoreModule } from './app-store.module';
@ -47,6 +46,8 @@ import { GUARDS } from './guards';
import { AppMessengerLayoutModule } from './layouts/messenger/messenger.layout.module'; import { AppMessengerLayoutModule } from './layouts/messenger/messenger.layout.module';
import { AppNativeLayoutModule } from './layouts/native/native.layout.module'; import { AppNativeLayoutModule } from './layouts/native/native.layout.module';
import { environment } from '../environments/environment';
@NgModule({ @NgModule({
imports: [ imports: [
BrowserModule, BrowserModule,
@ -58,28 +59,15 @@ import { AppNativeLayoutModule } from './layouts/native/native.layout.module';
PerfectScrollbarModule, PerfectScrollbarModule,
UCapCommonApiModule.forRoot({ UCapCommonApiModule.forRoot(environment.commonApiModuleConfig),
urls: environment.urls.apiCommon,
acceptableFileExtensions:
environment.modules.event.acceptableFileExtensions
}),
UCapPublicApiModule.forRoot({ UCapPublicApiModule.forRoot(environment.publicApiModuleConfig),
urls: environment.urls.apiPublic UCapExternalApiModule.forRoot(environment.externalApiModuleConfig),
}), UCapMessageApiModule.forRoot(environment.messageApiModuleConfig),
UCapExternalApiModule.forRoot({
urls: environment.urls.apiExternal
}),
UCapPiModule.forRoot({ UCapPiModule.forRoot(environment.piModuleConfig),
urls: environment.urls.pi
}),
UCapProtocolModule.forRoot({ UCapProtocolModule.forRoot(environment.protocolModuleConfig),
urls: environment.urls.protocol,
reconnect: environment.protocol.reconnect,
requestId: environment.protocol.requestId
}),
UCapAuthenticationProtocolModule.forRoot(), UCapAuthenticationProtocolModule.forRoot(),
UCapEventProtocolModule.forRoot(), UCapEventProtocolModule.forRoot(),
UCapGroupProtocolModule.forRoot(), UCapGroupProtocolModule.forRoot(),

View File

@ -1,11 +1,6 @@
<mat-progress-bar
*ngIf="fileDownloadItem && fileDownloadItem.downloadingProgress$"
mode="determinate"
[value]="fileDownloadItem.downloadingProgress$ | async"
></mat-progress-bar>
<ucap-file-viewer <ucap-file-viewer
[fileInfo]="fileInfo" [fileInfo]="fileInfo"
[fileDownloadUrl]="fileDownloadUrl" [fileDownloadUrl]="fileDownloadUrl"
(download)="onDownload()" (download)="onDownload($event)"
(closed)="onClosedViewer()" (closed)="onClosedViewer()"
></ucap-file-viewer> ></ucap-file-viewer>

View File

@ -3,7 +3,7 @@ import {
OnInit, OnInit,
OnDestroy, OnDestroy,
Inject, Inject,
EventEmitter EventEmitter,
} from '@angular/core'; } from '@angular/core';
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material'; import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material';
@ -15,7 +15,7 @@ import { take, map, finalize, tap } from 'rxjs/operators';
import { SnackBarService } from '@ucap-webmessenger/ui'; import { SnackBarService } from '@ucap-webmessenger/ui';
import { import {
FileDownloadItem, FileDownloadItem,
CommonApiService CommonApiService,
} from '@ucap-webmessenger/api-common'; } from '@ucap-webmessenger/api-common';
export interface FileViewerDialogData { export interface FileViewerDialogData {
@ -31,7 +31,7 @@ export interface FileViewerDialogResult {}
@Component({ @Component({
selector: 'app-layout-common-file-viewer', selector: 'app-layout-common-file-viewer',
templateUrl: './file-viewer.dialog.component.html', templateUrl: './file-viewer.dialog.component.html',
styleUrls: ['./file-viewer.dialog.component.scss'] styleUrls: ['./file-viewer.dialog.component.scss'],
}) })
export class FileViewerDialogComponent implements OnInit, OnDestroy { export class FileViewerDialogComponent implements OnInit, OnDestroy {
fileInfo: FileEventJson; fileInfo: FileEventJson;
@ -40,8 +40,6 @@ export class FileViewerDialogComponent implements OnInit, OnDestroy {
deviceType: DeviceType; deviceType: DeviceType;
token: string; token: string;
fileDownloadItem: FileDownloadItem;
fileDownloadUrl: string; fileDownloadUrl: string;
constructor( constructor(
@ -66,7 +64,7 @@ export class FileViewerDialogComponent implements OnInit, OnDestroy {
userSeq: this.userSeq, userSeq: this.userSeq,
deviceType: this.deviceType, deviceType: this.deviceType,
token: this.token, token: this.token,
attachmentsSeq: this.fileInfo.attachmentSeq attachmentsSeq: this.fileInfo.attachmentSeq,
}, },
this.downloadUrl this.downloadUrl
); );
@ -76,8 +74,7 @@ export class FileViewerDialogComponent implements OnInit, OnDestroy {
ngOnDestroy(): void {} ngOnDestroy(): void {}
onDownload(): void { onDownload(fileDownloadItem: FileDownloadItem): void {
this.fileDownloadItem = new FileDownloadItem();
this.commonApiService this.commonApiService
.fileTalkDownload( .fileTalkDownload(
{ {
@ -85,37 +82,36 @@ export class FileViewerDialogComponent implements OnInit, OnDestroy {
deviceType: this.deviceType, deviceType: this.deviceType,
token: this.token, token: this.token,
attachmentsSeq: this.fileInfo.attachmentSeq, attachmentsSeq: this.fileInfo.attachmentSeq,
fileDownloadItem: this.fileDownloadItem fileDownloadItem,
}, },
this.downloadUrl this.downloadUrl
) )
.pipe( .pipe(
take(1), take(1),
map(async rawBlob => { map(async rawBlob => {
const blob = rawBlob.slice( const mimeType = MimeUtil.getMimeFromExtension(this.fileInfo.fileExt);
0, const blob = rawBlob.slice(0, rawBlob.size, mimeType);
rawBlob.size,
MimeUtil.getMimeFromExtension(this.fileInfo.fileExt)
);
FileUtil.fromBlobToBuffer(blob) FileUtil.fromBlobToBuffer(blob)
.then(buffer => { .then(buffer => {
this.nativeService this.nativeService
.saveFile(buffer, this.fileInfo.fileName) .saveFile(buffer, this.fileInfo.fileName, mimeType)
.pipe(take(1)) .then(result => {
.subscribe(result => {
if (!!result) { if (!!result) {
this.snackBarService.open( this.snackBarService.open(
`파일이 경로[${result}]에 저장되었습니다.`, `파일이 경로[${result}]에 저장되었습니다.`,
'', '',
{ {
duration: 3000, duration: 3000,
verticalPosition: 'bottom' verticalPosition: 'bottom',
} }
); );
} else { } else {
this.snackBarService.open('파일 저장에 실패하였습니다.'); this.snackBarService.open('파일 저장에 실패하였습니다.');
} }
})
.catch(reason => {
this.snackBarService.open('파일 저장에 실패하였습니다.');
}); });
}) })
.catch(reason => { .catch(reason => {
@ -123,7 +119,9 @@ export class FileViewerDialogComponent implements OnInit, OnDestroy {
}); });
}), }),
finalize(() => { finalize(() => {
this.fileDownloadItem = undefined; setTimeout(() => {
fileDownloadItem.downloadingProgress$ = undefined;
}, 1000);
}) })
) )
.subscribe(); .subscribe();

View File

@ -9,8 +9,17 @@
<ng-template mat-tab-label> <ng-template mat-tab-label>
<!--<mat-icon>group</mat-icon>--> <!--<mat-icon>group</mat-icon>-->
<div class="icon-item"> <div class="icon-item">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" <svg
stroke-width="1.5" stroke-linecap="butt" stroke-linejoin="round"> xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="1.5"
stroke-linecap="butt"
stroke-linejoin="round"
>
<path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"></path> <path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"></path>
<circle cx="12" cy="7" r="4"></circle> <circle cx="12" cy="7" r="4"></circle>
</svg> </svg>
@ -18,7 +27,7 @@
</ng-template> </ng-template>
<app-layout-chat-left-sidenav-group <app-layout-chat-left-sidenav-group
class="left-group-side" class="left-group-side"
(newGroupAndMember)="onClickNewGroupAndMember($event)" (newGroupAndMember)="onClickNewGroupAndMember()"
(openProfile)="onClickOpenProfile($event)" (openProfile)="onClickOpenProfile($event)"
></app-layout-chat-left-sidenav-group> ></app-layout-chat-left-sidenav-group>
</mat-tab> </mat-tab>
@ -32,16 +41,28 @@
matBadgePosition="above after" matBadgePosition="above after"
>chat</mat-icon >chat</mat-icon
>--> >-->
<div class="icon-item" [matBadgeHidden]="(badgeChatUnReadCount$ | async) <= 0" <div
class="icon-item"
[matBadgeHidden]="(badgeChatUnReadCount$ | async) <= 0"
[matBadge]="badgeChatUnReadCount$ | async" [matBadge]="badgeChatUnReadCount$ | async"
matBadgeDescription="확인하지 않은 메시지가 있습니다." matBadgeDescription="확인하지 않은 메시지가 있습니다."
matBadgeColor="accent" matBadgeColor="accent"
matBadgePosition="above after"> matBadgePosition="above after"
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#000000" >
stroke-width="1.5" stroke-linecap="butt" stroke-linejoin="bevel"> <svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="#000000"
stroke-width="1.5"
stroke-linecap="butt"
stroke-linejoin="bevel"
>
<path <path
d="M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z"> d="M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z"
</path> ></path>
</svg> </svg>
</div> </div>
</ng-template> </ng-template>
@ -51,8 +72,17 @@
<ng-template mat-tab-label> <ng-template mat-tab-label>
<!--<mat-icon>device_hub</mat-icon>--> <!--<mat-icon>device_hub</mat-icon>-->
<div class="icon-item"> <div class="icon-item">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#000000" <svg
stroke-width="1.5" stroke-linecap="butt" stroke-linejoin="bevel"> xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="#000000"
stroke-width="1.5"
stroke-linecap="butt"
stroke-linejoin="bevel"
>
<circle class="st0" cx="18.4" cy="18.5" r="3" /> <circle class="st0" cx="18.4" cy="18.5" r="3" />
<circle class="st0" cx="12" cy="5" r="3" /> <circle class="st0" cx="12" cy="5" r="3" />
<path class="st0" d="M12.4,10.5h4c1.1,0,2,0.9,2,2v3" /> <path class="st0" d="M12.4,10.5h4c1.1,0,2,0.9,2,2v3" />
@ -73,16 +103,27 @@
<ng-template mat-tab-label> <ng-template mat-tab-label>
<!--<mat-icon>phone</mat-icon>--> <!--<mat-icon>phone</mat-icon>-->
<div class="icon-item"> <div class="icon-item">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" <svg
stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" class="feather feather-phone"> xmlns="http://www.w3.org/2000/svg"
<path class="st0" width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="1.5"
stroke-linecap="round"
stroke-linejoin="round"
class="feather feather-phone"
>
<path
class="st0"
d="M2,5.8c0.1-0.6,0.3-1.1,0.7-1.6l1.7-1.7C4.7,2.2,5,2.1,5.3,2.1c0.3,0,0.6,0.1,0.8,0.4c0.3,0.3,0.6,0.6,0.9,0.9 d="M2,5.8c0.1-0.6,0.3-1.1,0.7-1.6l1.7-1.7C4.7,2.2,5,2.1,5.3,2.1c0.3,0,0.6,0.1,0.8,0.4c0.3,0.3,0.6,0.6,0.9,0.9
c0.2,0.2,0.3,0.3,0.5,0.5l1.4,1.4c0.3,0.3,0.4,0.6,0.4,0.9S9.2,6.7,8.9,7C8.8,7.2,8.6,7.3,8.5,7.5C8.1,7.9,7.7,8.3,7.2,8.7 c0.2,0.2,0.3,0.3,0.5,0.5l1.4,1.4c0.3,0.3,0.4,0.6,0.4,0.9S9.2,6.7,8.9,7C8.8,7.2,8.6,7.3,8.5,7.5C8.1,7.9,7.7,8.3,7.2,8.7
c0,0,0,0,0,0C6.8,9.1,6.9,9.5,7,9.7c0,0,0,0,0,0c0.4,0.9,0.9,1.7,1.6,2.6c1.4,1.7,2.9,3,4.5,4.1c0.2,0.1,0.4,0.2,0.6,0.3 c0,0,0,0,0,0C6.8,9.1,6.9,9.5,7,9.7c0,0,0,0,0,0c0.4,0.9,0.9,1.7,1.6,2.6c1.4,1.7,2.9,3,4.5,4.1c0.2,0.1,0.4,0.2,0.6,0.3
c0.2,0.1,0.4,0.2,0.5,0.3c0,0,0,0,0.1,0c0.2,0.1,0.3,0.1,0.4,0.1c0.4,0,0.6-0.2,0.7-0.3l1.7-1.7c0.3-0.3,0.6-0.4,0.8-0.4 c0.2,0.1,0.4,0.2,0.5,0.3c0,0,0,0,0.1,0c0.2,0.1,0.3,0.1,0.4,0.1c0.4,0,0.6-0.2,0.7-0.3l1.7-1.7c0.3-0.3,0.6-0.4,0.8-0.4
c0.4,0,0.6,0.2,0.8,0.4l2.8,2.8c0.6,0.6,0.6,1.2,0,1.7c-0.2,0.2-0.4,0.4-0.6,0.6c-0.3,0.3-0.7,0.6-1,1c-0.5,0.6-1.2,0.8-2,0.8 c0.4,0,0.6,0.2,0.8,0.4l2.8,2.8c0.6,0.6,0.6,1.2,0,1.7c-0.2,0.2-0.4,0.4-0.6,0.6c-0.3,0.3-0.7,0.6-1,1c-0.5,0.6-1.2,0.8-2,0.8
c-0.1,0-0.2,0-0.2,0c-1.5-0.1-2.9-0.7-4-1.2c-2.9-1.4-5.4-3.4-7.5-5.9C4.5,13,3.3,11.1,2.6,9C2.1,7.7,1.9,6.7,2,5.8z"> c-0.1,0-0.2,0-0.2,0c-1.5-0.1-2.9-0.7-4-1.2c-2.9-1.4-5.4-3.4-7.5-5.9C4.5,13,3.3,11.1,2.6,9C2.1,7.7,1.9,6.7,2,5.8z"
</path> ></path>
</svg> </svg>
</div> </div>
</ng-template> </ng-template>

View File

@ -20,6 +20,7 @@ import {
UserInfoDN UserInfoDN
} from '@ucap-webmessenger/protocol-query'; } from '@ucap-webmessenger/protocol-query';
import { MatTabChangeEvent, MatTabGroup } from '@angular/material'; import { MatTabChangeEvent, MatTabGroup } from '@angular/material';
import { RightDrawer } from '@app/types';
export enum MainMenu { export enum MainMenu {
Group = 'GROUP', Group = 'GROUP',
@ -144,6 +145,11 @@ export class LeftSideComponent implements OnInit {
icon: 'add', icon: 'add',
tooltip: 'New Group Add', tooltip: 'New Group Add',
divisionType: 'GROUP_NEW_ADD' divisionType: 'GROUP_NEW_ADD'
},
{
icon: 'sms',
tooltip: 'Message',
divisionType: 'MESSAGE'
} }
]; ];
} }
@ -247,6 +253,16 @@ export class LeftSideComponent implements OnInit {
this.onClickNewChat('TIMER'); this.onClickNewChat('TIMER');
} }
break; break;
case 'MESSAGE':
{
this.store.dispatch(
ChatStore.selectedRightDrawer({
req: RightDrawer.Message
})
);
}
break;
} }
} }
} }

View File

@ -17,7 +17,7 @@
[companyList]="companyList$ | async" [companyList]="companyList$ | async"
[companyCode]="companyCode" [companyCode]="companyCode"
(keyDownEnter)="onKeyDownEnterOrganizationTenantSearch($event)" (keyDownEnter)="onKeyDownEnterOrganizationTenantSearch($event)"
(cancel)="onClickCancel($event)" (cancel)="onClickCancel()"
></ucap-organization-tenant-search> ></ucap-organization-tenant-search>
<mat-menu <mat-menu
@ -28,8 +28,17 @@
> >
<button mat-menu-item (click)="onClickGroupMenu('GROUP_NEW')"> <button mat-menu-item (click)="onClickGroupMenu('GROUP_NEW')">
<!--<mat-icon>group_add</mat-icon>--> <!--<mat-icon>group_add</mat-icon>-->
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" <svg
stroke-width="1.5" stroke-linecap="butt" stroke-linejoin="round"> xmlns="http://www.w3.org/2000/svg"
width="18"
height="18"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="1.5"
stroke-linecap="butt"
stroke-linejoin="round"
>
<path d="M16 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"></path> <path d="M16 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"></path>
<circle cx="8.5" cy="7" r="4"></circle> <circle cx="8.5" cy="7" r="4"></circle>
<line x1="20" y1="8" x2="20" y2="14"></line> <line x1="20" y1="8" x2="20" y2="14"></line>

View File

@ -6,7 +6,7 @@
[companyList]="companyList$ | async" [companyList]="companyList$ | async"
[companyCode]="companyCode" [companyCode]="companyCode"
(keyDownEnter)="onKeyDownEnterOrganizationTenantSearch($event)" (keyDownEnter)="onKeyDownEnterOrganizationTenantSearch($event)"
(cancel)="onClickCancel($event)" (cancel)="onClickCancel()"
> >
</ucap-organization-tenant-search> </ucap-organization-tenant-search>
</div> </div>

View File

@ -66,7 +66,7 @@
<button <button
*ngIf="!!roomInfo" *ngIf="!!roomInfo"
mat-icon-button mat-icon-button
(click)="onClickReceiveAlarm($event)" (click)="onClickReceiveAlarm()"
aria-label="Toggle Receive Alarm" aria-label="Toggle Receive Alarm"
> >
<mat-icon class="amber-fg" *ngIf="roomInfo.receiveAlarm" <mat-icon class="amber-fg" *ngIf="roomInfo.receiveAlarm"
@ -92,6 +92,9 @@
<button mat-menu-item (click)="onClickContextMenu('OPEN_FILE_LIST')"> <button mat-menu-item (click)="onClickContextMenu('OPEN_FILE_LIST')">
파일함 파일함
</button> </button>
<button mat-menu-item (click)="onClickContextMenu('OPEN_ROOM_USER')">
대화참여자목록
</button>
<button mat-menu-item (click)="onClickContextMenu('ADD_MEMBER')"> <button mat-menu-item (click)="onClickContextMenu('ADD_MEMBER')">
대화상대추가 대화상대추가
</button> </button>

View File

@ -6,7 +6,7 @@ import {
ElementRef, ElementRef,
AfterViewInit, AfterViewInit,
Output, Output,
EventEmitter EventEmitter,
} from '@angular/core'; } from '@angular/core';
import { import {
ucapAnimations, ucapAnimations,
@ -20,7 +20,7 @@ import {
AlertDialogData, AlertDialogData,
AlertDialogResult, AlertDialogResult,
FileUploadQueueComponent, FileUploadQueueComponent,
StringUtil StringUtil,
} from '@ucap-webmessenger/ui'; } from '@ucap-webmessenger/ui';
import { Store, select } from '@ngrx/store'; import { Store, select } from '@ngrx/store';
import { NGXLogger } from 'ngx-logger'; import { NGXLogger } from 'ngx-logger';
@ -33,7 +33,7 @@ import {
isRecallable, isRecallable,
InfoResponse, InfoResponse,
EventJson, EventJson,
FileEventJson FileEventJson,
} from '@ucap-webmessenger/protocol-event'; } from '@ucap-webmessenger/protocol-event';
import * as AppStore from '@app/store'; import * as AppStore from '@app/store';
@ -47,36 +47,36 @@ import {
EnvironmentsInfo, EnvironmentsInfo,
KEY_ENVIRONMENTS_INFO, KEY_ENVIRONMENTS_INFO,
UserSelectDialogType, UserSelectDialogType,
RightDrawer RightDrawer,
} from '@app/types'; } from '@app/types';
import { RoomInfo, UserInfo, RoomType } from '@ucap-webmessenger/protocol-room'; import { RoomInfo, UserInfo, RoomType } from '@ucap-webmessenger/protocol-room';
import { tap, take, map, catchError } from 'rxjs/operators'; import { tap, take, map, catchError } from 'rxjs/operators';
import { import {
FileInfo, FileInfo,
FormComponent as UCapUiChatFormComponent FormComponent as UCapUiChatFormComponent,
} from '@ucap-webmessenger/ui-chat'; } from '@ucap-webmessenger/ui-chat';
import { KEY_VER_INFO } from '@app/types/ver-info.type'; import { KEY_VER_INFO } from '@app/types/ver-info.type';
import { VersionInfo2Response } from '@ucap-webmessenger/api-public'; import { VersionInfo2Response } from '@ucap-webmessenger/api-public';
import { import {
MatMenuTrigger, MatMenuTrigger,
MatSnackBarRef, MatSnackBarRef,
SimpleSnackBar SimpleSnackBar,
} from '@angular/material'; } from '@angular/material';
import { import {
CommonApiService, CommonApiService,
FileUploadItem, FileUploadItem,
FileTalkSaveRequest, FileTalkSaveRequest,
FileTalkSaveResponse FileTalkSaveResponse,
} from '@ucap-webmessenger/api-common'; } from '@ucap-webmessenger/api-common';
import { import {
CreateChatDialogComponent, CreateChatDialogComponent,
CreateChatDialogData, CreateChatDialogData,
CreateChatDialogResult CreateChatDialogResult,
} from '../dialogs/chat/create-chat.dialog.component'; } from '../dialogs/chat/create-chat.dialog.component';
import { import {
FileViewerDialogComponent, FileViewerDialogComponent,
FileViewerDialogData, FileViewerDialogData,
FileViewerDialogResult FileViewerDialogResult,
} from '@app/layouts/common/dialogs/file-viewer.dialog.component'; } from '@app/layouts/common/dialogs/file-viewer.dialog.component';
import { CONST, FileUtil } from '@ucap-webmessenger/core'; import { CONST, FileUtil } from '@ucap-webmessenger/core';
import { PerfectScrollbarComponent } from 'ngx-perfect-scrollbar'; import { PerfectScrollbarComponent } from 'ngx-perfect-scrollbar';
@ -84,12 +84,12 @@ import { StatusCode } from '@ucap-webmessenger/api';
import { import {
EditChatRoomDialogComponent, EditChatRoomDialogComponent,
EditChatRoomDialogResult, EditChatRoomDialogResult,
EditChatRoomDialogData EditChatRoomDialogData,
} from '../dialogs/chat/edit-chat-room.dialog.component'; } from '../dialogs/chat/edit-chat-room.dialog.component';
import { import {
SelectGroupDialogComponent, SelectGroupDialogComponent,
SelectGroupDialogResult, SelectGroupDialogResult,
SelectGroupDialogData SelectGroupDialogData,
} from '../dialogs/group/select-group.dialog.component'; } from '../dialogs/group/select-group.dialog.component';
import { GroupDetailData } from '@ucap-webmessenger/protocol-sync'; import { GroupDetailData } from '@ucap-webmessenger/protocol-sync';
@ -97,7 +97,7 @@ import { GroupDetailData } from '@ucap-webmessenger/protocol-sync';
selector: 'app-layout-messenger-messages', selector: 'app-layout-messenger-messages',
templateUrl: './messages.component.html', templateUrl: './messages.component.html',
styleUrls: ['./messages.component.scss'], styleUrls: ['./messages.component.scss'],
animations: ucapAnimations animations: ucapAnimations,
}) })
export class MessagesComponent implements OnInit, OnDestroy, AfterViewInit { export class MessagesComponent implements OnInit, OnDestroy, AfterViewInit {
@Output() @Output()
@ -379,7 +379,7 @@ export class MessagesComponent implements OnInit, OnDestroy, AfterViewInit {
// duration: 3000, // duration: 3000,
verticalPosition: 'bottom', verticalPosition: 'bottom',
horizontalPosition: 'center', horizontalPosition: 'center',
panelClass: ['chat-snackbar-class'] panelClass: ['chat-snackbar-class'],
}); });
this.snackBarPreviewEvent.onAction().subscribe(() => { this.snackBarPreviewEvent.onAction().subscribe(() => {
this.setEventMoreInit(); this.setEventMoreInit();
@ -420,7 +420,7 @@ export class MessagesComponent implements OnInit, OnDestroy, AfterViewInit {
EventStore.info({ EventStore.info({
roomSeq: this.roomInfo.roomSeq, roomSeq: this.roomInfo.roomSeq,
baseSeq: seq, baseSeq: seq,
requestCount: CONST.EVENT_INFO_READ_COUNT requestCount: CONST.EVENT_INFO_READ_COUNT,
}) })
); );
} }
@ -438,8 +438,8 @@ export class MessagesComponent implements OnInit, OnDestroy, AfterViewInit {
width: '360px', width: '360px',
data: { data: {
title: 'Alert', title: 'Alert',
message: `대화내용을 입력해주세요.` message: `대화내용을 입력해주세요.`,
} },
}); });
return; return;
} }
@ -453,8 +453,8 @@ export class MessagesComponent implements OnInit, OnDestroy, AfterViewInit {
roomSeq: this.roomInfo.roomSeq, roomSeq: this.roomInfo.roomSeq,
eventType: EventType.MassText, eventType: EventType.MassText,
// sentMessage: message.replace(/\n/gi, '\r\n') // sentMessage: message.replace(/\n/gi, '\r\n')
sentMessage: message sentMessage: message,
} },
}) })
); );
} else { } else {
@ -464,8 +464,8 @@ export class MessagesComponent implements OnInit, OnDestroy, AfterViewInit {
req: { req: {
roomSeq: this.roomInfo.roomSeq, roomSeq: this.roomInfo.roomSeq,
eventType: EventType.Character, eventType: EventType.Character,
sentMessage: message sentMessage: message,
} },
}) })
); );
} }
@ -479,20 +479,19 @@ export class MessagesComponent implements OnInit, OnDestroy, AfterViewInit {
onMassDetail(value: number) { onMassDetail(value: number) {
this.store.dispatch( this.store.dispatch(
ChatStore.selectedMassDetail({ ChatStore.selectedMassDetail({
massEventSeq: value massEventSeq: value,
}) })
); );
} }
async onFileViewer(fileInfo: FileEventJson) { async onFileViewer(fileInfo: FileEventJson) {
this.logger.debug('onFileViewer', fileInfo);
const result = await this.dialogService.open< const result = await this.dialogService.open<
FileViewerDialogComponent, FileViewerDialogComponent,
FileViewerDialogData, FileViewerDialogData,
FileViewerDialogResult FileViewerDialogResult
>(FileViewerDialogComponent, { >(FileViewerDialogComponent, {
position: { position: {
top: '30px' top: '30px',
}, },
maxWidth: '100vw', maxWidth: '100vw',
maxHeight: '100vh', maxHeight: '100vh',
@ -505,8 +504,8 @@ export class MessagesComponent implements OnInit, OnDestroy, AfterViewInit {
downloadUrl: this.sessionVerInfo.downloadUrl, downloadUrl: this.sessionVerInfo.downloadUrl,
deviceType: this.environmentsInfo.deviceType, deviceType: this.environmentsInfo.deviceType,
token: this.loginRes.tokenString, token: this.loginRes.tokenString,
userSeq: this.loginRes.userSeq userSeq: this.loginRes.userSeq,
} },
}); });
} }
@ -532,7 +531,7 @@ export class MessagesComponent implements OnInit, OnDestroy, AfterViewInit {
const info = { const info = {
senderSeq: this.loginRes.userSeq, senderSeq: this.loginRes.userSeq,
roomSeq: this.roomInfo.roomSeq roomSeq: this.roomInfo.roomSeq,
}; };
const allObservables: Observable<FileTalkSaveResponse>[] = []; const allObservables: Observable<FileTalkSaveResponse>[] = [];
@ -553,7 +552,7 @@ export class MessagesComponent implements OnInit, OnDestroy, AfterViewInit {
'rv', 'rv',
'ts', 'ts',
'webm', 'webm',
'wmv' 'wmv',
].indexOf(FileUtil.getExtension(fileUploadItem.file.name)) ].indexOf(FileUtil.getExtension(fileUploadItem.file.name))
) { ) {
thumbnail = await FileUtil.thumbnail(fileUploadItem.file); thumbnail = await FileUtil.thumbnail(fileUploadItem.file);
@ -568,7 +567,7 @@ export class MessagesComponent implements OnInit, OnDestroy, AfterViewInit {
file: fileUploadItem.file, file: fileUploadItem.file,
fileName: fileUploadItem.file.name, fileName: fileUploadItem.file.name,
thumb: thumbnail, thumb: thumbnail,
fileUploadItem fileUploadItem,
}; };
allObservables.push( allObservables.push(
@ -600,8 +599,8 @@ export class MessagesComponent implements OnInit, OnDestroy, AfterViewInit {
req: { req: {
roomSeq: info.roomSeq, roomSeq: info.roomSeq,
eventType: EventType.File, eventType: EventType.File,
sentMessage: res.returnJson sentMessage: res.returnJson,
} },
}) })
); );
} }
@ -627,7 +626,7 @@ export class MessagesComponent implements OnInit, OnDestroy, AfterViewInit {
this.messageContextMenuTrigger.menu.focusFirstItem('mouse'); this.messageContextMenuTrigger.menu.focusFirstItem('mouse');
this.messageContextMenuTrigger.menuData = { this.messageContextMenuTrigger.menuData = {
message: params.message, message: params.message,
loginRes: this.loginRes loginRes: this.loginRes,
}; };
this.messageContextMenuTrigger.openMenu(); this.messageContextMenuTrigger.openMenu();
} }
@ -647,7 +646,7 @@ export class MessagesComponent implements OnInit, OnDestroy, AfterViewInit {
this.snackBarService.open('클립보드에 복사되었습니다.', '', { this.snackBarService.open('클립보드에 복사되었습니다.', '', {
duration: 3000, duration: 3000,
verticalPosition: 'top', verticalPosition: 'top',
horizontalPosition: 'center' horizontalPosition: 'center',
}); });
} }
} }
@ -659,7 +658,7 @@ export class MessagesComponent implements OnInit, OnDestroy, AfterViewInit {
userSeq: this.loginRes.userSeq, userSeq: this.loginRes.userSeq,
deviceType: this.environmentsInfo.deviceType, deviceType: this.environmentsInfo.deviceType,
token: this.loginRes.tokenString, token: this.loginRes.tokenString,
eventMassSeq: message.seq eventMassSeq: message.seq,
}) })
.pipe(take(1)) .pipe(take(1))
.subscribe(res => { .subscribe(res => {
@ -670,7 +669,7 @@ export class MessagesComponent implements OnInit, OnDestroy, AfterViewInit {
{ {
duration: 3000, duration: 3000,
verticalPosition: 'top', verticalPosition: 'top',
horizontalPosition: 'center' horizontalPosition: 'center',
} }
); );
} }
@ -694,8 +693,8 @@ export class MessagesComponent implements OnInit, OnDestroy, AfterViewInit {
data: { data: {
type: UserSelectDialogType.MessageForward, type: UserSelectDialogType.MessageForward,
title: 'MessageForward', title: 'MessageForward',
ignoreRoom: [this.roomInfo] ignoreRoom: [this.roomInfo],
} },
}); });
if (!!result && !!result.choice && result.choice) { if (!!result && !!result.choice && result.choice) {
@ -719,10 +718,10 @@ export class MessagesComponent implements OnInit, OnDestroy, AfterViewInit {
req: { req: {
roomSeq: '-999', roomSeq: '-999',
eventType: message.type, eventType: message.type,
sentMessage: message.sentMessage sentMessage: message.sentMessage,
}, },
trgtUserSeqs: userSeqs, trgtUserSeqs: userSeqs,
trgtRoomSeq: roomSeq trgtRoomSeq: roomSeq,
}) })
); );
} }
@ -738,9 +737,9 @@ export class MessagesComponent implements OnInit, OnDestroy, AfterViewInit {
req: { req: {
roomSeq: '-999', roomSeq: '-999',
eventType: message.type, eventType: message.type,
sentMessage: message.sentMessage sentMessage: message.sentMessage,
}, },
trgtUserSeqs: [this.loginRes.talkWithMeBotSeq] trgtUserSeqs: [this.loginRes.talkWithMeBotSeq],
}) })
); );
} }
@ -756,15 +755,15 @@ export class MessagesComponent implements OnInit, OnDestroy, AfterViewInit {
width: '220px', width: '220px',
data: { data: {
title: 'Delete', title: 'Delete',
html: `선택한 메시지를 삭제하시겠습니까?<br/>삭제된 메시지는 내 대화방에서만 적용되며 상대방의 대화방에서는 삭제되지 않습니다.` html: `선택한 메시지를 삭제하시겠습니까?<br/>삭제된 메시지는 내 대화방에서만 적용되며 상대방의 대화방에서는 삭제되지 않습니다.`,
} },
}); });
if (!!result && !!result.choice && result.choice) { if (!!result && !!result.choice && result.choice) {
this.store.dispatch( this.store.dispatch(
EventStore.del({ EventStore.del({
roomSeq: this.roomInfo.roomSeq, roomSeq: this.roomInfo.roomSeq,
eventSeq: message.seq eventSeq: message.seq,
}) })
); );
} }
@ -780,8 +779,8 @@ export class MessagesComponent implements OnInit, OnDestroy, AfterViewInit {
width: '220px', width: '220px',
data: { data: {
title: 'ReCall', title: 'ReCall',
html: `해당 대화를 회수하시겠습니까?<br/>상대방 대화창에서도 회수됩니다.` html: `해당 대화를 회수하시겠습니까?<br/>상대방 대화창에서도 회수됩니다.`,
} },
}); });
if (!!result && !!result.choice && result.choice) { if (!!result && !!result.choice && result.choice) {
@ -789,7 +788,7 @@ export class MessagesComponent implements OnInit, OnDestroy, AfterViewInit {
EventStore.cancel({ EventStore.cancel({
roomSeq: this.roomInfo.roomSeq, roomSeq: this.roomInfo.roomSeq,
eventSeq: message.seq, eventSeq: message.seq,
deviceType: this.environmentsInfo.deviceType deviceType: this.environmentsInfo.deviceType,
}) })
); );
} }
@ -806,7 +805,7 @@ export class MessagesComponent implements OnInit, OnDestroy, AfterViewInit {
{ {
this.store.dispatch( this.store.dispatch(
ChatStore.selectedRightDrawer({ ChatStore.selectedRightDrawer({
req: RightDrawer.AlbumBox req: RightDrawer.AlbumBox,
}) })
); );
} }
@ -815,7 +814,16 @@ export class MessagesComponent implements OnInit, OnDestroy, AfterViewInit {
{ {
this.store.dispatch( this.store.dispatch(
ChatStore.selectedRightDrawer({ ChatStore.selectedRightDrawer({
req: RightDrawer.FileBox req: RightDrawer.FileBox,
})
);
}
break;
case 'OPEN_ROOM_USER':
{
this.store.dispatch(
ChatStore.selectedRightDrawer({
req: RightDrawer.RoomUser,
}) })
); );
} }
@ -833,8 +841,8 @@ export class MessagesComponent implements OnInit, OnDestroy, AfterViewInit {
title: 'Edit Chat Member', title: 'Edit Chat Member',
curRoomUser: this.userInfoList.filter( curRoomUser: this.userInfoList.filter(
user => user.seq !== this.loginRes.userSeq user => user.seq !== this.loginRes.userSeq
) ),
} },
}); });
if (!!result && !!result.choice && result.choice) { if (!!result && !!result.choice && result.choice) {
@ -856,8 +864,8 @@ export class MessagesComponent implements OnInit, OnDestroy, AfterViewInit {
RoomStore.inviteOrOpen({ RoomStore.inviteOrOpen({
req: { req: {
divCd: 'Invite', divCd: 'Invite',
userSeqs userSeqs,
} },
}) })
); );
} }
@ -873,8 +881,8 @@ export class MessagesComponent implements OnInit, OnDestroy, AfterViewInit {
>(SelectGroupDialogComponent, { >(SelectGroupDialogComponent, {
width: '600px', width: '600px',
data: { data: {
title: 'Group Select' title: 'Group Select',
} },
}); });
if (!!result && !!result.choice && result.choice) { if (!!result && !!result.choice && result.choice) {
@ -891,7 +899,7 @@ export class MessagesComponent implements OnInit, OnDestroy, AfterViewInit {
this.store.dispatch( this.store.dispatch(
SyncStore.updateGroupMember({ SyncStore.updateGroupMember({
oldGroup, oldGroup,
trgtUserSeq trgtUserSeq,
}) })
); );
} }
@ -908,8 +916,8 @@ export class MessagesComponent implements OnInit, OnDestroy, AfterViewInit {
width: '600px', width: '600px',
data: { data: {
title: 'Edit Chat Room', title: 'Edit Chat Room',
roomInfo: this.roomInfo roomInfo: this.roomInfo,
} },
}); });
if (!!result && !!result.choice && result.choice) { if (!!result && !!result.choice && result.choice) {
@ -926,8 +934,8 @@ export class MessagesComponent implements OnInit, OnDestroy, AfterViewInit {
roomName, roomName,
receiveAlarm: roomInfo.receiveAlarm, receiveAlarm: roomInfo.receiveAlarm,
syncAll: syncAll:
roomNameChangeTarget.toUpperCase() === 'ALL' ? true : false roomNameChangeTarget.toUpperCase() === 'ALL' ? true : false,
} },
}) })
); );
@ -939,7 +947,7 @@ export class MessagesComponent implements OnInit, OnDestroy, AfterViewInit {
this.store.dispatch( this.store.dispatch(
RoomStore.updateTimeRoomInterval({ RoomStore.updateTimeRoomInterval({
roomSeq: roomInfo.roomSeq, roomSeq: roomInfo.roomSeq,
timerInterval: timeRoomInterval timerInterval: timeRoomInterval,
}) })
); );
} }

View File

@ -1,7 +1,34 @@
<div>
<span>{{ selectedRightDrawer }}</span>
<span>
<button
mat-button
matSuffix
mat-icon-button
aria-label="Close"
(click)="onClickClose()"
>
<mat-icon>close</mat-icon>
</button>
</span>
</div>
<ng-container *ngIf="selectedRightDrawer" [ngSwitch]="selectedRightDrawer"> <ng-container *ngIf="selectedRightDrawer" [ngSwitch]="selectedRightDrawer">
<!-- [S] About Chat room -->
<app-layout-chat-right-drawer-file-box *ngSwitchCase="RightDrawer.FileBox"> <app-layout-chat-right-drawer-file-box *ngSwitchCase="RightDrawer.FileBox">
</app-layout-chat-right-drawer-file-box> </app-layout-chat-right-drawer-file-box>
<app-layout-chat-right-drawer-album-box *ngSwitchCase="RightDrawer.AlbumBox"> <app-layout-chat-right-drawer-album-box *ngSwitchCase="RightDrawer.AlbumBox">
</app-layout-chat-right-drawer-album-box> </app-layout-chat-right-drawer-album-box>
<app-layout-chat-right-drawer-room-user-list
*ngSwitchCase="RightDrawer.RoomUser"
(openProfile)="onClickOpenProfile($event)"
>
</app-layout-chat-right-drawer-room-user-list>
<!-- [E] About Chat room -->
<!-- [S] About Common -->
<app-layout-chat-right-drawer-message-box *ngSwitchCase="RightDrawer.Message">
</app-layout-chat-right-drawer-message-box>
<!-- [E] About Common -->
</ng-container> </ng-container>

View File

@ -1,18 +1,39 @@
import { Component, OnInit, Input } from '@angular/core'; import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
import { RightDrawer } from '@app/types'; import { RightDrawer } from '@app/types';
import { UserInfo } from '@ucap-webmessenger/protocol-room';
import {
UserInfoSS,
UserInfoF,
UserInfoDN,
} from '@ucap-webmessenger/protocol-query';
@Component({ @Component({
selector: 'app-layout-messenger-right-drawer', selector: 'app-layout-messenger-right-drawer',
templateUrl: './right-drawer.component.html', templateUrl: './right-drawer.component.html',
styleUrls: ['./right-drawer.component.scss'] styleUrls: ['./right-drawer.component.scss'],
}) })
export class RightDrawerComponent implements OnInit { export class RightDrawerComponent implements OnInit {
@Input() @Input()
selectedRightDrawer: RightDrawer; selectedRightDrawer: RightDrawer;
@Output()
openProfile = new EventEmitter<
UserInfo | UserInfoSS | UserInfoF | UserInfoDN
>();
@Output()
closeRightDrawer = new EventEmitter();
RightDrawer = RightDrawer; RightDrawer = RightDrawer;
constructor() {} constructor() {}
ngOnInit() {} ngOnInit() {}
onClickOpenProfile(userInfo: UserInfo | UserInfoSS | UserInfoF | UserInfoDN) {
this.openProfile.emit(userInfo);
}
onClickClose() {
this.closeRightDrawer.emit();
}
} }

View File

@ -1 +1,104 @@
<p>album-box works!</p> <div fxLayout="column" style="width: 600px;" class="album-box">
<div>
<mat-tab-group (selectedIndexChange)="onSelectedIndexChange($event)">
<mat-tab label="Image"></mat-tab>
<mat-tab label="Video"></mat-tab>
</mat-tab-group>
</div>
<div fxFlex="0 0 400px">
<ng-container *ngIf="!selectedFile">
Select File.
</ng-container>
<ng-container *ngIf="selectedFile">
<img
*ngIf="selectedFile.info.type === FileType.Image"
[src]="getImageUrl(selectedFile)"
class="preview-image"
/>
<video
controls
*ngIf="selectedFile.info.type === FileType.Video"
class="preview-image"
>
<source [src]="getImageUrl(selectedFile)" />
</video>
<ul>
<li>name : {{ selectedFile.info.name }}</li>
<li>size : {{ selectedFile.info.size | ucapBytes }}</li>
<li>
date :
{{ selectedFile.info.sendDate | dateToStringFormat: 'YYYY.MM.DD' }}
</li>
</ul>
</ng-container>
</div>
<div class="search-list">
<div
*ngFor="let fileInfo of filteredList"
class="img-item"
matTooltip="fileInfo.info.name"
(click)="onClickImage($event, fileInfo)"
>
<dl>
<dt>
<div
*ngIf="
!!fileInfo.eventInfo &&
!!fileInfo.eventInfo.sentMessageJson &&
!!fileInfo.eventInfo.sentMessageJson.thumbUrl;
then thumb;
else icon
"
></div>
<ng-template #thumb>
<img [src]="fileInfo.eventInfo.sentMessageJson.thumbUrl" />
</ng-template>
<ng-template #icon>
<div
[ngClass]="[
'mime-icon',
'light',
'ico-' + getExtention(fileInfo.info.name)
]"
>
<div class="ico"></div>
</div>
</ng-template>
</dt>
<dd>
<span>
<mat-checkbox
#checkbox
[checked]="getCheckItem(fileInfo)"
(change)="onCheckItem(checkbox.checked, fileInfo)"
(click)="$event.stopPropagation()"
>
</mat-checkbox>
</span>
<span>
<button mat-button (click)="onClickDownload(fileInfo)">
<mat-icon>vertical_align_bottom</mat-icon>
</button>
</span>
</dd>
</dl>
</div>
</div>
<div
fxFlex="1 1 50px"
fxLayout="row"
fxLayoutAlign="center center"
class="btn-box"
>
<button
mat-flat-button
[disabled]="selectedFileList.length > 0 ? 'false' : 'true'"
class="mat-primary"
>
Download All
</button>
<button mat-flat-button class="mat-primary">
Open Folder
</button>
</div>
</div>

View File

@ -0,0 +1,24 @@
.album-box {
height: 100%;
overflow: hidden;
.search-list {
overflow: auto;
}
}
.img-item {
cursor: pointer;
max-width: 150px;
min-width: 150px;
}
.preview-image {
max-height: 300px;
}
.btn-box {
button {
margin: 5px;
}
}

View File

@ -1,12 +1,198 @@
import { Component, OnInit } from '@angular/core'; import { Component, OnInit, ViewChild, OnDestroy } from '@angular/core';
import { MatPaginator, MatTableDataSource } from '@angular/material';
import {
FileInfo,
FileDownloadInfo,
FileType,
} from '@ucap-webmessenger/protocol-file';
import { Subscription, combineLatest } from 'rxjs';
import { Store, select } from '@ngrx/store';
import * as AppStore from '@app/store';
import * as ChatStore from '@app/store/messenger/chat';
import { tap, map } from 'rxjs/operators';
import {
Info,
EventJson,
FileEventJson,
} from '@ucap-webmessenger/protocol-event';
import { FileUtil } from '@ucap-webmessenger/core';
import { CommonApiService } from '@ucap-webmessenger/api-common';
import { LoginResponse } from '@ucap-webmessenger/protocol-authentication';
import { SessionStorageService } from '@ucap-webmessenger/web-storage';
import { KEY_LOGIN_RES_INFO } from '@app/types/login-res-info.type';
import { EnvironmentsInfo, KEY_ENVIRONMENTS_INFO } from '@app/types';
import { VersionInfo2Response } from '@ucap-webmessenger/api-public';
import { KEY_VER_INFO } from '@app/types/ver-info.type';
export interface FileInfoTotal {
info: FileInfo;
checkInfo: FileDownloadInfo[];
eventInfo?: Info<FileEventJson>;
}
@Component({ @Component({
selector: 'app-layout-chat-right-drawer-album-box', selector: 'app-layout-chat-right-drawer-album-box',
templateUrl: './album-box.component.html', templateUrl: './album-box.component.html',
styleUrls: ['./album-box.component.scss'] styleUrls: ['./album-box.component.scss'],
}) })
export class AlbumBoxComponent implements OnInit { export class AlbumBoxComponent implements OnInit, OnDestroy {
constructor() {} filteredList: FileInfoTotal[] = [];
fileInfoTotal: FileInfoTotal[];
fileInfoList: FileInfo[];
fileInfoListSubscription: Subscription;
ngOnInit() {} selectedFile: FileInfoTotal;
selectedFileList: FileInfoTotal[] = [];
loginRes: LoginResponse;
environmentsInfo: EnvironmentsInfo;
sessionVerinfo: VersionInfo2Response;
FileType = FileType;
currentTabIndex = 0;
constructor(
private store: Store<any>,
private sessionStorageService: SessionStorageService,
private commonApiService: CommonApiService
) {
this.loginRes = this.sessionStorageService.get<LoginResponse>(
KEY_LOGIN_RES_INFO
);
this.environmentsInfo = this.sessionStorageService.get<EnvironmentsInfo>(
KEY_ENVIRONMENTS_INFO
);
this.sessionVerinfo = this.sessionStorageService.get<VersionInfo2Response>(
KEY_VER_INFO
);
}
ngOnInit() {
this.fileInfoListSubscription = combineLatest([
this.store.pipe(select(AppStore.MessengerSelector.RoomSelector.roomInfo)),
this.store.pipe(
select(AppStore.MessengerSelector.EventSelector.selectAllFileInfoList)
),
this.store.pipe(
select(
AppStore.MessengerSelector.EventSelector.selectAllFileInfoCheckList
)
),
this.store.pipe(
select(AppStore.MessengerSelector.EventSelector.selectAllInfoList)
),
])
.pipe(
tap(() => (this.fileInfoTotal = [])),
tap(([roomInfo, fileInfoList, fileInfoCheckList, eventList]) => {
this.fileInfoList = fileInfoList.filter(fileInfo => {
if (
fileInfo.roomSeq === roomInfo.roomSeq &&
(fileInfo.type === FileType.Image ||
fileInfo.type === FileType.Video)
) {
return true;
} else {
return false;
}
});
this.fileInfoList.map(fileInfo => {
const events = eventList.filter(
event => event.seq === fileInfo.eventSeq
);
this.fileInfoTotal.push({
info: fileInfo,
checkInfo: fileInfoCheckList.filter(
checkInfo => checkInfo.seq === fileInfo.seq
),
eventInfo:
events.length > 0 ? (events[0] as Info<FileEventJson>) : null,
});
});
this.onSelectedIndexChange(this.currentTabIndex);
})
)
.subscribe();
}
ngOnDestroy(): void {
if (!!this.fileInfoListSubscription) {
this.fileInfoListSubscription.unsubscribe();
}
}
getExtention(name: string): string {
return FileUtil.getExtension(name);
}
getImageUrl(fileInfo: FileInfoTotal): string {
return this.commonApiService.urlForFileTalkDownload(
{
userSeq: this.loginRes.userSeq,
deviceType: this.environmentsInfo.deviceType,
token: this.loginRes.tokenString,
attachmentsSeq: fileInfo.info.seq,
},
this.sessionVerinfo.downloadUrl
);
}
onSelectedIndexChange(index: number) {
this.selectedFile = null;
this.currentTabIndex = index;
if (this.currentTabIndex === 0) {
// Image
this.filteredList = this.fileInfoTotal.filter(
fileInfo => fileInfo.info.type === FileType.Image
);
} else {
// Video
this.filteredList = this.fileInfoTotal.filter(
fileInfo => fileInfo.info.type === FileType.Video
);
}
}
onClickImage(event: MouseEvent, fileInfo: FileInfoTotal) {
if (!!event) {
event.preventDefault();
event.stopPropagation();
}
this.selectedFile = fileInfo;
}
getCheckItem(fileInfo: FileInfoTotal) {
if (this.selectedFileList) {
if (
this.selectedFileList.filter(
info => info.info.seq === fileInfo.info.seq
).length > 0
) {
return true;
} else {
return false;
}
} else {
return false;
}
}
onCheckItem(value: boolean, fileInfo: FileInfoTotal) {
if (value) {
this.onClickImage(undefined, fileInfo);
this.selectedFileList.push(fileInfo);
} else {
this.selectedFileList = this.selectedFileList.filter(
info => info.info.seq !== fileInfo.info.seq
);
}
}
onClickDownload(fileInfo: FileInfoTotal) {
console.log(fileInfo);
}
} }

View File

@ -1 +1,108 @@
<p>file-box works!</p> <div fxLayout="column">
<div>
<mat-tab-group (selectedIndexChange)="onSelectedIndexChange($event)">
<mat-tab label="Receive"></mat-tab>
<mat-tab label="Send"></mat-tab>
</mat-tab-group>
</div>
<div fxFlex="1 1 300px">
<ng-container *ngIf="!selectedFile">
Select File.
</ng-container>
<ng-container *ngIf="selectedFile">
<div
[ngClass]="[
'mime-icon',
'light',
'ico-' + getExtention(selectedFile.info.name)
]"
>
<div class="ico"></div>
</div>
<ul>
<li>name : {{ selectedFile.info.name }}</li>
<li>size : {{ selectedFile.info.size | ucapBytes }}</li>
<li>
date :
{{ selectedFile.info.sendDate | dateToStringFormat: 'YYYY.MM.DD' }}
</li>
</ul>
</ng-container>
</div>
<div fxFlex="1 1 auto">
<table mat-table [dataSource]="dataSource" matSort>
<ng-container matColumnDef="check">
<th mat-header-cell *matHeaderCellDef>
<mat-checkbox
#checkboxAll
[checked]="getCheckAllUser()"
(change)="onCheckAllkUser(checkboxAll.checked)"
(click)="$event.stopPropagation()"
>
</mat-checkbox>
</th>
<td mat-cell *matCellDef="let element">
<mat-checkbox
#checkbox
[checked]="getCheckUser(element)"
(change)="onCheckUser(checkbox.checked, element)"
(click)="$event.stopPropagation()"
>
</mat-checkbox>
</td>
</ng-container>
<ng-container matColumnDef="name">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Name</th>
<td mat-cell *matCellDef="let element">{{ element.info.name }}</td>
</ng-container>
<ng-container matColumnDef="size">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Size</th>
<td mat-cell *matCellDef="let element">
{{ element.info.size | ucapBytes }}
</td>
</ng-container>
<ng-container matColumnDef="sendDate">
<th mat-header-cell *matHeaderCellDef mat-sort-header>sendDate</th>
<td mat-cell *matCellDef="let element">
{{ element.info.sendDate | dateToStringFormat: 'YYYY.MM.DD' }}
</td>
</ng-container>
<ng-container matColumnDef="receivedUserCount">
<th mat-header-cell *matHeaderCellDef mat-sort-header>receivedUser</th>
<td mat-cell *matCellDef="let element">
{{ element.info.receivedUserCount }}
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr
mat-row
*matRowDef="let row; columns: displayedColumns"
(click)="onClickRow(row)"
></tr>
</table>
<mat-paginator
[pageSize]="10"
[pageSizeOptions]="[5, 10, 20]"
showFirstLastButtons
></mat-paginator>
</div>
<div
fxFlex="1 1 50px"
fxLayout="row"
fxLayoutAlign="center center"
class="btn-box"
>
<button
mat-flat-button
[disabled]="selectedFileList.length > 0 ? 'false' : 'true'"
class="mat-primary"
>
Download All
</button>
<button mat-flat-button class="mat-primary">
Open Folder
</button>
</div>
</div>

View File

@ -0,0 +1,14 @@
table {
width: 100%;
}
.mat-row:hover {
background: rgba(0, 0, 0, 0.04);
cursor: pointer;
}
.btn-box {
button {
margin: 5px;
}
}

View File

@ -1,12 +1,218 @@
import { Component, OnInit } from '@angular/core'; import { Component, OnInit, ViewChild, OnDestroy } from '@angular/core';
import { MatPaginator, MatTableDataSource, MatSort } from '@angular/material';
import {
FileInfo,
FileDownloadInfo,
FileType,
} from '@ucap-webmessenger/protocol-file';
import { Subscription, combineLatest } from 'rxjs';
import { Store, select } from '@ngrx/store';
import * as AppStore from '@app/store';
import * as ChatStore from '@app/store/messenger/chat';
import { tap, map } from 'rxjs/operators';
import { FileUtil } from '@ucap-webmessenger/core';
import { LoginResponse } from '@ucap-webmessenger/protocol-authentication';
import { SessionStorageService } from '@ucap-webmessenger/web-storage';
import { KEY_LOGIN_RES_INFO } from '@app/types/login-res-info.type';
export interface FileInfoTotal {
info: FileInfo;
checkInfo: FileDownloadInfo[];
}
@Component({ @Component({
selector: 'app-layout-chat-right-drawer-file-box', selector: 'app-layout-chat-right-drawer-file-box',
templateUrl: './file-box.component.html', templateUrl: './file-box.component.html',
styleUrls: ['./file-box.component.scss'] styleUrls: ['./file-box.component.scss'],
}) })
export class FileBoxComponent implements OnInit { export class FileBoxComponent implements OnInit, OnDestroy {
constructor() {} displayedColumns: string[] = [
'check',
'name',
'size',
'sendDate',
'receivedUserCount',
];
dataSource = new MatTableDataSource<FileInfoTotal>();
ngOnInit() {} fileInfoTotal: FileInfoTotal[];
fileInfoList: FileInfo[];
fileInfoListSubscription: Subscription;
selectedFile: FileInfoTotal;
selectedFileList: FileInfoTotal[] = [];
loginRes: LoginResponse;
currentTabIndex = 0;
@ViewChild(MatPaginator, { static: true }) paginator: MatPaginator;
@ViewChild(MatSort, { static: true }) sort: MatSort;
constructor(
private store: Store<any>,
private sessionStorageService: SessionStorageService
) {
this.loginRes = this.sessionStorageService.get<LoginResponse>(
KEY_LOGIN_RES_INFO
);
}
ngOnInit() {
this.fileInfoListSubscription = combineLatest([
this.store.pipe(select(AppStore.MessengerSelector.RoomSelector.roomInfo)),
this.store.pipe(
select(AppStore.MessengerSelector.EventSelector.selectAllFileInfoList)
),
this.store.pipe(
select(
AppStore.MessengerSelector.EventSelector.selectAllFileInfoCheckList
)
),
])
.pipe(
tap(() => (this.fileInfoTotal = [])),
tap(([roomInfo, fileInfoList, fileInfoCheckList]) => {
this.fileInfoList = fileInfoList.filter(fileInfo => {
if (
fileInfo.roomSeq === roomInfo.roomSeq &&
(fileInfo.type === FileType.File ||
fileInfo.type === FileType.Sound)
) {
return true;
} else {
return false;
}
});
this.fileInfoList.map(fileInfo => {
this.fileInfoTotal.push({
info: fileInfo,
checkInfo: fileInfoCheckList.filter(
checkInfo => checkInfo.seq === fileInfo.seq
),
});
});
this.onSelectedIndexChange(this.currentTabIndex);
})
)
.subscribe();
this.dataSource.sortingDataAccessor = (item, property) => {
switch (property) {
case 'name':
return item.info.name;
case 'size':
return item.info.size;
case 'sendDate':
return item.info.sendDate;
case 'receivedUserCount':
return item.info.receivedUserCount;
default:
return item[property];
}
};
this.dataSource.sort = this.sort;
this.dataSource.paginator = this.paginator;
}
ngOnDestroy(): void {
if (!!this.fileInfoListSubscription) {
this.fileInfoListSubscription.unsubscribe();
}
}
getExtention(name: string): string {
return FileUtil.getExtension(name);
}
onSelectedIndexChange(index: number) {
this.selectedFile = null;
this.currentTabIndex = index;
if (this.currentTabIndex === 0) {
// Receive
this.dataSource.data = this.fileInfoTotal.filter(
fileInfo => fileInfo.info.senderSeq !== this.loginRes.userSeq
);
} else {
// send
this.dataSource.data = this.fileInfoTotal.filter(
fileInfo => fileInfo.info.senderSeq === this.loginRes.userSeq
);
}
}
getCheckAllUser() {
const data = this.dataSource
.sortData(this.dataSource.data, this.sort)
.filter((u, i) => i >= this.paginator.pageSize * this.paginator.pageIndex)
.filter((u, i) => i < this.paginator.pageSize);
if (
data.filter(
dInfo =>
this.selectedFileList.filter(
fileInfo => fileInfo.info.seq === dInfo.info.seq
).length === 0
).length > 0
) {
return false;
} else {
return true;
}
}
onCheckAllkUser(value: boolean) {
const data = this.dataSource
.sortData(this.dataSource.data, this.sort)
.filter((u, i) => i >= this.paginator.pageSize * this.paginator.pageIndex)
.filter((u, i) => i < this.paginator.pageSize);
if (!!data && data.length > 0) {
if (value) {
this.selectedFileList.push(
...data.filter(dInfo =>
this.selectedFileList.filter(
fileInfo => fileInfo.info.seq !== dInfo.info.seq
)
)
);
} else {
this.selectedFileList = this.selectedFileList.filter(
fileInfo =>
!(
data.filter(dInfo => dInfo.info.seq === fileInfo.info.seq)
.length > 0
)
);
}
}
}
getCheckUser(fileInfo: FileInfoTotal) {
if (this.selectedFileList) {
if (
this.selectedFileList.filter(
info => info.info.seq === fileInfo.info.seq
).length > 0
) {
return true;
} else {
return false;
}
} else {
return false;
}
}
onCheckUser(value: boolean, fileInfo: FileInfoTotal) {
if (value) {
this.selectedFileList.push(fileInfo);
} else {
this.selectedFileList = this.selectedFileList.filter(
info => info.info.seq !== fileInfo.info.seq
);
}
}
onClickRow(row: FileInfoTotal) {
this.selectedFile = row;
}
} }

View File

@ -1,4 +1,11 @@
import { FileBoxComponent } from './file-box.component'; import { FileBoxComponent } from './file-box.component';
import { AlbumBoxComponent } from './album-box.component'; import { AlbumBoxComponent } from './album-box.component';
import { RoomUserListComponent } from './room-user-list.component';
import { MessageBoxComponent } from './message-box.component';
export const RIGHT_DRAWER_COMPONENTS = [FileBoxComponent, AlbumBoxComponent]; export const RIGHT_DRAWER_COMPONENTS = [
FileBoxComponent,
AlbumBoxComponent,
RoomUserListComponent,
MessageBoxComponent
];

View File

@ -0,0 +1,3 @@
<div class="message-box container">
<p>message-box works!</p>
</div>

View File

@ -0,0 +1,3 @@
div.message-box {
width: 600px;
}

View File

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

View File

@ -0,0 +1,113 @@
import {
Component,
OnInit,
OnDestroy,
Output,
EventEmitter
} from '@angular/core';
import { Subscription, of } from 'rxjs';
import { Store, select } from '@ngrx/store';
import { tap, map, catchError } from 'rxjs/operators';
import * as AppStore from '@app/store';
import * as SyncStore from '@app/store/messenger/sync';
import * as RoomStore from '@app/store/messenger/room';
import { UserInfo } from '@ucap-webmessenger/protocol-room';
import { VersionInfo2Response } from '@ucap-webmessenger/api-public';
import { SessionStorageService } from '@ucap-webmessenger/web-storage';
import { KEY_VER_INFO } from '@app/types/ver-info.type';
import { DialogService } from '@ucap-webmessenger/ui';
import {
SelectGroupDialogComponent,
SelectGroupDialogResult,
SelectGroupDialogData
} from '../../dialogs/group/select-group.dialog.component';
import { GroupDetailData } from '@ucap-webmessenger/protocol-sync';
import {
CreateChatDialogComponent,
CreateChatDialogResult,
CreateChatDialogData
} from '../../dialogs/chat/create-chat.dialog.component';
import { UserSelectDialogType } from '@app/types';
import { LoginResponse } from '@ucap-webmessenger/protocol-authentication';
import { KEY_LOGIN_RES_INFO } from '@app/types/login-res-info.type';
import {
MessageApiService,
RetrieveRequest,
MessageType
} from '@ucap-webmessenger/api-message';
import { DeviceType } from '@ucap-webmessenger/core';
import { StatusCode } from '@ucap-webmessenger/api';
@Component({
selector: 'app-layout-chat-right-drawer-message-box',
templateUrl: './message-box.component.html',
styleUrls: ['./message-box.component.scss']
})
export class MessageBoxComponent implements OnInit, OnDestroy {
userInfoList: UserInfo[];
userInfoListSubscription: Subscription;
loginRes: LoginResponse;
sessionVerinfo: VersionInfo2Response;
messageSendListSubscription: Subscription;
pageSize = 100; // default
currentPage = 0; // start index is 0.
constructor(
private store: Store<any>,
private sessionStorageService: SessionStorageService,
private dialogService: DialogService,
private messageApiService: MessageApiService
) {
this.loginRes = this.sessionStorageService.get<LoginResponse>(
KEY_LOGIN_RES_INFO
);
this.sessionVerinfo = this.sessionStorageService.get<VersionInfo2Response>(
KEY_VER_INFO
);
}
ngOnInit() {
this.userInfoListSubscription = this.store
.pipe(
select(AppStore.MessengerSelector.RoomSelector.selectUserinfolist),
tap(userInfoList => {
this.userInfoList = userInfoList;
})
)
.subscribe();
this.messageSendListSubscription = this.messageApiService
.retrieveSendMessage({
userSeq: this.loginRes.userSeq,
deviceType: DeviceType.PC,
tokenKey: this.loginRes.tokenString,
type: MessageType.Send,
pageSize: this.pageSize,
pageCount: this.currentPage
} as RetrieveRequest)
.pipe(
map(res => {
console.log(res);
if (res.statusCode === StatusCode.Success) {
} else {
}
}),
catchError(error => of(console.log(error)))
)
.subscribe();
}
ngOnDestroy(): void {
if (!!this.userInfoListSubscription) {
this.userInfoListSubscription.unsubscribe();
}
if (!!this.messageSendListSubscription) {
this.messageSendListSubscription.unsubscribe();
}
}
}

View File

@ -0,0 +1,25 @@
<div fxLayout="column" class="list">
<div class="search-list">
<ucap-profile-user-list-item
*ngFor="let userInfo of userInfoList"
[userInfo]="userInfo"
[presence]="getStatusBulkInfo(userInfo) | async"
[sessionVerinfo]="sessionVerinfo"
(openProfile)="onClickOpenProfile($event)"
>
</ucap-profile-user-list-item>
</div>
<div
fxFlex="1 1 50px"
fxLayout="row"
fxLayoutAlign="center center"
class="btn-box"
>
<button mat-flat-button class="mat-primary" (click)="onClickAddMember()">
대화상대추가
</button>
<button mat-flat-button class="mat-primary" (click)="onClickAddGroup()">
그룹멤버로추가
</button>
</div>
</div>

View File

@ -0,0 +1,15 @@
.list {
width: 300px;
height: 100%;
overflow: hidden;
.search-list {
overflow: auto;
}
}
.btn-box {
button {
margin: 5px;
}
}

View File

@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { RoomUserListComponent } from './room-user-list.component';
describe('RoomUserListComponent', () => {
let component: RoomUserListComponent;
let fixture: ComponentFixture<RoomUserListComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ RoomUserListComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(RoomUserListComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,168 @@
import {
Component,
OnInit,
OnDestroy,
Output,
EventEmitter,
} from '@angular/core';
import { Subscription } from 'rxjs';
import { Store, select } from '@ngrx/store';
import { tap, map } from 'rxjs/operators';
import * as AppStore from '@app/store';
import * as SyncStore from '@app/store/messenger/sync';
import * as RoomStore from '@app/store/messenger/room';
import { UserInfo } from '@ucap-webmessenger/protocol-room';
import { VersionInfo2Response } from '@ucap-webmessenger/api-public';
import { SessionStorageService } from '@ucap-webmessenger/web-storage';
import { KEY_VER_INFO } from '@app/types/ver-info.type';
import { DialogService } from '@ucap-webmessenger/ui';
import {
SelectGroupDialogComponent,
SelectGroupDialogResult,
SelectGroupDialogData,
} from '../../dialogs/group/select-group.dialog.component';
import { GroupDetailData } from '@ucap-webmessenger/protocol-sync';
import {
CreateChatDialogComponent,
CreateChatDialogResult,
CreateChatDialogData,
} from '../../dialogs/chat/create-chat.dialog.component';
import { UserSelectDialogType } from '@app/types';
import { LoginResponse } from '@ucap-webmessenger/protocol-authentication';
import { KEY_LOGIN_RES_INFO } from '@app/types/login-res-info.type';
@Component({
selector: 'app-layout-chat-right-drawer-room-user-list',
templateUrl: './room-user-list.component.html',
styleUrls: ['./room-user-list.component.scss'],
})
export class RoomUserListComponent implements OnInit, OnDestroy {
@Output()
openProfile = new EventEmitter<UserInfo>();
userInfoList: UserInfo[];
userInfoListSubscription: Subscription;
loginRes: LoginResponse;
sessionVerinfo: VersionInfo2Response;
constructor(
private store: Store<any>,
private sessionStorageService: SessionStorageService,
private dialogService: DialogService
) {
this.loginRes = this.sessionStorageService.get<LoginResponse>(
KEY_LOGIN_RES_INFO
);
this.sessionVerinfo = this.sessionStorageService.get<VersionInfo2Response>(
KEY_VER_INFO
);
}
ngOnInit() {
this.userInfoListSubscription = this.store
.pipe(
select(AppStore.MessengerSelector.RoomSelector.selectUserinfolist),
tap(userInfoList => {
this.userInfoList = userInfoList;
})
)
.subscribe();
}
ngOnDestroy(): void {
if (!!this.userInfoListSubscription) {
this.userInfoListSubscription.unsubscribe();
}
}
getStatusBulkInfo(buddy: UserInfo) {
return this.store.pipe(
select(
AppStore.MessengerSelector.StatusSelector.selectEntitiesStatusBulkInfo
),
map(statusBulkInfo =>
!!statusBulkInfo ? statusBulkInfo[buddy.seq] : undefined
)
);
}
onClickOpenProfile(userInfo: UserInfo) {
this.openProfile.emit(userInfo);
}
async onClickAddMember() {
const result = await this.dialogService.open<
CreateChatDialogComponent,
CreateChatDialogData,
CreateChatDialogResult
>(CreateChatDialogComponent, {
width: '600px',
data: {
type: UserSelectDialogType.EditChatMember,
title: 'Edit Chat Member',
curRoomUser: this.userInfoList.filter(
user => user.seq !== this.loginRes.userSeq
),
},
});
if (!!result && !!result.choice && result.choice) {
const userSeqs: number[] = [];
if (!!result.selectedUserList && result.selectedUserList.length > 0) {
result.selectedUserList.map(user => {
userSeqs.push(user.seq);
});
}
if (userSeqs.length > 0) {
// include me
userSeqs.push(this.loginRes.userSeq);
this.store.dispatch(
RoomStore.inviteOrOpen({
req: {
divCd: 'Invite',
userSeqs,
},
})
);
}
}
}
async onClickAddGroup() {
const result = await this.dialogService.open<
SelectGroupDialogComponent,
SelectGroupDialogData,
SelectGroupDialogResult
>(SelectGroupDialogComponent, {
width: '600px',
data: {
title: 'Group Select',
},
});
if (!!result && !!result.choice && result.choice) {
if (!!result.group) {
const oldGroup: GroupDetailData = result.group;
const trgtUserSeq: number[] = [];
result.group.userSeqs.map(seq => trgtUserSeq.push(seq));
this.userInfoList
.filter(v => result.group.userSeqs.indexOf(v.seq) < 0)
.forEach(user => {
trgtUserSeq.push(user.seq);
});
this.store.dispatch(
SyncStore.updateGroupMember({
oldGroup,
trgtUserSeq,
})
);
}
}
}
}

View File

@ -44,7 +44,7 @@
(keyDownEnter)=" (keyDownEnter)="
onKeyDownEnterOrganizationTenantSearch($event) onKeyDownEnterOrganizationTenantSearch($event)
" "
(cancel)="onClickCancel($event)" (cancel)="onClickCancel()"
></ucap-organization-tenant-search> ></ucap-organization-tenant-search>
</div> </div>
<div *ngIf="!isShowSearch" class="list-panel"> <div *ngIf="!isShowSearch" class="list-panel">

View File

@ -22,7 +22,13 @@ import { MatTabsModule } from '@angular/material/tabs';
import { MatToolbarModule } from '@angular/material/toolbar'; import { MatToolbarModule } from '@angular/material/toolbar';
import { MatFormFieldModule } from '@angular/material/form-field'; import { MatFormFieldModule } from '@angular/material/form-field';
import { MatInputModule } from '@angular/material/input'; import { MatInputModule } from '@angular/material/input';
import { MatCheckboxModule } from '@angular/material'; import {
MatCheckboxModule,
MatTableModule,
MatPaginatorModule,
MatRippleModule,
MatSortModule
} from '@angular/material';
import { MatListModule } from '@angular/material/list'; import { MatListModule } from '@angular/material/list';
import { MatChipsModule } from '@angular/material/chips'; import { MatChipsModule } from '@angular/material/chips';
@ -70,6 +76,10 @@ import { DIALOGS } from './dialogs';
MatCheckboxModule, MatCheckboxModule,
MatRadioModule, MatRadioModule,
MatSelectModule, MatSelectModule,
MatTableModule,
MatSortModule,
MatPaginatorModule,
MatRippleModule,
PerfectScrollbarModule, PerfectScrollbarModule,

View File

@ -1,9 +1,25 @@
<div class="container"> <div class="container">
<as-split
unit="pixel"
gutterSize="5"
useTransition="true"
gutterDblClickDuration="300"
(dragEnd)="onGutterDragEnd($event)"
(gutterDblClick)="onGutterDblClick($event)"
>
<as-split-area
#asSplitLeft
[size]="leftSideComponentWidth"
minSize="300"
maxSize="500"
>
<div class="left-side"> <div class="left-side">
<app-layout-messenger-left-side <app-layout-messenger-left-side
(openProfile)="onClickOpenProfile($event)" (openProfile)="onClickOpenProfile($event)"
></app-layout-messenger-left-side> ></app-layout-messenger-left-side>
</div> </div>
</as-split-area>
<as-split-area size="*">
<mat-drawer-container class="contents" autosize> <mat-drawer-container class="contents" autosize>
<!-- <mat-drawer #drawer mode="over"> <!-- <mat-drawer #drawer mode="over">
<p>Auto-resizing sidenav</p> <p>Auto-resizing sidenav</p>
@ -28,10 +44,14 @@
> >
<app-layout-messenger-right-drawer <app-layout-messenger-right-drawer
[selectedRightDrawer]="selectedRightDrawer$ | async" [selectedRightDrawer]="selectedRightDrawer$ | async"
(openProfile)="onClickOpenProfile($event)"
(closeRightDrawer)="onCloseRightDrawer($event)"
> >
</app-layout-messenger-right-drawer> </app-layout-messenger-right-drawer>
</mat-drawer> </mat-drawer>
</mat-drawer-container> </mat-drawer-container>
</as-split-area>
</as-split>
<!-- <div class="right-side"> <!-- <div class="right-side">
<app-layout-messenger-right-side></app-layout-messenger-right-side> <app-layout-messenger-right-side></app-layout-messenger-right-side>

View File

@ -3,11 +3,11 @@
display: flex; display: flex;
flex-flow: row; flex-flow: row;
padding-top: 30px; padding-top: 30px;
border:3px solid #4f4f4f; border: 3px solid #4f4f4f;
border-top:none; border-top: none;
.left-side { .left-side {
width: 380px; width: 100%;
height: 100%; height: 100%;
flex: 0 0 auto; flex: 0 0 auto;
position: relative; position: relative;

View File

@ -1,37 +1,38 @@
import { map, tap } from "rxjs/operators"; import { map, tap } from 'rxjs/operators';
import { Component, OnInit, Inject, OnDestroy, ViewChild } from "@angular/core"; import { Component, OnInit, Inject, OnDestroy, ViewChild } from '@angular/core';
import { Store, select } from "@ngrx/store"; import { Store, select } from '@ngrx/store';
import * as AppSotre from "@app/store"; import * as AppSotre from '@app/store';
import * as ChatStore from "@app/store/messenger/chat"; import * as ChatStore from '@app/store/messenger/chat';
import { Observable, Subscription } from "rxjs"; import { Observable, Subscription } from 'rxjs';
import { import {
WindowIdle, WindowIdle,
UCAP_NATIVE_SERVICE, UCAP_NATIVE_SERVICE,
NativeService NativeService,
} from "@ucap-webmessenger/native"; } from '@ucap-webmessenger/native';
import { UserInfo } from "@ucap-webmessenger/protocol-sync"; import { UserInfo } from '@ucap-webmessenger/protocol-sync';
import { import {
UserInfoSS, UserInfoSS,
UserInfoF, UserInfoF,
UserInfoDN UserInfoDN,
} from "@ucap-webmessenger/protocol-query"; } from '@ucap-webmessenger/protocol-query';
import { StatusProtocolService } from "@ucap-webmessenger/protocol-status"; import { StatusProtocolService } from '@ucap-webmessenger/protocol-status';
import { StatusType, StatusCode } from "@ucap-webmessenger/core"; import { StatusType, StatusCode } from '@ucap-webmessenger/core';
import { DialogService } from "@ucap-webmessenger/ui"; import { DialogService } from '@ucap-webmessenger/ui';
import { import {
ProfileDialogComponent, ProfileDialogComponent,
ProfileDialogData, ProfileDialogData,
ProfileDialogResult ProfileDialogResult,
} from "@app/layouts/messenger/dialogs/profile/profile.dialog.component"; } from '@app/layouts/messenger/dialogs/profile/profile.dialog.component';
import { MatSidenav, MatDrawer } from "@angular/material"; import { MatSidenav, MatDrawer } from '@angular/material';
import { SplitAreaDirective } from 'angular-split';
@Component({ @Component({
selector: "app-page-messenger-main", selector: 'app-page-messenger-main',
templateUrl: "./main.page.component.html", templateUrl: './main.page.component.html',
styleUrls: ["./main.page.component.scss"] styleUrls: ['./main.page.component.scss'],
}) })
export class MainPageComponent implements OnInit { export class MainPageComponent implements OnInit {
selectedChat$: Observable<string | null>; selectedChat$: Observable<string | null>;
@ -39,7 +40,10 @@ export class MainPageComponent implements OnInit {
idleStateChangedSubscription: Subscription; idleStateChangedSubscription: Subscription;
chatOpenRoomSubscription: Subscription; chatOpenRoomSubscription: Subscription;
@ViewChild("rightDrawer", { static: true }) rightDrawer: MatDrawer; defaultLeftSideComponentWidth = 380;
leftSideComponentWidth = this.defaultLeftSideComponentWidth;
@ViewChild('rightDrawer', { static: true }) rightDrawer: MatDrawer;
constructor( constructor(
@Inject(UCAP_NATIVE_SERVICE) private nativeService: NativeService, @Inject(UCAP_NATIVE_SERVICE) private nativeService: NativeService,
@ -75,7 +79,7 @@ export class MainPageComponent implements OnInit {
console.log(action); console.log(action);
let statusType: StatusCode; let statusType: StatusCode;
if (action === "IDLE") { if (action === 'IDLE') {
// away // away
statusType = StatusCode.Away; statusType = StatusCode.Away;
} else { } else {
@ -86,7 +90,7 @@ export class MainPageComponent implements OnInit {
this.statusProtocolService.status({ this.statusProtocolService.status({
statusDivisionType: StatusType.Messenger, statusDivisionType: StatusType.Messenger,
statusType, statusType,
statusMessage: "" statusMessage: '',
}); });
}); });
@ -111,12 +115,19 @@ export class MainPageComponent implements OnInit {
if (!event) { if (!event) {
this.store.dispatch( this.store.dispatch(
ChatStore.selectedRightDrawer({ ChatStore.selectedRightDrawer({
req: null req: null,
}) })
); );
} }
} }
onGutterDragEnd(e: { gutterNum: number; sizes: Array<number> }) {
this.leftSideComponentWidth = e.sizes[0];
}
onGutterDblClick(e: { gutterNum: number; sizes: Array<number> }) {
this.leftSideComponentWidth = this.defaultLeftSideComponentWidth;
}
onClickOpenProfile(userInfo: UserInfo | UserInfoSS | UserInfoF | UserInfoDN) { onClickOpenProfile(userInfo: UserInfo | UserInfoSS | UserInfoF | UserInfoDN) {
this.dialogService.open< this.dialogService.open<
ProfileDialogComponent, ProfileDialogComponent,
@ -124,8 +135,12 @@ export class MainPageComponent implements OnInit {
ProfileDialogResult ProfileDialogResult
>(ProfileDialogComponent, { >(ProfileDialogComponent, {
data: { data: {
userInfo userInfo,
} },
}); });
} }
onCloseRightDrawer() {
this.rightDrawer.close();
}
} }

View File

@ -11,15 +11,19 @@ import { AppMessengerRoutingPageModule } from './messenger-routing.page.module';
import { COMPONENTS } from './components'; import { COMPONENTS } from './components';
import { AngularSplitModule } from 'angular-split';
@NgModule({ @NgModule({
imports: [ imports: [
CommonModule, CommonModule,
FlexLayoutModule, FlexLayoutModule,
MatSidenavModule, MatSidenavModule,
AppMessengerLayoutModule, AppMessengerLayoutModule,
AppMessengerRoutingPageModule AppMessengerRoutingPageModule,
AngularSplitModule.forRoot(),
], ],
declarations: [...COMPONENTS], declarations: [...COMPONENTS],
entryComponents: [] entryComponents: [],
}) })
export class AppMessengerPageModule {} export class AppMessengerPageModule {}

View File

@ -32,7 +32,7 @@ export class AppService {
this.sessionStorageService.set<EnvironmentsInfo>( this.sessionStorageService.set<EnvironmentsInfo>(
KEY_ENVIRONMENTS_INFO, KEY_ENVIRONMENTS_INFO,
{ {
deviceType deviceType,
} }
); );

View File

@ -6,7 +6,7 @@ import { LoginResponse } from '@ucap-webmessenger/protocol-authentication';
import { LoginInfo } from '@app/types'; import { LoginInfo } from '@app/types';
import { import {
UserPasswordSetRequest, UserPasswordSetRequest,
UserPasswordSetResponse UserPasswordSetResponse,
} from '@ucap-webmessenger/protocol-service'; } from '@ucap-webmessenger/protocol-service';
export const webLogin = createAction( export const webLogin = createAction(

View File

@ -1,7 +1,7 @@
import { Injectable, Inject } from '@angular/core'; import { Injectable, Inject } from '@angular/core';
import { Router } from '@angular/router'; import { Router } from '@angular/router';
import { of } from 'rxjs'; import { of, Observable } from 'rxjs';
import { catchError, exhaustMap, map, tap, switchMap } from 'rxjs/operators'; import { catchError, exhaustMap, map, tap, switchMap } from 'rxjs/operators';
import { Actions, ofType, createEffect } from '@ngrx/effects'; import { Actions, ofType, createEffect } from '@ngrx/effects';
@ -9,14 +9,14 @@ import { Actions, ofType, createEffect } from '@ngrx/effects';
import { import {
PiService, PiService,
Login2Response, Login2Response,
UserTermsActionResponse UserTermsActionResponse,
} from '@ucap-webmessenger/pi'; } from '@ucap-webmessenger/pi';
import { NativeService, UCAP_NATIVE_SERVICE } from '@ucap-webmessenger/native'; import { NativeService, UCAP_NATIVE_SERVICE } from '@ucap-webmessenger/native';
import { import {
DialogService, DialogService,
ConfirmDialogComponent, ConfirmDialogComponent,
ConfirmDialogData, ConfirmDialogData,
ConfirmDialogResult ConfirmDialogResult,
} from '@ucap-webmessenger/ui'; } from '@ucap-webmessenger/ui';
import { import {
@ -34,13 +34,13 @@ import {
privacyAgreeSuccess, privacyAgreeSuccess,
changePassword, changePassword,
changePasswordFailure, changePasswordFailure,
changePasswordSuccess changePasswordSuccess,
} from './actions'; } from './actions';
import { import {
LoginInfo, LoginInfo,
KEY_LOGIN_INFO, KEY_LOGIN_INFO,
EnvironmentsInfo, EnvironmentsInfo,
KEY_ENVIRONMENTS_INFO KEY_ENVIRONMENTS_INFO,
} from '@app/types'; } from '@app/types';
import { AppAuthenticationService } from '@app/services/authentication.service'; import { AppAuthenticationService } from '@app/services/authentication.service';
import { NGXLogger } from 'ngx-logger'; import { NGXLogger } from 'ngx-logger';
@ -48,7 +48,7 @@ import { Store } from '@ngrx/store';
import { SessionStorageService } from '@ucap-webmessenger/web-storage'; import { SessionStorageService } from '@ucap-webmessenger/web-storage';
import { import {
ServiceProtocolService, ServiceProtocolService,
UserPasswordSetResponse UserPasswordSetResponse,
} from '@ucap-webmessenger/protocol-service'; } from '@ucap-webmessenger/protocol-service';
@Injectable() @Injectable()
@ -62,7 +62,7 @@ export class Effects {
.login2({ .login2({
loginId: params.loginInfo.loginId, loginId: params.loginInfo.loginId,
loginPw: params.loginInfo.loginPw, loginPw: params.loginInfo.loginPw,
companyCode: params.loginInfo.companyCode companyCode: params.loginInfo.companyCode,
}) })
.pipe( .pipe(
map((res: Login2Response) => { map((res: Login2Response) => {
@ -72,7 +72,7 @@ export class Effects {
return webLoginSuccess({ return webLoginSuccess({
loginInfo: params.loginInfo, loginInfo: params.loginInfo,
rememberMe: params.rememberMe, rememberMe: params.rememberMe,
login2Response: res login2Response: res,
}); });
} }
}), }),
@ -86,9 +86,12 @@ export class Effects {
() => () =>
this.actions$.pipe( this.actions$.pipe(
ofType(webLoginSuccess), ofType(webLoginSuccess),
switchMap(params => switchMap(
this.nativeService.checkForUpdates().pipe( params =>
map((update: boolean) => { new Observable<void>(subscriber => {
this.nativeService
.checkForUpdates()
.then((update: boolean) => {
if (!update) { if (!update) {
this.appAuthenticationService.login( this.appAuthenticationService.login(
params.loginInfo, params.loginInfo,
@ -96,9 +99,15 @@ export class Effects {
); );
this.router.navigate(['/messenger']); this.router.navigate(['/messenger']);
} }
}), subscriber.next();
catchError(error => of(error)) })
) .catch(reason => {
subscriber.error(reason);
})
.finally(() => {
subscriber.complete();
});
})
) )
), ),
{ dispatch: false } { dispatch: false }
@ -138,8 +147,8 @@ export class Effects {
width: '220px', width: '220px',
data: { data: {
title: 'Logout', title: 'Logout',
message: 'Logout ?' message: 'Logout ?',
} },
}); });
return result.choice; return result.choice;
@ -168,7 +177,7 @@ export class Effects {
token: loginRes.tokenString, token: loginRes.tokenString,
deviceType: environmentsInfo.deviceType, deviceType: environmentsInfo.deviceType,
localeCode: loginInfo.localeCode, localeCode: loginInfo.localeCode,
textOnly: 'true' textOnly: 'true',
}); });
const result = await this.dialogService.open< const result = await this.dialogService.open<
@ -180,9 +189,9 @@ export class Effects {
height: '500px', height: '500px',
disableClose: true, disableClose: true,
data: { data: {
title: '개인정보 동의' title: '개인정보 동의',
// html: `<iframe id="ifm_privacy" src="${privacyTotalUrl}" style="width: 100%;height: 300px;" />` // html: `<iframe id="ifm_privacy" src="${privacyTotalUrl}" style="width: 100%;height: 300px;" />`
} },
}); });
if (result.choice) { if (result.choice) {
@ -204,8 +213,8 @@ export class Effects {
disableClose: true, disableClose: true,
data: { data: {
title: '패스워드 만료', title: '패스워드 만료',
message: '' message: '',
} },
}); });
if (result.choice) { if (result.choice) {
@ -232,7 +241,7 @@ export class Effects {
return { return {
loginInfo, loginInfo,
environmentsInfo, environmentsInfo,
loginResponse: action.loginRes loginResponse: action.loginRes,
}; };
}), }),
exhaustMap(params => exhaustMap(params =>
@ -240,7 +249,7 @@ export class Effects {
.userTermsAction({ .userTermsAction({
userSeq: params.loginResponse.userSeq, userSeq: params.loginResponse.userSeq,
token: params.loginResponse.tokenString, token: params.loginResponse.tokenString,
deviceType: params.environmentsInfo.deviceType deviceType: params.environmentsInfo.deviceType,
}) })
.pipe( .pipe(
map((res: UserTermsActionResponse) => { map((res: UserTermsActionResponse) => {
@ -264,7 +273,7 @@ export class Effects {
this.serviceProtocolService.userPasswordSet(req).pipe( this.serviceProtocolService.userPasswordSet(req).pipe(
map((res: UserPasswordSetResponse) => { map((res: UserPasswordSetResponse) => {
return changePasswordSuccess({ return changePasswordSuccess({
res res,
}); });
}), }),
catchError(error => of(changePasswordFailure({ error }))) catchError(error => of(changePasswordFailure({ error })))

View File

@ -7,7 +7,7 @@ export const reducer = createReducer(
on(loginSuccess, (state, action) => { on(loginSuccess, (state, action) => {
return { return {
...state, ...state,
loginRes: action.loginRes loginRes: action.loginRes,
}; };
}) })
); );

View File

@ -7,14 +7,11 @@ export interface State {
} }
export const initialState: State = { export const initialState: State = {
loginRes: null loginRes: null,
}; };
export function selectors<S>(selector: Selector<any, State>) { export function selectors<S>(selector: Selector<any, State>) {
return { return {
loginRes: createSelector( loginRes: createSelector(selector, (state: State) => state.loginRes),
selector,
(state: State) => state.loginRes
)
}; };
} }

View File

@ -1,4 +1,11 @@
export enum RightDrawer { export enum RightDrawer {
/** 대화방 > 앨범함 */
AlbumBox = 'ALBUM_BOX',
/** 대화방 > 파일함 */
FileBox = 'FILE_BOX', FileBox = 'FILE_BOX',
AlbumBox = 'ALBUM_BOX' /** 대화방 > 대화참여자목록 */
RoomUser = 'ROOM_USER',
/** 쪽지함 */
Message = 'MESSAGE_BOX'
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 999 B

View File

@ -1,18 +1,7 @@
import { Environment, build } from './environment.type'; import { Environment } from './environment.type';
import { BrowserNativeService } from '@ucap-webmessenger/native-browser'; import { environment as devEnvironment } from './environment.dev';
// This file can be replaced during build by using the `fileReplacements` array. export const environment: Environment = {
// `ng build --prod` replaces `environment.ts` with `environment.prod.ts`. ...devEnvironment,
// The list of file replacements can be found in `angular.json`. runtime: 'browser',
};
export const environment: Environment = build(false);
environment.modules.native.serviceClass = BrowserNativeService;
/*
* For easier debugging in development mode, you can import the following file
* to ignore zone related error stack frames such as `zone.run`, `zoneDelegate.invokeTask`.
*
* This import should be commented out in production mode because it will have a negative impact
* on performance if an error is thrown.
*/
// import 'zone.js/dist/zone-error'; // Included with Angular CLI.

View File

@ -1,5 +1,7 @@
import { Environment, build } from './environment.type'; import { Environment } from './environment.type';
import { BrowserNativeService } from '@ucap-webmessenger/native-browser'; import { environment as prodEnvironment } from './environment.prod';
export const environment: Environment = build(true); export const environment: Environment = {
environment.modules.native.serviceClass = BrowserNativeService; ...prodEnvironment,
runtime: 'browser',
};

View File

@ -1,18 +1,7 @@
import { Environment, build } from './environment.type'; import { Environment } from './environment.type';
import { ElectronNativeService } from '@ucap-webmessenger/native-electron'; import { environment as devEnvironment } from './environment.dev';
// This file can be replaced during build by using the `fileReplacements` array. export const environment: Environment = {
// `ng build --prod` replaces `environment.ts` with `environment.prod.ts`. ...devEnvironment,
// The list of file replacements can be found in `angular.json`. runtime: 'electron',
};
export const environment: Environment = build(false);
environment.modules.native.serviceClass = ElectronNativeService;
/*
* For easier debugging in development mode, you can import the following file
* to ignore zone related error stack frames such as `zone.run`, `zoneDelegate.invokeTask`.
*
* This import should be commented out in production mode because it will have a negative impact
* on performance if an error is thrown.
*/
// import 'zone.js/dist/zone-error'; // Included with Angular CLI.

View File

@ -1,5 +1,7 @@
import { Environment, build } from './environment.type'; import { Environment } from './environment.type';
import { ElectronNativeService } from '@ucap-webmessenger/native-electron'; import { environment as prodEnvironment } from './environment.prod';
export const environment: Environment = build(true); export const environment: Environment = {
environment.modules.native.serviceClass = ElectronNativeService; ...prodEnvironment,
runtime: 'electron',
};

Some files were not shown because too many files have changed in this diff Show More