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,
"singleQuote": true
}

View File

@ -41,6 +41,8 @@
"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,
"outputHashing": "all",
"sourceMap": true,
@ -70,6 +72,8 @@
"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,
"outputHashing": "all",
"sourceMap": false,
@ -82,7 +86,7 @@
"budgets": [
{
"type": "initial",
"maximumWarning": "2mb",
"maximumWarning": "4mb",
"maximumError": "5mb"
},
{
@ -140,7 +144,7 @@
"budgets": [
{
"type": "initial",
"maximumWarning": "2mb",
"maximumWarning": "4mb",
"maximumError": "5mb"
},
{
@ -155,7 +159,8 @@
"serve": {
"builder": "@angular-builders/custom-webpack:dev-server",
"options": {
"browserTarget": "ucap-webmessenger-app:build"
"browserTarget": "ucap-webmessenger-app:build",
"disableHostCheck": true
},
"configurations": {
"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": {
"projectType": "library",
"root": "projects/ucap-webmessenger-api",

View File

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

View File

@ -13,6 +13,6 @@ export function getEnviroments() {
__DEV__: channel === 'development',
'process.platform': s(process.platform),
'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,
'..',
'electron-projects/ucap-webmessenger-electron/src/index'
)
),
},
target: 'electron-main',
mode: enviroments.__DEV__ ? 'development' : 'production',
devtool: 'source-map',
optimization: {
noEmitOnErrors: true
noEmitOnErrors: true,
},
externals,
output: {
filename: '[name].js',
path: path.resolve(__dirname, '..', outputDir)
path: path.resolve(__dirname, '..', outputDir),
},
module: {
rules: [
@ -44,7 +44,7 @@ const mainConfig: webpack.Configuration = {
'electron-projects/ucap-webmessenger-electron/src'
),
path.resolve(__dirname, '..', 'electron-projects'),
path.resolve(__dirname, '..', 'projects')
path.resolve(__dirname, '..', 'projects'),
],
use: [
{
@ -55,20 +55,20 @@ const mainConfig: webpack.Configuration = {
__dirname,
'..',
'electron-projects/ucap-webmessenger-electron/tsconfig.electron.json'
)
}
}
),
},
},
],
exclude: /node_modules/
exclude: /node_modules/,
},
{
test: /\.node$/,
loader: 'awesome-node-loader',
options: {
name: '[name].[ext]'
}
}
]
name: '[name].[ext]',
},
},
],
},
plugins: [
new CleanWebpackPlugin({ verbose: false }),
@ -77,16 +77,16 @@ const mainConfig: webpack.Configuration = {
new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),
new webpack.DefinePlugin(
Object.assign({}, enviroments, {
__PROCESS_KIND__: JSON.stringify('main')
__PROCESS_KIND__: JSON.stringify('main'),
})
),
new CopyWebpackPlugin([
{
from: 'ucap-webmessenger-electron/resources/**/*',
to: path.resolve(__dirname, '..', 'dist'),
context: 'electron-projects'
}
])
context: 'electron-projects',
},
]),
],
resolve: {
extensions: ['.js', '.ts'],
@ -101,6 +101,11 @@ const mainConfig: webpack.Configuration = {
'..',
'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(
__dirname,
'..',
@ -115,14 +120,14 @@ const mainConfig: webpack.Configuration = {
__dirname,
'..',
'electron-projects/ucap-webmessenger-electron/src/public-api'
)
),
},
modules: [path.resolve(__dirname, '..', 'node_modules/')]
modules: [path.resolve(__dirname, '..', 'node_modules/')],
},
node: {
__dirname: false,
__filename: false
}
__filename: false,
},
};
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 {
const buffer: Buffer = args[0];
const fileName: string = args[1];
const mimeType: string = args[2];
let savePath: string = path.join(
!!args[2] ? args[2] : DefaultFolder.downloads(),
!!args[3] ? args[3] : DefaultFolder.downloads(),
fileName
);
savePath = await FileUtil.uniqueFileName(savePath);

View File

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

21
package-lock.json generated
View File

@ -2789,6 +2789,15 @@
"integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=",
"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": {
"version": "3.0.0",
"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": {
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.1.tgz",
@ -15387,6 +15402,12 @@
"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": {
"version": "2.1.0",
"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: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",
"build": "npm-run-all -p build:renderer build:main:production",
"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: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",
@ -59,8 +61,10 @@
"@types/webpack": "^4.39.5",
"@types/webpack-merge": "^4.1.5",
"@types/webpack-node-externals": "^1.6.3",
"angular-split": "^3.0.2",
"awesome-node-loader": "^1.1.1",
"awesome-typescript-loader": "^5.2.1",
"classlist.js": "^1.1.20150312",
"clean-webpack-plugin": "^3.0.0",
"copy-webpack-plugin": "^5.0.4",
"codelyzer": "^5.0.0",
@ -106,6 +110,7 @@
"tslint": "~5.15.0",
"typescript": "~3.5.3",
"wait-on": "^3.3.0",
"web-animations-js": "^2.3.2",
"webpack": "4.39.2",
"webpack-cli": "^3.3.7",
"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,
HttpEventType,
HttpResponse,
HttpRequest
HttpRequest,
} from '@angular/common/http';
import { Observable, Subject } from 'rxjs';
import { map, filter } from 'rxjs/operators';
import { _MODULE_CONFIG } from '../types/token';
import { ModuleConfig } from '../types/module-config';
import {
FileProfileSaveRequest,
FileProfileSaveResponse,
encodeFileProfileSave,
decodeFileProfileSave
decodeFileProfileSave,
} from '../apis/file-profile-save';
import {
FileTalkDownloadRequest,
encodeFileTalkDownload,
encodeFormDataFileTalkDownload
encodeFormDataFileTalkDownload,
} from '../apis/file-talk-download';
import {
FileTalkSaveRequest,
FileTalkSaveResponse,
encodeFileTalkSave,
decodeFileTalkSave
decodeFileTalkSave,
} from '../apis/file-talk-save';
import {
FileTalkShareRequest,
FileTalkShareResponse,
encodeFileTalkShare,
decodeFileTalkShare
decodeFileTalkShare,
} from '../apis/file-talk-share';
import {
MassTalkDownloadRequest,
MassTalkDownloadResponse,
encodeMassTalkDownload,
decodeMassTalkDownload
decodeMassTalkDownload,
} from '../apis/mass-talk-download';
import {
MassTalkSaveRequest,
MassTalkSaveResponse,
encodeMassTalkSave,
decodeMassTalkSave
decodeMassTalkSave,
} from '../apis/mass-talk-save';
import {
TransMassTalkDownloadRequest,
TransMassTalkDownloadResponse,
encodeTransMassTalkDownload,
decodeTransMassTalkDownload
decodeTransMassTalkDownload,
} from '../apis/trans-mass-talk-download';
import {
TransMassTalkSaveRequest,
TransMassTalkSaveResponse,
encodeTransMassTalkSave,
decodeTransMassTalkSave
decodeTransMassTalkSave,
} from '../apis/trans-mass-talk-save';
import {
TranslationReqRequest,
TranslationReqResponse,
encodeTranslationReq,
decodeTranslationReq
decodeTranslationReq,
} from '../apis/translation-req';
import {
TranslationSaveRequest,
TranslationSaveResponse,
encodeTranslationSave,
decodeTranslationSave
decodeTranslationSave,
} 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({
providedIn: 'root'
providedIn: 'root',
})
export class CommonApiService {
readonly urls: Urls;
constructor(
@Inject(_MODULE_CONFIG) private moduleConfig: ModuleConfig,
private httpClient: HttpClient
) {}
) {
this.urls = UrlConfig.getUrls(
this.moduleConfig.hostConfig,
this.moduleConfig.urls
);
}
public fileProfileSave(
req: FileProfileSaveRequest,
@ -86,12 +96,10 @@ export class CommonApiService {
): Observable<FileProfileSaveResponse> {
return this.httpClient
.post<any>(
!!fileProfileSaveUrl
? fileProfileSaveUrl
: this.moduleConfig.urls.fileProfileSave,
!!fileProfileSaveUrl ? fileProfileSaveUrl : this.urls.fileProfileSave,
{},
{
params: encodeFileProfileSave(req)
params: encodeFileProfileSave(req),
}
)
.pipe(map(res => decodeFileProfileSave(res)));
@ -103,12 +111,10 @@ export class CommonApiService {
): string {
const httpReq = new HttpRequest(
'GET',
!!fileTalkDownloadUrl
? fileTalkDownloadUrl
: this.moduleConfig.urls.fileTalkDownload,
!!fileTalkDownloadUrl ? fileTalkDownloadUrl : this.urls.fileTalkDownload,
{},
{
params: encodeFileTalkDownload(req)
params: encodeFileTalkDownload(req),
}
);
@ -121,9 +127,7 @@ export class CommonApiService {
): Observable<Blob> {
const httpReq = new HttpRequest(
'POST',
!!fileTalkDownloadUrl
? fileTalkDownloadUrl
: this.moduleConfig.urls.fileTalkDownload,
!!fileTalkDownloadUrl ? fileTalkDownloadUrl : this.urls.fileTalkDownload,
encodeFormDataFileTalkDownload(req),
{ reportProgress: true, responseType: 'blob' }
);
@ -159,7 +163,7 @@ export class CommonApiService {
): Observable<FileTalkSaveResponse> {
const httpReq = new HttpRequest(
'POST',
!!fileTalkSaveUrl ? fileTalkSaveUrl : this.moduleConfig.urls.fileTalkSave,
!!fileTalkSaveUrl ? fileTalkSaveUrl : this.urls.fileTalkSave,
encodeFileTalkSave(req),
{ reportProgress: true, responseType: 'text' as 'json' }
);
@ -185,7 +189,10 @@ export class CommonApiService {
public acceptableExtensionForFileTalk(extensions: string[]): boolean {
for (const extension of extensions) {
if (
-1 === this.moduleConfig.acceptableFileExtensions.indexOf(extension.toLowerCase())
-1 ===
this.moduleConfig.acceptableFileExtensions.indexOf(
extension.toLowerCase()
)
) {
return false;
}
@ -198,10 +205,10 @@ export class CommonApiService {
): Observable<FileTalkShareResponse> {
return this.httpClient
.post<any>(
this.moduleConfig.urls.fileTalkShare,
this.urls.fileTalkShare,
{},
{
params: encodeFileTalkShare(req)
params: encodeFileTalkShare(req),
}
)
.pipe(map(res => decodeFileTalkShare(res)));
@ -212,11 +219,11 @@ export class CommonApiService {
): Observable<MassTalkDownloadResponse> {
return this.httpClient
.post<any>(
this.moduleConfig.urls.massTalkDownload,
this.urls.massTalkDownload,
{},
{
params: encodeMassTalkDownload(req),
responseType: 'text' as 'json'
responseType: 'text' as 'json',
}
)
.pipe(map(res => decodeMassTalkDownload(res)));
@ -227,11 +234,11 @@ export class CommonApiService {
): Observable<MassTalkSaveResponse> {
return this.httpClient
.post<any>(
this.moduleConfig.urls.massTalkSave,
this.urls.massTalkSave,
{},
{
params: encodeMassTalkSave(req),
responseType: 'text' as 'json'
responseType: 'text' as 'json',
}
)
.pipe(map(res => decodeMassTalkSave(res)));
@ -242,10 +249,10 @@ export class CommonApiService {
): Observable<TransMassTalkDownloadResponse> {
return this.httpClient
.post<any>(
this.moduleConfig.urls.transMassTalkDownload,
this.urls.transMassTalkDownload,
{},
{
params: encodeTransMassTalkDownload(req)
params: encodeTransMassTalkDownload(req),
}
)
.pipe(map(res => decodeTransMassTalkDownload(res)));
@ -256,10 +263,10 @@ export class CommonApiService {
): Observable<TransMassTalkSaveResponse> {
return this.httpClient
.post<any>(
this.moduleConfig.urls.transMassTalkSave,
this.urls.transMassTalkSave,
{},
{
params: encodeTransMassTalkSave(req)
params: encodeTransMassTalkSave(req),
}
)
.pipe(map(res => decodeTransMassTalkSave(res)));
@ -270,10 +277,10 @@ export class CommonApiService {
): Observable<TranslationReqResponse> {
return this.httpClient
.post<any>(
this.moduleConfig.urls.translationReq,
this.urls.translationReq,
{},
{
params: encodeTranslationReq(req)
params: encodeTranslationReq(req),
}
)
.pipe(map(res => decodeTranslationReq(res)));
@ -284,10 +291,10 @@ export class CommonApiService {
): Observable<TranslationSaveResponse> {
return this.httpClient
.post<any>(
this.moduleConfig.urls.translationSave,
this.urls.translationSave,
{},
{
params: encodeTranslationSave(req)
params: encodeTranslationSave(req),
}
)
.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 { _MODULE_CONFIG } from './types/token';
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];
@NgModule({
declarations: [],
imports: [],
exports: []
exports: [],
})
export class UCapCommonApiModule {
public static forRoot(
@ -17,7 +18,7 @@ export class UCapCommonApiModule {
): ModuleWithProviders<UCapCommonApiModule> {
return {
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
*/
export * from './lib/types/module-config';
export * from './lib/apis/file-profile-save';
export * from './lib/apis/file-talk-download';
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/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 { map } from 'rxjs/operators';
import { _MODULE_CONFIG } from '../types/token';
import { ModuleConfig } from '../types/module-config';
import {
CheckUserInfoExRequest,
CheckUserInfoExResponse,
encodeCheckUserInfoEx,
decodeCheckUserInfoEx
decodeCheckUserInfoEx,
} from '../apis/check-user-info-ex';
import {
CompanyListRequest,
CompanyListResponse,
encodeCompanyList,
decodeCompanyList
decodeCompanyList,
} from '../apis/company-list';
import {
TokenUpdateRequest,
TokenUpdateResponse,
encodeTokenUpdate,
decodeTokenUpdate
decodeTokenUpdate,
} from '../apis/token-update';
import {
UrlInfoResponse,
UrlInfoRequest,
encodeUrlInfo,
decodeUrlInfo
decodeUrlInfo,
} 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({
providedIn: 'root'
providedIn: 'root',
})
export class ExternalApiService {
readonly urls: Urls;
constructor(
@Inject(_MODULE_CONFIG) private moduleConfig: ModuleConfig,
private httpClient: HttpClient
) {}
) {
this.urls = UrlConfig.getUrls(
this.moduleConfig.hostConfig,
this.moduleConfig.urls
);
}
public checkUserInfoEx(
req: CheckUserInfoExRequest
): Observable<CheckUserInfoExResponse> {
return this.httpClient
.post<any>(
this.moduleConfig.urls.checkUserInfoEx,
this.urls.checkUserInfoEx,
{},
{
params: encodeCheckUserInfoEx(req)
params: encodeCheckUserInfoEx(req),
}
)
.pipe(map(res => decodeCheckUserInfoEx(res)));
@ -57,10 +67,10 @@ export class ExternalApiService {
public companyList(req: CompanyListRequest): Observable<CompanyListResponse> {
return this.httpClient
.post<any>(
this.moduleConfig.urls.companyList,
this.urls.companyList,
{},
{
params: encodeCompanyList(req)
params: encodeCompanyList(req),
}
)
.pipe(map(res => decodeCompanyList(res)));
@ -69,10 +79,10 @@ export class ExternalApiService {
public tokenUpdate(req: TokenUpdateRequest): Observable<TokenUpdateResponse> {
return this.httpClient
.post<any>(
this.moduleConfig.urls.tokenUpdate,
this.urls.tokenUpdate,
{},
{
params: encodeTokenUpdate(req)
params: encodeTokenUpdate(req),
}
)
.pipe(map(res => decodeTokenUpdate(res)));
@ -81,10 +91,10 @@ export class ExternalApiService {
public urlInfo(req: UrlInfoRequest): Observable<UrlInfoResponse> {
return this.httpClient
.post<any>(
this.moduleConfig.urls.urlInfo,
this.urls.urlInfo,
{},
{
params: encodeUrlInfo(req)
params: encodeUrlInfo(req),
}
)
.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 { _MODULE_CONFIG } from './types/token';
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];
@NgModule({
declarations: [],
imports: [],
exports: []
exports: [],
})
export class UCapExternalApiModule {
public static forRoot(
@ -17,7 +18,7 @@ export class UCapExternalApiModule {
): ModuleWithProviders<UCapExternalApiModule> {
return {
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
*/
export * from './lib/types/module-config';
export * from './lib/models/company';
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/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,
APIEncoder,
APIDecoder,
ParameterUtil
ParameterUtil,
} from '@ucap-webmessenger/api';
export interface UpdateInfoRequest extends APIRequest {
@ -19,7 +19,7 @@ export interface UpdateInfoResponse extends APIResponse {
}
const updateInfoEncodeMap = {
deviceType: 'p_device_type'
deviceType: 'p_device_type',
};
export const encodeUpdateInfo: APIEncoder<UpdateInfoRequest> = (
@ -35,6 +35,6 @@ export const decodeUpdateInfo: APIDecoder<UpdateInfoResponse> = (res: any) => {
appVersion: res.AppVer,
installUrl: res.InstallURL,
launcherAppVersion: res.LauncherAppVer,
launcherInstallUrl: res.LauncherInstallURL
launcherInstallUrl: res.LauncherInstallURL,
} 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 { map } from 'rxjs/operators';
import { _MODULE_CONFIG } from '../types/token';
import {
VersionInfo2Request,
VersionInfo2Response,
encodeVersionInfo2,
decodeVersionInfo2
decodeVersionInfo2,
} from '../apis/version-info2';
import {
UpdateInfoRequest,
UpdateInfoResponse,
encodeUpdateInfo,
decodeUpdateInfo
decodeUpdateInfo,
} 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({
providedIn: 'root'
providedIn: 'root',
})
export class PublicApiService {
readonly urls: Urls;
constructor(
@Inject(_MODULE_CONFIG) private moduleConfig: ModuleConfig,
private httpClient: HttpClient
) {}
) {
this.urls = UrlConfig.getUrls(
this.moduleConfig.hostConfig,
this.moduleConfig.urls
);
}
public versionInfo2(
req: VersionInfo2Request
): Observable<VersionInfo2Response> {
return this.httpClient
.post<any>(
this.moduleConfig.urls.versionInfo2,
this.urls.versionInfo2,
{},
{
params: encodeVersionInfo2(req)
params: encodeVersionInfo2(req),
}
)
.pipe(map((res: any) => decodeVersionInfo2(res)));
@ -45,10 +55,10 @@ export class PublicApiService {
public updateInfo(req: UpdateInfoRequest): Observable<UpdateInfoResponse> {
return this.httpClient
.post<any>(
this.moduleConfig.urls.updateInfo,
this.urls.updateInfo,
{},
{
params: encodeUpdateInfo(req)
params: encodeUpdateInfo(req),
}
)
.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 { _MODULE_CONFIG } from './types/token';
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];
@NgModule({
declarations: [],
imports: [],
exports: []
exports: [],
})
export class UCapPublicApiModule {
public static forRoot(
@ -17,7 +18,7 @@ export class UCapPublicApiModule {
): ModuleWithProviders<UCapPublicApiModule> {
return {
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/types/module-config';
export * from './lib/types/sync-mode.type';
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 {
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 { SERVICES } from './services';
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 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({
imports: [],
exports: [],
providers: [
...SERVICES,
...RESOLVERS,
{
provide: UCAP_NATIVE_SERVICE,
useClass: environment.modules.native.serviceClass,
deps: [HttpClient]
// useFactory: nativeServiceFactory,
useClass:
'browser' === environment.runtime
? BrowserNativeService
: ElectronNativeService,
deps: [HttpClient],
},
...SERVICES,
...RESOLVERS,
{
provide: APP_INITIALIZER,
useFactory: initializeApp,
deps: [AppService, UCAP_NATIVE_SERVICE],
multi: true
}
]
multi: true,
},
],
})
export class AppProviderModule {}

View File

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

View File

@ -7,8 +7,16 @@ import { MatProgressBarModule } from '@angular/material/progress-bar';
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 { UCapExternalApiModule } from '@ucap-webmessenger/api-external';
import { UCapMessageApiModule } from '@ucap-webmessenger/api-message';
import { UCapPublicApiModule } from '@ucap-webmessenger/api-public';
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 { 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 { environment } from '../environments/environment';
import { AppProviderModule } from './app-provider.module';
import { AppRoutingModule } from './app-routing.module';
import { AppStoreModule } from './app-store.module';
@ -47,6 +46,8 @@ import { GUARDS } from './guards';
import { AppMessengerLayoutModule } from './layouts/messenger/messenger.layout.module';
import { AppNativeLayoutModule } from './layouts/native/native.layout.module';
import { environment } from '../environments/environment';
@NgModule({
imports: [
BrowserModule,
@ -58,28 +59,15 @@ import { AppNativeLayoutModule } from './layouts/native/native.layout.module';
PerfectScrollbarModule,
UCapCommonApiModule.forRoot({
urls: environment.urls.apiCommon,
acceptableFileExtensions:
environment.modules.event.acceptableFileExtensions
}),
UCapCommonApiModule.forRoot(environment.commonApiModuleConfig),
UCapPublicApiModule.forRoot({
urls: environment.urls.apiPublic
}),
UCapExternalApiModule.forRoot({
urls: environment.urls.apiExternal
}),
UCapPublicApiModule.forRoot(environment.publicApiModuleConfig),
UCapExternalApiModule.forRoot(environment.externalApiModuleConfig),
UCapMessageApiModule.forRoot(environment.messageApiModuleConfig),
UCapPiModule.forRoot({
urls: environment.urls.pi
}),
UCapPiModule.forRoot(environment.piModuleConfig),
UCapProtocolModule.forRoot({
urls: environment.urls.protocol,
reconnect: environment.protocol.reconnect,
requestId: environment.protocol.requestId
}),
UCapProtocolModule.forRoot(environment.protocolModuleConfig),
UCapAuthenticationProtocolModule.forRoot(),
UCapEventProtocolModule.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
[fileInfo]="fileInfo"
[fileDownloadUrl]="fileDownloadUrl"
(download)="onDownload()"
(download)="onDownload($event)"
(closed)="onClosedViewer()"
></ucap-file-viewer>

View File

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

View File

@ -9,8 +9,17 @@
<ng-template mat-tab-label>
<!--<mat-icon>group</mat-icon>-->
<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"
stroke-width="1.5" stroke-linecap="butt" stroke-linejoin="round">
<svg
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>
<circle cx="12" cy="7" r="4"></circle>
</svg>
@ -18,7 +27,7 @@
</ng-template>
<app-layout-chat-left-sidenav-group
class="left-group-side"
(newGroupAndMember)="onClickNewGroupAndMember($event)"
(newGroupAndMember)="onClickNewGroupAndMember()"
(openProfile)="onClickOpenProfile($event)"
></app-layout-chat-left-sidenav-group>
</mat-tab>
@ -32,16 +41,28 @@
matBadgePosition="above after"
>chat</mat-icon
>-->
<div class="icon-item" [matBadgeHidden]="(badgeChatUnReadCount$ | async) <= 0"
<div
class="icon-item"
[matBadgeHidden]="(badgeChatUnReadCount$ | async) <= 0"
[matBadge]="badgeChatUnReadCount$ | async"
matBadgeDescription="확인하지 않은 메시지가 있습니다."
matBadgeColor="accent"
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">
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"
>
<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">
</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"
></path>
</svg>
</div>
</ng-template>
@ -51,8 +72,17 @@
<ng-template mat-tab-label>
<!--<mat-icon>device_hub</mat-icon>-->
<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"
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"
>
<circle class="st0" cx="18.4" cy="18.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" />
@ -73,16 +103,27 @@
<ng-template mat-tab-label>
<!--<mat-icon>phone</mat-icon>-->
<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"
stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" class="feather feather-phone">
<path class="st0"
<svg
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="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
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.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
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>
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>
</svg>
</div>
</ng-template>

View File

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

View File

@ -17,7 +17,7 @@
[companyList]="companyList$ | async"
[companyCode]="companyCode"
(keyDownEnter)="onKeyDownEnterOrganizationTenantSearch($event)"
(cancel)="onClickCancel($event)"
(cancel)="onClickCancel()"
></ucap-organization-tenant-search>
<mat-menu
@ -28,8 +28,17 @@
>
<button mat-menu-item (click)="onClickGroupMenu('GROUP_NEW')">
<!--<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"
stroke-width="1.5" stroke-linecap="butt" stroke-linejoin="round">
<svg
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>
<circle cx="8.5" cy="7" r="4"></circle>
<line x1="20" y1="8" x2="20" y2="14"></line>

View File

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

View File

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

View File

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

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 { UserInfo } from '@ucap-webmessenger/protocol-room';
import {
UserInfoSS,
UserInfoF,
UserInfoDN,
} from '@ucap-webmessenger/protocol-query';
@Component({
selector: 'app-layout-messenger-right-drawer',
templateUrl: './right-drawer.component.html',
styleUrls: ['./right-drawer.component.scss']
styleUrls: ['./right-drawer.component.scss'],
})
export class RightDrawerComponent implements OnInit {
@Input()
selectedRightDrawer: RightDrawer;
@Output()
openProfile = new EventEmitter<
UserInfo | UserInfoSS | UserInfoF | UserInfoDN
>();
@Output()
closeRightDrawer = new EventEmitter();
RightDrawer = RightDrawer;
constructor() {}
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({
selector: 'app-layout-chat-right-drawer-album-box',
templateUrl: './album-box.component.html',
styleUrls: ['./album-box.component.scss']
styleUrls: ['./album-box.component.scss'],
})
export class AlbumBoxComponent implements OnInit {
constructor() {}
export class AlbumBoxComponent implements OnInit, OnDestroy {
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({
selector: 'app-layout-chat-right-drawer-file-box',
templateUrl: './file-box.component.html',
styleUrls: ['./file-box.component.scss']
styleUrls: ['./file-box.component.scss'],
})
export class FileBoxComponent implements OnInit {
constructor() {}
export class FileBoxComponent implements OnInit, OnDestroy {
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 { 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)="
onKeyDownEnterOrganizationTenantSearch($event)
"
(cancel)="onClickCancel($event)"
(cancel)="onClickCancel()"
></ucap-organization-tenant-search>
</div>
<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 { MatFormFieldModule } from '@angular/material/form-field';
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 { MatChipsModule } from '@angular/material/chips';
@ -70,6 +76,10 @@ import { DIALOGS } from './dialogs';
MatCheckboxModule,
MatRadioModule,
MatSelectModule,
MatTableModule,
MatSortModule,
MatPaginatorModule,
MatRippleModule,
PerfectScrollbarModule,

View File

@ -1,37 +1,57 @@
<div class="container">
<div class="left-side">
<app-layout-messenger-left-side
(openProfile)="onClickOpenProfile($event)"
></app-layout-messenger-left-side>
</div>
<mat-drawer-container class="contents" autosize>
<!-- <mat-drawer #drawer mode="over">
<p>Auto-resizing sidenav</p>
</mat-drawer> -->
<div class="messages">
<app-layout-messenger-intro
*ngIf="!(this.selectedChat$ | async)"
></app-layout-messenger-intro>
<!-- <app-layout-messenger-intro
*ngIf="!(this.selectedChat$ | async)"
></app-layout-messenger-intro> -->
<app-layout-messenger-messages
*ngIf="!!(this.selectedChat$ | async)"
(openProfile)="onClickOpenProfile($event)"
></app-layout-messenger-messages>
</div>
<mat-drawer
#rightDrawer
mode="side"
position="end"
(openedChange)="onOpenedChange($event)"
<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"
>
<app-layout-messenger-right-drawer
[selectedRightDrawer]="selectedRightDrawer$ | async"
>
</app-layout-messenger-right-drawer>
</mat-drawer>
</mat-drawer-container>
<div class="left-side">
<app-layout-messenger-left-side
(openProfile)="onClickOpenProfile($event)"
></app-layout-messenger-left-side>
</div>
</as-split-area>
<as-split-area size="*">
<mat-drawer-container class="contents" autosize>
<!-- <mat-drawer #drawer mode="over">
<p>Auto-resizing sidenav</p>
</mat-drawer> -->
<div class="messages">
<app-layout-messenger-intro
*ngIf="!(this.selectedChat$ | async)"
></app-layout-messenger-intro>
<!-- <app-layout-messenger-intro
*ngIf="!(this.selectedChat$ | async)"
></app-layout-messenger-intro> -->
<app-layout-messenger-messages
*ngIf="!!(this.selectedChat$ | async)"
(openProfile)="onClickOpenProfile($event)"
></app-layout-messenger-messages>
</div>
<mat-drawer
#rightDrawer
mode="side"
position="end"
(openedChange)="onOpenedChange($event)"
>
<app-layout-messenger-right-drawer
[selectedRightDrawer]="selectedRightDrawer$ | async"
(openProfile)="onClickOpenProfile($event)"
(closeRightDrawer)="onCloseRightDrawer($event)"
>
</app-layout-messenger-right-drawer>
</mat-drawer>
</mat-drawer-container>
</as-split-area>
</as-split>
<!-- <div class="right-side">
<app-layout-messenger-right-side></app-layout-messenger-right-side>

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,4 +1,11 @@
export enum RightDrawer {
/** 대화방 > 앨범함 */
AlbumBox = 'ALBUM_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 { BrowserNativeService } from '@ucap-webmessenger/native-browser';
import { Environment } from './environment.type';
import { environment as devEnvironment } from './environment.dev';
// This file can be replaced during build by using the `fileReplacements` array.
// `ng build --prod` replaces `environment.ts` with `environment.prod.ts`.
// The list of file replacements can be found in `angular.json`.
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.
export const environment: Environment = {
...devEnvironment,
runtime: 'browser',
};

View File

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

View File

@ -1,18 +1,7 @@
import { Environment, build } from './environment.type';
import { ElectronNativeService } from '@ucap-webmessenger/native-electron';
import { Environment } from './environment.type';
import { environment as devEnvironment } from './environment.dev';
// This file can be replaced during build by using the `fileReplacements` array.
// `ng build --prod` replaces `environment.ts` with `environment.prod.ts`.
// The list of file replacements can be found in `angular.json`.
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.
export const environment: Environment = {
...devEnvironment,
runtime: 'electron',
};

View File

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

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