diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..212426a --- /dev/null +++ b/.prettierrc @@ -0,0 +1,5 @@ +{ + "trailingComma": "none", + "tabWidth": 2, + "singleQuote": true +} diff --git a/.vscode/settings.json b/.vscode/settings.json index df8e24a..2cdeaf4 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -7,8 +7,10 @@ "editor.trimAutoWhitespace": true, "files.trimTrailingWhitespace": true, "files.trimFinalNewlines": true, + "files.watcherExclude": { + "**/dist/electron/win-unpacked/**": true + }, "go.testFlags": ["-v"], "go.testTimeout": "100s", - "prettier.singleQuote": true, "debug.node.autoAttach": "on" } diff --git a/angular.json b/angular.json index e493b62..5f3b5fa 100644 --- a/angular.json +++ b/angular.json @@ -30,18 +30,52 @@ "styles": ["projects/ucap-webmessenger-app/src/styles.scss"], "scripts": [], "customWebpackConfig": { - "path": "./config/renderer.webpack.config.js", - "mergeStrategies": { "externals": "replace" } + "path": "./config/angular.webpack.config.js" } }, "configurations": { - "production": { + "browser-development": { "fileReplacements": [ { "replace": "projects/ucap-webmessenger-app/src/environments/environment.ts", - "with": "projects/ucap-webmessenger-app/src/environments/environment.prod.ts" + "with": "projects/ucap-webmessenger-app/src/environments/environment-browser.dev.ts" } ], + "outputPath": "dist/ucap-webmessenger-app-browser", + "polyfills": "projects/ucap-webmessenger-app/src/polyfills-es5.ts", + "tsConfig": "projects/ucap-webmessenger-app/tsconfig-es5.app.json", + "optimization": false, + "outputHashing": "all", + "sourceMap": true, + "extractCss": true, + "namedChunks": false, + "aot": false, + "extractLicenses": true, + "vendorChunk": false, + "buildOptimizer": false, + "budgets": [ + { + "type": "initial", + "maximumWarning": "2mb", + "maximumError": "5mb" + }, + { + "type": "anyComponentStyle", + "maximumWarning": "6kb", + "maximumError": "10kb" + } + ] + }, + "browser-production": { + "fileReplacements": [ + { + "replace": "projects/ucap-webmessenger-app/src/environments/environment.ts", + "with": "projects/ucap-webmessenger-app/src/environments/environment-browser.prod.ts" + } + ], + "outputPath": "dist/ucap-webmessenger-app-browser", + "polyfills": "projects/ucap-webmessenger-app/src/polyfills-es5.ts", + "tsConfig": "projects/ucap-webmessenger-app/tsconfig-es5.app.json", "optimization": true, "outputHashing": "all", "sourceMap": false, @@ -51,6 +85,36 @@ "extractLicenses": true, "vendorChunk": false, "buildOptimizer": true, + "budgets": [ + { + "type": "initial", + "maximumWarning": "4mb", + "maximumError": "5mb" + }, + { + "type": "anyComponentStyle", + "maximumWarning": "6kb", + "maximumError": "10kb" + } + ] + }, + "renderer-development": { + "fileReplacements": [ + { + "replace": "projects/ucap-webmessenger-app/src/environments/environment.ts", + "with": "projects/ucap-webmessenger-app/src/environments/environment-renderer.dev.ts" + } + ], + "tsConfig": "projects/ucap-webmessenger-app/tsconfig-es5.app.json", + "optimization": false, + "outputHashing": "all", + "sourceMap": true, + "extractCss": true, + "namedChunks": false, + "aot": false, + "extractLicenses": true, + "vendorChunk": false, + "buildOptimizer": false, "budgets": [ { "type": "initial", @@ -63,17 +127,57 @@ "maximumError": "10kb" } ] + }, + "renderer-production": { + "fileReplacements": [ + { + "replace": "projects/ucap-webmessenger-app/src/environments/environment.ts", + "with": "projects/ucap-webmessenger-app/src/environments/environment-renderer.prod.ts" + } + ], + "tsConfig": "projects/ucap-webmessenger-app/tsconfig-es5.app.json", + "optimization": true, + "outputHashing": "all", + "sourceMap": false, + "extractCss": true, + "namedChunks": false, + "aot": true, + "extractLicenses": true, + "vendorChunk": false, + "buildOptimizer": true, + "budgets": [ + { + "type": "initial", + "maximumWarning": "4mb", + "maximumError": "5mb" + }, + { + "type": "anyComponentStyle", + "maximumWarning": "6kb", + "maximumError": "10kb" + } + ] } } }, "serve": { "builder": "@angular-builders/custom-webpack:dev-server", "options": { - "browserTarget": "ucap-webmessenger-app:build" + "browserTarget": "ucap-webmessenger-app:build", + "disableHostCheck": true }, "configurations": { - "production": { - "browserTarget": "ucap-webmessenger-app:build:production" + "browser-development": { + "browserTarget": "ucap-webmessenger-app:build:browser-development" + }, + "browser-production": { + "browserTarget": "ucap-webmessenger-app:build:browser-production" + }, + "renderer-development": { + "browserTarget": "ucap-webmessenger-app:build:renderer-development" + }, + "renderer-production": { + "browserTarget": "ucap-webmessenger-app:build:renderer-production" } } }, @@ -84,7 +188,7 @@ } }, "test": { - "builder": "@angular-devkit/build-angular:karma", + "builder": "@angular-builders/custom-webpack:karma", "options": { "main": "projects/ucap-webmessenger-app/src/test.ts", "polyfills": "projects/ucap-webmessenger-app/src/polyfills.ts", @@ -95,7 +199,10 @@ "projects/ucap-webmessenger-app/src/assets" ], "styles": ["projects/ucap-webmessenger-app/src/styles.scss"], - "scripts": [] + "scripts": [], + "customWebpackConfig": { + "path": "./config/angular.webpack.config.js" + } } }, "lint": { @@ -256,6 +363,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", @@ -588,6 +729,39 @@ } } }, + "ucap-webmessenger-ui-settings": { + "projectType": "library", + "root": "projects/ucap-webmessenger-ui-settings", + "sourceRoot": "projects/ucap-webmessenger-ui-settings/src", + "prefix": "ucap-settings", + "architect": { + "build": { + "builder": "@angular-devkit/build-ng-packagr:build", + "options": { + "tsConfig": "projects/ucap-webmessenger-ui-settings/tsconfig.lib.json", + "project": "projects/ucap-webmessenger-ui-settings/ng-package.json" + } + }, + "test": { + "builder": "@angular-devkit/build-angular:karma", + "options": { + "main": "projects/ucap-webmessenger-ui-settings/src/test.ts", + "tsConfig": "projects/ucap-webmessenger-ui-settings/tsconfig.spec.json", + "karmaConfig": "projects/ucap-webmessenger-ui-settings/karma.conf.js" + } + }, + "lint": { + "builder": "@angular-devkit/build-angular:tslint", + "options": { + "tsConfig": [ + "projects/ucap-webmessenger-ui-settings/tsconfig.lib.json", + "projects/ucap-webmessenger-ui-settings/tsconfig.spec.json" + ], + "exclude": ["**/node_modules/**"] + } + } + } + }, "ucap-webmessenger-protocol": { "projectType": "library", "root": "projects/ucap-webmessenger-protocol", @@ -1182,72 +1356,6 @@ } } }, - "ucap-webmessenger-native": { - "projectType": "library", - "root": "projects/ucap-webmessenger-native", - "sourceRoot": "projects/ucap-webmessenger-native/src", - "prefix": "ucap-native", - "architect": { - "build": { - "builder": "@angular-devkit/build-ng-packagr:build", - "options": { - "tsConfig": "projects/ucap-webmessenger-native/tsconfig.lib.json", - "project": "projects/ucap-webmessenger-native/ng-package.json" - } - }, - "test": { - "builder": "@angular-devkit/build-angular:karma", - "options": { - "main": "projects/ucap-webmessenger-native/src/test.ts", - "tsConfig": "projects/ucap-webmessenger-native/tsconfig.spec.json", - "karmaConfig": "projects/ucap-webmessenger-native/karma.conf.js" - } - }, - "lint": { - "builder": "@angular-devkit/build-angular:tslint", - "options": { - "tsConfig": [ - "projects/ucap-webmessenger-native/tsconfig.lib.json", - "projects/ucap-webmessenger-native/tsconfig.spec.json" - ], - "exclude": ["**/node_modules/**"] - } - } - } - }, - "ucap-webmessenger-native-electron": { - "projectType": "library", - "root": "projects/ucap-webmessenger-native-electron", - "sourceRoot": "projects/ucap-webmessenger-native-electron/src", - "prefix": "ucap-native-electron", - "architect": { - "build": { - "builder": "@angular-devkit/build-ng-packagr:build", - "options": { - "tsConfig": "projects/ucap-webmessenger-native-electron/tsconfig.lib.json", - "project": "projects/ucap-webmessenger-native-electron/ng-package.json" - } - }, - "test": { - "builder": "@angular-devkit/build-angular:karma", - "options": { - "main": "projects/ucap-webmessenger-native-electron/src/test.ts", - "tsConfig": "projects/ucap-webmessenger-native-electron/tsconfig.spec.json", - "karmaConfig": "projects/ucap-webmessenger-native-electron/karma.conf.js" - } - }, - "lint": { - "builder": "@angular-devkit/build-angular:tslint", - "options": { - "tsConfig": [ - "projects/ucap-webmessenger-native-electron/tsconfig.lib.json", - "projects/ucap-webmessenger-native-electron/tsconfig.spec.json" - ], - "exclude": ["**/node_modules/**"] - } - } - } - }, "ucap-webmessenger-web-socket": { "projectType": "library", "root": "projects/ucap-webmessenger-web-socket", @@ -1413,6 +1521,72 @@ } } }, + "ucap-webmessenger-native": { + "projectType": "library", + "root": "projects/ucap-webmessenger-native", + "sourceRoot": "projects/ucap-webmessenger-native/src", + "prefix": "ucap-native", + "architect": { + "build": { + "builder": "@angular-devkit/build-ng-packagr:build", + "options": { + "tsConfig": "projects/ucap-webmessenger-native/tsconfig.lib.json", + "project": "projects/ucap-webmessenger-native/ng-package.json" + } + }, + "test": { + "builder": "@angular-devkit/build-angular:karma", + "options": { + "main": "projects/ucap-webmessenger-native/src/test.ts", + "tsConfig": "projects/ucap-webmessenger-native/tsconfig.spec.json", + "karmaConfig": "projects/ucap-webmessenger-native/karma.conf.js" + } + }, + "lint": { + "builder": "@angular-devkit/build-angular:tslint", + "options": { + "tsConfig": [ + "projects/ucap-webmessenger-native/tsconfig.lib.json", + "projects/ucap-webmessenger-native/tsconfig.spec.json" + ], + "exclude": ["**/node_modules/**"] + } + } + } + }, + "ucap-webmessenger-native-electron": { + "projectType": "library", + "root": "projects/ucap-webmessenger-native-electron", + "sourceRoot": "projects/ucap-webmessenger-native-electron/src", + "prefix": "ucap-native-electron", + "architect": { + "build": { + "builder": "@angular-devkit/build-ng-packagr:build", + "options": { + "tsConfig": "projects/ucap-webmessenger-native-electron/tsconfig.lib.json", + "project": "projects/ucap-webmessenger-native-electron/ng-package.json" + } + }, + "test": { + "builder": "@angular-devkit/build-angular:karma", + "options": { + "main": "projects/ucap-webmessenger-native-electron/src/test.ts", + "tsConfig": "projects/ucap-webmessenger-native-electron/tsconfig.spec.json", + "karmaConfig": "projects/ucap-webmessenger-native-electron/karma.conf.js" + } + }, + "lint": { + "builder": "@angular-devkit/build-angular:tslint", + "options": { + "tsConfig": [ + "projects/ucap-webmessenger-native-electron/tsconfig.lib.json", + "projects/ucap-webmessenger-native-electron/tsconfig.spec.json" + ], + "exclude": ["**/node_modules/**"] + } + } + } + }, "ucap-webmessenger-native-browser": { "projectType": "library", "root": "projects/ucap-webmessenger-native-browser", @@ -1445,76 +1619,6 @@ } } } - }, - "ucap-webmessenger-electron-notification": { - "projectType": "library", - "root": "projects/ucap-webmessenger-electron-notification", - "sourceRoot": "projects/ucap-webmessenger-electron-notification/src", - "prefix": "ucap-electron-notification", - "architect": { - "build": { - "builder": "@angular-devkit/build-ng-packagr:build", - "options": { - "tsConfig": "projects/ucap-webmessenger-electron-notification/tsconfig.lib.json", - "project": "projects/ucap-webmessenger-electron-notification/ng-package.json" - } - }, - "test": { - "builder": "@angular-devkit/build-angular:karma", - "options": { - "main": "projects/ucap-webmessenger-electron-notification/src/test.ts", - "tsConfig": "projects/ucap-webmessenger-electron-notification/tsconfig.spec.json", - "karmaConfig": "projects/ucap-webmessenger-electron-notification/karma.conf.js" - } - }, - "lint": { - "builder": "@angular-devkit/build-angular:tslint", - "options": { - "tsConfig": [ - "projects/ucap-webmessenger-electron-notification/tsconfig.lib.json", - "projects/ucap-webmessenger-electron-notification/tsconfig.spec.json" - ], - "exclude": [ - "**/node_modules/**" - ] - } - } - } - }, - "ucap-webmessenger-electron-core": { - "projectType": "library", - "root": "projects/ucap-webmessenger-electron-core", - "sourceRoot": "projects/ucap-webmessenger-electron-core/src", - "prefix": "ucap-electron-core", - "architect": { - "build": { - "builder": "@angular-devkit/build-ng-packagr:build", - "options": { - "tsConfig": "projects/ucap-webmessenger-electron-core/tsconfig.lib.json", - "project": "projects/ucap-webmessenger-electron-core/ng-package.json" - } - }, - "test": { - "builder": "@angular-devkit/build-angular:karma", - "options": { - "main": "projects/ucap-webmessenger-electron-core/src/test.ts", - "tsConfig": "projects/ucap-webmessenger-electron-core/tsconfig.spec.json", - "karmaConfig": "projects/ucap-webmessenger-electron-core/karma.conf.js" - } - }, - "lint": { - "builder": "@angular-devkit/build-angular:tslint", - "options": { - "tsConfig": [ - "projects/ucap-webmessenger-electron-core/tsconfig.lib.json", - "projects/ucap-webmessenger-electron-core/tsconfig.spec.json" - ], - "exclude": [ - "**/node_modules/**" - ] - } - } - } } }, "defaultProject": "ucap-webmessenger-app" diff --git a/config/renderer.webpack.config.js b/config/angular.webpack.config.js similarity index 58% rename from config/renderer.webpack.config.js rename to config/angular.webpack.config.js index 7d76c60..71303bb 100644 --- a/config/renderer.webpack.config.js +++ b/config/angular.webpack.config.js @@ -2,8 +2,16 @@ const path = require('path'); module.exports = (config, options) => { const PRODUCTION = process.env.NODE_ENV === 'production'; + const BROWSER = process.env.UCAP_ENV_RUNTIME === 'BROWSER'; - config.target = 'electron-renderer'; + if (!BROWSER) { + config.target = 'electron-renderer'; + } else { + config.target = 'web'; + config.node = { + fs: 'empty', + }; + } config.resolve.alias = { ...config.resolve.alias, @@ -11,7 +19,7 @@ module.exports = (config, options) => { __dirname, '..', 'projects/ucap-webmessenger-ui/src/assets/scss' - ) + ), }; return config; diff --git a/config/enviroment.ts b/config/enviroment.ts index 6ce87ed..70f97e5 100644 --- a/config/enviroment.ts +++ b/config/enviroment.ts @@ -1,4 +1,3 @@ -import * as fs from 'fs'; import * as Path from 'path'; const projectRoot = Path.dirname(__dirname); @@ -14,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), }; } diff --git a/config/main.webpack.config.ts b/config/main.webpack.config.ts index aad0c9b..1d8a5ea 100644 --- a/config/main.webpack.config.ts +++ b/config/main.webpack.config.ts @@ -12,28 +12,39 @@ export const externals = [nodeExternals()]; // externals.push('devtron'); // } -const outputDir = 'dist/main'; +const outputDir = 'dist/ucap-webmessenger-electron'; const mainConfig: webpack.Configuration = { - entry: { main: path.resolve(__dirname, '..', 'main/src/index') }, + entry: { + main: path.resolve( + __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: [ { test: /\.tsx?$/, include: [ - path.resolve(__dirname, '..', 'main/src'), - path.resolve(__dirname, '..', 'projects') + path.resolve( + __dirname, + '..', + 'electron-projects/ucap-webmessenger-electron/src' + ), + path.resolve(__dirname, '..', 'electron-projects'), + path.resolve(__dirname, '..', 'projects'), ], use: [ { @@ -43,21 +54,21 @@ const mainConfig: webpack.Configuration = { configFileName: path.resolve( __dirname, '..', - 'main/tsconfig.main.json' - ) - } - } + '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 }), @@ -66,15 +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: 'main/resources/**/*', - to: path.resolve(__dirname, '..', 'dist') - } - ]) + from: 'ucap-webmessenger-electron/resources/**/*', + to: path.resolve(__dirname, '..', 'dist'), + context: 'electron-projects', + }, + ]), ], resolve: { extensions: ['.js', '.ts'], @@ -82,12 +94,17 @@ const mainConfig: webpack.Configuration = { '@ucap-webmessenger/electron-core': path.resolve( __dirname, '..', - 'projects/ucap-webmessenger-electron-core/src/public-api' + 'electron-projects/ucap-webmessenger-electron-core/src/public-api' ), '@ucap-webmessenger/electron-notification': path.resolve( __dirname, '..', - 'projects/ucap-webmessenger-electron-notification/src/public-api' + 'electron-projects/ucap-webmessenger-electron-notification/src/public-api' + ), + '@ucap-webmessenger/core': path.resolve( + __dirname, + '..', + 'projects/ucap-webmessenger-core/src/public-api' ), '@ucap-webmessenger/native': path.resolve( __dirname, @@ -98,14 +115,19 @@ const mainConfig: webpack.Configuration = { __dirname, '..', 'projects/ucap-webmessenger-native-electron/src/public-api' - ) + ), + '@ucap-webmessenger/electron': path.resolve( + __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]; diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml new file mode 100644 index 0000000..a5445db --- /dev/null +++ b/docker/docker-compose.yml @@ -0,0 +1,10 @@ +version: '3.1' + +services: + nginx: + image: nginx:1.17.5-alpine + volumes: + - ../dist/web:/usr/share/nginx/html:ro + - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro + ports: + - 8099:80 diff --git a/docker/nginx/nginx.conf b/docker/nginx/nginx.conf new file mode 100644 index 0000000..ea65e87 --- /dev/null +++ b/docker/nginx/nginx.conf @@ -0,0 +1,40 @@ +worker_processes 4; + +events { worker_connections 1024; } + +http { + ssl_session_cache shared:SSL:10m; + ssl_session_timeout 30m; + + #See http://blog.argteam.com/coding/hardening-node-js-for-production-part-2-using-nginx-to-avoid-node-js-load + proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=one:8m max_size=3000m inactive=600m; + proxy_temp_path /var/tmp; + include mime.types; + default_type application/octet-stream; + sendfile on; + keepalive_timeout 65; + + gzip on; + gzip_comp_level 6; + gzip_vary on; + gzip_min_length 1000; + gzip_proxied any; + gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript; + gzip_buffers 16 8k; + + server { + listen 80; + server_name localhost; + + location / { + root /usr/share/nginx/html; + index index.html; + expires -1; + add_header Pragma "no-cache"; + add_header Cache-Control "no-store, no-cache, must-revalidate, post-check=0, pre-check=0"; + try_files $uri$args $uri$args/ $uri $uri/ /index.html =404; + } + } + + +} \ No newline at end of file diff --git a/electron-builder.json b/electron-builder.json index d2cced2..fa84f18 100644 --- a/electron-builder.json +++ b/electron-builder.json @@ -1,10 +1,10 @@ { - "productName": "WooriTalk", - "appId": "lgcns.ucap.messenger", + "productName": "UCapMessenger", + "appId": "com.lgucap.messenger", "asar": true, "protocols": { - "name": "WooriTalk", - "schemes": ["WooriTalk"] + "name": "UCapMessenger", + "schemes": ["UCapMessenger"] }, "publish": { "provider": "generic", @@ -12,19 +12,19 @@ }, "mac": { "target": ["default"], - "icon": "./resources/installer/woori.icns" + "icon": "./dist/ucap-webmessenger-electron/resources/installer/woori.icns" }, "dmg": { - "title": "WooriTalk", - "icon": "./resources/installer/woori.icns" + "title": "UCapMessenger", + "icon": "./dist/ucap-webmessenger-electron/resources/installer/woori.icns" }, "win": { "target": ["zip", "nsis"], - "icon": "./resources/installer/woori_256x256.ico" + "icon": "./dist/ucap-webmessenger-electron/resources/image/16_16.ico" }, "linux": { "target": ["AppImage", "deb", "rpm", "zip", "tar.gz"], - "icon": "./resources/linuxicon" + "icon": "./dist/ucap-webmessenger-electron/resources/linuxicon" }, "nsis": { "oneClick": false, @@ -33,8 +33,8 @@ "differentialPackage": true }, "directories": { - "buildResources": "resources/installer/", - "output": "dist-electron/", + "buildResources": "./dist/ucap-webmessenger-electron/resources/installer/", + "output": "./dist/electron/", "app": "." } } diff --git a/projects/ucap-webmessenger-electron-core/README.md b/electron-projects/ucap-webmessenger-electron-core/README.md similarity index 100% rename from projects/ucap-webmessenger-electron-core/README.md rename to electron-projects/ucap-webmessenger-electron-core/README.md diff --git a/electron-projects/ucap-webmessenger-electron-core/karma.conf.js b/electron-projects/ucap-webmessenger-electron-core/karma.conf.js new file mode 100644 index 0000000..ddd5108 --- /dev/null +++ b/electron-projects/ucap-webmessenger-electron-core/karma.conf.js @@ -0,0 +1,34 @@ +// 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'], + plugins: [ + require('karma-jasmine'), + require('karma-chrome-launcher'), + require('karma-jasmine-html-reporter'), + require('karma-coverage-istanbul-reporter') + ], + client: { + clearContext: false // leave Jasmine Spec Runner output visible in browser + }, + coverageIstanbulReporter: { + dir: require('path').join( + __dirname, + '../../coverage/ucap-webmessenger-electron-core' + ), + 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 + }); +}; diff --git a/electron-projects/ucap-webmessenger-electron-core/package.json b/electron-projects/ucap-webmessenger-electron-core/package.json new file mode 100644 index 0000000..1285c0f --- /dev/null +++ b/electron-projects/ucap-webmessenger-electron-core/package.json @@ -0,0 +1,5 @@ +{ + "name": "@ucap-webmessenger/electron-core", + "version": "0.0.1", + "peerDependencies": {} +} diff --git a/projects/ucap-webmessenger-electron-core/src/lib/types/channel.type.ts b/electron-projects/ucap-webmessenger-electron-core/src/lib/types/channel.type.ts similarity index 100% rename from projects/ucap-webmessenger-electron-core/src/lib/types/channel.type.ts rename to electron-projects/ucap-webmessenger-electron-core/src/lib/types/channel.type.ts diff --git a/projects/ucap-webmessenger-electron-core/src/public-api.ts b/electron-projects/ucap-webmessenger-electron-core/src/public-api.ts similarity index 100% rename from projects/ucap-webmessenger-electron-core/src/public-api.ts rename to electron-projects/ucap-webmessenger-electron-core/src/public-api.ts diff --git a/projects/ucap-webmessenger-electron-core/src/test.ts b/electron-projects/ucap-webmessenger-electron-core/src/test.ts similarity index 100% rename from projects/ucap-webmessenger-electron-core/src/test.ts rename to electron-projects/ucap-webmessenger-electron-core/src/test.ts diff --git a/electron-projects/ucap-webmessenger-electron-core/tsconfig.lib.json b/electron-projects/ucap-webmessenger-electron-core/tsconfig.lib.json new file mode 100644 index 0000000..a4240e9 --- /dev/null +++ b/electron-projects/ucap-webmessenger-electron-core/tsconfig.lib.json @@ -0,0 +1,13 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": "../../out-tsc/lib", + "target": "es2015", + "declaration": true, + "inlineSources": true, + "types": [], + "lib": ["dom", "es2018"] + }, + + "exclude": ["src/test.ts", "**/*.spec.ts"] +} diff --git a/electron-projects/ucap-webmessenger-electron-core/tsconfig.spec.json b/electron-projects/ucap-webmessenger-electron-core/tsconfig.spec.json new file mode 100644 index 0000000..ec3528a --- /dev/null +++ b/electron-projects/ucap-webmessenger-electron-core/tsconfig.spec.json @@ -0,0 +1,9 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": "../../out-tsc/spec", + "types": ["jasmine", "node"] + }, + "files": ["src/test.ts"], + "include": ["**/*.spec.ts", "**/*.d.ts"] +} diff --git a/projects/ucap-webmessenger-electron-core/tslint.json b/electron-projects/ucap-webmessenger-electron-core/tslint.json similarity index 100% rename from projects/ucap-webmessenger-electron-core/tslint.json rename to electron-projects/ucap-webmessenger-electron-core/tslint.json diff --git a/projects/ucap-webmessenger-electron-notification/README.md b/electron-projects/ucap-webmessenger-electron-notification/README.md similarity index 100% rename from projects/ucap-webmessenger-electron-notification/README.md rename to electron-projects/ucap-webmessenger-electron-notification/README.md diff --git a/electron-projects/ucap-webmessenger-electron-notification/karma.conf.js b/electron-projects/ucap-webmessenger-electron-notification/karma.conf.js new file mode 100644 index 0000000..24d5a09 --- /dev/null +++ b/electron-projects/ucap-webmessenger-electron-notification/karma.conf.js @@ -0,0 +1,34 @@ +// 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'], + plugins: [ + require('karma-jasmine'), + require('karma-chrome-launcher'), + require('karma-jasmine-html-reporter'), + require('karma-coverage-istanbul-reporter') + ], + client: { + clearContext: false // leave Jasmine Spec Runner output visible in browser + }, + coverageIstanbulReporter: { + dir: require('path').join( + __dirname, + '../../coverage/ucap-webmessenger-electron-notification' + ), + 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 + }); +}; diff --git a/projects/ucap-webmessenger-electron-notification/package.json b/electron-projects/ucap-webmessenger-electron-notification/package.json similarity index 100% rename from projects/ucap-webmessenger-electron-notification/package.json rename to electron-projects/ucap-webmessenger-electron-notification/package.json diff --git a/projects/ucap-webmessenger-electron-notification/src/lib/models/electron-notification-options.ts b/electron-projects/ucap-webmessenger-electron-notification/src/lib/models/electron-notification-options.ts similarity index 94% rename from projects/ucap-webmessenger-electron-notification/src/lib/models/electron-notification-options.ts rename to electron-projects/ucap-webmessenger-electron-notification/src/lib/models/electron-notification-options.ts index 6cbec62..faafe33 100644 --- a/projects/ucap-webmessenger-electron-notification/src/lib/models/electron-notification-options.ts +++ b/electron-projects/ucap-webmessenger-electron-notification/src/lib/models/electron-notification-options.ts @@ -40,7 +40,7 @@ export const DefaultElectronNotificationOptions: ElectronNotificationOptions = { borderRadius: 5, displayTime: 5000, animationSteps: 5, - animationStepMs: 5, + animationStepMs: 20, appIcon: null, pathToModule: '', logging: true, diff --git a/projects/ucap-webmessenger-electron-notification/src/lib/models/electron-notification.ts b/electron-projects/ucap-webmessenger-electron-notification/src/lib/models/electron-notification.ts similarity index 90% rename from projects/ucap-webmessenger-electron-notification/src/lib/models/electron-notification.ts rename to electron-projects/ucap-webmessenger-electron-notification/src/lib/models/electron-notification.ts index 133bed8..fd7eea6 100644 --- a/projects/ucap-webmessenger-electron-notification/src/lib/models/electron-notification.ts +++ b/electron-projects/ucap-webmessenger-electron-notification/src/lib/models/electron-notification.ts @@ -3,7 +3,7 @@ import { ElectronNotificationEventType } from '../types/event.type'; export interface ElectronNotificationEvent { type: ElectronNotificationEventType; id: number; - close?: (reason: any) => void; + close?: (reason?: any) => void; } export interface ElectronNotification { diff --git a/projects/ucap-webmessenger-electron-notification/src/lib/services/electron-notification.service.ts b/electron-projects/ucap-webmessenger-electron-notification/src/lib/services/electron-notification.service.ts similarity index 75% rename from projects/ucap-webmessenger-electron-notification/src/lib/services/electron-notification.service.ts rename to electron-projects/ucap-webmessenger-electron-notification/src/lib/services/electron-notification.service.ts index 5f949e3..6095fb2 100644 --- a/projects/ucap-webmessenger-electron-notification/src/lib/services/electron-notification.service.ts +++ b/electron-projects/ucap-webmessenger-electron-notification/src/lib/services/electron-notification.service.ts @@ -1,10 +1,11 @@ import * as path from 'path'; import * as url from 'url'; +import * as fse from 'fs-extra'; import { AnimationQueue } from '../utils/animation-queue'; import { ElectronNotificationOptions, - DefaultElectronNotificationOptions + DefaultElectronNotificationOptions, } from '../models/electron-notification-options'; import { screen, BrowserWindow, ipcMain, IpcMainEvent, shell } from 'electron'; import { ElectronNotification } from '../models/electron-notification'; @@ -42,12 +43,12 @@ export class ElectronNotificationService { constructor(options?: ElectronNotificationOptions) { this.customOptions = { - ...DefaultElectronNotificationOptions + ...DefaultElectronNotificationOptions, }; if (!!options) { this.customOptions = { ...this.customOptions, - ...options + ...options, }; } @@ -59,7 +60,7 @@ export class ElectronNotificationService { if (!!options) { this.customOptions = { ...this.customOptions, - ...options + ...options, }; } this.calcDimensions(); @@ -88,7 +89,7 @@ export class ElectronNotificationService { this.animationQueue.push({ context: this, func: this.showNotification, - args: [notification] + args: [notification], }); return notification.id; } @@ -123,7 +124,7 @@ export class ElectronNotificationService { this.lowerRightCornerPosition = { x: display.bounds.x + display.workArea.x + display.workAreaSize.width, - y: display.bounds.y + display.workArea.y + display.workAreaSize.height + y: display.bounds.y + display.workArea.y + display.workAreaSize.height, }; this.calcDimensions(); @@ -176,7 +177,7 @@ export class ElectronNotificationService { notificationWindow[onClickElectronNotification]({ type: ElectronNotificationEventType.Click, id: notification.id, - close: self.buildCloseNotificationSafely(onClose) + close: self.buildCloseNotificationSafely(onClose), }); delete notificationWindow[onClickElectronNotification]; } @@ -187,17 +188,17 @@ export class ElectronNotificationService { private calcDimensions() { this.totalDimension = { width: this.customOptions.width + this.customOptions.padding, - height: this.customOptions.height + this.customOptions.padding + height: this.customOptions.height + this.customOptions.padding, }; this.firstPosition = { - x: this.lowerRightCornerPosition.x = this.totalDimension.width, - y: this.lowerRightCornerPosition.y = this.totalDimension.height + x: this.lowerRightCornerPosition.x - this.totalDimension.width, + y: this.lowerRightCornerPosition.y - this.totalDimension.height, }; this.nextInsertPosition = { x: this.firstPosition.x, - y: this.firstPosition.y + y: this.firstPosition.y, }; } @@ -211,19 +212,13 @@ export class ElectronNotificationService { private updateTemplatePath() { try { - import('fs') - .then(fs => { - fs.statSync(this.customOptions.templatePath).isFile(); + fse.statSync(this.customOptions.templatePath).isFile(); - this.templateUrl = url.format({ - pathname: this.customOptions.templatePath, - protocol: 'file:', - slashes: true - }); - }) - .catch(reason => { - throw reason; - }); + this.templateUrl = url.format({ + pathname: this.customOptions.templatePath, + protocol: 'file:', + slashes: true, + }); } catch (e) { console.log( 'electron-notify: Could not find template ("' + @@ -237,26 +232,27 @@ export class ElectronNotificationService { } private showNotification(notification: ElectronNotification): Promise { + const self = this; return new Promise((resolve, reject) => { if (this.activeNotifications.length < this.maxVisibleNotifications) { - this.getWindow().then(notificationWindow => { - this.calcInsertPosition(); + self.getWindow().then(notificationWindow => { + self.calcInsertPosition(); notificationWindow.setPosition( - this.nextInsertPosition.x, - this.nextInsertPosition.y + self.nextInsertPosition.x, + self.nextInsertPosition.y ); - this.activeNotifications.push(notificationWindow); + self.activeNotifications.push(notificationWindow); const displayTime = !!notification.displayTime ? notification.displayTime - : this.customOptions.displayTime; + : self.customOptions.displayTime; let timeoutId: any; - const onClose = this.buildCloseNotification( + const onClose = self.buildCloseNotification( notificationWindow, notification, () => timeoutId ); - const onCloseNotificationSafely = this.buildCloseNotificationSafely( + const onCloseNotificationSafely = self.buildCloseNotificationSafely( onClose ); timeoutId = setTimeout(() => { @@ -270,11 +266,11 @@ export class ElectronNotificationService { notification.onShow({ type: ElectronNotificationEventType.Show, id: notification.id, - close: onCloseNotificationSafely + close: onCloseNotificationSafely, }); } - if (!!notification.onClose) { + if (!!notification.onClick) { notificationWindow[onClickElectronNotification] = notification.onClick; } else { @@ -296,7 +292,7 @@ export class ElectronNotificationService { resolve(notificationWindow); }); } else { - this.notificationQueue.push(notification); + self.notificationQueue.push(notification); resolve(); } }); @@ -307,24 +303,25 @@ export class ElectronNotificationService { notification: ElectronNotification, timeoutIdFunc?: () => number ) { + const self = this; return (e: ElectronNotificationEventType): Promise => { if (notificationWindow.isDestroyed()) { return; } - if (this.closedNotifications.has(notification.id)) { - this.closedNotifications.delete(notification.id); + if (self.closedNotifications.has(notification.id)) { + self.closedNotifications.delete(notification.id); return new Promise(resolve => { resolve(); }); } else { - this.closedNotifications.set(notification.id, true); + self.closedNotifications.set(notification.id, true); } if (!!notificationWindow[onCloseElectronNotification]) { notificationWindow[onCloseElectronNotification]({ type: e, - id: notification.id + id: notification.id, }); delete notificationWindow[onCloseElectronNotification]; } @@ -334,29 +331,30 @@ export class ElectronNotificationService { if (!!timeoutIdFunc) { clearTimeout(timeoutIdFunc()); } - const i = this.activeNotifications.indexOf(notificationWindow); - this.activeNotifications.splice(i, 1); - this.inactiveWindows.push(notificationWindow); + const i = self.activeNotifications.indexOf(notificationWindow); + self.activeNotifications.splice(i, 1); + self.inactiveWindows.push(notificationWindow); notificationWindow.hide(); - this.checkForQueuedNotifications(); + self.checkForQueuedNotifications(); - return this.moveOneDown(i); + return self.moveOneDown(i); }; } private buildCloseNotificationSafely( onClose: (e: ElectronNotificationEventType) => any ) { + const self = this; return (reason: any) => { if (!reason) { reason = 'closedByAPI'; - this.animationQueue.push({ - context: this, - func: onClose, - args: [reason] - }); } + self.animationQueue.push({ + context: self, + func: onClose, + args: [reason], + }); }; } @@ -368,30 +366,31 @@ export class ElectronNotificationService { this.animationQueue.push({ context: this, func: this.showNotification, - args: [this.notificationQueue.shift()] + args: [this.notificationQueue.shift()], }); } } private getWindow(): Promise { + const slef = this; return new Promise((resolve, reject) => { - if (0 < this.inactiveWindows.length) { - resolve(this.inactiveWindows.pop()); + if (0 < slef.inactiveWindows.length) { + resolve(slef.inactiveWindows.pop()); } else { - const windowProperties = this.customOptions.defaultWindow; - windowProperties.width = this.customOptions.width; - windowProperties.height = this.customOptions.height; + const windowProperties = slef.customOptions.defaultWindow; + windowProperties.width = slef.customOptions.width; + windowProperties.height = slef.customOptions.height; const notificationWindow = new BrowserWindow(windowProperties); notificationWindow.setVisibleOnAllWorkspaces(true); - notificationWindow.loadURL(this.templatePath); + notificationWindow.loadURL(slef.templatePath); notificationWindow.webContents.on( ElectronWebContentsChannel.DidFinishLoad, () => { // Done notificationWindow.webContents.send( Channel.loadConfig, - this.customOptions + slef.customOptions ); resolve(notificationWindow); } @@ -407,20 +406,21 @@ export class ElectronNotificationService { } private moveOneDown(startPos: number): Promise { + const self = this; return new Promise(async (resolve, reject) => { - if (startPos >= this.activeNotifications.length || -1 === startPos) { + if (startPos >= self.activeNotifications.length || -1 === startPos) { resolve(); return; } const aryNotificationPos: number[] = []; - for (let i = startPos; i < this.activeNotifications.length; i++) { + for (let i = startPos; i < self.activeNotifications.length; i++) { aryNotificationPos.push(i); } await Promise.all( aryNotificationPos.map(async index => { - await this.moveNotificationAnimation(index); + await self.moveNotificationAnimation(index); }) ); resolve(); @@ -428,28 +428,29 @@ export class ElectronNotificationService { } private moveNotificationAnimation(index: number): Promise { + const self = this; return new Promise((resolve, reject) => { - const notificationWindow = this.activeNotifications[index]; + const notificationWindow = self.activeNotifications[index]; const newY = - this.lowerRightCornerPosition.y - - this.totalDimension.height * (index + 1); + self.lowerRightCornerPosition.y - + self.totalDimension.height * (index + 1); const startY = notificationWindow.getPosition()[1]; - const step = (newY - startY) / this.customOptions.animationSteps; + const step = (newY - startY) / self.customOptions.animationSteps; let curStep = 1; const animationInterval = setInterval(() => { // Abort condition - if (curStep === this.customOptions.animationSteps) { - notificationWindow.setPosition(this.firstPosition.x, newY); + if (curStep === self.customOptions.animationSteps) { + notificationWindow.setPosition(self.firstPosition.x, newY); clearInterval(animationInterval); return resolve(); } // Move one step down notificationWindow.setPosition( - this.firstPosition.x, + self.firstPosition.x, Math.trunc(startY + curStep * step) ); curStep++; - }, this.customOptions.animationStepMs); + }, self.customOptions.animationStepMs); }); } } diff --git a/projects/ucap-webmessenger-electron-notification/src/lib/types/channel.type.ts b/electron-projects/ucap-webmessenger-electron-notification/src/lib/types/channel.type.ts similarity index 100% rename from projects/ucap-webmessenger-electron-notification/src/lib/types/channel.type.ts rename to electron-projects/ucap-webmessenger-electron-notification/src/lib/types/channel.type.ts diff --git a/projects/ucap-webmessenger-electron-notification/src/lib/types/event.type.ts b/electron-projects/ucap-webmessenger-electron-notification/src/lib/types/event.type.ts similarity index 100% rename from projects/ucap-webmessenger-electron-notification/src/lib/types/event.type.ts rename to electron-projects/ucap-webmessenger-electron-notification/src/lib/types/event.type.ts diff --git a/projects/ucap-webmessenger-electron-notification/src/lib/utils/animation-queue.ts b/electron-projects/ucap-webmessenger-electron-notification/src/lib/utils/animation-queue.ts similarity index 100% rename from projects/ucap-webmessenger-electron-notification/src/lib/utils/animation-queue.ts rename to electron-projects/ucap-webmessenger-electron-notification/src/lib/utils/animation-queue.ts diff --git a/projects/ucap-webmessenger-electron-notification/src/public-api.ts b/electron-projects/ucap-webmessenger-electron-notification/src/public-api.ts similarity index 100% rename from projects/ucap-webmessenger-electron-notification/src/public-api.ts rename to electron-projects/ucap-webmessenger-electron-notification/src/public-api.ts diff --git a/projects/ucap-webmessenger-electron-notification/src/test.ts b/electron-projects/ucap-webmessenger-electron-notification/src/test.ts similarity index 100% rename from projects/ucap-webmessenger-electron-notification/src/test.ts rename to electron-projects/ucap-webmessenger-electron-notification/src/test.ts diff --git a/electron-projects/ucap-webmessenger-electron-notification/tsconfig.lib.json b/electron-projects/ucap-webmessenger-electron-notification/tsconfig.lib.json new file mode 100644 index 0000000..33840d8 --- /dev/null +++ b/electron-projects/ucap-webmessenger-electron-notification/tsconfig.lib.json @@ -0,0 +1,12 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": "../../out-tsc/lib", + "target": "es2015", + "declaration": true, + "inlineSources": true, + "types": [], + "lib": ["dom", "es2018"] + }, + "exclude": ["src/test.ts", "**/*.spec.ts"] +} diff --git a/projects/ucap-webmessenger-electron-core/tsconfig.spec.json b/electron-projects/ucap-webmessenger-electron-notification/tsconfig.spec.json similarity index 100% rename from projects/ucap-webmessenger-electron-core/tsconfig.spec.json rename to electron-projects/ucap-webmessenger-electron-notification/tsconfig.spec.json diff --git a/projects/ucap-webmessenger-electron-notification/tslint.json b/electron-projects/ucap-webmessenger-electron-notification/tslint.json similarity index 100% rename from projects/ucap-webmessenger-electron-notification/tslint.json rename to electron-projects/ucap-webmessenger-electron-notification/tslint.json diff --git a/electron-projects/ucap-webmessenger-electron/README.md b/electron-projects/ucap-webmessenger-electron/README.md new file mode 100644 index 0000000..67e9c69 --- /dev/null +++ b/electron-projects/ucap-webmessenger-electron/README.md @@ -0,0 +1,24 @@ +# UcapWebmessengerElectron + +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-electron` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module --project ucap-webmessenger-electron`. +> Note: Don't forget to add `--project ucap-webmessenger-electron` or else it will be added to the default project in your `angular.json` file. + +## Build + +Run `ng build ucap-webmessenger-electron` to build the project. The build artifacts will be stored in the `dist/` directory. + +## Publishing + +After building your library with `ng build ucap-webmessenger-electron`, go to the dist folder `cd dist/ucap-webmessenger-electron` and run `npm publish`. + +## Running unit tests + +Run `ng test ucap-webmessenger-electron` 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). diff --git a/electron-projects/ucap-webmessenger-electron/karma.conf.js b/electron-projects/ucap-webmessenger-electron/karma.conf.js new file mode 100644 index 0000000..7173861 --- /dev/null +++ b/electron-projects/ucap-webmessenger-electron/karma.conf.js @@ -0,0 +1,34 @@ +// 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'], + plugins: [ + require('karma-jasmine'), + require('karma-chrome-launcher'), + require('karma-jasmine-html-reporter'), + require('karma-coverage-istanbul-reporter') + ], + client: { + clearContext: false // leave Jasmine Spec Runner output visible in browser + }, + coverageIstanbulReporter: { + dir: require('path').join( + __dirname, + '../../coverage/ucap-webmessenger-electron' + ), + 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 + }); +}; diff --git a/electron-projects/ucap-webmessenger-electron/package.json b/electron-projects/ucap-webmessenger-electron/package.json new file mode 100644 index 0000000..b977c9c --- /dev/null +++ b/electron-projects/ucap-webmessenger-electron/package.json @@ -0,0 +1,5 @@ +{ + "name": "@ucap-webmessenger/electron", + "version": "0.0.1", + "peerDependencies": {} +} diff --git a/electron-projects/ucap-webmessenger-electron/resources/image/128_128.png b/electron-projects/ucap-webmessenger-electron/resources/image/128_128.png new file mode 100644 index 0000000..8156347 Binary files /dev/null and b/electron-projects/ucap-webmessenger-electron/resources/image/128_128.png differ diff --git a/electron-projects/ucap-webmessenger-electron/resources/image/16_16.ico b/electron-projects/ucap-webmessenger-electron/resources/image/16_16.ico new file mode 100644 index 0000000..3d8f6d9 Binary files /dev/null and b/electron-projects/ucap-webmessenger-electron/resources/image/16_16.ico differ diff --git a/electron-projects/ucap-webmessenger-electron/resources/image/16_16.png b/electron-projects/ucap-webmessenger-electron/resources/image/16_16.png new file mode 100644 index 0000000..f0d7ecf Binary files /dev/null and b/electron-projects/ucap-webmessenger-electron/resources/image/16_16.png differ diff --git a/electron-projects/ucap-webmessenger-electron/resources/image/256_256.png b/electron-projects/ucap-webmessenger-electron/resources/image/256_256.png new file mode 100644 index 0000000..8c189ac Binary files /dev/null and b/electron-projects/ucap-webmessenger-electron/resources/image/256_256.png differ diff --git a/electron-projects/ucap-webmessenger-electron/resources/image/32_32.png b/electron-projects/ucap-webmessenger-electron/resources/image/32_32.png new file mode 100644 index 0000000..cded28d Binary files /dev/null and b/electron-projects/ucap-webmessenger-electron/resources/image/32_32.png differ diff --git a/electron-projects/ucap-webmessenger-electron/resources/image/48_48.png b/electron-projects/ucap-webmessenger-electron/resources/image/48_48.png new file mode 100644 index 0000000..0401b9a Binary files /dev/null and b/electron-projects/ucap-webmessenger-electron/resources/image/48_48.png differ diff --git a/electron-projects/ucap-webmessenger-electron/resources/image/64_64.png b/electron-projects/ucap-webmessenger-electron/resources/image/64_64.png new file mode 100644 index 0000000..fa0bb81 Binary files /dev/null and b/electron-projects/ucap-webmessenger-electron/resources/image/64_64.png differ diff --git a/electron-projects/ucap-webmessenger-electron/resources/image/ico_64_64.png b/electron-projects/ucap-webmessenger-electron/resources/image/ico_64_64.png new file mode 100644 index 0000000..382110d Binary files /dev/null and b/electron-projects/ucap-webmessenger-electron/resources/image/ico_64_64.png differ diff --git a/electron-projects/ucap-webmessenger-electron/resources/image/ico_64x64.ico b/electron-projects/ucap-webmessenger-electron/resources/image/ico_64x64.ico new file mode 100644 index 0000000..8af2432 Binary files /dev/null and b/electron-projects/ucap-webmessenger-electron/resources/image/ico_64x64.ico differ diff --git a/electron-projects/ucap-webmessenger-electron/resources/image/ico_64x64_r.png b/electron-projects/ucap-webmessenger-electron/resources/image/ico_64x64_r.png new file mode 100644 index 0000000..84b33e4 Binary files /dev/null and b/electron-projects/ucap-webmessenger-electron/resources/image/ico_64x64_r.png differ diff --git a/electron-projects/ucap-webmessenger-electron/resources/image/lgRed/128_128.png b/electron-projects/ucap-webmessenger-electron/resources/image/lgRed/128_128.png new file mode 100644 index 0000000..3255604 Binary files /dev/null and b/electron-projects/ucap-webmessenger-electron/resources/image/lgRed/128_128.png differ diff --git a/electron-projects/ucap-webmessenger-electron/resources/image/lgRed/16_16.png b/electron-projects/ucap-webmessenger-electron/resources/image/lgRed/16_16.png new file mode 100644 index 0000000..84d630b Binary files /dev/null and b/electron-projects/ucap-webmessenger-electron/resources/image/lgRed/16_16.png differ diff --git a/electron-projects/ucap-webmessenger-electron/resources/image/lgRed/256_256.png b/electron-projects/ucap-webmessenger-electron/resources/image/lgRed/256_256.png new file mode 100644 index 0000000..6644c35 Binary files /dev/null and b/electron-projects/ucap-webmessenger-electron/resources/image/lgRed/256_256.png differ diff --git a/electron-projects/ucap-webmessenger-electron/resources/image/lgRed/32_32.png b/electron-projects/ucap-webmessenger-electron/resources/image/lgRed/32_32.png new file mode 100644 index 0000000..9f5fb1b Binary files /dev/null and b/electron-projects/ucap-webmessenger-electron/resources/image/lgRed/32_32.png differ diff --git a/electron-projects/ucap-webmessenger-electron/resources/image/lgRed/48_48.png b/electron-projects/ucap-webmessenger-electron/resources/image/lgRed/48_48.png new file mode 100644 index 0000000..5f3bf87 Binary files /dev/null and b/electron-projects/ucap-webmessenger-electron/resources/image/lgRed/48_48.png differ diff --git a/electron-projects/ucap-webmessenger-electron/resources/image/lgRed/64_64.png b/electron-projects/ucap-webmessenger-electron/resources/image/lgRed/64_64.png new file mode 100644 index 0000000..84b33e4 Binary files /dev/null and b/electron-projects/ucap-webmessenger-electron/resources/image/lgRed/64_64.png differ diff --git a/electron-projects/ucap-webmessenger-electron/resources/image/lgRed/ico_64_64.png b/electron-projects/ucap-webmessenger-electron/resources/image/lgRed/ico_64_64.png new file mode 100644 index 0000000..382110d Binary files /dev/null and b/electron-projects/ucap-webmessenger-electron/resources/image/lgRed/ico_64_64.png differ diff --git a/electron-projects/ucap-webmessenger-electron/resources/image/lgRed/ico_64x64.ico b/electron-projects/ucap-webmessenger-electron/resources/image/lgRed/ico_64x64.ico new file mode 100644 index 0000000..8af2432 Binary files /dev/null and b/electron-projects/ucap-webmessenger-electron/resources/image/lgRed/ico_64x64.ico differ diff --git a/electron-projects/ucap-webmessenger-electron/resources/image/lgRed/ico_64x64_r.png b/electron-projects/ucap-webmessenger-electron/resources/image/lgRed/ico_64x64_r.png new file mode 100644 index 0000000..84b33e4 Binary files /dev/null and b/electron-projects/ucap-webmessenger-electron/resources/image/lgRed/ico_64x64_r.png differ diff --git a/main/resources/installer/woori.icns b/electron-projects/ucap-webmessenger-electron/resources/installer/woori.icns similarity index 100% rename from main/resources/installer/woori.icns rename to electron-projects/ucap-webmessenger-electron/resources/installer/woori.icns diff --git a/main/resources/installer/woori.ico b/electron-projects/ucap-webmessenger-electron/resources/installer/woori.ico similarity index 100% rename from main/resources/installer/woori.ico rename to electron-projects/ucap-webmessenger-electron/resources/installer/woori.ico diff --git a/main/resources/installer/woori_256x256.ico b/electron-projects/ucap-webmessenger-electron/resources/installer/woori_256x256.ico similarity index 100% rename from main/resources/installer/woori_256x256.ico rename to electron-projects/ucap-webmessenger-electron/resources/installer/woori_256x256.ico diff --git a/main/resources/installer/woori_256x256.png b/electron-projects/ucap-webmessenger-electron/resources/installer/woori_256x256.png similarity index 100% rename from main/resources/installer/woori_256x256.png rename to electron-projects/ucap-webmessenger-electron/resources/installer/woori_256x256.png diff --git a/main/resources/linuxicon/256x256.png b/electron-projects/ucap-webmessenger-electron/resources/linuxicon/256x256.png similarity index 100% rename from main/resources/linuxicon/256x256.png rename to electron-projects/ucap-webmessenger-electron/resources/linuxicon/256x256.png diff --git a/main/resources/notification/image/btn_call_message.png b/electron-projects/ucap-webmessenger-electron/resources/notification/image/btn_call_message.png similarity index 100% rename from main/resources/notification/image/btn_call_message.png rename to electron-projects/ucap-webmessenger-electron/resources/notification/image/btn_call_message.png diff --git a/main/resources/notification/image/btn_call_receive.png b/electron-projects/ucap-webmessenger-electron/resources/notification/image/btn_call_receive.png similarity index 100% rename from main/resources/notification/image/btn_call_receive.png rename to electron-projects/ucap-webmessenger-electron/resources/notification/image/btn_call_receive.png diff --git a/main/resources/notification/image/btn_call_refuse.png b/electron-projects/ucap-webmessenger-electron/resources/notification/image/btn_call_refuse.png similarity index 100% rename from main/resources/notification/image/btn_call_refuse.png rename to electron-projects/ucap-webmessenger-electron/resources/notification/image/btn_call_refuse.png diff --git a/main/resources/notification/image/btn_call_transfer.png b/electron-projects/ucap-webmessenger-electron/resources/notification/image/btn_call_transfer.png similarity index 100% rename from main/resources/notification/image/btn_call_transfer.png rename to electron-projects/ucap-webmessenger-electron/resources/notification/image/btn_call_transfer.png diff --git a/main/resources/notification/image/btn_close.png b/electron-projects/ucap-webmessenger-electron/resources/notification/image/btn_close.png similarity index 100% rename from main/resources/notification/image/btn_close.png rename to electron-projects/ucap-webmessenger-electron/resources/notification/image/btn_close.png diff --git a/main/resources/notification/image/btn_close_gray.png b/electron-projects/ucap-webmessenger-electron/resources/notification/image/btn_close_gray.png similarity index 100% rename from main/resources/notification/image/btn_close_gray.png rename to electron-projects/ucap-webmessenger-electron/resources/notification/image/btn_close_gray.png diff --git a/main/resources/notification/image/btn_noti_call.png b/electron-projects/ucap-webmessenger-electron/resources/notification/image/btn_noti_call.png similarity index 100% rename from main/resources/notification/image/btn_noti_call.png rename to electron-projects/ucap-webmessenger-electron/resources/notification/image/btn_noti_call.png diff --git a/main/resources/notification/image/img_nophoto_50.png b/electron-projects/ucap-webmessenger-electron/resources/notification/image/img_nophoto_50.png similarity index 100% rename from main/resources/notification/image/img_nophoto_50.png rename to electron-projects/ucap-webmessenger-electron/resources/notification/image/img_nophoto_50.png diff --git a/main/resources/notification/preload.js b/electron-projects/ucap-webmessenger-electron/resources/notification/preload.js similarity index 100% rename from main/resources/notification/preload.js rename to electron-projects/ucap-webmessenger-electron/resources/notification/preload.js diff --git a/main/resources/notification/sound/messageAlarm.mp3 b/electron-projects/ucap-webmessenger-electron/resources/notification/sound/messageAlarm.mp3 similarity index 100% rename from main/resources/notification/sound/messageAlarm.mp3 rename to electron-projects/ucap-webmessenger-electron/resources/notification/sound/messageAlarm.mp3 diff --git a/main/resources/notification/styles/noti_messege.css b/electron-projects/ucap-webmessenger-electron/resources/notification/styles/noti_messege.css similarity index 100% rename from main/resources/notification/styles/noti_messege.css rename to electron-projects/ucap-webmessenger-electron/resources/notification/styles/noti_messege.css diff --git a/main/resources/notification/template.html b/electron-projects/ucap-webmessenger-electron/resources/notification/template.html similarity index 100% rename from main/resources/notification/template.html rename to electron-projects/ucap-webmessenger-electron/resources/notification/template.html diff --git a/main/src/app/AppWindow.ts b/electron-projects/ucap-webmessenger-electron/src/app/AppWindow.ts similarity index 89% rename from main/src/app/AppWindow.ts rename to electron-projects/ucap-webmessenger-electron/src/app/AppWindow.ts index e39874c..d109d19 100644 --- a/main/src/app/AppWindow.ts +++ b/electron-projects/ucap-webmessenger-electron/src/app/AppWindow.ts @@ -26,7 +26,7 @@ export class AppWindow { private minWidth = 960; private minHeight = 660; - public constructor() { + public constructor(private appIconPath: string) { const savedWindowState = windowStateKeeper({ defaultWidth: this.minWidth, defaultHeight: this.minHeight @@ -52,7 +52,7 @@ export class AppWindow { nodeIntegration: true }, acceptFirstMouse: true, - icon: path.join(__dirname, 'resources/image', 'ico_64_64.png') + icon: this.appIconPath }; if (__DARWIN__) { @@ -60,7 +60,6 @@ export class AppWindow { } else if (__WIN32__) { windowOptions.frame = false; } else if (__LINUX__) { - windowOptions.icon = path.join(__dirname, 'static', 'icon-logo.png'); } this.window = new BrowserWindow(windowOptions); @@ -85,6 +84,19 @@ export class AppWindow { e.preventDefault(); } }); + } else if (__WIN32__) { + this.window.on(ElectronBrowserWindowChannel.Minimize, e => { + if (!quitting) { + e.preventDefault(); + this.window.hide(); + } + }); + this.window.on(ElectronBrowserWindowChannel.Close, e => { + if (!quitting) { + e.preventDefault(); + this.window.hide(); + } + }); } if (__WIN32__) { @@ -200,6 +212,10 @@ export class AppWindow { this.window.show(); } + public hide() { + this.window.hide(); + } + /** * Get the time (in milliseconds) spent loading the page. * diff --git a/main/src/crash/CrashWindow.ts b/electron-projects/ucap-webmessenger-electron/src/crash/CrashWindow.ts similarity index 100% rename from main/src/crash/CrashWindow.ts rename to electron-projects/ucap-webmessenger-electron/src/crash/CrashWindow.ts diff --git a/main/src/crash/show-uncaught-exception.ts b/electron-projects/ucap-webmessenger-electron/src/crash/show-uncaught-exception.ts similarity index 100% rename from main/src/crash/show-uncaught-exception.ts rename to electron-projects/ucap-webmessenger-electron/src/crash/show-uncaught-exception.ts diff --git a/main/src/global.d.ts b/electron-projects/ucap-webmessenger-electron/src/global.d.ts similarity index 100% rename from main/src/global.d.ts rename to electron-projects/ucap-webmessenger-electron/src/global.d.ts diff --git a/main/src/index.ts b/electron-projects/ucap-webmessenger-electron/src/index.ts similarity index 77% rename from main/src/index.ts rename to electron-projects/ucap-webmessenger-electron/src/index.ts index ed9548b..1304c60 100644 --- a/main/src/index.ts +++ b/electron-projects/ucap-webmessenger-electron/src/index.ts @@ -1,4 +1,12 @@ -import { app, ipcMain, IpcMainEvent, remote } from 'electron'; +import { + app, + ipcMain, + IpcMainEvent, + remote, + Tray, + Menu, + dialog +} from 'electron'; import * as path from 'path'; import * as url from 'url'; import * as fse from 'fs-extra'; @@ -12,7 +20,9 @@ import { UpdaterChannel, FileChannel, IdleStateChannel, - NotificationChannel + NotificationChannel, + ChatChannel, + MessengerChannel } from '@ucap-webmessenger/native-electron'; import { ElectronNotificationService } from '@ucap-webmessenger/electron-notification'; @@ -24,7 +34,12 @@ import { IdleChecker } from './lib/idle-checker'; import { NotificationRequest } from '@ucap-webmessenger/native'; import { ElectronAppChannel } from '@ucap-webmessenger/electron-core'; +const appIconPath = __LINUX__ + ? path.join(__dirname, 'static', 'icon-logo.png') + : path.join(__dirname, 'resources/image', 'ico_64_64.png'); + let appWindow: AppWindow | null = null; +let appTray: Tray | null = null; const launchTime = now(); let readyTime: number | null = null; @@ -90,7 +105,7 @@ if (isDuplicateInstance) { } function createWindow() { - const window = new AppWindow(); + const window = new AppWindow(appIconPath); if (__DEV__) { // const { @@ -142,6 +157,48 @@ function createWindow() { appWindow = window; } +function createTray() { + appTray = new Tray(appIconPath); + + const contextMenu = Menu.buildFromTemplate([ + { + label: '로그아웃', + // accelerator: 'Q', + // selector: 'terminate:', + click: () => { + appWindow.show(); + appWindow.browserWindow.webContents.send(MessengerChannel.Logout); + } + }, + { + label: '설정', + // accelerator: 'Q', + // selector: 'terminate:', + click: () => { + appWindow.show(); + appWindow.browserWindow.webContents.send(MessengerChannel.ShowSetting); + } + }, + { label: '버전', submenu: [{ label: 'Ver. ' + app.getVersion() }] }, + { + label: '종료', + // accelerator: 'Q', + // selector: 'terminate:', + click: () => { + // 메신저에 로그아웃 후 종료 + appWindow = null; + app.exit(); + } + } + ]); + appTray.setToolTip('UCapMessenger'); + appTray.setContextMenu(contextMenu); + + appTray.on('click', () => { + appWindow.isVisible() ? appWindow.hide() : appWindow.show(); + }); +} + // This method will be called when Electron has finished // initialization and is ready to create browser windows. // Some APIs can only be used after this event occurs. @@ -154,10 +211,12 @@ app.on(ElectronAppChannel.Ready, () => { createWindow(); + createTray(); + notificationService = new ElectronNotificationService({ width: 340, height: 100, - padding: 10, + padding: 0, borderRadius: 0, // appIcon: iconPath, displayTime: 5000, @@ -240,8 +299,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); @@ -289,12 +349,15 @@ ipcMain.on( 'resources/notification/sound/messageAlarm.mp3' ) : '', - onClick: () => { - console.log('onClick'); + onClick: e => { + appWindow.browserWindow.webContents.send( + ChatChannel.OpenRoom, + noti.roomSeq + ); + appWindow.show(); + e.close(); } }); - - console.log('Channel.notify', noti); } ); diff --git a/main/src/lib/default-folder.ts b/electron-projects/ucap-webmessenger-electron/src/lib/default-folder.ts similarity index 100% rename from main/src/lib/default-folder.ts rename to electron-projects/ucap-webmessenger-electron/src/lib/default-folder.ts diff --git a/main/src/lib/file-util.ts b/electron-projects/ucap-webmessenger-electron/src/lib/file-util.ts similarity index 100% rename from main/src/lib/file-util.ts rename to electron-projects/ucap-webmessenger-electron/src/lib/file-util.ts diff --git a/main/src/lib/idle-checker.ts b/electron-projects/ucap-webmessenger-electron/src/lib/idle-checker.ts similarity index 89% rename from main/src/lib/idle-checker.ts rename to electron-projects/ucap-webmessenger-electron/src/lib/idle-checker.ts index fe8761c..98bad21 100644 --- a/main/src/lib/idle-checker.ts +++ b/electron-projects/ucap-webmessenger-electron/src/lib/idle-checker.ts @@ -51,11 +51,9 @@ export class IdleChecker { // global.opt_idleTimeLimit = limitedMin; this.startChecker(); - console.log('RESET IDLE TIMER in ' + limitedMin + 'm'); } public startChecker() { - console.log('Idle Checker Start'); if (!this.intervalObject) { this.intervalObject = setInterval(() => { this.doCheckIdle(); @@ -64,7 +62,6 @@ export class IdleChecker { } public destoryChecker() { - console.log('Idle Checker Destory'); if (!!this.intervalObject) { clearInterval(this.intervalObject); } diff --git a/main/src/lib/storage.ts b/electron-projects/ucap-webmessenger-electron/src/lib/storage.ts similarity index 100% rename from main/src/lib/storage.ts rename to electron-projects/ucap-webmessenger-electron/src/lib/storage.ts diff --git a/main/src/lib/window-state.ts b/electron-projects/ucap-webmessenger-electron/src/lib/window-state.ts similarity index 100% rename from main/src/lib/window-state.ts rename to electron-projects/ucap-webmessenger-electron/src/lib/window-state.ts diff --git a/main/src/util/now.ts b/electron-projects/ucap-webmessenger-electron/src/util/now.ts similarity index 100% rename from main/src/util/now.ts rename to electron-projects/ucap-webmessenger-electron/src/util/now.ts diff --git a/main/src/util/root.ts b/electron-projects/ucap-webmessenger-electron/src/util/root.ts similarity index 100% rename from main/src/util/root.ts rename to electron-projects/ucap-webmessenger-electron/src/util/root.ts diff --git a/main/tsconfig.main.json b/electron-projects/ucap-webmessenger-electron/tsconfig.electron.json similarity index 50% rename from main/tsconfig.main.json rename to electron-projects/ucap-webmessenger-electron/tsconfig.electron.json index 39a7730..d01f9dc 100644 --- a/main/tsconfig.main.json +++ b/electron-projects/ucap-webmessenger-electron/tsconfig.electron.json @@ -1,7 +1,7 @@ { "compilerOptions": { "baseUrl": "./", - "outDir": "../dist/main", + "outDir": "../../dist/main", "sourceMap": true, "declaration": false, "module": "commonjs", @@ -14,19 +14,24 @@ "lib": ["es2017", "es2016", "es2015", "dom"], "paths": { "@ucap-webmessenger/electron-core": [ - "../projects/ucap-webmessenger-electron-core/src/public-api" + "../ucap-webmessenger-electron-core/src/public-api" ], "@ucap-webmessenger/electron-notification": [ - "../projects/ucap-webmessenger-electron-notification/src/public-api" + "../ucap-webmessenger-electron-notification/src/public-api" + ], + "@ucap-webmessenger/core": [ + "../../projects/ucap-webmessenger-core/src/public-api" ], "@ucap-webmessenger/native": [ - "../projects/ucap-webmessenger-native/src/public-api" + "../../projects/ucap-webmessenger-native/src/public-api" ], "@ucap-webmessenger/native-electron": [ - "../projects/ucap-webmessenger-native-electron/src/public-api" + "../../projects/ucap-webmessenger-native-electron/src/public-api" + ], + "@ucap-webmessenger/electron": [ + "../../projects/ucap-webmessenger-electron/src/public-api" ] } }, - - "exclude": ["../node_modules", "**/*.spec.ts"] + "exclude": ["../../node_modules", "**/*.spec.ts"] } diff --git a/projects/ucap-webmessenger-electron-notification/tsconfig.spec.json b/electron-projects/ucap-webmessenger-electron/tsconfig.spec.json similarity index 100% rename from projects/ucap-webmessenger-electron-notification/tsconfig.spec.json rename to electron-projects/ucap-webmessenger-electron/tsconfig.spec.json diff --git a/electron-projects/ucap-webmessenger-electron/tslint.json b/electron-projects/ucap-webmessenger-electron/tslint.json new file mode 100644 index 0000000..37d97a1 --- /dev/null +++ b/electron-projects/ucap-webmessenger-electron/tslint.json @@ -0,0 +1,7 @@ +{ + "extends": "../../tslint.json", + "rules": { + "directive-selector": [true, "attribute", "ucapElectron", "camelCase"], + "component-selector": [true, "element", "ucap-electron", "kebab-case"] + } +} diff --git a/main/resources/image/128_128.png b/main/resources/image/128_128.png deleted file mode 100644 index 197dd6f..0000000 Binary files a/main/resources/image/128_128.png and /dev/null differ diff --git a/main/resources/image/16_16.png b/main/resources/image/16_16.png deleted file mode 100644 index 9c4e5ee..0000000 Binary files a/main/resources/image/16_16.png and /dev/null differ diff --git a/main/resources/image/256_256.png b/main/resources/image/256_256.png deleted file mode 100644 index 532e389..0000000 Binary files a/main/resources/image/256_256.png and /dev/null differ diff --git a/main/resources/image/32_32.png b/main/resources/image/32_32.png deleted file mode 100644 index 4d956fa..0000000 Binary files a/main/resources/image/32_32.png and /dev/null differ diff --git a/main/resources/image/48_48.png b/main/resources/image/48_48.png deleted file mode 100644 index 9e1330d..0000000 Binary files a/main/resources/image/48_48.png and /dev/null differ diff --git a/main/resources/image/64_64.png b/main/resources/image/64_64.png deleted file mode 100644 index caa67f2..0000000 Binary files a/main/resources/image/64_64.png and /dev/null differ diff --git a/main/resources/image/ico_64x64.ico b/main/resources/image/ico_64x64.ico deleted file mode 100644 index d62de46..0000000 Binary files a/main/resources/image/ico_64x64.ico and /dev/null differ diff --git a/main/resources/image/ico_64x64.png b/main/resources/image/ico_64x64.png deleted file mode 100644 index adbc1dd..0000000 Binary files a/main/resources/image/ico_64x64.png and /dev/null differ diff --git a/main/resources/image/ico_64x64_r.ico b/main/resources/image/ico_64x64_r.ico deleted file mode 100644 index 94ece2b..0000000 Binary files a/main/resources/image/ico_64x64_r.ico and /dev/null differ diff --git a/main/resources/image/ico_64x64_r.png b/main/resources/image/ico_64x64_r.png deleted file mode 100644 index caa67f2..0000000 Binary files a/main/resources/image/ico_64x64_r.png and /dev/null differ diff --git a/package-lock.json b/package-lock.json index 53a0907..5152686 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1127,7 +1127,6 @@ "version": "8.2.12", "resolved": "https://registry.npmjs.org/@angular/core/-/core-8.2.12.tgz", "integrity": "sha512-wEFwhHCuuXynXAMeA1G+0KIYY0jqXYs7I8p+GO+ufKoUmzWHFTvtMJ6nvKgy+LmZTByO2gf9oVAAlRodNb8ttQ==", - "dev": true, "requires": { "tslib": "^1.9.0" } @@ -2095,6 +2094,22 @@ "ajv-keywords": "^3.1.0" } }, + "@electron/get": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@electron/get/-/get-1.7.0.tgz", + "integrity": "sha512-Xzo+xLQ+gwmGywFnFuG7HNIALPVJOCkvKagGxSXU1LC3s/j3h2Nku9OdwJ4KDkITeUuXfvAO5KS8rLGcmAunNQ==", + "dev": true, + "requires": { + "debug": "^4.1.1", + "env-paths": "^2.2.0", + "fs-extra": "^8.1.0", + "global-agent": "^2.0.2", + "global-tunnel-ng": "^2.7.1", + "got": "^9.6.0", + "sanitize-filename": "^1.6.2", + "sumchecker": "^3.0.0" + } + }, "@hapi/address": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/@hapi/address/-/address-2.1.1.tgz", @@ -2789,6 +2804,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", @@ -2985,12 +3009,6 @@ "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", "dev": true }, - "array-find-index": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", - "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=", - "dev": true - }, "array-flatten": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz", @@ -3131,6 +3149,15 @@ "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", "dev": true }, + "autolinker": { + "version": "3.11.1", + "resolved": "https://registry.npmjs.org/autolinker/-/autolinker-3.11.1.tgz", + "integrity": "sha512-6sAmetStorjXvwmV8MBxI5DGICHKD1B5EjdkIrq34X6YBDN6jj54EUHnoHgNqmNCclcf8c409zuVMNy449u80g==", + "dev": true, + "requires": { + "tslib": "^1.9.3" + } + }, "autoprefixer": { "version": "9.6.1", "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-9.6.1.tgz", @@ -3619,6 +3646,13 @@ "multicast-dns-service-types": "^1.1.0" } }, + "boolean": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/boolean/-/boolean-2.0.3.tgz", + "integrity": "sha512-iHzXeFCXWrpjYE7DToXGCBPGZf0eVISqzL+4sgrOSYEKXnb59WHPFvGTTyCj6zJ/MuuLAxEn8zPkrTHHzlt3IA==", + "dev": true, + "optional": true + }, "boxen": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/boxen/-/boxen-3.2.0.tgz", @@ -3939,6 +3973,17 @@ "ssri": "^6.0.1", "unique-filename": "^1.1.1", "y18n": "^4.0.0" + }, + "dependencies": { + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + } } }, "cache-base": { @@ -4038,24 +4083,6 @@ "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", "dev": true }, - "camelcase-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", - "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", - "dev": true, - "requires": { - "camelcase": "^2.0.0", - "map-obj": "^1.0.0" - }, - "dependencies": { - "camelcase": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", - "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=", - "dev": true - } - } - }, "caniuse-lite": { "version": "1.0.30000989", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000989.tgz", @@ -4184,6 +4211,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", @@ -4499,24 +4532,27 @@ } }, "conf": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/conf/-/conf-5.0.0.tgz", - "integrity": "sha512-lRNyt+iRD4plYaOSVTxu1zPWpaH0EOxgFIR1l3mpC/DGZ7XzhoGFMKmbl54LAgXcSu6knqWgOwdINkqm58N85A==", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/conf/-/conf-6.2.0.tgz", + "integrity": "sha512-fvl40R6YemHrFsNiyP7TD0tzOe3pQD2dfT2s20WvCaq57A1oV+RImbhn2Y4sQGDz1lB0wNSb7dPcPIvQB69YNA==", "dev": true, "requires": { - "ajv": "^6.10.0", + "ajv": "^6.10.2", + "debounce-fn": "^3.0.1", "dot-prop": "^5.0.0", "env-paths": "^2.2.0", - "json-schema-typed": "^7.0.0", + "json-schema-typed": "^7.0.1", "make-dir": "^3.0.0", + "onetime": "^5.1.0", "pkg-up": "^3.0.1", + "semver": "^6.2.0", "write-file-atomic": "^3.0.0" }, "dependencies": { "dot-prop": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.1.1.tgz", - "integrity": "sha512-QCHI6Lkf+9fJMpwfAFsTvbiSh6ujoPmhCLiDvD/n4dGtLvHfhuBwPdN6z2x4YSOwwtTcLoO/LP70xELWGF/JVA==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.2.0.tgz", + "integrity": "sha512-uEUyaDKoSQ1M4Oq8l45hSE26SnTxL6snNnqvK/VWx5wJhmff5z0FUVJDKDanor/6w3kzE3i7XZOk+7wC0EXr1A==", "dev": true, "requires": { "is-obj": "^2.0.0" @@ -4551,6 +4587,17 @@ } } }, + "config-chain": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.12.tgz", + "integrity": "sha512-a1eOIcu8+7lUInge4Rpf/n4Krkf3Dd9lqhljRzII1/Zno/kRtUWnznPO3jOKBmTEktkt3fkxisUcivoj0ebzoA==", + "dev": true, + "optional": true, + "requires": { + "ini": "^1.3.4", + "proto-list": "~1.2.1" + } + }, "configstore": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/configstore/-/configstore-4.0.0.tgz", @@ -4680,6 +4727,17 @@ "mkdirp": "^0.5.1", "rimraf": "^2.5.4", "run-queue": "^1.0.0" + }, + "dependencies": { + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + } } }, "copy-descriptor": { @@ -4728,6 +4786,17 @@ "ssri": "^6.0.1", "unique-filename": "^1.1.1", "y18n": "^4.0.0" + }, + "dependencies": { + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + } } }, "find-cache-dir": { @@ -4987,15 +5056,6 @@ "integrity": "sha1-QICG1AlVDCYxFVYZ6fp7ytw7mRs=", "dev": true }, - "currently-unhandled": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", - "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", - "dev": true, - "requires": { - "array-find-index": "^1.0.1" - } - }, "custom-event": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/custom-event/-/custom-event-1.0.1.tgz", @@ -5051,6 +5111,15 @@ "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=", "dev": true }, + "debounce-fn": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/debounce-fn/-/debounce-fn-3.0.1.tgz", + "integrity": "sha512-aBoJh5AhpqlRoHZjHmOzZlRx+wz2xVwGL9rjs+Kj0EWUrL4/h4K7OD176thl2Tdoqui/AaA4xhHrNArGLAaI3Q==", + "dev": true, + "requires": { + "mimic-fn": "^2.1.0" + } + }, "debug": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", @@ -5231,6 +5300,15 @@ "dev": true } } + }, + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } } } }, @@ -5496,14 +5574,22 @@ "dev": true }, "electron": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/electron/-/electron-6.1.2.tgz", - "integrity": "sha512-zVste1obJC645RrU4PP+CqU8Yq33h8fzS7zx3tWbiNnyRzp6m7O2bpgKLJBRZ/4BPRsNCqSSXm4vimyGPUXVaw==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/electron/-/electron-7.1.1.tgz", + "integrity": "sha512-NJPv4SuMJlRUtXBd/Ey9XKSLOZ4+hxsOrHHPXwrBQNNdeZesoSrTMgPymee/FwMRtrSt0Pz8NccEZUu/pxmbhQ==", "dev": true, "requires": { - "@types/node": "^10.12.18", - "electron-download": "^4.1.0", + "@electron/get": "^1.0.1", + "@types/node": "^12.0.12", "extract-zip": "^1.0.3" + }, + "dependencies": { + "@types/node": { + "version": "12.12.8", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.8.tgz", + "integrity": "sha512-XLla8N+iyfjvsa0KKV+BP/iGSoTmwxsu5Ci5sM33z9TjohF72DEz95iNvD6pPmemvbQgxAv/909G73gUn8QR7w==", + "dev": true + } } }, "electron-builder": { @@ -5656,55 +5742,13 @@ "semver": "^5.3.0" }, "dependencies": { - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - } - } - }, - "electron-download": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/electron-download/-/electron-download-4.1.1.tgz", - "integrity": "sha512-FjEWG9Jb/ppK/2zToP+U5dds114fM1ZOJqMAR4aXXL5CvyPE9fiqBK/9YcwC9poIFQTEJk/EM/zyRwziziRZrg==", - "dev": true, - "requires": { - "debug": "^3.0.0", - "env-paths": "^1.0.0", - "fs-extra": "^4.0.1", - "minimist": "^1.2.0", - "nugget": "^2.0.1", - "path-exists": "^3.0.0", - "rc": "^1.2.1", - "semver": "^5.4.1", - "sumchecker": "^2.0.2" - }, - "dependencies": { - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", "dev": true, "requires": { - "ms": "^2.1.1" - } - }, - "env-paths": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-1.0.0.tgz", - "integrity": "sha1-QWgTO0K7BcOKNbGuQ5fIKYqzaeA=", - "dev": true - }, - "fs-extra": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-4.0.3.tgz", - "integrity": "sha512-q6rbdDd1o2mAnQreO7YADIxf/Whx4AHBiRf6d+/cVT8h44ss+lHgxf1FemcqDnQt9X3ct4McHr+JMGlYSsK7Cg==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" + "glob": "^7.1.3" } }, "semver": { @@ -5757,9 +5801,9 @@ } }, "electron-log": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/electron-log/-/electron-log-3.0.8.tgz", - "integrity": "sha512-B9+eJ8z3UbDnWEz+G33SIJvEDeKLznHEV4sCu6bR31KuOdp3dYN046QBWbLNsvKU+lzFI6eOi+xNCpNHZvatiw==", + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/electron-log/-/electron-log-3.0.9.tgz", + "integrity": "sha512-kfV4riUqW8uooYLAfrlB3EJW66W29ePipJU4/Fm8UxQekVNcR2qHI/0tiJX3oWM79VdAUiiYqL9V49lhnSIO8g==", "dev": true }, "electron-publish": { @@ -5806,13 +5850,21 @@ } }, "electron-store": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/electron-store/-/electron-store-4.0.0.tgz", - "integrity": "sha512-qgkDetwB9bz+ZA7mNCQGm6zLJOMT4yBkTZ7f16M9iS0GcI/bOeOeFkLkIaJddTtPca7MOiaUM1imMjFqUfQgSA==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/electron-store/-/electron-store-5.1.0.tgz", + "integrity": "sha512-uhAF/4+zDb+y0hWqlBirEPEAR4ciCZDp4fRWGFNV62bG+ArdQPpXk7jS0MEVj3CfcG5V7hx7Dpq5oD+1j6GD8Q==", "dev": true, "requires": { - "conf": "^5.0.0", - "type-fest": "^0.5.2" + "conf": "^6.2.0", + "type-fest": "^0.7.1" + }, + "dependencies": { + "type-fest": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.7.1.tgz", + "integrity": "sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg==", + "dev": true + } } }, "electron-to-chromium": { @@ -5822,26 +5874,43 @@ "dev": true }, "electron-updater": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/electron-updater/-/electron-updater-4.1.2.tgz", - "integrity": "sha512-4Sk8IW0LfOilDz+WAB/gEDmX7+FUFRbKHGN1zGjehPilnd6H9cmjgBHK6Xzq/FLq/uOHGJ6GX/9tsF+jr7CvnA==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/electron-updater/-/electron-updater-4.2.0.tgz", + "integrity": "sha512-GuS3g7HDh17x/SaFjxjswlWUaKHczksYkV2Xc5CKj/bZH0YCvTSHtOmnBAdAmCk99u/71p3zP8f0jIqDfGcjww==", "dev": true, "requires": { - "@types/semver": "^6.0.1", - "builder-util-runtime": "8.3.0", + "@types/semver": "^6.0.2", + "builder-util-runtime": "8.4.0", "fs-extra": "^8.1.0", "js-yaml": "^3.13.1", "lazy-val": "^1.0.4", "lodash.isequal": "^4.5.0", "pako": "^1.0.10", - "semver": "^6.2.0" + "semver": "^6.3.0" + }, + "dependencies": { + "builder-util-runtime": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/builder-util-runtime/-/builder-util-runtime-8.4.0.tgz", + "integrity": "sha512-CJB/eKfPf2vHrkmirF5eicVnbDCkMBbwd5tRYlTlgud16zFeqD7QmrVUAOEXdnsrcNkiLg9dbuUsQKtl/AwsYQ==", + "dev": true, + "requires": { + "debug": "^4.1.1", + "sax": "^1.2.4" + } + }, + "sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", + "dev": true + } } }, "electron-window-state": { "version": "5.0.3", "resolved": "https://registry.npmjs.org/electron-window-state/-/electron-window-state-5.0.3.tgz", "integrity": "sha512-1mNTwCfkolXl3kMf50yW3vE2lZj0y92P/HYWFBrb+v2S/pCka5mdwN3cagKm458A7NjndSwijynXgcLWRodsVg==", - "dev": true, "requires": { "jsonfile": "^4.0.0", "mkdirp": "^0.5.1" @@ -6099,6 +6168,13 @@ "next-tick": "^1.0.0" } }, + "es6-error": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", + "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", + "dev": true, + "optional": true + }, "es6-iterator": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", @@ -6849,7 +6925,6 @@ "version": "8.1.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", - "dev": true, "requires": { "graceful-fs": "^4.2.0", "jsonfile": "^4.0.0", @@ -6908,12 +6983,6 @@ "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", "dev": true }, - "get-stdin": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", - "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", - "dev": true - }, "get-stream": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", @@ -6973,6 +7042,31 @@ } } }, + "global-agent": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/global-agent/-/global-agent-2.1.6.tgz", + "integrity": "sha512-fL+xfraAlc1MXU8Gs0DAg/eHH+H1CjxbK+BLU3Qt55dAVMAQ8fH8k/UrLwV4A+Vk/hl/TePWuTxFnqJzCV1/Kw==", + "dev": true, + "optional": true, + "requires": { + "boolean": "^2.0.3", + "core-js": "^3.4.0", + "es6-error": "^4.1.1", + "matcher": "^2.0.0", + "roarr": "^2.14.4", + "semver": "^6.3.0", + "serialize-error": "^5.0.0" + }, + "dependencies": { + "core-js": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.4.1.tgz", + "integrity": "sha512-KX/dnuY/J8FtEwbnrzmAjUYgLqtk+cxM86hfG60LGiW3MmltIc2yAmDgBgEkfm0blZhUrdr1Zd84J2Y14mLxzg==", + "dev": true, + "optional": true + } + } + }, "global-dirs": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-0.1.1.tgz", @@ -7017,12 +7111,37 @@ "which": "^1.2.14" } }, + "global-tunnel-ng": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/global-tunnel-ng/-/global-tunnel-ng-2.7.1.tgz", + "integrity": "sha512-4s+DyciWBV0eK148wqXxcmVAbFVPqtc3sEtUE/GTQfuU80rySLcMhUmHKSHI7/LDj8q0gDYI1lIhRRB7ieRAqg==", + "dev": true, + "optional": true, + "requires": { + "encodeurl": "^1.0.2", + "lodash": "^4.17.10", + "npm-conf": "^1.1.3", + "tunnel": "^0.0.6" + } + }, "globals": { "version": "11.12.0", "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", "dev": true }, + "globalthis": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.0.tgz", + "integrity": "sha512-vcCAZTJ3r5Qcu5l8/2oyVdoFwxKgfYnMTR2vwWeux/NAVZK3PwcMaWkdUIn4GJbmKuRK7xcvDsLuK+CKcXyodg==", + "dev": true, + "optional": true, + "requires": { + "define-properties": "^1.1.2", + "function-bind": "^1.1.1", + "object-keys": "^1.0.12" + } + }, "globby": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/globby/-/globby-7.1.1.tgz", @@ -7067,8 +7186,7 @@ "graceful-fs": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.2.tgz", - "integrity": "sha512-IItsdsea19BoLC7ELy13q1iJFNmd7ofZH5+X/pJr90/nRoPEX0DJo1dHDbgtYWOhJhcCgMDTOw84RZ72q6lB+Q==", - "dev": true + "integrity": "sha512-IItsdsea19BoLC7ELy13q1iJFNmd7ofZH5+X/pJr90/nRoPEX0DJo1dHDbgtYWOhJhcCgMDTOw84RZ72q6lB+Q==" }, "hammerjs": { "version": "2.0.8", @@ -7540,15 +7658,6 @@ "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", "dev": true }, - "indent-string": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", - "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", - "dev": true, - "requires": { - "repeating": "^2.0.0" - } - }, "indexof": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", @@ -7977,12 +8086,6 @@ "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", "dev": true }, - "is-utf8": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", - "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", - "dev": true - }, "is-windows": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", @@ -8216,6 +8319,15 @@ "integrity": "sha512-8aXznuEPCJvGnMSRft4udDRDtb1V3pkQkMMI5LI+6HuQz5oQ4J2UFn1H82raA3qJtyOLkkwVqICBQkjnGtn5mA==", "dev": true }, + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -8368,9 +8480,9 @@ "dev": true }, "json-schema-typed": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/json-schema-typed/-/json-schema-typed-7.0.1.tgz", - "integrity": "sha512-IqUK+Cqc8/MqHsCvv1TMccbKdBzoATOLHXZAF5UDu70/CCxo648cHUig24hc+XTK53TyeNk1UeVTlc2Haovtsw==", + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/json-schema-typed/-/json-schema-typed-7.0.2.tgz", + "integrity": "sha512-40FRIcBSz4y0Ego3gMpbkhtIgebpxKRgW/7i1FfDNL4/xEPQKBM12tKSiCZFNQvad5K4IS3I5Sc8cxza/KSwog==", "dev": true }, "json-stable-stringify": { @@ -8407,7 +8519,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", - "dev": true, "requires": { "graceful-fs": "^4.1.6" } @@ -9176,6 +9287,15 @@ "readable-stream": "^2.0.2" } }, + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -9384,36 +9504,6 @@ "integrity": "sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=", "dev": true }, - "load-json-file": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", - "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0", - "strip-bom": "^2.0.0" - }, - "dependencies": { - "parse-json": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", - "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "dev": true, - "requires": { - "error-ex": "^1.2.0" - } - }, - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - } - } - }, "loader-runner": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.4.0.tgz", @@ -9524,16 +9614,6 @@ "js-tokens": "^3.0.0 || ^4.0.0" } }, - "loud-rejection": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", - "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", - "dev": true, - "requires": { - "currently-unhandled": "^0.4.1", - "signal-exit": "^3.0.0" - } - }, "lowercase-keys": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", @@ -9643,12 +9723,6 @@ "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", "dev": true }, - "map-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", - "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", - "dev": true - }, "map-visit": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", @@ -9658,6 +9732,25 @@ "object-visit": "^1.0.0" } }, + "matcher": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/matcher/-/matcher-2.0.0.tgz", + "integrity": "sha512-nlmfSlgHBFx36j/Pl/KQPbIaqE8Zf0TqmSMjsuddHDg6PMSVgmyW9HpkLs0o0M1n2GIZ/S2BZBLIww/xjhiGng==", + "dev": true, + "optional": true, + "requires": { + "escape-string-regexp": "^2.0.0" + }, + "dependencies": { + "escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true, + "optional": true + } + } + }, "md5.js": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", @@ -9702,24 +9795,6 @@ "integrity": "sha1-htcJCzDORV1j+64S3aUaR93K+bI=", "dev": true }, - "meow": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", - "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", - "dev": true, - "requires": { - "camelcase-keys": "^2.0.0", - "decamelize": "^1.1.2", - "loud-rejection": "^1.0.0", - "map-obj": "^1.0.1", - "minimist": "^1.1.3", - "normalize-package-data": "^2.3.4", - "object-assign": "^4.0.1", - "read-pkg-up": "^1.0.1", - "redent": "^1.0.0", - "trim-newlines": "^1.0.0" - } - }, "merge-descriptors": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", @@ -9987,7 +10062,6 @@ "version": "0.5.1", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", - "dev": true, "requires": { "minimist": "0.0.8" }, @@ -9995,8 +10069,7 @@ "minimist": { "version": "0.0.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", - "dev": true + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" } } }, @@ -10018,6 +10091,17 @@ "mkdirp": "^0.5.1", "rimraf": "^2.5.4", "run-queue": "^1.0.3" + }, + "dependencies": { + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + } } }, "ms": { @@ -10373,6 +10457,26 @@ "integrity": "sha512-8/JCaftHwbd//k6y2rEWp6k1wxVfpFzB6t1p825+cUb7Ym2XQfhwIC5KwhrvzZRJu+LtDE585zVaS32+CGtf0g==", "dev": true }, + "npm-conf": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/npm-conf/-/npm-conf-1.1.3.tgz", + "integrity": "sha512-Yic4bZHJOt9RCFbRP3GgpqhScOY4HH3V2P8yBj6CeYq118Qr+BLXqT2JvpJ00mryLESpgOxf5XlFv4ZjXxLScw==", + "dev": true, + "optional": true, + "requires": { + "config-chain": "^1.1.11", + "pify": "^3.0.0" + }, + "dependencies": { + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true, + "optional": true + } + } + }, "npm-package-arg": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-6.1.0.tgz", @@ -10508,38 +10612,6 @@ "path-key": "^2.0.0" } }, - "nugget": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/nugget/-/nugget-2.0.1.tgz", - "integrity": "sha1-IBCVpIfhrTYIGzQy+jytpPjQcbA=", - "dev": true, - "requires": { - "debug": "^2.1.3", - "minimist": "^1.1.0", - "pretty-bytes": "^1.0.2", - "progress-stream": "^1.1.0", - "request": "^2.45.0", - "single-line-log": "^1.1.2", - "throttleit": "0.0.2" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } - } - }, "null-check": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/null-check/-/null-check-1.0.0.tgz", @@ -10910,6 +10982,15 @@ "semver": "^5.4.1" } }, + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, "semver": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", @@ -11368,16 +11449,6 @@ "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=", "dev": true }, - "pretty-bytes": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-1.0.4.tgz", - "integrity": "sha1-CiLoIQYJrTVUL4yNXSFZr/B1HIQ=", - "dev": true, - "requires": { - "get-stdin": "^4.0.1", - "meow": "^3.1.0" - } - }, "private": { "version": "0.1.8", "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", @@ -11396,67 +11467,6 @@ "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", "dev": true }, - "progress-stream": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/progress-stream/-/progress-stream-1.2.0.tgz", - "integrity": "sha1-LNPP6jO6OonJwSHsM0er6asSX3c=", - "dev": true, - "requires": { - "speedometer": "~0.1.2", - "through2": "~0.2.3" - }, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "object-keys": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-0.4.0.tgz", - "integrity": "sha1-KKaq50KN0sOpLz2V8hM13SBOAzY=", - "dev": true - }, - "readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - }, - "through2": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/through2/-/through2-0.2.3.tgz", - "integrity": "sha1-6zKE2k6jEbbMis42U3SKUqvyWj8=", - "dev": true, - "requires": { - "readable-stream": "~1.1.9", - "xtend": "~2.1.1" - } - }, - "xtend": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz", - "integrity": "sha1-bv7MKk2tjmlixJAbM3znuoe10os=", - "dev": true, - "requires": { - "object-keys": "~0.4.0" - } - } - } - }, "promise": { "version": "7.3.1", "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", @@ -11491,6 +11501,13 @@ } } }, + "proto-list": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", + "integrity": "sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk=", + "dev": true, + "optional": true + }, "protoduck": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/protoduck/-/protoduck-5.0.1.tgz", @@ -11555,6 +11572,17 @@ "pify": "^2.0.0", "pinkie-promise": "^2.0.0", "rimraf": "^2.2.8" + }, + "dependencies": { + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + } } }, "globby": { @@ -11645,6 +11673,17 @@ "rimraf": "^2.5.2", "semver": "^5.3.0", "xml2js": "^0.4.17" + }, + "dependencies": { + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + } } } } @@ -11957,65 +11996,6 @@ } } }, - "read-pkg-up": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", - "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", - "dev": true, - "requires": { - "find-up": "^1.0.0", - "read-pkg": "^1.0.0" - }, - "dependencies": { - "find-up": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", - "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", - "dev": true, - "requires": { - "path-exists": "^2.0.0", - "pinkie-promise": "^2.0.0" - } - }, - "path-exists": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", - "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", - "dev": true, - "requires": { - "pinkie-promise": "^2.0.0" - } - }, - "path-type": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", - "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" - } - }, - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - }, - "read-pkg": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", - "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", - "dev": true, - "requires": { - "load-json-file": "^1.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^1.0.0" - } - } - } - }, "readable-stream": { "version": "2.3.6", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", @@ -12052,16 +12032,6 @@ "picomatch": "^2.0.4" } }, - "redent": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", - "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=", - "dev": true, - "requires": { - "indent-string": "^2.1.0", - "strip-indent": "^1.0.1" - } - }, "reflect-metadata": { "version": "0.1.13", "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz", @@ -12343,9 +12313,9 @@ "dev": true }, "rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.0.tgz", + "integrity": "sha512-NDGVxTsjqfunkds7CqsOiEnxln4Bo7Nddl3XhS4pXg5OzwkLqJ971ZVAAnB+DDLnF76N+VnDEiBHaVV8I06SUg==", "dev": true, "requires": { "glob": "^7.1.3" @@ -12361,6 +12331,30 @@ "inherits": "^2.0.1" } }, + "roarr": { + "version": "2.14.5", + "resolved": "https://registry.npmjs.org/roarr/-/roarr-2.14.5.tgz", + "integrity": "sha512-jwwW1NEYh06O+teTDJt4ETtLdxb3BBir0vThgQQGz88bYypRv69jQhMVRKI8Ps/6LeqsRBGe28V3Awjy38LFoQ==", + "dev": true, + "optional": true, + "requires": { + "boolean": "^2.0.3", + "detect-node": "^2.0.4", + "globalthis": "^1.0.0", + "json-stringify-safe": "^5.0.1", + "semver-compare": "^1.0.0", + "sprintf-js": "^1.1.2" + }, + "dependencies": { + "sprintf-js": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.2.tgz", + "integrity": "sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==", + "dev": true, + "optional": true + } + } + }, "rollup": { "version": "1.21.4", "resolved": "https://registry.npmjs.org/rollup/-/rollup-1.21.4.tgz", @@ -12468,7 +12462,6 @@ "version": "6.5.3", "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.3.tgz", "integrity": "sha512-wuYsAYYFdWTAnAaPoKGNhfpWwKZbJW+HgAJ+mImp+Epl7BG8oNWBCTyRM8gba9k4lk8BgWdoYm21Mo/RYhhbgA==", - "dev": true, "requires": { "tslib": "^1.9.0" } @@ -12577,6 +12570,15 @@ "xml2js": "^0.4.17" }, "dependencies": { + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, "tmp": { "version": "0.0.30", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.30.tgz", @@ -12603,6 +12605,13 @@ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true }, + "semver-compare": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", + "integrity": "sha1-De4hahyUGrN+nvsXiPavxf9VN/w=", + "dev": true, + "optional": true + }, "semver-diff": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-2.1.0.tgz", @@ -12700,6 +12709,25 @@ } } }, + "serialize-error": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-5.0.0.tgz", + "integrity": "sha512-/VtpuyzYf82mHYTtI4QKtwHa79vAdU5OQpNPAmE/0UDdlGT0ZxHwC+J6gXkw29wwoVI8fMPsfcVHOwXtUQYYQA==", + "dev": true, + "optional": true, + "requires": { + "type-fest": "^0.8.0" + }, + "dependencies": { + "type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true, + "optional": true + } + } + }, "serialize-javascript": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-1.9.1.tgz", @@ -12867,37 +12895,6 @@ "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", "dev": true }, - "single-line-log": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/single-line-log/-/single-line-log-1.1.2.tgz", - "integrity": "sha1-wvg/Jzo+GhbtsJlWYdoO1e8DM2Q=", - "dev": true, - "requires": { - "string-width": "^1.0.1" - }, - "dependencies": { - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - } - } - }, "slash": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", @@ -13407,12 +13404,6 @@ "chalk": "^2.0.1" } }, - "speedometer": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/speedometer/-/speedometer-0.1.4.tgz", - "integrity": "sha1-mHbb0qFp0xFUAtSObqYynIgWpQ0=", - "dev": true - }, "split-string": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", @@ -13652,30 +13643,12 @@ "ansi-regex": "^2.0.0" } }, - "strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "dev": true, - "requires": { - "is-utf8": "^0.2.0" - } - }, "strip-eof": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", "dev": true }, - "strip-indent": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", - "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", - "dev": true, - "requires": { - "get-stdin": "^4.0.1" - } - }, "strip-json-comments": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", @@ -13755,29 +13728,12 @@ } }, "sumchecker": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/sumchecker/-/sumchecker-2.0.2.tgz", - "integrity": "sha1-D0LBDl0F2l1C7qPlbDOZo31sWz4=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/sumchecker/-/sumchecker-3.0.0.tgz", + "integrity": "sha512-yreseuC/z4iaodVoq07XULEOO9p4jnQazO7mbrnDSvWAU/y2cbyIKs+gWJptfcGu9R+1l27K8Rkj0bfvqnBpgQ==", "dev": true, "requires": { - "debug": "^2.2.0" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } + "debug": "^4.1.0" } }, "supports-color": { @@ -13953,12 +13909,6 @@ } } }, - "throttleit": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-0.0.2.tgz", - "integrity": "sha1-z+34jmDADdlpe2H90qg0OptoDq8=", - "dev": true - }, "through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", @@ -14094,12 +14044,6 @@ "integrity": "sha512-4hjqbObwlh2dLyW4tcz0Ymw0ggoaVDMveUB9w8kFSQScdRLo0gxO9J7WFcUBo+W3C1TLdFIEwNOWebgZZ0RH9Q==", "dev": true }, - "trim-newlines": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", - "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=", - "dev": true - }, "trim-right": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", @@ -14197,6 +14141,13 @@ "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=", "dev": true }, + "tunnel": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", + "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==", + "dev": true, + "optional": true + }, "tunnel-agent": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", @@ -14373,8 +14324,7 @@ "universalify": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", - "dev": true + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==" }, "unpipe": { "version": "1.0.0", @@ -15387,6 +15337,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", diff --git a/package.json b/package.json index 2253cb4..5770fb0 100644 --- a/package.json +++ b/package.json @@ -2,21 +2,31 @@ "name": "ucap-webmessenger", "version": "0.0.0", "scripts": { + "postinstall": "electron-builder install-app-deps", "ng": "ng", "start": "npm-run-all -p start:renderer start:main", - "start:main": "wait-on http-get://localhost:4200/ && npm run build:main:dev && electron --nolazy --inspect-brk=9229 .", - "start:renderer": "ng serve", - "start:web": "cross-env UCAP_ENV=WEB ng serve", - "start:production": "npm run build:renderer && npm run build:main:prod && electron --nolazy --inspect-brk=9229 .", - "build:renderer": "cross-env NODE_ENV=production ng build --base-href ./", - "build:main:dev": "cross-env NODE_ENV=development TS_NODE_PROJECT='./config/tsconfig.webpack.json' parallel-webpack --config=config/main.webpack.config.ts", - "build:main:prod": "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", + "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 -c renderer-development --base-href ./", + "build:browser": "cross-env UCAP_ENV_RUNTIME=BROWSER ng build -c browser-development --base-href ./NextMessenger_POC", + "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", + "electron:local": "electron .", + "electron:windows": "npm run build && electron-builder build --windows", + "electron:mac": "npm run build && electron-builder build --mac", + "electron:linux": "npm run build && electron-builder build --linux", "test": "ng test", "lint": "ng lint", "e2e": "ng e2e" }, "private": true, "dependencies": { + "@angular/core": "~8.2.12", + "electron-window-state": "^5.0.3", + "fs-extra": "^8.1.0", + "rxjs": "^6.5.2", "tslib": "^1.10.0" }, "devDependencies": { @@ -29,7 +39,6 @@ "@angular/common": "~8.2.12", "@angular/compiler": "~8.2.12", "@angular/compiler-cli": "~8.2.12", - "@angular/core": "~8.2.12", "@angular/flex-layout": "^8.0.0-beta.27", "@angular/forms": "~8.2.12", "@angular/language-service": "~8.2.12", @@ -60,8 +69,11 @@ "@types/webpack": "^4.39.5", "@types/webpack-merge": "^4.1.5", "@types/webpack-node-externals": "^1.6.3", + "angular-split": "^3.0.2", + "autolinker": "^3.11.1", "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", @@ -70,17 +82,15 @@ "cross-env": "^5.2.1", "detect-browser": "^4.6.0", "devtron": "^1.4.0", - "electron": "^6.1.2", + "electron": "^7.1.1", "electron-builder": "^21.2.0", "electron-debug": "^3.0.1", "electron-devtools-installer": "^2.2.4", - "electron-log": "^3.0.8", + "electron-log": "^3.0.9", "electron-reload": "^1.5.0", - "electron-store": "^4.0.0", - "electron-updater": "^4.1.2", - "electron-window-state": "^5.0.3", + "electron-store": "^5.1.0", + "electron-updater": "^4.2.0", "file-saver": "^2.0.2", - "fs-extra": "^8.1.0", "filesize": "^4.1.2", "hammerjs": "^2.0.8", "jasmine-core": "~3.4.0", @@ -95,11 +105,11 @@ "ngrx-store-freeze": "^0.2.4", "ngx-logger": "^4.0.5", "ngx-perfect-scrollbar": "^8.0.0", + "rimraf": "^3.0.0", "npm-run-all": "^4.1.5", "parallel-webpack": "^2.4.0", "protractor": "~5.4.0", "queueing-subject": "^0.3.4", - "rxjs": "^6.5.2", "semver": "^6.3.0", "ts-node": "~7.0.0", "tsickle": "^0.37.0", @@ -107,10 +117,11 @@ "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", "zone.js": "~0.9.1" }, - "main": "./dist/main/main.js" + "main": "./dist/ucap-webmessenger-electron/main.js" } diff --git a/projects/ucap-webmessenger-api-common/src/lib/config/module-config.ts b/projects/ucap-webmessenger-api-common/src/lib/config/module-config.ts new file mode 100644 index 0000000..4364908 --- /dev/null +++ b/projects/ucap-webmessenger-api-common/src/lib/config/module-config.ts @@ -0,0 +1,7 @@ +import { ModuleConfig as CoreModuleConfig } from '@ucap-webmessenger/core'; + +import { Urls } from './urls'; + +export interface ModuleConfig extends CoreModuleConfig { + acceptableFileExtensions: string[]; +} diff --git a/projects/ucap-webmessenger-api-common/src/lib/types/token.ts b/projects/ucap-webmessenger-api-common/src/lib/config/token.ts similarity index 100% rename from projects/ucap-webmessenger-api-common/src/lib/types/token.ts rename to projects/ucap-webmessenger-api-common/src/lib/config/token.ts diff --git a/projects/ucap-webmessenger-api-common/src/lib/config/urls.ts b/projects/ucap-webmessenger-api-common/src/lib/config/urls.ts new file mode 100644 index 0000000..0c61bd5 --- /dev/null +++ b/projects/ucap-webmessenger-api-common/src/lib/config/urls.ts @@ -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; +} diff --git a/projects/ucap-webmessenger-api-common/src/lib/services/common-api.service.ts b/projects/ucap-webmessenger-api-common/src/lib/services/common-api.service.ts index f67b1c9..00a1443 100644 --- a/projects/ucap-webmessenger-api-common/src/lib/services/common-api.service.ts +++ b/projects/ucap-webmessenger-api-common/src/lib/services/common-api.service.ts @@ -9,8 +9,6 @@ import { 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, @@ -71,14 +69,26 @@ import { 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' }) 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,9 +96,7 @@ export class CommonApiService { ): Observable { return this.httpClient .post( - !!fileProfileSaveUrl - ? fileProfileSaveUrl - : this.moduleConfig.urls.fileProfileSave, + !!fileProfileSaveUrl ? fileProfileSaveUrl : this.urls.fileProfileSave, {}, { params: encodeFileProfileSave(req) @@ -103,9 +111,7 @@ export class CommonApiService { ): string { const httpReq = new HttpRequest( 'GET', - !!fileTalkDownloadUrl - ? fileTalkDownloadUrl - : this.moduleConfig.urls.fileTalkDownload, + !!fileTalkDownloadUrl ? fileTalkDownloadUrl : this.urls.fileTalkDownload, {}, { params: encodeFileTalkDownload(req) @@ -121,9 +127,7 @@ export class CommonApiService { ): Observable { 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 { const httpReq = new HttpRequest( 'POST', - !!fileTalkSaveUrl ? fileTalkSaveUrl : this.moduleConfig.urls.fileTalkSave, + !!fileTalkSaveUrl ? fileTalkSaveUrl : this.urls.fileTalkSave, encodeFileTalkSave(req), { reportProgress: true, responseType: 'text' as 'json' } ); @@ -182,15 +186,26 @@ export class CommonApiService { ); } - public acceptableExtensionForFileTalk(extensions: string[]): boolean { + public acceptableExtensionForFileTalk( + extensions: string[] + ): { accept: boolean; reject: string[] } { + let accept = true; + const reject: string[] = []; for (const extension of extensions) { if ( - -1 === this.moduleConfig.acceptableFileExtensions.indexOf(extension.toLowerCase()) + -1 === + this.moduleConfig.acceptableFileExtensions.indexOf( + extension.toLowerCase() + ) ) { - return false; + reject.push(extension); + accept = false; } } - return true; + return { + accept, + reject + }; } public fileTalkShare( @@ -198,7 +213,7 @@ export class CommonApiService { ): Observable { return this.httpClient .post( - this.moduleConfig.urls.fileTalkShare, + this.urls.fileTalkShare, {}, { params: encodeFileTalkShare(req) @@ -212,7 +227,7 @@ export class CommonApiService { ): Observable { return this.httpClient .post( - this.moduleConfig.urls.massTalkDownload, + this.urls.massTalkDownload, {}, { params: encodeMassTalkDownload(req), @@ -227,7 +242,7 @@ export class CommonApiService { ): Observable { return this.httpClient .post( - this.moduleConfig.urls.massTalkSave, + this.urls.massTalkSave, {}, { params: encodeMassTalkSave(req), @@ -242,7 +257,7 @@ export class CommonApiService { ): Observable { return this.httpClient .post( - this.moduleConfig.urls.transMassTalkDownload, + this.urls.transMassTalkDownload, {}, { params: encodeTransMassTalkDownload(req) @@ -256,7 +271,7 @@ export class CommonApiService { ): Observable { return this.httpClient .post( - this.moduleConfig.urls.transMassTalkSave, + this.urls.transMassTalkSave, {}, { params: encodeTransMassTalkSave(req) @@ -270,7 +285,7 @@ export class CommonApiService { ): Observable { return this.httpClient .post( - this.moduleConfig.urls.translationReq, + this.urls.translationReq, {}, { params: encodeTranslationReq(req) @@ -284,7 +299,7 @@ export class CommonApiService { ): Observable { return this.httpClient .post( - this.moduleConfig.urls.translationSave, + this.urls.translationSave, {}, { params: encodeTranslationSave(req) diff --git a/projects/ucap-webmessenger-api-common/src/lib/types/module-config.ts b/projects/ucap-webmessenger-api-common/src/lib/types/module-config.ts deleted file mode 100644 index 8728921..0000000 --- a/projects/ucap-webmessenger-api-common/src/lib/types/module-config.ts +++ /dev/null @@ -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[]; -} diff --git a/projects/ucap-webmessenger-api-common/src/lib/ucap-common-api.module.ts b/projects/ucap-webmessenger-api-common/src/lib/ucap-common-api.module.ts index 3e3baff..2292850 100644 --- a/projects/ucap-webmessenger-api-common/src/lib/ucap-common-api.module.ts +++ b/projects/ucap-webmessenger-api-common/src/lib/ucap-common-api.module.ts @@ -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 { return { ngModule: UCapCommonApiModule, - providers: [{ provide: _MODULE_CONFIG, useValue: config }, ...SERVICES] + providers: [{ provide: _MODULE_CONFIG, useValue: config }, ...SERVICES], }; } } diff --git a/projects/ucap-webmessenger-api-common/src/public-api.ts b/projects/ucap-webmessenger-api-common/src/public-api.ts index 0a47d28..82e0038 100644 --- a/projects/ucap-webmessenger-api-common/src/public-api.ts +++ b/projects/ucap-webmessenger-api-common/src/public-api.ts @@ -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'; diff --git a/projects/ucap-webmessenger-api-external/src/lib/config/module-config.ts b/projects/ucap-webmessenger-api-external/src/lib/config/module-config.ts new file mode 100644 index 0000000..7091509 --- /dev/null +++ b/projects/ucap-webmessenger-api-external/src/lib/config/module-config.ts @@ -0,0 +1,5 @@ +import { ModuleConfig as CoreModuleConfig } from '@ucap-webmessenger/core'; + +import { Urls } from './urls'; + +export interface ModuleConfig extends CoreModuleConfig {} diff --git a/projects/ucap-webmessenger-api-external/src/lib/types/token.ts b/projects/ucap-webmessenger-api-external/src/lib/config/token.ts similarity index 100% rename from projects/ucap-webmessenger-api-external/src/lib/types/token.ts rename to projects/ucap-webmessenger-api-external/src/lib/config/token.ts diff --git a/projects/ucap-webmessenger-api-external/src/lib/config/urls.ts b/projects/ucap-webmessenger-api-external/src/lib/config/urls.ts new file mode 100644 index 0000000..850d22d --- /dev/null +++ b/projects/ucap-webmessenger-api-external/src/lib/config/urls.ts @@ -0,0 +1,6 @@ +export interface Urls { + checkUserInfoEx: string; + companyList: string; + tokenUpdate: string; + urlInfo: string; +} diff --git a/projects/ucap-webmessenger-api-external/src/lib/services/external-api.service.ts b/projects/ucap-webmessenger-api-external/src/lib/services/external-api.service.ts index a4730ad..5da6b02 100644 --- a/projects/ucap-webmessenger-api-external/src/lib/services/external-api.service.ts +++ b/projects/ucap-webmessenger-api-external/src/lib/services/external-api.service.ts @@ -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 { return this.httpClient .post( - 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 { return this.httpClient .post( - 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 { return this.httpClient .post( - 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 { return this.httpClient .post( - this.moduleConfig.urls.urlInfo, + this.urls.urlInfo, {}, { - params: encodeUrlInfo(req) + params: encodeUrlInfo(req), } ) .pipe(map(res => decodeUrlInfo(res))); diff --git a/projects/ucap-webmessenger-api-external/src/lib/types/module-config.ts b/projects/ucap-webmessenger-api-external/src/lib/types/module-config.ts deleted file mode 100644 index 6b3b036..0000000 --- a/projects/ucap-webmessenger-api-external/src/lib/types/module-config.ts +++ /dev/null @@ -1,8 +0,0 @@ -export interface ModuleConfig { - urls: { - checkUserInfoEx: string; - companyList: string; - tokenUpdate: string; - urlInfo: string; - }; -} diff --git a/projects/ucap-webmessenger-api-external/src/lib/ucap-external-api.module.ts b/projects/ucap-webmessenger-api-external/src/lib/ucap-external-api.module.ts index c21dada..c6283c7 100644 --- a/projects/ucap-webmessenger-api-external/src/lib/ucap-external-api.module.ts +++ b/projects/ucap-webmessenger-api-external/src/lib/ucap-external-api.module.ts @@ -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 { return { ngModule: UCapExternalApiModule, - providers: [{ provide: _MODULE_CONFIG, useValue: config }, ...SERVICES] + providers: [{ provide: _MODULE_CONFIG, useValue: config }, ...SERVICES], }; } } diff --git a/projects/ucap-webmessenger-api-external/src/public-api.ts b/projects/ucap-webmessenger-api-external/src/public-api.ts index b9a5d5a..375f649 100644 --- a/projects/ucap-webmessenger-api-external/src/public-api.ts +++ b/projects/ucap-webmessenger-api-external/src/public-api.ts @@ -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'; diff --git a/projects/ucap-webmessenger-api-message/README.md b/projects/ucap-webmessenger-api-message/README.md new file mode 100644 index 0000000..8265c6c --- /dev/null +++ b/projects/ucap-webmessenger-api-message/README.md @@ -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). diff --git a/projects/ucap-webmessenger-electron-core/karma.conf.js b/projects/ucap-webmessenger-api-message/karma.conf.js similarity index 97% rename from projects/ucap-webmessenger-electron-core/karma.conf.js rename to projects/ucap-webmessenger-api-message/karma.conf.js index 5eed153..30ab22f 100644 --- a/projects/ucap-webmessenger-electron-core/karma.conf.js +++ b/projects/ucap-webmessenger-api-message/karma.conf.js @@ -16,7 +16,7 @@ module.exports = function (config) { clearContext: false // leave Jasmine Spec Runner output visible in browser }, coverageIstanbulReporter: { - dir: require('path').join(__dirname, '../../coverage/ucap-webmessenger-electron-core'), + dir: require('path').join(__dirname, '../../coverage/ucap-webmessenger-api-message'), reports: ['html', 'lcovonly', 'text-summary'], fixWebpackSourcePaths: true }, diff --git a/projects/ucap-webmessenger-electron-core/ng-package.json b/projects/ucap-webmessenger-api-message/ng-package.json similarity index 68% rename from projects/ucap-webmessenger-electron-core/ng-package.json rename to projects/ucap-webmessenger-api-message/ng-package.json index e9e6f76..7b43c75 100644 --- a/projects/ucap-webmessenger-electron-core/ng-package.json +++ b/projects/ucap-webmessenger-api-message/ng-package.json @@ -1,6 +1,6 @@ { "$schema": "../../node_modules/ng-packagr/ng-package.schema.json", - "dest": "../../dist/ucap-webmessenger-electron-core", + "dest": "../../dist/ucap-webmessenger-api-message", "lib": { "entryFile": "src/public-api.ts" } diff --git a/projects/ucap-webmessenger-electron-core/package.json b/projects/ucap-webmessenger-api-message/package.json similarity index 72% rename from projects/ucap-webmessenger-electron-core/package.json rename to projects/ucap-webmessenger-api-message/package.json index a7ad1a3..2bc9d39 100644 --- a/projects/ucap-webmessenger-electron-core/package.json +++ b/projects/ucap-webmessenger-api-message/package.json @@ -1,5 +1,5 @@ { - "name": "@ucap-webmessenger/electron-core", + "name": "@ucap-webmessenger/api-message", "version": "0.0.1", "peerDependencies": { "@angular/common": "^8.2.11", diff --git a/projects/ucap-webmessenger-api-message/src/lib/apis/del.ts b/projects/ucap-webmessenger-api-message/src/lib/apis/del.ts new file mode 100644 index 0000000..16bf092 --- /dev/null +++ b/projects/ucap-webmessenger-api-message/src/lib/apis/del.ts @@ -0,0 +1,31 @@ +import { + APIRequest, + APIResponse, + APIDecoder, + APIJsonEncoder, + MessageAPIResponse +} from '@ucap-webmessenger/api'; +import { DeviceType } from '@ucap-webmessenger/core'; +import { MessageType } from '../types/message.type'; + +export interface DelRequest extends APIRequest { + userSeq: number; + deviceType: DeviceType; + tokenKey: string; + type: MessageType; + + msgList: { msgId: number }[]; +} + +export interface DelResponse extends MessageAPIResponse {} + +export const encodeDel: APIJsonEncoder = (req: DelRequest) => { + return JSON.stringify(req); +}; + +export const decodeDel: APIDecoder = (res: any) => { + return { + responseCode: res.responseCode, + responseMsg: res.responseMsg + } as DelResponse; +}; diff --git a/projects/ucap-webmessenger-api-message/src/lib/apis/detail.ts b/projects/ucap-webmessenger-api-message/src/lib/apis/detail.ts new file mode 100644 index 0000000..99d3ee4 --- /dev/null +++ b/projects/ucap-webmessenger-api-message/src/lib/apis/detail.ts @@ -0,0 +1,182 @@ +import { + APIRequest, + MessageAPIResponse, + APIDecoder, + APIJsonEncoder +} from '@ucap-webmessenger/api'; +import { DeviceType } from '@ucap-webmessenger/core'; +import { MessageType } from '../types/message.type'; +import { CategoryType } from '../types/category.type'; + +export interface DetailRequest extends APIRequest { + userSeq: number; + deviceType: DeviceType; + tokenKey: string; + type: MessageType; + + msgId: number; +} + +export interface DetailResponse extends MessageAPIResponse { + msgInfo: { + msgId: number; + category: CategoryType; + title: string; + titleYn: boolean; + }; + + content: { + type: MessageType; + sendUserSeq: number; + sendUserName: string; + reservationTime: string | null; + sendYn: boolean; + regDate: string; + attachmentYn: boolean; + smsYn: boolean; + fileAllow: string; + }[]; + + recvList: { + userSeq: number; + userName: string; + cancelYn: boolean; + readDate: string; + readYn: boolean; + }[]; +} + +export const encodeDetail: APIJsonEncoder = ( + req: DetailRequest +) => { + return JSON.stringify(req); +}; + +export const decodeDetail: APIDecoder = (res: any) => { + return { + responseCode: res.responseCode, + responseMsg: res.responseMsg, + + msgInfo: null, + + content: [], + + recvList: [] + } as DetailResponse; +}; + +export interface ReadRequest extends APIRequest { + userSeq: number; + deviceType: DeviceType; + tokenKey: string; + type: MessageType; + + msgId: number; +} + +export interface ReadResponse extends MessageAPIResponse {} + +export const encodeRead: APIJsonEncoder = (req: ReadRequest) => { + return JSON.stringify(req); +}; + +export const decodeRead: APIDecoder = (res: any) => { + return { + responseCode: res.responseCode, + responseMsg: res.responseMsg + } as ReadResponse; +}; + +export interface ReadCheckResponse extends MessageAPIResponse { + recvList: { + userSeq: number; + userName: string; + cancelYn: boolean; + readDate: string; + readYn: boolean; + }[]; +} + +export const decodeReadCheck: APIDecoder = (res: any) => { + return { + responseCode: res.responseCode, + responseMsg: res.responseMsg, + + recvList: [] + } as ReadCheckResponse; +}; + +export interface CancelRequest extends APIRequest { + userSeq: number; + deviceType: DeviceType; + tokenKey: string; + type: MessageType; + + msgId: number; + recvUserList: { userSeq: number }[]; +} + +export interface CancelResponse extends MessageAPIResponse {} + +export const encodeCancel: APIJsonEncoder = ( + req: CancelRequest +) => { + return JSON.stringify(req); +}; + +export const decodeCancel: APIDecoder = (res: any) => { + return { + responseCode: res.responseCode, + responseMsg: res.responseMsg + } as CancelResponse; +}; + +export interface CancelReservationRequest extends APIRequest { + userSeq: number; + deviceType: DeviceType; + tokenKey: string; + type: MessageType; + + msgId: number; +} + +export interface CancelReservationResponse extends MessageAPIResponse {} + +export const encodeCancelReservation: APIJsonEncoder = ( + req: CancelReservationRequest +) => { + return JSON.stringify(req); +}; + +export const decodeCancelReservation: APIDecoder = ( + res: any +) => { + return { + responseCode: res.responseCode, + responseMsg: res.responseMsg + } as CancelReservationResponse; +}; + +export interface RetrieveResourceFileRequest extends APIRequest { + userSeq: number; + deviceType: DeviceType; + tokenKey: string; + type: MessageType; + + msgId: number; + resUrl: string; +} + +export interface RetrieveResourceFileResponse extends MessageAPIResponse {} + +export const encodeRetrieveResourceFile: APIJsonEncoder = ( + req: RetrieveResourceFileRequest +) => { + return JSON.stringify(req); +}; + +export const decodeRetrieveResourceFile: APIDecoder = ( + res: any +) => { + return {} as RetrieveResourceFileResponse; +}; diff --git a/projects/ucap-webmessenger-api-message/src/lib/apis/edit-reservation-ex.ts b/projects/ucap-webmessenger-api-message/src/lib/apis/edit-reservation-ex.ts new file mode 100644 index 0000000..c0562cf --- /dev/null +++ b/projects/ucap-webmessenger-api-message/src/lib/apis/edit-reservation-ex.ts @@ -0,0 +1,42 @@ +import { + APIRequest, + MessageAPIResponse, + APIJsonEncoder, + APIDecoder +} from '@ucap-webmessenger/api'; +import { DeviceType } from '@ucap-webmessenger/core'; +import { CategoryType } from '../types/category.type'; +import { ContentType } from '../types/content.type'; + +export interface EditReservationRequest extends APIRequest { + userSeq: number; + deviceType: DeviceType; + tokenKey: string; + msgId: number; + category: CategoryType; + title: string; + titleYn: boolean; + listOrder: ContentType[]; + reservationTime: string; + smsYn: boolean; + + textContent: { text: string }[]; + recvUserList: { userSeq: number; userName: string }[]; +} + +export interface EditReservationResponse extends MessageAPIResponse {} + +export const encodeEditReservation: APIJsonEncoder = ( + req: EditReservationRequest +) => { + return JSON.stringify(req); +}; + +export const decodeEditReservation: APIDecoder = ( + res: any +) => { + return { + responseCode: res.responseCode, + responseMsg: res.responseMsg + } as EditReservationResponse; +}; diff --git a/projects/ucap-webmessenger-api-message/src/lib/apis/my-message.ts b/projects/ucap-webmessenger-api-message/src/lib/apis/my-message.ts new file mode 100644 index 0000000..d112997 --- /dev/null +++ b/projects/ucap-webmessenger-api-message/src/lib/apis/my-message.ts @@ -0,0 +1,104 @@ +import { + APIRequest, + MessageAPIResponse, + APIJsonEncoder, + APIDecoder +} from '@ucap-webmessenger/api'; +import { DeviceType } from '@ucap-webmessenger/core'; + +export interface SaveMyRequest extends APIRequest { + userSeq: number; + deviceType: DeviceType; + tokenKey: string; + userName: string; + message: string; +} + +export interface SaveMyResponse extends MessageAPIResponse {} + +export const encodeSaveMy: APIJsonEncoder = ( + req: SaveMyRequest +) => { + return JSON.stringify(req); +}; + +export const decodeSaveMy: APIDecoder = (res: any) => { + return { + responseCode: res.responseCode, + responseMsg: res.responseMsg + } as SaveMyResponse; +}; + +export interface RetrieveMyRequest extends APIRequest { + userSeq: number; + deviceType: DeviceType; + tokenKey: string; + pageSize: number; + pageCount: number; +} + +export interface RetrieveMyResponse extends MessageAPIResponse { + msgList: { + msgId: number; + message: string; + }[]; +} + +export const encodeRetrieveMy: APIJsonEncoder = ( + req: RetrieveMyRequest +) => { + return JSON.stringify(req); +}; + +export const decodeRetrieveMy: APIDecoder = (res: any) => { + return { + responseCode: res.responseCode, + responseMsg: res.responseMsg, + + msgList: [] + } as RetrieveMyResponse; +}; + +export interface DelMyRequest extends APIRequest { + userSeq: number; + deviceType: DeviceType; + tokenKey: string; +} + +export interface DelMyResponse extends MessageAPIResponse {} + +export const encodeDelMy: APIJsonEncoder = ( + req: DelMyRequest +) => { + return JSON.stringify(req); +}; + +export const decodeDelMy: APIDecoder = (res: any) => { + return { + responseCode: res.responseCode, + responseMsg: res.responseMsg + } as DelMyResponse; +}; + +export interface EditMyRequest extends APIRequest { + userSeq: number; + deviceType: DeviceType; + tokenKey: string; + msgId: number; + message: string; +} + +export interface EditMyResponse extends MessageAPIResponse {} + +export const encodeEditMy: APIJsonEncoder = ( + req: EditMyRequest +) => { + return JSON.stringify(req); +}; + +export const decodeEditMy: APIDecoder = (res: any) => { + return { + responseCode: res.responseCode, + responseMsg: res.responseMsg + } as EditMyResponse; +}; diff --git a/projects/ucap-webmessenger-api-message/src/lib/apis/retrieve.ts b/projects/ucap-webmessenger-api-message/src/lib/apis/retrieve.ts new file mode 100644 index 0000000..bd5b7c6 --- /dev/null +++ b/projects/ucap-webmessenger-api-message/src/lib/apis/retrieve.ts @@ -0,0 +1,181 @@ +import { + APIRequest, + MessageAPIResponse, + APIDecoder, + APIJsonEncoder +} from '@ucap-webmessenger/api'; +import { DeviceType } from '@ucap-webmessenger/core'; +import { MessageType } from '../types/message.type'; +import { MessageList } from '../models/message-list'; +import { CategoryType } from '../types/category.type'; +import { ContentType } from '../types/content.type'; + +export interface RetrieveRequest extends APIRequest { + userSeq: number; + deviceType: DeviceType; + tokenKey: string; + type: MessageType; + pageSize: number; + pageCount: number; +} +export interface RetrieveSearchRequest extends RetrieveRequest { + searchTitle: string; + searchName: string; + searchContent: string; +} + +export interface RetrieveResponse extends MessageAPIResponse { + pageCount: number; + pageSize: number; + totalCount: number; + + messageList: MessageList[]; +} + +export const encodeRetrieve: APIJsonEncoder = ( + req: RetrieveRequest +) => { + return JSON.stringify(req); +}; +export const encodeRetrieveSearch: APIJsonEncoder = ( + req: RetrieveResponse +) => { + return JSON.stringify(req); +}; + +export const decodeRetrieveSend: APIDecoder = (res: any) => { + const messageList: MessageList[] = []; + if (!!res.msgList && res.msgList.length > 0) { + for (const msgList of res.msgList) { + messageList.push({ + ...msgList, + userCount: + !msgList.userCount || msgList.userCount === null + ? 0 + : msgList.userCount, + userReadCount: + !msgList.userReadCount || msgList.userReadCount === null + ? 0 + : msgList.userReadCount, + titleYn: msgList.titleYn === 'Y' ? true : false, + attachmentYn: msgList.attachmentYn === 'Y' ? true : false + } as MessageList); + } + } + + return { + responseCode: res.responseCode, + responseMsg: res.responseMsg, + + pageCount: res.pageCount, + pageSize: res.pageSize, + totalCount: res.totalCount, + + messageList + } as RetrieveResponse; +}; + +export const decodeRetrieveReceive: APIDecoder = ( + res: any +) => { + const messageList: MessageList[] = []; + if (!!res.msgList && res.msgList.length > 0) { + for (const msgList of res.msgList) { + messageList.push({ + ...msgList, + userCount: + !msgList.userCount || msgList.userCount === null + ? 0 + : msgList.userCount, + userReadCount: + !msgList.userReadCount || msgList.userReadCount === null + ? 0 + : msgList.userReadCount, + titleYn: msgList.titleYn === 'Y' ? true : false, + attachmentYn: msgList.attachmentYn === 'Y' ? true : false, + readYn: msgList.readYn === 'Y' ? true : false + } as MessageList); + } + } + + return { + responseCode: res.responseCode, + responseMsg: res.responseMsg, + + pageCount: res.pageCount, + pageSize: res.pageSize, + totalCount: res.totalCount, + + messageList + } as RetrieveResponse; +}; + +export const decodeRetrieveReservation: APIDecoder = ( + res: any +) => { + const messageList: MessageList[] = []; + if (!!res.msgList && res.msgList.length > 0) { + for (const msgList of res.msgList) { + messageList.push({ + ...msgList, + + userCount: + !msgList.userCount || msgList.userCount === null + ? 0 + : msgList.userCount, + userReadCount: + !msgList.userReadCount || msgList.userReadCount === null + ? 0 + : msgList.userReadCount, + titleYn: msgList.titleYn === 'Y' ? true : false, + attachmentYn: msgList.attachmentYn === 'Y' ? true : false + } as MessageList); + } + } + + return { + responseCode: res.responseCode, + responseMsg: res.responseMsg, + + pageCount: res.pageCount, + pageSize: res.pageSize, + totalCount: res.totalCount, + + messageList + } as RetrieveResponse; +}; + +export const decodeRetrieveSearch: APIDecoder = ( + res: any +) => { + const messageList: MessageList[] = []; + if (!!res.msgList && res.msgList.length > 0) { + for (const msgList of res.msgList) { + messageList.push({ + ...msgList, + + userCount: + !msgList.userCount || msgList.userCount === null + ? 0 + : msgList.userCount, + userReadCount: + !msgList.userReadCount || msgList.userReadCount === null + ? 0 + : msgList.userReadCount, + titleYn: msgList.titleYn === 'Y' ? true : false, + attachmentYn: msgList.attachmentYn === 'Y' ? true : false + } as MessageList); + } + } + + return { + responseCode: res.responseCode, + responseMsg: res.responseMsg, + + pageCount: res.pageCount, + pageSize: res.pageSize, + totalCount: res.totalCount, + + messageList + } as RetrieveResponse; +}; diff --git a/projects/ucap-webmessenger-api-message/src/lib/apis/send-copy.ts b/projects/ucap-webmessenger-api-message/src/lib/apis/send-copy.ts new file mode 100644 index 0000000..e61f623 --- /dev/null +++ b/projects/ucap-webmessenger-api-message/src/lib/apis/send-copy.ts @@ -0,0 +1,41 @@ +import { + APIRequest, + MessageAPIResponse, + APIJsonEncoder, + APIDecoder +} from '@ucap-webmessenger/api'; +import { DeviceType } from '@ucap-webmessenger/core'; +import { CategoryType } from '../types/category.type'; +import { ContentType } from '../types/content.type'; + +export interface SendCopyRequest extends APIRequest { + userSeq: number; + deviceType: DeviceType; + tokenKey: string; + userName: string; + msgId: number; + category: CategoryType; + title: string; + titleYn: boolean; + listOrder: ContentType[]; + reservationTime: string; + smsYn: boolean; + + textContent: { text: string }[]; + recvUserList: { userSeq: number; userName: string }[]; +} + +export interface SendCopyResponse extends MessageAPIResponse {} + +export const encodeSendCopy: APIJsonEncoder = ( + req: SendCopyRequest +) => { + return JSON.stringify(req); +}; + +export const decodeSendCopy: APIDecoder = (res: any) => { + return { + responseCode: res.responseCode, + responseMsg: res.responseMsg + } as SendCopyResponse; +}; diff --git a/projects/ucap-webmessenger-api-message/src/lib/apis/send.ts b/projects/ucap-webmessenger-api-message/src/lib/apis/send.ts new file mode 100644 index 0000000..1e97bc0 --- /dev/null +++ b/projects/ucap-webmessenger-api-message/src/lib/apis/send.ts @@ -0,0 +1,41 @@ +import { + APIRequest, + MessageAPIResponse, + APIJsonEncoder, + APIDecoder +} from '@ucap-webmessenger/api'; +import { DeviceType } from '@ucap-webmessenger/core'; +import { MessageType } from '../types/message.type'; +import { CategoryType } from '../types/category.type'; +import { ContentType } from '../types/content.type'; + +export interface SendRequest extends APIRequest { + userSeq: number; + deviceType: DeviceType; + tokenKey: string; + type: MessageType; + + userName: string; + category: CategoryType; + title: string; + titleYn: boolean; + listOrder: ContentType[]; + reservationTime: string; + smsYn: boolean; + + textContent: { text: string }[]; + recvUserList: { userSeq: number; userName: string }[]; +} + +export interface SendResponse extends MessageAPIResponse {} + +export const encodeSend: APIJsonEncoder = (req: SendRequest) => { + return JSON.stringify(req); +}; + +export const decodeSend: APIDecoder = (res: any) => { + return { + responseCode: res.responseCode, + responseMsg: res.responseMsg + } as SendResponse; +}; diff --git a/projects/ucap-webmessenger-api-message/src/lib/apis/unread-count.ts b/projects/ucap-webmessenger-api-message/src/lib/apis/unread-count.ts new file mode 100644 index 0000000..75db2a2 --- /dev/null +++ b/projects/ucap-webmessenger-api-message/src/lib/apis/unread-count.ts @@ -0,0 +1,33 @@ +import { + APIRequest, + MessageAPIResponse, + APIJsonEncoder, + APIDecoder +} from '@ucap-webmessenger/api'; +import { DeviceType } from '@ucap-webmessenger/core'; + +export interface UnreadCountRequest extends APIRequest { + userSeq: number; + deviceType: DeviceType; + tokenKey: string; +} + +export interface UnreadCountResponse extends MessageAPIResponse { + unreadCount: number; +} + +export const encodeUnreadCount: APIJsonEncoder = ( + req: UnreadCountRequest +) => { + return JSON.stringify(req); +}; + +export const decodeUnreadCount: APIDecoder = ( + res: any +) => { + return { + responseCode: res.responseCode, + responseMsg: res.responseMsg, + unreadCount: res.unreadCount + } as UnreadCountResponse; +}; diff --git a/projects/ucap-webmessenger-api-message/src/lib/config/module-config.ts b/projects/ucap-webmessenger-api-message/src/lib/config/module-config.ts new file mode 100644 index 0000000..7091509 --- /dev/null +++ b/projects/ucap-webmessenger-api-message/src/lib/config/module-config.ts @@ -0,0 +1,5 @@ +import { ModuleConfig as CoreModuleConfig } from '@ucap-webmessenger/core'; + +import { Urls } from './urls'; + +export interface ModuleConfig extends CoreModuleConfig {} diff --git a/projects/ucap-webmessenger-api-message/src/lib/config/token.ts b/projects/ucap-webmessenger-api-message/src/lib/config/token.ts new file mode 100644 index 0000000..95f75df --- /dev/null +++ b/projects/ucap-webmessenger-api-message/src/lib/config/token.ts @@ -0,0 +1,5 @@ +import { InjectionToken } from '@angular/core'; + +export const _MODULE_CONFIG = new InjectionToken( + '@ucap-webmessenger/api-message config of module' +); diff --git a/projects/ucap-webmessenger-api-message/src/lib/config/urls.ts b/projects/ucap-webmessenger-api-message/src/lib/config/urls.ts new file mode 100644 index 0000000..78f47ae --- /dev/null +++ b/projects/ucap-webmessenger-api-message/src/lib/config/urls.ts @@ -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; +} diff --git a/projects/ucap-webmessenger-api-message/src/lib/models/message-list.ts b/projects/ucap-webmessenger-api-message/src/lib/models/message-list.ts new file mode 100644 index 0000000..3d34e52 --- /dev/null +++ b/projects/ucap-webmessenger-api-message/src/lib/models/message-list.ts @@ -0,0 +1,34 @@ +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; + /** 예약시간 :: DATE 형식은 "yyyy-MM-dd HH:mm:ss" (단 초는 00고정. 예약메일은 분단위까지만) */ + reservationTime?: string; + /** 발신시간 */ + regDate: string; + /** CONTENT 타입 */ + resType: ContentType; + /** 첨부파일 존재여부 */ + attachmentYn: boolean; + /** 읽음여부 */ + readYn?: boolean; +} diff --git a/projects/ucap-webmessenger-api-message/src/lib/services/message-api.service.spec.ts b/projects/ucap-webmessenger-api-message/src/lib/services/message-api.service.spec.ts new file mode 100644 index 0000000..bf2baae --- /dev/null +++ b/projects/ucap-webmessenger-api-message/src/lib/services/message-api.service.spec.ts @@ -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(); + }); +}); diff --git a/projects/ucap-webmessenger-api-message/src/lib/services/message-api.service.ts b/projects/ucap-webmessenger-api-message/src/lib/services/message-api.service.ts new file mode 100644 index 0000000..444ca0c --- /dev/null +++ b/projects/ucap-webmessenger-api-message/src/lib/services/message-api.service.ts @@ -0,0 +1,293 @@ +import { Injectable, Inject } from '@angular/core'; +import { HttpClient, HttpHeaders } 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, + RetrieveResponse, + encodeRetrieve, + decodeRetrieveSend, + decodeRetrieveReceive, + decodeRetrieveReservation, + RetrieveSearchRequest, + decodeRetrieveSearch +} from '../apis/retrieve'; +import { + SendRequest, + SendResponse, + encodeSend, + decodeSend +} from '../apis/send'; +import { + DetailRequest, + DetailResponse, + encodeDetail, + decodeDetail, + ReadRequest, + ReadResponse, + encodeRead, + decodeRead, + ReadCheckResponse, + decodeReadCheck, + CancelRequest, + CancelResponse, + encodeCancel, + decodeCancel, + CancelReservationRequest, + CancelReservationResponse, + encodeCancelReservation, + decodeCancelReservation, + RetrieveResourceFileRequest, + RetrieveResourceFileResponse, + encodeRetrieveResourceFile, + decodeRetrieveResourceFile +} from '../apis/detail'; +import { DelRequest, DelResponse, decodeDel, encodeDel } from '../apis/del'; +import { + SaveMyRequest, + SaveMyResponse, + encodeSaveMy, + decodeSaveMy, + RetrieveMyRequest, + RetrieveMyResponse, + encodeRetrieveMy, + decodeRetrieveMy, + DelMyRequest, + DelMyResponse, + encodeDelMy, + decodeDelMy, + EditMyRequest, + EditMyResponse, + encodeEditMy, + decodeEditMy +} from '../apis/my-message'; +import { + EditReservationRequest, + EditReservationResponse, + encodeEditReservation, + decodeEditReservation +} from '../apis/edit-reservation-ex'; +import { + SendCopyRequest, + SendCopyResponse, + encodeSendCopy, + decodeSendCopy +} from '../apis/send-copy'; +import { + UnreadCountRequest, + UnreadCountResponse, + encodeUnreadCount, + decodeUnreadCount +} from '../apis/unread-count'; + +@Injectable({ + providedIn: 'root' +}) +export class MessageApiService { + readonly urls: Urls; + + headers: HttpHeaders; + + constructor( + @Inject(_MODULE_CONFIG) private moduleConfig: ModuleConfig, + private httpClient: HttpClient + ) { + this.urls = UrlConfig.getUrls( + this.moduleConfig.hostConfig, + this.moduleConfig.urls + ); + + this.headers = new HttpHeaders({ + 'Content-Type': 'application/json; charset=utf-8' + }); + } + + /** retrieve */ + public retrieveSendMessage( + req: RetrieveRequest + ): Observable { + return this.httpClient + .post(this.urls.retrieveSendMessageList, encodeRetrieve(req), { + headers: this.headers + }) + .pipe(map(res => decodeRetrieveSend(res))); + } + public retrieveReceiveMessage( + req: RetrieveRequest + ): Observable { + return this.httpClient + .post(this.urls.retrieveRecvMessageList, encodeRetrieve(req), { + headers: this.headers + }) + .pipe(map(res => decodeRetrieveReceive(res))); + } + public retrieveReservationMessage( + req: RetrieveRequest + ): Observable { + return this.httpClient + .post( + this.urls.retrieveReservationMessageList, + encodeRetrieve(req), + { + headers: this.headers + } + ) + .pipe(map(res => decodeRetrieveReservation(res))); + } + public retrieveSearchMessage( + req: RetrieveSearchRequest + ): Observable { + return this.httpClient + .post(this.urls.retrieveSearchMessage, encodeRetrieve(req), { + headers: this.headers + }) + .pipe(map(res => decodeRetrieveSearch(res))); + } + + /** send */ + public sendMessage(req: SendRequest): Observable { + return this.httpClient + .post(this.urls.sendNewMessage, encodeSend(req), { + headers: this.headers + }) + .pipe(map(res => decodeSend(res))); + } + + /** detail */ + public detailMessage(req: DetailRequest): Observable { + return this.httpClient + .post(this.urls.retrieveMessageDetail, encodeDetail(req), { + headers: this.headers + }) + .pipe(map(res => decodeDetail(res))); + } + public readMessage(req: ReadRequest): Observable { + return this.httpClient + .post(this.urls.readMessage, encodeRead(req), { + headers: this.headers + }) + .pipe(map(res => decodeRead(res))); + } + public retrieveReadCheck(req: ReadRequest): Observable { + return this.httpClient + .post(this.urls.retrieveReadCheck, encodeRead(req), { + headers: this.headers + }) + .pipe(map(res => decodeReadCheck(res))); + } + public cancelMessage(req: CancelRequest): Observable { + return this.httpClient + .post(this.urls.cancelMessage, encodeCancel(req), { + headers: this.headers + }) + .pipe(map(res => decodeCancel(res))); + } + public cancelReservationMessage( + req: CancelReservationRequest + ): Observable { + return this.httpClient + .post( + this.urls.cancelReservationMessage, + encodeCancelReservation(req), + { + headers: this.headers + } + ) + .pipe(map(res => decodeCancelReservation(res))); + } + public retrieveResourceFile( + req: RetrieveResourceFileRequest + ): Observable { + return this.httpClient + .post( + this.urls.retrieveResourceFile, + encodeRetrieveResourceFile(req), + { + headers: this.headers + } + ) + .pipe(map(res => decodeRetrieveResourceFile(res))); + } + + /** del */ + public deleteMessage(req: DelRequest): Observable { + return this.httpClient + .post(this.urls.deleteMessage, encodeDel(req), { + headers: this.headers + }) + .pipe(map(res => decodeDel(res))); + } + + /** save my message */ + public saveMyMessage(req: SaveMyRequest): Observable { + return this.httpClient + .post(this.urls.saveMyMessage, encodeSaveMy(req), { + headers: this.headers + }) + .pipe(map(res => decodeSaveMy(res))); + } + public retrieveMyMessage( + req: RetrieveMyRequest + ): Observable { + return this.httpClient + .post(this.urls.retrieveMyMessage, encodeRetrieveMy(req), { + headers: this.headers + }) + .pipe(map(res => decodeRetrieveMy(res))); + } + public deleteMyMessage(req: DelMyRequest): Observable { + return this.httpClient + .post(this.urls.deleteMyMessage, encodeDelMy(req), { + headers: this.headers + }) + .pipe(map(res => decodeDelMy(res))); + } + public editMyMessage(req: EditMyRequest): Observable { + return this.httpClient + .post(this.urls.editMyMessage, encodeEditMy(req), { + headers: this.headers + }) + .pipe(map(res => decodeEditMy(res))); + } + + /** edit reservation */ + public editReservationMessageEx( + req: EditReservationRequest + ): Observable { + return this.httpClient + .post( + this.urls.editReservationMessageEx, + encodeEditReservation(req), + { + headers: this.headers + } + ) + .pipe(map(res => decodeEditReservation(res))); + } + + /** send-copy(forward) */ + public sendCopyMessage(req: SendCopyRequest): Observable { + return this.httpClient + .post(this.urls.sendCopyMessage, encodeSendCopy(req), { + headers: this.headers + }) + .pipe(map(res => decodeSendCopy(res))); + } + + /** unread count */ + public retrieveUnreadCount( + req: UnreadCountRequest + ): Observable { + return this.httpClient + .post(this.urls.retrieveUnreadCount, encodeUnreadCount(req), { + headers: this.headers + }) + .pipe(map(res => decodeUnreadCount(res))); + } +} diff --git a/projects/ucap-webmessenger-api-message/src/lib/types/category.type.ts b/projects/ucap-webmessenger-api-message/src/lib/types/category.type.ts new file mode 100644 index 0000000..f45094a --- /dev/null +++ b/projects/ucap-webmessenger-api-message/src/lib/types/category.type.ts @@ -0,0 +1,6 @@ +export enum CategoryType { + /** 일반 */ + General = 'G', + /** 공지 */ + Notice = 'N' +} diff --git a/projects/ucap-webmessenger-api-message/src/lib/types/content.type.ts b/projects/ucap-webmessenger-api-message/src/lib/types/content.type.ts new file mode 100644 index 0000000..c626cb0 --- /dev/null +++ b/projects/ucap-webmessenger-api-message/src/lib/types/content.type.ts @@ -0,0 +1,8 @@ +export enum ContentType { + /** 텍스트 */ + Text = 'T', + /** 이미지파일 */ + Image = 'F', + /** 첨부파일 */ + AttachFile = 'A' +} diff --git a/projects/ucap-webmessenger-api-message/src/lib/types/message.search.type.ts b/projects/ucap-webmessenger-api-message/src/lib/types/message.search.type.ts new file mode 100644 index 0000000..6bc9dea --- /dev/null +++ b/projects/ucap-webmessenger-api-message/src/lib/types/message.search.type.ts @@ -0,0 +1,5 @@ +export enum MessageSearchType { + Title = 'T', + Name = 'N', + Contents = 'C' +} diff --git a/projects/ucap-webmessenger-api-message/src/lib/types/message.type.ts b/projects/ucap-webmessenger-api-message/src/lib/types/message.type.ts new file mode 100644 index 0000000..416651b --- /dev/null +++ b/projects/ucap-webmessenger-api-message/src/lib/types/message.type.ts @@ -0,0 +1,6 @@ +export enum MessageType { + Send = 'S', + Receive = 'R', + Reservation = 'B', + All = 'A' +} diff --git a/projects/ucap-webmessenger-api-message/src/lib/ucap-message-api.module.ts b/projects/ucap-webmessenger-api-message/src/lib/ucap-message-api.module.ts new file mode 100644 index 0000000..601084a --- /dev/null +++ b/projects/ucap-webmessenger-api-message/src/lib/ucap-message-api.module.ts @@ -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 { + return { + ngModule: UCapMessageApiModule, + providers: [{ provide: _MODULE_CONFIG, useValue: config }, ...SERVICES], + }; + } +} diff --git a/projects/ucap-webmessenger-api-message/src/public-api.ts b/projects/ucap-webmessenger-api-message/src/public-api.ts new file mode 100644 index 0000000..f51e2be --- /dev/null +++ b/projects/ucap-webmessenger-api-message/src/public-api.ts @@ -0,0 +1,24 @@ +/* + * Public API Surface of ucap-webmessenger-api-message + */ +export * from './lib/apis/del'; +export * from './lib/apis/detail'; +export * from './lib/apis/edit-reservation-ex'; +export * from './lib/apis/my-message'; +export * from './lib/apis/retrieve'; +export * from './lib/apis/send-copy'; +export * from './lib/apis/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.search.type'; +export * from './lib/types/message.type'; + +export * from './lib/config/urls'; +export * from './lib/config/module-config'; diff --git a/projects/ucap-webmessenger-api-message/src/test.ts b/projects/ucap-webmessenger-api-message/src/test.ts new file mode 100644 index 0000000..978c64f --- /dev/null +++ b/projects/ucap-webmessenger-api-message/src/test.ts @@ -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); diff --git a/projects/ucap-webmessenger-electron-core/tsconfig.lib.json b/projects/ucap-webmessenger-api-message/tsconfig.lib.json similarity index 100% rename from projects/ucap-webmessenger-electron-core/tsconfig.lib.json rename to projects/ucap-webmessenger-api-message/tsconfig.lib.json diff --git a/projects/ucap-webmessenger-api-message/tsconfig.spec.json b/projects/ucap-webmessenger-api-message/tsconfig.spec.json new file mode 100644 index 0000000..16da33d --- /dev/null +++ b/projects/ucap-webmessenger-api-message/tsconfig.spec.json @@ -0,0 +1,17 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": "../../out-tsc/spec", + "types": [ + "jasmine", + "node" + ] + }, + "files": [ + "src/test.ts" + ], + "include": [ + "**/*.spec.ts", + "**/*.d.ts" + ] +} diff --git a/projects/ucap-webmessenger-api-message/tslint.json b/projects/ucap-webmessenger-api-message/tslint.json new file mode 100644 index 0000000..75be226 --- /dev/null +++ b/projects/ucap-webmessenger-api-message/tslint.json @@ -0,0 +1,17 @@ +{ + "extends": "../../tslint.json", + "rules": { + "directive-selector": [ + true, + "attribute", + "ucapApiMessage", + "camelCase" + ], + "component-selector": [ + true, + "element", + "ucap-api-message", + "kebab-case" + ] + } +} diff --git a/projects/ucap-webmessenger-api-public/src/lib/apis/update-info.ts b/projects/ucap-webmessenger-api-public/src/lib/apis/update-info.ts index 37bd0a9..1afb5f5 100644 --- a/projects/ucap-webmessenger-api-public/src/lib/apis/update-info.ts +++ b/projects/ucap-webmessenger-api-public/src/lib/apis/update-info.ts @@ -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 = ( @@ -35,6 +35,6 @@ export const decodeUpdateInfo: APIDecoder = (res: any) => { appVersion: res.AppVer, installUrl: res.InstallURL, launcherAppVersion: res.LauncherAppVer, - launcherInstallUrl: res.LauncherInstallURL + launcherInstallUrl: res.LauncherInstallURL, } as UpdateInfoResponse; }; diff --git a/projects/ucap-webmessenger-api-public/src/lib/config/module-config.ts b/projects/ucap-webmessenger-api-public/src/lib/config/module-config.ts new file mode 100644 index 0000000..7091509 --- /dev/null +++ b/projects/ucap-webmessenger-api-public/src/lib/config/module-config.ts @@ -0,0 +1,5 @@ +import { ModuleConfig as CoreModuleConfig } from '@ucap-webmessenger/core'; + +import { Urls } from './urls'; + +export interface ModuleConfig extends CoreModuleConfig {} diff --git a/projects/ucap-webmessenger-api-public/src/lib/types/token.ts b/projects/ucap-webmessenger-api-public/src/lib/config/token.ts similarity index 100% rename from projects/ucap-webmessenger-api-public/src/lib/types/token.ts rename to projects/ucap-webmessenger-api-public/src/lib/config/token.ts diff --git a/projects/ucap-webmessenger-api-public/src/lib/config/urls.ts b/projects/ucap-webmessenger-api-public/src/lib/config/urls.ts new file mode 100644 index 0000000..0156cf5 --- /dev/null +++ b/projects/ucap-webmessenger-api-public/src/lib/config/urls.ts @@ -0,0 +1,4 @@ +export interface Urls { + versionInfo2: string; + updateInfo: string; +} diff --git a/projects/ucap-webmessenger-api-public/src/lib/services/public-api.service.ts b/projects/ucap-webmessenger-api-public/src/lib/services/public-api.service.ts index d3dd1f9..739fdb6 100644 --- a/projects/ucap-webmessenger-api-public/src/lib/services/public-api.service.ts +++ b/projects/ucap-webmessenger-api-public/src/lib/services/public-api.service.ts @@ -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 { return this.httpClient .post( - 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 { return this.httpClient .post( - this.moduleConfig.urls.updateInfo, + this.urls.updateInfo, {}, { - params: encodeUpdateInfo(req) + params: encodeUpdateInfo(req), } ) .pipe(map(res => decodeUpdateInfo(res))); diff --git a/projects/ucap-webmessenger-api-public/src/lib/types/module-config.ts b/projects/ucap-webmessenger-api-public/src/lib/types/module-config.ts deleted file mode 100644 index 4ed6691..0000000 --- a/projects/ucap-webmessenger-api-public/src/lib/types/module-config.ts +++ /dev/null @@ -1,6 +0,0 @@ -export interface ModuleConfig { - urls: { - versionInfo2: string; - updateInfo: string; - }; -} diff --git a/projects/ucap-webmessenger-api-public/src/lib/ucap-public-api.module.ts b/projects/ucap-webmessenger-api-public/src/lib/ucap-public-api.module.ts index 3424d78..cc92903 100644 --- a/projects/ucap-webmessenger-api-public/src/lib/ucap-public-api.module.ts +++ b/projects/ucap-webmessenger-api-public/src/lib/ucap-public-api.module.ts @@ -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 { return { ngModule: UCapPublicApiModule, - providers: [{ provide: _MODULE_CONFIG, useValue: config }, ...SERVICES] + providers: [{ provide: _MODULE_CONFIG, useValue: config }, ...SERVICES], }; } } diff --git a/projects/ucap-webmessenger-api-public/src/public-api.ts b/projects/ucap-webmessenger-api-public/src/public-api.ts index eb7db5e..41cd5c4 100644 --- a/projects/ucap-webmessenger-api-public/src/public-api.ts +++ b/projects/ucap-webmessenger-api-public/src/public-api.ts @@ -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'; diff --git a/projects/ucap-webmessenger-api/src/lib/apis/api.ts b/projects/ucap-webmessenger-api/src/lib/apis/api.ts index b4b9b04..399b218 100644 --- a/projects/ucap-webmessenger-api/src/lib/apis/api.ts +++ b/projects/ucap-webmessenger-api/src/lib/apis/api.ts @@ -1,6 +1,7 @@ import { HttpParams } from '@angular/common/http'; import { StatusCode } from '../types/status-code.type'; +import { MessageStatusCode } from '../types/message-status-code.type'; export interface APIRequest { _id?: string; @@ -11,9 +12,16 @@ export interface APIResponse { statusCode: StatusCode; errorMessage: string; } +export interface MessageAPIResponse { + _id?: string; + responseCode: MessageStatusCode; + responseMsg: string; +} export type APIEncoder = (req: REQ) => HttpParams; +export type APIJsonEncoder = (req: REQ) => string; + export type APIFormDataEncoder = (req: REQ) => FormData; export type APIDecoder = (res: any) => RES; diff --git a/projects/ucap-webmessenger-api/src/lib/types/message-status-code.type.ts b/projects/ucap-webmessenger-api/src/lib/types/message-status-code.type.ts new file mode 100644 index 0000000..b275cd5 --- /dev/null +++ b/projects/ucap-webmessenger-api/src/lib/types/message-status-code.type.ts @@ -0,0 +1,28 @@ +export enum MessageStatusCode { + /** 성공 */ + Success = '00', + /** 사용자 토큰이 일치하지 않을 경우 발생 (인증 실패) */ + Fail_Auth = '10', + /** 메시지 타입이 일치하지 않을 경우 발생 */ + Fail_Msg_Type = '20', + /** 메시지 아이디가 NULL일 경우 발생 */ + Fail_Msg_Id_Null = '21', + /** 예약 메시지 발송 시, 예약 시간이 지정되어있지 않을 경우 발생 */ + Fail_Msg_Reservation_Time_Null = '22', + /** 메시지 발송 시, 제목이 최대 길이보다 길 경우 발생 */ + Fail_Msg_Title_length = '23', + /** 예약 메시지 발송 시, 현재 시간 10분 전일 경우 발생 */ + Fail_Msg_Reservation_Time_Less = '24', + /** 예약 메시지 수정 시, 발송 시간 10분 전일 경우 발생 */ + Fail_Msg_Edit_Reservation_Time_Less = '25', + /** 예약 메시지 수정 및 발송 취소 시, 이미 발송된 메시지일 경우 발생 */ + Fail_Msg_Edit_Cancel_Reservation_Sended = '26', + /** 파일 업로드 시, 경로가 올바르지 않을 경우 발생 */ + Fail_File_Path = '40', + /** 파일 업로드 시, 파일 크기가 최대 크기보다 클 경우 발생 */ + Fail_File_Size = '41', + /** 파일 업로드 시, 업로드할 수 없는 파일 형식일 경우 발생 */ + Fail_File_Ext = '42', + /** Exception 에러 발생 */ + Fail = '99' +} diff --git a/projects/ucap-webmessenger-api/src/lib/types/status-code.type.ts b/projects/ucap-webmessenger-api/src/lib/types/status-code.type.ts index 89d7a3f..5c279b1 100644 --- a/projects/ucap-webmessenger-api/src/lib/types/status-code.type.ts +++ b/projects/ucap-webmessenger-api/src/lib/types/status-code.type.ts @@ -1,4 +1,4 @@ export enum StatusCode { Success = '200', - Fail = '500' + Fail = '500', } diff --git a/projects/ucap-webmessenger-api/src/public-api.ts b/projects/ucap-webmessenger-api/src/public-api.ts index 6669470..67b54c8 100644 --- a/projects/ucap-webmessenger-api/src/public-api.ts +++ b/projects/ucap-webmessenger-api/src/public-api.ts @@ -4,6 +4,7 @@ export * from './lib/apis/api'; +export * from './lib/types/message-status-code.type'; export * from './lib/types/status-code.type'; export * from './lib/utils/json.util'; diff --git a/projects/ucap-webmessenger-app/src/app/app-provider.module.ts b/projects/ucap-webmessenger-app/src/app/app-provider.module.ts index 05b2801..f33498e 100644 --- a/projects/ucap-webmessenger-app/src/app/app-provider.module.ts +++ b/projects/ucap-webmessenger-app/src/app/app-provider.module.ts @@ -1,31 +1,59 @@ -import { NgModule, APP_INITIALIZER } from '@angular/core'; - -import { UCAP_NATIVE_SERVICE } from '@ucap-webmessenger/native'; -import { ElectronNativeService } from '@ucap-webmessenger/native-electron'; - -import { RESOLVERS } from './resolvers'; -import { SERVICES } from './services'; -import { AppService } from './services/app.service'; - -export function initializeApp(appService: AppService) { - return (): Promise => { - return appService.postInit(); - }; -} - -@NgModule({ - imports: [], - exports: [], - providers: [ - ...SERVICES, - ...RESOLVERS, - { - provide: APP_INITIALIZER, - useFactory: initializeApp, - deps: [AppService], - multi: true - }, - { provide: UCAP_NATIVE_SERVICE, useClass: ElectronNativeService } - ] -}) -export class AppProviderModule {} +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 { 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 => { + 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: [ + { + provide: UCAP_NATIVE_SERVICE, + // useFactory: nativeServiceFactory, + useClass: + 'browser' === environment.runtime + ? BrowserNativeService + : ElectronNativeService, + deps: [HttpClient], + }, + ...SERVICES, + ...RESOLVERS, + { + provide: APP_INITIALIZER, + useFactory: initializeApp, + deps: [AppService, UCAP_NATIVE_SERVICE], + multi: true, + }, + ], +}) +export class AppProviderModule {} diff --git a/projects/ucap-webmessenger-app/src/app/app-routing.module.ts b/projects/ucap-webmessenger-app/src/app/app-routing.module.ts index 6b51755..34ed1d5 100644 --- a/projects/ucap-webmessenger-app/src/app/app-routing.module.ts +++ b/projects/ucap-webmessenger-app/src/app/app-routing.module.ts @@ -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 {} diff --git a/projects/ucap-webmessenger-app/src/app/app-translate.module.ts b/projects/ucap-webmessenger-app/src/app/app-translate.module.ts index 5faaf63..77a3fd7 100644 --- a/projects/ucap-webmessenger-app/src/app/app-translate.module.ts +++ b/projects/ucap-webmessenger-app/src/app/app-translate.module.ts @@ -6,16 +6,13 @@ import { UCAP_NATIVE_SERVICE, NativeService } from '@ucap-webmessenger/native'; export async function createTranslateLoader(nativeService: NativeService) { // tslint:disable-next-line: variable-name - let _TranslateLoader; - _TranslateLoader = await import('@ucap-webmessenger/native-browser').then( - m => m.TranslateBrowserLoader - ); - _TranslateLoader = await import('@ucap-webmessenger/native-electron').then( - m => m.TranslateElectronLoader + const translateLoader = nativeService.getTranslateLoader( + './assets/i18n/', + '.json' ); // return new TranslateBrowserLoader(nativeService, './assets/i18n/', '.json'); - return new _TranslateLoader(nativeService, './assets/i18n/', '.json'); + return translateLoader; } @NgModule({ diff --git a/projects/ucap-webmessenger-app/src/app/app.component.ts b/projects/ucap-webmessenger-app/src/app/app.component.ts index 5447618..e80551d 100644 --- a/projects/ucap-webmessenger-app/src/app/app.component.ts +++ b/projects/ucap-webmessenger-app/src/app/app.component.ts @@ -1,4 +1,5 @@ import { Component } from '@angular/core'; +import { SplashScreenService } from '@ucap-webmessenger/ui'; @Component({ selector: 'app-root', @@ -6,5 +7,5 @@ import { Component } from '@angular/core'; styleUrls: ['./app.component.scss'] }) export class AppComponent { - title = 'ucap-webmessenger-app'; + constructor(private splashScreenService: SplashScreenService) {} } diff --git a/projects/ucap-webmessenger-app/src/app/app.module.ts b/projects/ucap-webmessenger-app/src/app/app.module.ts index 2e3bc2e..3899a04 100644 --- a/projects/ucap-webmessenger-app/src/app/app.module.ts +++ b/projects/ucap-webmessenger-app/src/app/app.module.ts @@ -1,118 +1,106 @@ -import { NgModule } from '@angular/core'; -import { BrowserModule } from '@angular/platform-browser'; -import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; -import { HttpClientModule } from '@angular/common/http'; - -import { MatProgressBarModule } from '@angular/material/progress-bar'; - -import { PerfectScrollbarModule } from 'ngx-perfect-scrollbar'; - -import { UCapCommonApiModule } from '@ucap-webmessenger/api-common'; -import { UCapExternalApiModule } from '@ucap-webmessenger/api-external'; -import { UCapPublicApiModule } from '@ucap-webmessenger/api-public'; - -import { UCapPiModule } from '@ucap-webmessenger/pi'; - -import { UCapProtocolModule } from '@ucap-webmessenger/protocol'; -import { UCapAuthenticationProtocolModule } from '@ucap-webmessenger/protocol-authentication'; -import { UCapEventProtocolModule } from '@ucap-webmessenger/protocol-event'; -import { UCapGroupProtocolModule } from '@ucap-webmessenger/protocol-group'; -import { UCapInfoProtocolModule } from '@ucap-webmessenger/protocol-info'; -import { UCapInnerProtocolModule } from '@ucap-webmessenger/protocol-inner'; -import { UCapOptionProtocolModule } from '@ucap-webmessenger/protocol-option'; -import { UCapRoomProtocolModule } from '@ucap-webmessenger/protocol-room'; -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'; -import { AppTranslateModule } from './app-translate.module'; - -import { AppComponent } from './app.component'; - -import { GUARDS } from './guards'; -import { AppMessengerLayoutModule } from './layouts/messenger/messenger.layout.module'; -import { AppNativeLayoutModule } from './layouts/native/native.layout.module'; - -@NgModule({ - imports: [ - BrowserModule, - BrowserAnimationsModule, - - HttpClientModule, - - MatProgressBarModule, - - PerfectScrollbarModule, - - UCapCommonApiModule.forRoot({ - urls: environment.urls.apiCommon, - acceptableFileExtensions: - environment.modules.event.acceptableFileExtensions - }), - - UCapPublicApiModule.forRoot({ - urls: environment.urls.apiPublic - }), - UCapExternalApiModule.forRoot({ - urls: environment.urls.apiExternal - }), - - UCapPiModule.forRoot({ - urls: environment.urls.pi - }), - - UCapProtocolModule.forRoot({ - urls: environment.urls.protocol, - reconnect: environment.protocol.reconnect, - requestId: environment.protocol.requestId - }), - UCapAuthenticationProtocolModule.forRoot(), - UCapEventProtocolModule.forRoot(), - UCapGroupProtocolModule.forRoot(), - UCapInfoProtocolModule.forRoot(), - UCapInnerProtocolModule.forRoot(), - UCapOptionProtocolModule.forRoot(), - UCapRoomProtocolModule.forRoot(), - UCapServiceProtocolModule.forRoot(), - UCapStatusProtocolModule.forRoot(), - UCapSyncProtocolModule.forRoot(), - - UCapUiModule.forRoot(), - UCapUiAccountModule.forRoot(), - - UCapWebStorageModule.forRoot(), - - UCapUtilModule.forRoot(), - - AppProviderModule, - AppRoutingModule, - AppStoreModule, - AppTranslateModule, - - AppMessengerLayoutModule, - AppNativeLayoutModule, - - LoggerModule.forRoot({ - level: NgxLoggerLevel.DEBUG - }) - ], - providers: [...GUARDS], - declarations: [AppComponent], - bootstrap: [AppComponent], - entryComponents: [] -}) -export class AppModule {} +import { NgModule } from '@angular/core'; +import { BrowserModule } from '@angular/platform-browser'; +import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; +import { HttpClientModule } from '@angular/common/http'; + +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'; + +import { UCapProtocolModule } from '@ucap-webmessenger/protocol'; +import { UCapAuthenticationProtocolModule } from '@ucap-webmessenger/protocol-authentication'; +import { UCapEventProtocolModule } from '@ucap-webmessenger/protocol-event'; +import { UCapGroupProtocolModule } from '@ucap-webmessenger/protocol-group'; +import { UCapInfoProtocolModule } from '@ucap-webmessenger/protocol-info'; +import { UCapInnerProtocolModule } from '@ucap-webmessenger/protocol-inner'; +import { UCapOptionProtocolModule } from '@ucap-webmessenger/protocol-option'; +import { UCapRoomProtocolModule } from '@ucap-webmessenger/protocol-room'; +import { UCapServiceProtocolModule } from '@ucap-webmessenger/protocol-service'; +import { UCapStatusProtocolModule } from '@ucap-webmessenger/protocol-status'; +import { UCapSyncProtocolModule } from '@ucap-webmessenger/protocol-sync'; + +import { LoggerModule, NgxLoggerLevel } from 'ngx-logger'; + +import { AppProviderModule } from './app-provider.module'; +import { AppRoutingModule } from './app-routing.module'; +import { AppStoreModule } from './app-store.module'; +import { AppTranslateModule } from './app-translate.module'; + +import { AppComponent } from './app.component'; + +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, + BrowserAnimationsModule, + + HttpClientModule, + + MatProgressBarModule, + + PerfectScrollbarModule, + + UCapCommonApiModule.forRoot(environment.commonApiModuleConfig), + + UCapPublicApiModule.forRoot(environment.publicApiModuleConfig), + UCapExternalApiModule.forRoot(environment.externalApiModuleConfig), + UCapMessageApiModule.forRoot(environment.messageApiModuleConfig), + + UCapPiModule.forRoot(environment.piModuleConfig), + + UCapProtocolModule.forRoot(environment.protocolModuleConfig), + UCapAuthenticationProtocolModule.forRoot(), + UCapEventProtocolModule.forRoot(), + UCapGroupProtocolModule.forRoot(), + UCapInfoProtocolModule.forRoot(), + UCapInnerProtocolModule.forRoot(), + UCapOptionProtocolModule.forRoot(), + UCapRoomProtocolModule.forRoot(), + UCapServiceProtocolModule.forRoot(), + UCapStatusProtocolModule.forRoot(), + UCapSyncProtocolModule.forRoot(), + + UCapUiModule.forRoot(), + UCapUiAccountModule.forRoot(), + + UCapWebStorageModule.forRoot(), + + UCapUtilModule.forRoot(), + + AppProviderModule, + AppRoutingModule, + AppStoreModule, + AppTranslateModule, + + AppMessengerLayoutModule, + AppNativeLayoutModule, + + LoggerModule.forRoot({ + level: NgxLoggerLevel.DEBUG + }) + ], + providers: [...GUARDS], + declarations: [AppComponent], + bootstrap: [AppComponent], + entryComponents: [] +}) +export class AppModule {} diff --git a/projects/ucap-webmessenger-app/src/app/app.theme.scss b/projects/ucap-webmessenger-app/src/app/app.theme.scss index e636333..88f3bd5 100644 --- a/projects/ucap-webmessenger-app/src/app/app.theme.scss +++ b/projects/ucap-webmessenger-app/src/app/app.theme.scss @@ -103,24 +103,51 @@ body.theme-pink-dark { // ----------------------------------------------------------------------------------------------------- // Define the primary, accent and warn palettes -$pink-light-theme-primary-palette: mat-palette($mat-grey,800); -$pink-light-theme-accent-palette: mat-palette($lg-red, 400); -$pink-light-theme-warn-palette: mat-palette($mat-red); +$lgRed-light-theme-primary-palette: mat-palette($mat-grey,800); +$lgRed-light-theme-accent-palette: mat-palette($lg-red, 400); +$lgRed-light-theme-warn-palette: mat-palette($mat-cyan); + // Create the Material theme object -$pink-light-theme: mat-light-theme( - $pink-light-theme-primary-palette, - $pink-light-theme-accent-palette, - $pink-light-theme-warn-palette +$lgRed-light-theme: mat-light-theme( + $lgRed-light-theme-primary-palette, + $lgRed-light-theme-accent-palette, + $lgRed-light-theme-warn-palette ); // Add ".theme-pink-dark" class to the body to activate this theme. // Class name must start with "theme-" !!! -body.theme-default { +body.theme-lgRed{ // Generate the Angular Material theme - @include angular-material-theme($pink-light-theme); + @include angular-material-theme($lgRed-light-theme); // Apply the theme to the user components - @include components-theme($pink-light-theme); - @include ucap-material-theme($pink-light-theme); + @include components-theme($lgRed-light-theme); + @include ucap-material-theme($lgRed-light-theme); +} + +// ----------------------------------------------------------------------------------------------------- +//aqua-blue-daesang +// ----------------------------------------------------------------------------------------------------- + +$aquaBlue-light-theme-primary-palette: mat-palette($daesang-grey, 900); +$aquaBlue-theme-accent-palette: mat-palette($aquaBlue-daesang); +$aquaBlue-theme-warn-palette: mat-palette($mat-orange); + +// Create the Material theme object +$aquaBlue-light-theme: mat-light-theme( + $aquaBlue-light-theme-primary-palette, + $aquaBlue-theme-accent-palette, + $aquaBlue-theme-warn-palette +); + +// Add ".theme-pink-dark" class to the body to activate this theme. +// Class name must start with "theme-" !!! +body.theme-default { + // Generate the Angular Material theme + @include angular-material-theme($aquaBlue-light-theme); + + // Apply the theme to the user components + @include components-theme($aquaBlue-light-theme); + @include ucap-material-theme($aquaBlue-light-theme); } diff --git a/projects/ucap-webmessenger-app/src/app/layouts/common/dialogs/file-viewer.dialog.component.html b/projects/ucap-webmessenger-app/src/app/layouts/common/dialogs/file-viewer.dialog.component.html index 343050b..21049de 100644 --- a/projects/ucap-webmessenger-app/src/app/layouts/common/dialogs/file-viewer.dialog.component.html +++ b/projects/ucap-webmessenger-app/src/app/layouts/common/dialogs/file-viewer.dialog.component.html @@ -1,11 +1,6 @@ - diff --git a/projects/ucap-webmessenger-app/src/app/layouts/common/dialogs/file-viewer.dialog.component.ts b/projects/ucap-webmessenger-app/src/app/layouts/common/dialogs/file-viewer.dialog.component.ts index d084019..b8a2aab 100644 --- a/projects/ucap-webmessenger-app/src/app/layouts/common/dialogs/file-viewer.dialog.component.ts +++ b/projects/ucap-webmessenger-app/src/app/layouts/common/dialogs/file-viewer.dialog.component.ts @@ -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(); diff --git a/projects/ucap-webmessenger-app/src/app/layouts/messenger/components/index.ts b/projects/ucap-webmessenger-app/src/app/layouts/messenger/components/index.ts index 7348ada..08c254a 100644 --- a/projects/ucap-webmessenger-app/src/app/layouts/messenger/components/index.ts +++ b/projects/ucap-webmessenger-app/src/app/layouts/messenger/components/index.ts @@ -2,14 +2,18 @@ import { IntroComponent } from './intro.component'; import { LeftSideComponent } from './left-side.component'; import { MessagesComponent } from './messages.component'; import { RightSideComponent } from './right-side.component'; +import { RightDrawerComponent } from './right-drawer.component'; import { LEFT_SIDENAV_COMPONENTS } from './left-sidenav'; +import { RIGHT_DRAWER_COMPONENTS } from './right-drawer'; export const COMPONENTS = [ IntroComponent, LeftSideComponent, MessagesComponent, RightSideComponent, + RightDrawerComponent, - ...LEFT_SIDENAV_COMPONENTS + ...LEFT_SIDENAV_COMPONENTS, + ...RIGHT_DRAWER_COMPONENTS ]; diff --git a/projects/ucap-webmessenger-app/src/app/layouts/messenger/components/left-side.component.html b/projects/ucap-webmessenger-app/src/app/layouts/messenger/components/left-side.component.html index 77e14cd..e2cffc4 100644 --- a/projects/ucap-webmessenger-app/src/app/layouts/messenger/components/left-side.component.html +++ b/projects/ucap-webmessenger-app/src/app/layouts/messenger/components/left-side.component.html @@ -8,50 +8,73 @@ -
- +
+
- - -
- + matTooltip="Chat" + matTooltipPosition="after" + > + - + 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" + >
-
-
- +
+ @@ -61,33 +84,125 @@
- - + + - -
- - device_hub--> +
+ + + +
+ + + + + + + +
+
+ +
+ + + + +
+ ; +export class LeftSideComponent implements OnInit, OnDestroy { + @Output() + openProfile = new EventEmitter< + UserInfo | UserInfoSS | UserInfoF | UserInfoDN + >(); + + @ViewChildren('tabs') tabs: QueryList>; + currentTabLable: string; + + badgeChatUnReadCount: number; + badgeChatUnReadCountSubscription: Subscription; /** 조직도에서 부서원 선택 */ selectedUserList: (UserInfo | UserInfoSS | UserInfoF | UserInfoDN)[] = []; @@ -47,18 +72,42 @@ export class LeftSideComponent implements OnInit { MainMenu = MainMenu; + sessionVerinfo: VersionInfo2Response; + loginRes: LoginResponse; + constructor( private store: Store, private dialogService: DialogService, + private sessionStorageService: SessionStorageService, private logger: NGXLogger - ) {} + ) { + this.loginRes = this.sessionStorageService.get( + KEY_LOGIN_RES_INFO + ); + this.sessionVerinfo = this.sessionStorageService.get( + KEY_VER_INFO + ); + } ngOnInit() { - this.badgeChatUnReadCount$ = this.store.pipe( - select(AppStore.MessengerSelector.SyncSelector.selectChatUnreadCount) - ); + this.badgeChatUnReadCountSubscription = this.store + .pipe( + select(AppStore.MessengerSelector.SyncSelector.selectChatUnreadCount) + ) + .subscribe(count => { + this.badgeChatUnReadCount = count; + }); this.setFabInitial(MainMenu.Group); + this.currentTabLable = MainMenu.Group; + } + + ngOnDestroy(): void { + if (!!this.badgeChatUnReadCountSubscription) { + this.badgeChatUnReadCountSubscription.unsubscribe(); + } + + this.logger.debug('-----------------------LeftSideComponent ngOnDestroy'); } async onClickNewChat(type: string = 'NORMAL') { @@ -106,7 +155,7 @@ export class LeftSideComponent implements OnInit { if (!!result && !!result.choice && result.choice) { if ( !!result.selectedUserList && - result.selectedUserList.length > 0 && + // result.selectedUserList.length > 0 && result.groupName.trim().length > 0 ) { const userSeqs: number[] = []; @@ -122,8 +171,21 @@ export class LeftSideComponent implements OnInit { } } + onClickOpenProfile(userInfo: UserInfo | UserInfoSS | UserInfoF | UserInfoDN) { + this.openProfile.emit(userInfo); + } + onSelectedTabChange(event: MatTabChangeEvent) { this.setFabInitial(event.tab.ariaLabel); + this.currentTabLable = event.tab.ariaLabel; + + this.tabs.forEach(tab => { + if (`tabs-${event.index}` === tab.nativeElement.id) { + tab.nativeElement.style.display = 'block'; + } else { + tab.nativeElement.style.display = 'none'; + } + }); } setFabInitial(type: string) { switch (type) { @@ -212,6 +274,18 @@ export class LeftSideComponent implements OnInit { ); } } + onToggleUser(userInfo: UserInfo | UserInfoSS | UserInfoF | UserInfoDN) { + if ( + this.selectedUserList.filter(user => user.seq === userInfo.seq).length === + 0 + ) { + this.selectedUserList = [...this.selectedUserList, userInfo]; + } else { + this.selectedUserList = this.selectedUserList.filter( + item => item.seq !== userInfo.seq + ); + } + } /** FAB */ onClickFab(params: { btn: any }) { diff --git a/projects/ucap-webmessenger-app/src/app/layouts/messenger/components/left-sidenav/chat.component.html b/projects/ucap-webmessenger-app/src/app/layouts/messenger/components/left-sidenav/chat.component.html index e240d96..77d1ec4 100644 --- a/projects/ucap-webmessenger-app/src/app/layouts/messenger/components/left-sidenav/chat.component.html +++ b/projects/ucap-webmessenger-app/src/app/layouts/messenger/components/left-sidenav/chat.component.html @@ -57,26 +57,24 @@ [roomInfo]="room" [roomUserInfo]="getRoomUserList(room)" [sessionVerinfo]="sessionVerinfo" - (click)="onSelectedRoom(room)" + (click)="onClickContextMenu('SELECT_ROOM', room)" (contextmenu)="onContextMenuChat($event, room)" + class="ucap-clickable" > - +
-
+
-
-
- +
+
+
+ +
+
검색결과({{ searchUserInfos.length }}명)
+ + + + + + +
- + - + --> @@ -166,23 +218,40 @@ (ucapClickOutside)="groupContextMenuTrigger.closeMenu()" > - - - - + + + + - diff --git a/projects/ucap-webmessenger-app/src/app/layouts/messenger/components/left-sidenav/group.component.scss b/projects/ucap-webmessenger-app/src/app/layouts/messenger/components/left-sidenav/group.component.scss index 966be1f..dc2984b 100644 --- a/projects/ucap-webmessenger-app/src/app/layouts/messenger/components/left-sidenav/group.component.scss +++ b/projects/ucap-webmessenger-app/src/app/layouts/messenger/components/left-sidenav/group.component.scss @@ -1,14 +1,6 @@ @charset 'utf-8'; .current-head { - display: flex; - justify-content: center; - padding: 0 10px; - height: 70px; - background-color: #eeeeee; - background: #f15f79; - background: -webkit-linear-gradient(to right, #352a37, #f15f79); - background: linear-gradient(to right, #352a37, #ef4c73); - color:#ffffff; + color: #ffffff; h3 { display: inline-flex; padding-left: 10px; @@ -19,11 +11,12 @@ margin-left: auto; display: inline-flex; align-items: center; - svg{ - stroke:#333333; + svg { + stroke: #333333; } } } + .search-result { height: calc(100% - 130px); overflow: auto; @@ -32,8 +25,27 @@ display: flex; height: 40px; } + .ps { + .ps-content { + position: relative; + width: 100%; + height: 100%; + } + } } ::ng-deep .mat-tab-body-content { height: 100%; overflow: unset; } +.mat-menu-item { + display: flex; + align-items: center; + svg { + margin-right: 10px; + } +} + +.list-item-frame { + width: 100%; + height: 100%; +} diff --git a/projects/ucap-webmessenger-app/src/app/layouts/messenger/components/left-sidenav/group.component.ts b/projects/ucap-webmessenger-app/src/app/layouts/messenger/components/left-sidenav/group.component.ts index 9f300c1..94d52a4 100644 --- a/projects/ucap-webmessenger-app/src/app/layouts/messenger/components/left-sidenav/group.component.ts +++ b/projects/ucap-webmessenger-app/src/app/layouts/messenger/components/left-sidenav/group.component.ts @@ -56,6 +56,11 @@ import { EditGroupDialogData, EditGroupDialogResult } from '@app/layouts/messenger/dialogs/group/edit-group.dialog.component'; +import { + SelectGroupDialogComponent, + SelectGroupDialogResult, + SelectGroupDialogData +} from '../../dialogs/group/select-group.dialog.component'; @Component({ selector: 'app-layout-chat-left-sidenav-group', @@ -66,8 +71,12 @@ import { export class GroupComponent implements OnInit, OnDestroy { @Output() newGroupAndMember = new EventEmitter(); + @Output() + openProfile = new EventEmitter< + UserInfo | UserInfoSS | UserInfoF | UserInfoDN + >(); - @ViewChild('groupExpansionPanel', { static: true }) + @ViewChild('groupExpansionPanel', { static: false }) groupExpansionPanel: GroupExpansionPanelComponent; @ViewChild('profileContextMenuTrigger', { static: true }) @@ -161,10 +170,11 @@ export class GroupComponent implements OnInit, OnDestroy { } ngOnDestroy(): void { - this.logger.debug('ngOnDestroy'); if (!!this.loginResSubscription) { this.loginResSubscription.unsubscribe(); } + + this.logger.debug('-----------------------GroupComponent ngOnDestroy'); } async onClickGroupMenu(menuType: string) { @@ -277,22 +287,167 @@ export class GroupComponent implements OnInit, OnDestroy { this.searchUserInfos = []; } - getShowContextMenu(userInfo: UserInfo | UserInfoF) { + /** 그룹 header > more 버튼 > visible of context menu */ + getShowGroupContextMenu(menuType: string, group: GroupDetailData) { + // 즐겨찾기 그룹 숨김메뉴 + if ( + menuType === 'DIV1' || + menuType === 'RENAME' || + menuType === 'EDIT_MEMBER' || + menuType === 'DELETE' + ) { + if (!group || group === undefined) { + return false; + } + } + + // 기본 그룹 숨김메뉴 + if (menuType === 'RENAME' || menuType === 'DELETE') { + if (!!group && group.seq === 0) { + return false; + } + } + + return true; + } + + /** 그룹 > 그룹원 > visible of context menu */ + getShowProfileContextMenu( + menuType: string, + userInfo: UserInfo | UserInfoF, + group?: GroupDetailData + ) { if (userInfo.seq === this.loginRes.userSeq) { return false; - } else { - return true; } + + if (!group || group === undefined) { + if ( + menuType === 'REGISTER_FAVORITE' || + menuType === 'SEND_NOTE' || + menuType === 'REGISTER_NICKNAME' + ) { + // continue; + } else { + return false; + } + } + + return true; } - onClickProfileContextMenu(menuType: string, userInfo: UserInfo | UserInfoF) { + async onClickProfileContextMenu( + menuType: string, + userInfo: UserInfo | UserInfoF, + group?: GroupDetailData + ) { this.logger.debug( 'onClickProfileContextMenu', 'menuType', menuType, 'userInfo', - userInfo + userInfo, + 'group', + group ); switch (menuType) { + case 'VIEW_PROFILE': + this.openProfile.emit(userInfo); + break; + case 'CHAT': + this.onSelectBuddy(userInfo); + break; + case 'REMOVE_FROM_GROUP': + { + const result = await this.dialogService.open< + ConfirmDialogComponent, + ConfirmDialogData, + ConfirmDialogResult + >(ConfirmDialogComponent, { + width: '360px', + data: { + title: 'Delete Member in Group', + html: `[${userInfo.name} ${userInfo.grade}]를 [${group.name}]그룹에서 삭제하시겠습니까?` + } + }); + + if (!!result && !!result.choice && result.choice) { + const trgtUserSeq = group.userSeqs.filter( + user => user !== userInfo.seq + ); + this.store.dispatch( + SyncStore.updateGroupMember({ + oldGroup: group, + trgtUserSeq + }) + ); + } + } + break; + case 'COPY_BUDDY': + { + 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[] = []; + let exist = false; + result.group.userSeqs.map(seq => { + trgtUserSeq.push(seq); + if (seq === userInfo.seq) { + exist = true; + } + }); + + if (!exist) { + trgtUserSeq.push(userInfo.seq); + } + + this.store.dispatch( + SyncStore.updateGroupMember({ + oldGroup, + trgtUserSeq + }) + ); + } + } + } + break; + case 'MOVE_BUDDY': + { + 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) { + this.store.dispatch( + SyncStore.moveGroupMember({ + fromGroup: group, + toGroup: result.group, + trgtUserSeq: [userInfo.seq] + }) + ); + } + } + } + break; case 'REGISTER_FAVORITE': this.store.dispatch( SyncStore.updateBuddy({ @@ -304,9 +459,14 @@ export class GroupComponent implements OnInit, OnDestroy { } } + onClickOpenProfile(userInfo: UserInfo | UserInfoSS | UserInfoF | UserInfoDN) { + this.openProfile.emit(userInfo); + } + onContextMenuProfile( event: MouseEvent, - userInfo: UserInfo | UserInfoSS | UserInfoF | UserInfoDN + userInfo: UserInfo | UserInfoSS | UserInfoF | UserInfoDN, + group: GroupDetailData ) { event.preventDefault(); event.stopPropagation(); @@ -314,7 +474,7 @@ export class GroupComponent implements OnInit, OnDestroy { this.profileContextMenuPosition.x = event.clientX + 'px'; this.profileContextMenuPosition.y = event.clientY + 'px'; this.profileContextMenuTrigger.menu.focusFirstItem('mouse'); - this.profileContextMenuTrigger.menuData = { userInfo }; + this.profileContextMenuTrigger.menuData = { userInfo, group }; this.profileContextMenuTrigger.openMenu(); } diff --git a/projects/ucap-webmessenger-app/src/app/layouts/messenger/components/left-sidenav/index.ts b/projects/ucap-webmessenger-app/src/app/layouts/messenger/components/left-sidenav/index.ts index e957286..7e0cfc9 100644 --- a/projects/ucap-webmessenger-app/src/app/layouts/messenger/components/left-sidenav/index.ts +++ b/projects/ucap-webmessenger-app/src/app/layouts/messenger/components/left-sidenav/index.ts @@ -2,10 +2,12 @@ import { CallComponent } from './call.component'; import { ChatComponent } from './chat.component'; import { GroupComponent } from './group.component'; import { OrganizationComponent } from './organization.component'; +import { MessageBoxComponent } from './message.component'; export const LEFT_SIDENAV_COMPONENTS = [ CallComponent, ChatComponent, GroupComponent, - OrganizationComponent + OrganizationComponent, + MessageBoxComponent ]; diff --git a/projects/ucap-webmessenger-app/src/app/layouts/messenger/components/left-sidenav/message.component.html b/projects/ucap-webmessenger-app/src/app/layouts/messenger/components/left-sidenav/message.component.html new file mode 100644 index 0000000..c2c1736 --- /dev/null +++ b/projects/ucap-webmessenger-app/src/app/layouts/messenger/components/left-sidenav/message.component.html @@ -0,0 +1,198 @@ +
+
+

쪽지

+
+ +
+
+ +
+ + + + 수신 + + +
+
+
+ image + attach_file +
    +
  • {{ message.userName }}
  • +
  • {{ message.title }}
  • +
+
+
+ {{ message.regDate | dateToStringFormat: 'MM:DD' }} +
+
+
+
+ + + 발신 + + +
+
+
+ image + attach_file +
    +
  • {{ message.userName }}
  • +
  • {{ message.title }}
  • +
+
+
+ {{ message.regDate | dateToStringFormat: 'MM:DD' }} +
+
+
+
+ + + 예약 + + +
+
+
+ image + attach_file +
    +
  • {{ message.userName }}
  • +
  • {{ message.title }}
  • +
+
+
+ {{ message.regDate | dateToStringFormat: 'MM:DD' }} +
+
+
+
+
+
+
+
+
+ + + 전체 + 수신 + 발신 + 예약 + + + + 이름 + 제목 + 내용 + +
+
+
+
+
+ image + attach_file +
    +
  • {{ message.userName }}
  • +
  • {{ message.title }}
  • +
+
+
+ {{ message.regDate | dateToStringFormat: 'MM:DD' }} +
+
+
+
+
diff --git a/projects/ucap-webmessenger-app/src/app/layouts/messenger/components/left-sidenav/message.component.scss b/projects/ucap-webmessenger-app/src/app/layouts/messenger/components/left-sidenav/message.component.scss new file mode 100644 index 0000000..50961ba --- /dev/null +++ b/projects/ucap-webmessenger-app/src/app/layouts/messenger/components/left-sidenav/message.component.scss @@ -0,0 +1,67 @@ +.current-head { + h3 { + display: inline-flex; + padding-left: 10px; + align-items: center; + color: #ffffff; + } + .btn-box { + height: 100%; + margin-left: auto; + display: inline-flex; + align-items: center; + } +} + +.list-search { + display: flex; + flex-direction: row; + height: 60px; + align-items: center; + padding: 0; + font-size: 14px; + background-color: #f9f9f9; + border-bottom: 1px solid #dddddd; + .searchbox { + width: 100%; + height: 100%; + } +} +::ng-deep .searchbox { + .mat-form-field { + display: block; + .mat-form-field-wrapper { + padding: 0; + padding-bottom: 0 !important; + height: 100%; + .mat-form-field-flex { + height: 59px; + padding: 0 10px 0 20px; + align-items: center; + .mat-form-field-infix { + width: 90%; + font-size: 14px; + border: none; + } + .mat-form-field-suffix { + .mat-icon { + line-height: 24px; + } + } + } + } + } + .mat-form-field-appearance-legacy { + .mat-form-field-wrapper { + padding: 0; + } + .mat-form-field-underline { + bottom: 0; + background-color: unset !important; + } + } +} + +.mat-tab-label-active { + opacity: 1; +} diff --git a/projects/ucap-webmessenger-app/src/app/layouts/messenger/components/left-sidenav/message.component.spec.ts b/projects/ucap-webmessenger-app/src/app/layouts/messenger/components/left-sidenav/message.component.spec.ts new file mode 100644 index 0000000..807c302 --- /dev/null +++ b/projects/ucap-webmessenger-app/src/app/layouts/messenger/components/left-sidenav/message.component.spec.ts @@ -0,0 +1,24 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { MessageBoxComponent } from './message.component'; + +describe('MessageBoxComponent', () => { + let component: MessageBoxComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [MessageBoxComponent] + }).compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(MessageBoxComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/projects/ucap-webmessenger-app/src/app/layouts/messenger/components/left-sidenav/message.component.ts b/projects/ucap-webmessenger-app/src/app/layouts/messenger/components/left-sidenav/message.component.ts new file mode 100644 index 0000000..acc6451 --- /dev/null +++ b/projects/ucap-webmessenger-app/src/app/layouts/messenger/components/left-sidenav/message.component.ts @@ -0,0 +1,317 @@ +import { + Component, + OnInit, + OnDestroy, + Output, + EventEmitter, + ViewChild, + Input, + AfterViewChecked +} 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 { 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 { LoginResponse } from '@ucap-webmessenger/protocol-authentication'; +import { KEY_LOGIN_RES_INFO } from '@app/types/login-res-info.type'; +import { + MessageApiService, + MessageType, + RetrieveRequest, + MessageList, + RetrieveSearchRequest, + MessageSearchType +} from '@ucap-webmessenger/api-message'; +import { DeviceType } from '@ucap-webmessenger/core'; +import { MessageStatusCode } from '@ucap-webmessenger/api'; +import { ContentType } from '@ucap-webmessenger/api-message'; +import { FormGroup, FormBuilder } from '@angular/forms'; +import { + MatTabGroup, + MatSelectChange, + MatRadioChange +} from '@angular/material'; + +@Component({ + selector: 'app-layout-chat-left-sidenav-message', + templateUrl: './message.component.html', + styleUrls: ['./message.component.scss'] +}) +export class MessageBoxComponent + implements OnInit, OnDestroy, AfterViewChecked { + @Input() + isVisible = false; + + @ViewChild('tabs', { static: false }) tabs: MatTabGroup; + isInitTabs = false; + + fgSearch: FormGroup; + fgSearchType: FormGroup; + + loginRes: LoginResponse; + sessionVerinfo: VersionInfo2Response; + + messageList: MessageList[] = []; + + messageRecieveListSubscription: Subscription; + messageSendListSubscription: Subscription; + messageReservationListSubscription: Subscription; + messageSearchListSubscription: Subscription; + + defaultPageSize = 100; // default + recieveCurrentPage = 0; // start index is 0. + sendCurrentPage = 0; // start index is 0. + reservationCurrentPage = 0; // start index is 0. + searchCurrentPage = 0; // start index is 0. + + currentTotalCount = 0; + currentPage = 0; + + ContentType = ContentType; + MessageType = MessageType; + MessageSearchType = MessageSearchType; + + isSearch = false; + + constructor( + private store: Store, + private formBuilder: FormBuilder, + private sessionStorageService: SessionStorageService, + private dialogService: DialogService, + private messageApiService: MessageApiService + ) { + this.loginRes = this.sessionStorageService.get( + KEY_LOGIN_RES_INFO + ); + this.sessionVerinfo = this.sessionStorageService.get( + KEY_VER_INFO + ); + } + + ngOnInit() { + this.fgSearch = this.formBuilder.group({ + searchInput: null + }); + this.fgSearchType = this.formBuilder.group({ + searchMessageType: [MessageType.All], + searchMessageSearchType: [MessageSearchType.Name] + }); + + // 초기 검색은 수신함. + this.getRetrieveMessage(MessageType.Receive, this.recieveCurrentPage); + + if (!!this.tabs) { + this.tabs.realignInkBar(); + } + } + + ngAfterViewChecked(): void { + if (!!this.tabs && !this.isInitTabs && this.isVisible) { + this.isInitTabs = true; + this.tabs.realignInkBar(); + } + } + + ngOnDestroy(): void { + if (!!this.messageRecieveListSubscription) { + this.messageRecieveListSubscription.unsubscribe(); + } + if (!!this.messageSendListSubscription) { + this.messageSendListSubscription.unsubscribe(); + } + if (!!this.messageReservationListSubscription) { + this.messageReservationListSubscription.unsubscribe(); + } + if (!!this.messageSearchListSubscription) { + this.messageSearchListSubscription.unsubscribe(); + } + } + + onSelectedIndexChange(value: number) { + switch (value) { + case 0: + { + // Recieve + this.getRetrieveMessage(MessageType.Receive, this.recieveCurrentPage); + } + break; + case 1: + { + // Send + this.getRetrieveMessage(MessageType.Send, this.sendCurrentPage); + } + break; + case 2: + { + // Reservation + this.getRetrieveMessage( + MessageType.Reservation, + this.reservationCurrentPage + ); + } + break; + } + } + + onChangeSelection(event: MatSelectChange) { + this.searchCurrentPage = 0; + this.getSearchMessage( + event.value, + this.fgSearchType.get('searchMessageSearchType').value, + this.fgSearch.get('searchInput').value + ); + } + onChangeSearchType(event: MatRadioChange) { + this.searchCurrentPage = 0; + this.getSearchMessage( + this.fgSearchType.get('searchMessageType').value, + event.value, + this.fgSearch.get('searchInput').value + ); + } + onKeyDownEnter(event: KeyboardEvent, search: string) { + event.preventDefault(); + event.stopPropagation(); + + this.searchCurrentPage = 0; + + this.getSearchMessage( + MessageType.All, + MessageSearchType.Name, + search.trim() + ); + } + getSearchMessage( + messageType: MessageType, + searchType: MessageSearchType, + searchStr: string + ) { + this.isSearch = true; + this.messageSendListSubscription = this.messageApiService + .retrieveSearchMessage({ + userSeq: this.loginRes.userSeq, + deviceType: DeviceType.PC, + tokenKey: this.loginRes.tokenString, + type: messageType, + pageSize: this.defaultPageSize, + pageCount: this.searchCurrentPage, + + searchTitle: searchType === MessageSearchType.Title ? searchStr : '', + searchName: searchType === MessageSearchType.Name ? searchStr : '', + searchContent: + searchType === MessageSearchType.Contents ? searchStr : '' + } as RetrieveSearchRequest) + .pipe( + map(res => { + console.log(res); + if (res.responseCode === MessageStatusCode.Success) { + this.currentTotalCount = res.totalCount; + this.currentPage = res.pageCount; + this.searchCurrentPage = res.pageCount; + this.messageList = res.messageList; + } else { + } + }), + catchError(error => of(console.log(error))) + ) + .subscribe(); + } + + onClickSearchCancel() { + this.isSearch = false; + this.getRetrieveMessage(MessageType.Receive, this.recieveCurrentPage); + } + + getRetrieveMessage(type: MessageType, trgtPageIndex: number) { + switch (type) { + case MessageType.Receive: + { + this.messageSendListSubscription = this.messageApiService + .retrieveReceiveMessage({ + userSeq: this.loginRes.userSeq, + deviceType: DeviceType.PC, + tokenKey: this.loginRes.tokenString, + type: MessageType.Receive, + pageSize: this.defaultPageSize, + pageCount: this.recieveCurrentPage + } as RetrieveRequest) + .pipe( + map(res => { + console.log(res); + if (res.responseCode === MessageStatusCode.Success) { + this.currentTotalCount = res.totalCount; + this.currentPage = res.pageCount; + this.recieveCurrentPage = res.pageCount; + this.messageList = res.messageList; + } else { + } + }), + catchError(error => of(console.log(error))) + ) + .subscribe(); + } + break; + case MessageType.Send: + { + this.messageSendListSubscription = this.messageApiService + .retrieveSendMessage({ + userSeq: this.loginRes.userSeq, + deviceType: DeviceType.PC, + tokenKey: this.loginRes.tokenString, + type: MessageType.Send, + pageSize: this.defaultPageSize, + pageCount: this.sendCurrentPage + } as RetrieveRequest) + .pipe( + map(res => { + console.log(res); + if (res.responseCode === MessageStatusCode.Success) { + this.currentTotalCount = res.totalCount; + this.currentPage = res.pageCount; + this.sendCurrentPage = res.pageCount; + this.messageList = res.messageList; + } else { + } + }), + catchError(error => of(console.log(error))) + ) + .subscribe(); + } + break; + case MessageType.Reservation: + { + this.messageSendListSubscription = this.messageApiService + .retrieveReservationMessage({ + userSeq: this.loginRes.userSeq, + deviceType: DeviceType.PC, + tokenKey: this.loginRes.tokenString, + type: MessageType.Reservation, + pageSize: this.defaultPageSize, + pageCount: this.reservationCurrentPage + } as RetrieveRequest) + .pipe( + map(res => { + console.log(res); + if (res.responseCode === MessageStatusCode.Success) { + this.currentTotalCount = res.totalCount; + this.currentPage = res.pageCount; + this.reservationCurrentPage = res.pageCount; + this.messageList = res.messageList; + } else { + } + }), + catchError(error => of(console.log(error))) + ) + .subscribe(); + } + break; + } + } +} diff --git a/projects/ucap-webmessenger-app/src/app/layouts/messenger/components/left-sidenav/organization.component.html b/projects/ucap-webmessenger-app/src/app/layouts/messenger/components/left-sidenav/organization.component.html index 9481b09..de64189 100644 --- a/projects/ucap-webmessenger-app/src/app/layouts/messenger/components/left-sidenav/organization.component.html +++ b/projects/ucap-webmessenger-app/src/app/layouts/messenger/components/left-sidenav/organization.component.html @@ -1,36 +1,60 @@ -
-
+
+
+

조직도

+
+ + +
+
+
-
-
-
+
+
+
+ {{ getSelectedDepartmentName() }} -
-
- + + 검색결과({{ searchUserInfos.length }}명) - -
-
-
- + +
+
+ + +
+
+
+
+ +
-
+
- Loading... - + + +
-
  • -
  • -
@@ -58,7 +66,7 @@ - + + + - + - @@ -92,10 +142,14 @@
- +
+
+ +
+
@@ -139,6 +195,16 @@ class="file-drop-zone" >
+ +
+ +
+
@@ -150,6 +216,8 @@ [fileUploadQueue]="fileUploadQueue" (send)="onSendMessage($event)" (sendFiles)="onFileSelected($event)" + (clearView)="clearView()" + (toggleStickerSelector)="onShowToggleStickerSelector($event)" >
diff --git a/projects/ucap-webmessenger-app/src/app/layouts/messenger/components/messages.component.scss b/projects/ucap-webmessenger-app/src/app/layouts/messenger/components/messages.component.scss index e8dada5..4000bfc 100644 --- a/projects/ucap-webmessenger-app/src/app/layouts/messenger/components/messages.component.scss +++ b/projects/ucap-webmessenger-app/src/app/layouts/messenger/components/messages.component.scss @@ -24,12 +24,12 @@ } .chat-toolbar { width: 100%; - height: 80px; + height: 70px; min-height: 70px; align-items: center; background-color: #ffffff !important; border-bottom: 1px solid #dddddd; - box-shadow: 0 3px 6px rgba(0,0,0,.16); + box-shadow: 0 3px 6px rgba(0, 0, 0, 0.16); .chat-header { width: 100%; align-items: center; @@ -45,7 +45,6 @@ width: 40px; height: 40px; border-radius: 50%; - background-color: #604850; color: #efefef; font-size: 16px; line-height: 40px; @@ -68,7 +67,7 @@ height: 20px; span { border-radius: 10px; - padding: 1px 10px; + padding: 2px 10px; margin-right: 6px; font-size: 13px; } @@ -95,12 +94,26 @@ .file-drop-zone { position: absolute; - background-color: rgb(180, 180, 180); + padding: 10px 10px 0 10px; + background-color: rgb(54, 54, 54, 0.8); + bottom: 0; + width: 100%; + } + } - top: calc(100% - 200px); - left: 20%; - width: 60%; - height: 200px; + .sticker-selector-container { + position: absolute; + bottom: 0; + left: 0; + width: 100%; + background-color: transparent; + + .sticker-selector-zone { + position: absolute; + padding: 10px 10px 0 10px; + background-color: rgba(250, 255, 255, 0.8); + bottom: 0; + width: 100%; } } } diff --git a/projects/ucap-webmessenger-app/src/app/layouts/messenger/components/messages.component.ts b/projects/ucap-webmessenger-app/src/app/layouts/messenger/components/messages.component.ts index 13066a1..b48e4d3 100644 --- a/projects/ucap-webmessenger-app/src/app/layouts/messenger/components/messages.component.ts +++ b/projects/ucap-webmessenger-app/src/app/layouts/messenger/components/messages.component.ts @@ -4,7 +4,9 @@ import { OnDestroy, ViewChild, ElementRef, - AfterViewInit + AfterViewInit, + Output, + EventEmitter } from '@angular/core'; import { ucapAnimations, @@ -31,19 +33,26 @@ import { isRecallable, InfoResponse, EventJson, - FileEventJson + FileEventJson, + StickerEventJson } from '@ucap-webmessenger/protocol-event'; import * as AppStore from '@app/store'; import * as EventStore from '@app/store/messenger/event'; import * as ChatStore from '@app/store/messenger/chat'; import * as RoomStore from '@app/store/messenger/room'; +import * as SyncStore from '@app/store/messenger/sync'; import { LoginResponse } from '@ucap-webmessenger/protocol-authentication'; -import { SessionStorageService } from '@ucap-webmessenger/web-storage'; +import { + SessionStorageService, + LocalStorageService +} from '@ucap-webmessenger/web-storage'; import { EnvironmentsInfo, KEY_ENVIRONMENTS_INFO, - UserSelectDialogType + UserSelectDialogType, + RightDrawer, + KEY_STICKER_HISTORY } from '@app/types'; import { RoomInfo, UserInfo, RoomType } from '@ucap-webmessenger/protocol-room'; import { tap, take, map, catchError } from 'rxjs/operators'; @@ -74,7 +83,14 @@ import { FileViewerDialogData, FileViewerDialogResult } from '@app/layouts/common/dialogs/file-viewer.dialog.component'; -import { CONST, FileUtil } from '@ucap-webmessenger/core'; +import { + CONST, + FileUtil, + StickerFilesInfo, + StickerUtil, + StickerInfo, + StickerMap +} from '@ucap-webmessenger/core'; import { PerfectScrollbarComponent } from 'ngx-perfect-scrollbar'; import { StatusCode } from '@ucap-webmessenger/api'; import { @@ -82,6 +98,12 @@ import { EditChatRoomDialogResult, EditChatRoomDialogData } from '../dialogs/chat/edit-chat-room.dialog.component'; +import { + SelectGroupDialogComponent, + SelectGroupDialogResult, + SelectGroupDialogData +} from '../dialogs/group/select-group.dialog.component'; +import { GroupDetailData } from '@ucap-webmessenger/protocol-sync'; @Component({ selector: 'app-layout-messenger-messages', @@ -90,6 +112,9 @@ import { animations: ucapAnimations }) export class MessagesComponent implements OnInit, OnDestroy, AfterViewInit { + @Output() + openProfile = new EventEmitter(); + @ViewChild('messageBoxContainer', { static: true }) private messageBoxContainer: ElementRef; @@ -134,11 +159,16 @@ export class MessagesComponent implements OnInit, OnDestroy, AfterViewInit { /** Timer 대화방의 대화 삭제를 위한 interval */ interval: any; + /** About Sticker */ + isShowStickerSelector = false; + selectedSticker: StickerFilesInfo; + snackBarPreviewEvent: MatSnackBarRef; constructor( private store: Store, private sessionStorageService: SessionStorageService, + private localStorageService: LocalStorageService, private commonApiService: CommonApiService, private clipboardService: ClipboardService, private dialogService: DialogService, @@ -175,7 +205,7 @@ export class MessagesComponent implements OnInit, OnDestroy, AfterViewInit { select(AppStore.MessengerSelector.RoomSelector.roomInfo), tap(roomInfo => { this.roomInfo = roomInfo; - + this.clearView(); this.setEventMoreInit(); }) ) @@ -255,6 +285,15 @@ export class MessagesComponent implements OnInit, OnDestroy, AfterViewInit { // this.readyToReply(); } + /** + * 채팅방의 여러 팝업들을 닫아준다. + */ + clearView() { + // Sticker Selector Clear.. + this.isShowStickerSelector = false; + this.selectedSticker = undefined; + } + getRoomName() { if (!this.roomInfo || !this.userInfoList) { return '대화방명을 가져오고 있습니다..'; @@ -316,6 +355,43 @@ export class MessagesComponent implements OnInit, OnDestroy, AfterViewInit { } } + getShowContextMenu(menuType: string) { + if ( + menuType === 'OPEN_ROOM_USER' || + menuType === 'ADD_MEMBER' || + menuType === 'ADD_GROUP' || + menuType === 'EDIT_ROOM' + ) { + if ( + !this.roomInfo || + !this.roomInfo.roomType || + this.roomInfo.roomType === RoomType.Mytalk || + this.roomInfo.roomType === RoomType.Allim || + this.roomInfo.roomType === RoomType.Bot || + this.roomInfo.roomType === RoomType.Link + ) { + return false; + } + } + + return true; + } + + getShowUnreadCount(): boolean { + if (!this.roomInfo || this.roomInfo === undefined) { + return true; + } + if ( + this.roomInfo.roomType === RoomType.Mytalk || + this.roomInfo.roomType === RoomType.Bot || + this.roomInfo.roomType === RoomType.Allim + ) { + return false; + } + + return true; + } + readyToReply(): void { setTimeout(() => { this.focusReplyInput(); @@ -416,22 +492,58 @@ export class MessagesComponent implements OnInit, OnDestroy, AfterViewInit { async onSendMessage(message: string) { this.setEventMoreInit(); - if (!message || message.trim().length === 0) { - const result = await this.dialogService.open< - AlertDialogComponent, - AlertDialogData, - AlertDialogResult - >(AlertDialogComponent, { - width: '360px', - data: { - title: 'Alert', - message: `대화내용을 입력해주세요.` - } - }); - return; + if (!this.selectedSticker) { + if (!message || message.trim().length === 0) { + const result = await this.dialogService.open< + AlertDialogComponent, + AlertDialogData, + AlertDialogResult + >(AlertDialogComponent, { + width: '360px', + data: { + title: 'Alert', + message: `대화내용을 입력해주세요.` + } + }); + return; + } } - if (message.trim().length > CONST.MASSTEXT_LEN) { + if (!!this.selectedSticker) { + // Send Sticker + if (message.trim().length > CONST.MASSTEXT_LEN) { + const result = await this.dialogService.open< + AlertDialogComponent, + AlertDialogData, + AlertDialogResult + >(AlertDialogComponent, { + width: '360px', + data: { + title: 'Alert', + message: `스티커를 포함할 경우 ${CONST.MASSTEXT_LEN}자 이상 보낼 수 없습니다.` + } + }); + return; + } + + const stickerJson: StickerEventJson = { + name: '스티커', + file: this.selectedSticker.index, + chat: message.trim() + }; + this.store.dispatch( + EventStore.send({ + senderSeq: this.loginRes.userSeq, + req: { + roomSeq: this.roomInfo.roomSeq, + eventType: EventType.Sticker, + sentMessage: JSON.stringify(stickerJson) + } + }) + ); + this.isShowStickerSelector = false; + this.setStickerHistory(this.selectedSticker); + } else if (message.trim().length > CONST.MASSTEXT_LEN) { // MASS TEXT this.store.dispatch( EventStore.sendMass({ @@ -472,18 +584,17 @@ export class MessagesComponent implements OnInit, OnDestroy, AfterViewInit { } async onFileViewer(fileInfo: FileEventJson) { - this.logger.debug('onFileViewer', fileInfo); const result = await this.dialogService.open< FileViewerDialogComponent, FileViewerDialogData, FileViewerDialogResult >(FileViewerDialogComponent, { position: { - top: '30px' + top: '50px' }, maxWidth: '100vw', maxHeight: '100vh', - height: 'calc(100% - 30px)', + height: 'calc(100% - 50px)', width: '100%', hasBackdrop: false, panelClass: 'app-dialog-full', @@ -503,6 +614,7 @@ export class MessagesComponent implements OnInit, OnDestroy, AfterViewInit { } onFileDragEnter(items: DataTransferItemList) { + this.clearView(); this.logger.debug('onFileDragEnter', items); } @@ -516,6 +628,7 @@ export class MessagesComponent implements OnInit, OnDestroy, AfterViewInit { async onFileSelected(fileUploadItems: FileUploadItem[]) { this.logger.debug('onFileSelected', fileUploadItems); + this.clearView(); const info = { senderSeq: this.loginRes.userSeq, @@ -595,6 +708,18 @@ export class MessagesComponent implements OnInit, OnDestroy, AfterViewInit { }, error => { this.logger.debug('onFileSelected error', error); + this.fileUploadQueue.onUploadComplete(); + + this.dialogService.open< + AlertDialogComponent, + AlertDialogData, + AlertDialogResult + >(AlertDialogComponent, { + data: { + title: 'Alert', + html: `파일전송에 실패하였습니다.
계속 문제 발생 시 관리자에게 문의하세요.` + } + }); }, () => { this.fileUploadQueue.onUploadComplete(); @@ -740,7 +865,7 @@ export class MessagesComponent implements OnInit, OnDestroy, AfterViewInit { ConfirmDialogData, ConfirmDialogResult >(ConfirmDialogComponent, { - width: '220px', + width: '400px', data: { title: 'Delete', html: `선택한 메시지를 삭제하시겠습니까?
삭제된 메시지는 내 대화방에서만 적용되며 상대방의 대화방에서는 삭제되지 않습니다.` @@ -764,7 +889,7 @@ export class MessagesComponent implements OnInit, OnDestroy, AfterViewInit { ConfirmDialogData, ConfirmDialogResult >(ConfirmDialogComponent, { - width: '220px', + width: '400px', data: { title: 'ReCall', html: `해당 대화를 회수하시겠습니까?
상대방 대화창에서도 회수됩니다.` @@ -789,6 +914,33 @@ export class MessagesComponent implements OnInit, OnDestroy, AfterViewInit { async onClickContextMenu(menuType: string) { switch (menuType) { + case 'OPEN_ALBUM_LIST': + { + this.store.dispatch( + ChatStore.selectedRightDrawer({ + req: RightDrawer.AlbumBox + }) + ); + } + break; + case 'OPEN_FILE_LIST': + { + this.store.dispatch( + ChatStore.selectedRightDrawer({ + req: RightDrawer.FileBox + }) + ); + } + break; + case 'OPEN_ROOM_USER': + { + this.store.dispatch( + ChatStore.selectedRightDrawer({ + req: RightDrawer.RoomUser + }) + ); + } + break; case 'ADD_MEMBER': { const result = await this.dialogService.open< @@ -807,13 +959,17 @@ export class MessagesComponent implements OnInit, OnDestroy, AfterViewInit { }); if (!!result && !!result.choice && result.choice) { - const userSeqs: number[] = []; + const userSeqs: number[] = this.userInfoList.map( + userInfo => userInfo.seq + ); if ( !!result.selectedUserList && result.selectedUserList.length > 0 ) { - result.selectedUserList.map(user => { - userSeqs.push(user.seq); + result.selectedUserList.forEach(user => { + if (userSeqs.indexOf(user.seq) < 0) { + userSeqs.push(user.seq); + } }); } @@ -833,6 +989,40 @@ export class MessagesComponent implements OnInit, OnDestroy, AfterViewInit { } } break; + case 'ADD_GROUP': + { + 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 + }) + ); + } + } + } + break; case 'EDIT_ROOM': { const result = await this.dialogService.open< @@ -890,4 +1080,42 @@ export class MessagesComponent implements OnInit, OnDestroy, AfterViewInit { break; } } + + onClickOpenProfile(userInfo: UserInfo) { + if ( + this.roomInfo.roomType !== RoomType.Allim && + this.roomInfo.roomType !== RoomType.Bot + ) { + this.openProfile.emit(userInfo); + } + } + + /** About Sticker */ + onShowToggleStickerSelector() { + this.isShowStickerSelector = !this.isShowStickerSelector; + } + + onSelectedSticker(stickerInfo: StickerFilesInfo) { + this.selectedSticker = stickerInfo; + } + setStickerHistory(sticker: StickerFilesInfo) { + const history = this.localStorageService.get(KEY_STICKER_HISTORY); + + if (!!history && history.length > 0) { + const stickers: string[] = []; + [sticker.index, ...history.filter(hist => hist !== sticker.index)].map( + (s, i) => { + if (i < 10) { + stickers.push(s); + } + } + ); + + this.localStorageService.set(KEY_STICKER_HISTORY, stickers); + } else { + this.localStorageService.set(KEY_STICKER_HISTORY, [ + sticker.index + ]); + } + } } diff --git a/projects/ucap-webmessenger-app/src/app/layouts/messenger/components/right-drawer.component.html b/projects/ucap-webmessenger-app/src/app/layouts/messenger/components/right-drawer.component.html new file mode 100644 index 0000000..2fc056d --- /dev/null +++ b/projects/ucap-webmessenger-app/src/app/layouts/messenger/components/right-drawer.component.html @@ -0,0 +1,32 @@ +
+

{{ selectedRightDrawer }}

+ + + +
+ + + + + + + + + + + + + + + diff --git a/projects/ucap-webmessenger-app/src/app/layouts/messenger/components/right-drawer.component.scss b/projects/ucap-webmessenger-app/src/app/layouts/messenger/components/right-drawer.component.scss new file mode 100644 index 0000000..1d0e594 --- /dev/null +++ b/projects/ucap-webmessenger-app/src/app/layouts/messenger/components/right-drawer.component.scss @@ -0,0 +1,19 @@ +.rightDrawer-title{ + height: 60px; + border-bottom: 1px solid #dddddd; + font-size: 16px; + align-items: center; + display: flex; + padding: 0 20px; + font-weight: 600; + span{ + margin-left:auto; + } +} +::ng-deep .mat-tab-labels { + display: flex; + width: 100%; + border-bottom: 2px solid #dddddd; + flex: 1 1 auto; + justify-content: space-around; +} \ No newline at end of file diff --git a/projects/ucap-webmessenger-app/src/app/layouts/messenger/components/right-drawer.component.spec.ts b/projects/ucap-webmessenger-app/src/app/layouts/messenger/components/right-drawer.component.spec.ts new file mode 100644 index 0000000..d8a9a8b --- /dev/null +++ b/projects/ucap-webmessenger-app/src/app/layouts/messenger/components/right-drawer.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { RightDrawerComponent } from './right-drawer.component'; + +describe('RightDrawerComponent', () => { + let component: RightDrawerComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ RightDrawerComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(RightDrawerComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/projects/ucap-webmessenger-app/src/app/layouts/messenger/components/right-drawer.component.ts b/projects/ucap-webmessenger-app/src/app/layouts/messenger/components/right-drawer.component.ts new file mode 100644 index 0000000..7016d3f --- /dev/null +++ b/projects/ucap-webmessenger-app/src/app/layouts/messenger/components/right-drawer.component.ts @@ -0,0 +1,39 @@ +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'], +}) +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(); + } +} diff --git a/projects/ucap-webmessenger-app/src/app/layouts/messenger/components/right-drawer/album-box.component.html b/projects/ucap-webmessenger-app/src/app/layouts/messenger/components/right-drawer/album-box.component.html new file mode 100644 index 0000000..7440c9c --- /dev/null +++ b/projects/ucap-webmessenger-app/src/app/layouts/messenger/components/right-drawer/album-box.component.html @@ -0,0 +1,154 @@ +
+
+ + + + +
+
+ + + +
+ + + + + + Select File. +
+ +
+ + + + + + + + + + + Select File. +
+
+ +
+ + +
+
    +
  • {{ selectedFile.info.name }}
  • +
  • + size : + {{ selectedFile.info.size | ucapBytes }} +
  • +
  • + date : + {{ selectedFile.info.sendDate | dateToStringFormat: 'YYYY.MM.DD' }} +
  • +
+
+
+
+ +
+
+
+
+ + + + +
+
+
+
+
+
+ + + + + + + +
+
+
+
+
+
+ + +
+
diff --git a/projects/ucap-webmessenger-app/src/app/layouts/messenger/components/right-drawer/album-box.component.scss b/projects/ucap-webmessenger-app/src/app/layouts/messenger/components/right-drawer/album-box.component.scss new file mode 100644 index 0000000..0facfaf --- /dev/null +++ b/projects/ucap-webmessenger-app/src/app/layouts/messenger/components/right-drawer/album-box.component.scss @@ -0,0 +1,123 @@ +@mixin ellipsis($row) { + overflow: hidden; + text-overflow: ellipsis; + @if $row == 1 { + display: block; + white-space: nowrap; + word-wrap: normal; + } @else if $row >= 2 { + display: -webkit-box; + -webkit-line-clamp: $row; + -webkit-box-orient: vertical; + word-wrap: break-word; + } +} + +::ng-deep .rightDrawer-albumbox { + height: 100%; + overflow: hidden; + .mat-tab-labels { + .mat-tab-label { + width: 50%; + } + } +} + +.select-filebox{ + display:flex; + flex-flow: column; + margin:10px; + padding:10px; + border:1px solid #cccccc; + border-radius: 4px; + .select-file{ + color: #212121; + border-bottom: 1px dotted #dddddd; + text-align:center; + padding-bottom:10px; + } + ul{ + padding-top:10px; + li{ + @include ellipsis(1); + &.name{ + font-weight:600; + } + } + } + .empty-msg{ + display:inline-flex; + flex-flow: column; + margin:auto 0; + align-items: center; + justify-content: center; + color:#999999; + span{ + padding:6px; + } + } +} + +.search-list{ + display:flex; + padding:0 10px; + height: calc(100% - 450px); + overflow-y: auto; + flex-wrap: wrap; + + .img-item { + cursor: pointer; + margin-bottom:10px; + margin-right:9px; + position: relative; + height: 150px; + dl{ + dt{ + display: flex; + justify-content: center; + align-items: center; + width: 120px; + height: 120px; + background-color: #efefef; + border: 1px dotted #cccccc; + box-sizing: border-box; + img{ + width:100%; + height:100%; + } + } + dd{ + .btn-download{ + margin-left:auto; + } + } + } + &:nth-child(3n+0){ + margin-right:0; + } + } +} + +::ng-deep .album-scrollbar{ + .ps{ + .ps-content{ + display:flex; + flex-flow: wrap; + } + } +} +.preview-image, +.preview-video{ + max-height: 140px; +} + +.btn-box { + position:absolute; + bottom:0; + height:50px; + margin-bottom:10px; + width:100%; + button { + margin: 5px; + } +} diff --git a/projects/ucap-webmessenger-app/src/app/layouts/messenger/components/right-drawer/album-box.component.spec.ts b/projects/ucap-webmessenger-app/src/app/layouts/messenger/components/right-drawer/album-box.component.spec.ts new file mode 100644 index 0000000..77cb6d3 --- /dev/null +++ b/projects/ucap-webmessenger-app/src/app/layouts/messenger/components/right-drawer/album-box.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { AlbumBoxComponent } from './album-box.component'; + +describe('AlbumBoxComponent', () => { + let component: AlbumBoxComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ AlbumBoxComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(AlbumBoxComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/projects/ucap-webmessenger-app/src/app/layouts/messenger/components/right-drawer/album-box.component.ts b/projects/ucap-webmessenger-app/src/app/layouts/messenger/components/right-drawer/album-box.component.ts new file mode 100644 index 0000000..772559c --- /dev/null +++ b/projects/ucap-webmessenger-app/src/app/layouts/messenger/components/right-drawer/album-box.component.ts @@ -0,0 +1,198 @@ +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; +} + +@Component({ + selector: 'app-layout-chat-right-drawer-album-box', + templateUrl: './album-box.component.html', + styleUrls: ['./album-box.component.scss'], +}) +export class AlbumBoxComponent implements OnInit, OnDestroy { + filteredList: FileInfoTotal[] = []; + fileInfoTotal: FileInfoTotal[]; + fileInfoList: FileInfo[]; + fileInfoListSubscription: Subscription; + + selectedFile: FileInfoTotal; + selectedFileList: FileInfoTotal[] = []; + + loginRes: LoginResponse; + environmentsInfo: EnvironmentsInfo; + sessionVerinfo: VersionInfo2Response; + + FileType = FileType; + currentTabIndex = 0; + + constructor( + private store: Store, + private sessionStorageService: SessionStorageService, + private commonApiService: CommonApiService + ) { + this.loginRes = this.sessionStorageService.get( + KEY_LOGIN_RES_INFO + ); + this.environmentsInfo = this.sessionStorageService.get( + KEY_ENVIRONMENTS_INFO + ); + this.sessionVerinfo = this.sessionStorageService.get( + 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) : 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); + } +} diff --git a/projects/ucap-webmessenger-app/src/app/layouts/messenger/components/right-drawer/file-box.component.html b/projects/ucap-webmessenger-app/src/app/layouts/messenger/components/right-drawer/file-box.component.html new file mode 100644 index 0000000..fbb91cc --- /dev/null +++ b/projects/ucap-webmessenger-app/src/app/layouts/messenger/components/right-drawer/file-box.component.html @@ -0,0 +1,204 @@ +
+
+ + + + +
+
+ +
+ + + + + Select File. +
+
+ +
+
+
+
+
    +
  • {{ selectedFile.info.name }}
  • +
  • size : {{ selectedFile.info.size | ucapBytes }}
  • +
  • + date : + {{ selectedFile.info.sendDate | dateToStringFormat: 'YYYY.MM.DD' }} +
  • +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+ + + + + + + + + + + + + + + + +
+ + + + + + + Name + +
+ {{ element.info.name }} +
+
+ + {{ element.info.sendDate | dateToStringFormat: 'YYYY.MM.DD' }} ~ + 2020.01.23 +
+
sendDate + + {{ element.info.size | ucapBytes }} +
+
+
+ +
diff --git a/projects/ucap-webmessenger-app/src/app/layouts/messenger/components/right-drawer/file-box.component.scss b/projects/ucap-webmessenger-app/src/app/layouts/messenger/components/right-drawer/file-box.component.scss new file mode 100644 index 0000000..bd6e8c3 --- /dev/null +++ b/projects/ucap-webmessenger-app/src/app/layouts/messenger/components/right-drawer/file-box.component.scss @@ -0,0 +1,171 @@ +@mixin ellipsis($row) { + overflow: hidden; + text-overflow: ellipsis; + @if $row == 1 { + display: block; + white-space: nowrap; + word-wrap: normal; + } @else if $row >= 2 { + display: -webkit-box; + -webkit-line-clamp: $row; + -webkit-box-orient: vertical; + word-wrap: break-word; + } +} + +::ng-deep .rightDrawer-filebox { + width: 100%; + height: calc(100% - 60px); + .rightDrawer-tab { + .mat-tab-label { + width: 50%; + } + } +} + +.select-filebox { + position: relative; + display: flex; + flex-flow: column; + margin: 10px; + border: 1px solid #cccccc; + border-radius: 4px; + .select-flie { + display: flex; + flex-flow: row; + align-items: center; + color: #212121; + align-items: center; + padding: 10px; + border-bottom: 1px dotted #dddddd; + ul { + padding: 0; + .name { + font-weight: 600; + } + } + } + .empty-msg { + display: inline-flex; + flex-flow: column; + margin: auto 0; + align-items: center; + justify-content: center; + color: #999999; + span { + padding: 6px; + } + } + .select-file-option { + position: absolute; + display: flex; + justify-content: space-between; + width: 100%; + text-align: center; + padding: 10px 0; + bottom: 4px; + span { + width: 28px; + height: 28px; + display: inline-flex; + text-align: center; + justify-content: center; + align-items: center; + margin: 0 20px; + cursor: pointer; + svg { + } + &:hover { + border-radius: 50%; + background-color: #999999; + color: #ffffff !important; + } + } + } +} + +.mat-table { + width: 100%; + position: relative; + th.infos { + padding: 10px; + } + tr.mat-row { + height: 70px; + .file-info { + padding: 16px; + display: grid; + height: 70px; + .file-name { + font-weight: 600; + margin-bottom: 2px; + width: 100%; + @include ellipsis(1); + } + .download-period { + font-size: 12px; + width: 100%; + @include ellipsis(1); + } + } + } +} +.table-box { + height: calc(100% - 440px); + overflow-y: auto; +} +.mat-paginator-container { + display: flex; + flex-flow: column; +} + +.mat-row:hover { + background: rgba(0, 0, 0, 0.04); + cursor: pointer; +} + +.footer-fix { + position: absolute; + bottom: 0; + height: 160px; + flex-direction: column; + box-sizing: border-box; + display: flex; + border-top: 1px solid #dddddd; + .btn-box { + height: 50px; + padding-bottom: 10px; + width: 100%; + background-color: #ffffff; + button { + margin: 5px; + } + } +} + +::ng-deep .mat-paginator { + .mat-paginator-container { + justify-content: center; + } + .mat-paginator-navigation-first { + order: 1; + } + .mat-paginator-navigation-previous { + order: 2; + } + // override material paginator page switch + .mat-paginator-range-label { + order: 3; + } + .mat-paginator-navigation-next { + order: 4; + } + .mat-paginator-navigation-last { + order: 5; + } +} +::ng-deep .mat-form-field-appearance-legacy { + .mat-form-field-infix { + padding: 6px; + } +} diff --git a/projects/ucap-webmessenger-app/src/app/layouts/messenger/components/right-drawer/file-box.component.spec.ts b/projects/ucap-webmessenger-app/src/app/layouts/messenger/components/right-drawer/file-box.component.spec.ts new file mode 100644 index 0000000..065e1da --- /dev/null +++ b/projects/ucap-webmessenger-app/src/app/layouts/messenger/components/right-drawer/file-box.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { FileBoxComponent } from './file-box.component'; + +describe('FileBoxComponent', () => { + let component: FileBoxComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ FileBoxComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(FileBoxComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/projects/ucap-webmessenger-app/src/app/layouts/messenger/components/right-drawer/file-box.component.ts b/projects/ucap-webmessenger-app/src/app/layouts/messenger/components/right-drawer/file-box.component.ts new file mode 100644 index 0000000..fb51a0b --- /dev/null +++ b/projects/ucap-webmessenger-app/src/app/layouts/messenger/components/right-drawer/file-box.component.ts @@ -0,0 +1,215 @@ +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'] +}) +export class FileBoxComponent implements OnInit, OnDestroy { + displayedColumns: string[] = ['check', 'name', 'sendDate']; + dataSource = new MatTableDataSource(); + + 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, + private sessionStorageService: SessionStorageService + ) { + this.loginRes = this.sessionStorageService.get( + 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; + default: + return item.info[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.length === 0) { + return false; + } + + 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; + } +} diff --git a/projects/ucap-webmessenger-app/src/app/layouts/messenger/components/right-drawer/index.ts b/projects/ucap-webmessenger-app/src/app/layouts/messenger/components/right-drawer/index.ts new file mode 100644 index 0000000..c51042c --- /dev/null +++ b/projects/ucap-webmessenger-app/src/app/layouts/messenger/components/right-drawer/index.ts @@ -0,0 +1,9 @@ +import { FileBoxComponent } from './file-box.component'; +import { AlbumBoxComponent } from './album-box.component'; +import { RoomUserListComponent } from './room-user-list.component'; + +export const RIGHT_DRAWER_COMPONENTS = [ + FileBoxComponent, + AlbumBoxComponent, + RoomUserListComponent +]; diff --git a/projects/ucap-webmessenger-app/src/app/layouts/messenger/components/right-drawer/room-user-list.component.html b/projects/ucap-webmessenger-app/src/app/layouts/messenger/components/right-drawer/room-user-list.component.html new file mode 100644 index 0000000..326e568 --- /dev/null +++ b/projects/ucap-webmessenger-app/src/app/layouts/messenger/components/right-drawer/room-user-list.component.html @@ -0,0 +1,25 @@ +
+
+ + +
+
+ + +
+
diff --git a/projects/ucap-webmessenger-app/src/app/layouts/messenger/components/right-drawer/room-user-list.component.scss b/projects/ucap-webmessenger-app/src/app/layouts/messenger/components/right-drawer/room-user-list.component.scss new file mode 100644 index 0000000..7954480 --- /dev/null +++ b/projects/ucap-webmessenger-app/src/app/layouts/messenger/components/right-drawer/room-user-list.component.scss @@ -0,0 +1,16 @@ +@import "../../../../../../../ucap-webmessenger-ui/src/assets/scss/partials/presence"; +.list { + width: 100%; + height: 100%; + overflow: hidden; + + .search-list { + overflow: auto; + } +} + +.btn-box { + button { + margin: 5px; + } +} diff --git a/projects/ucap-webmessenger-app/src/app/layouts/messenger/components/right-drawer/room-user-list.component.spec.ts b/projects/ucap-webmessenger-app/src/app/layouts/messenger/components/right-drawer/room-user-list.component.spec.ts new file mode 100644 index 0000000..d6ce153 --- /dev/null +++ b/projects/ucap-webmessenger-app/src/app/layouts/messenger/components/right-drawer/room-user-list.component.spec.ts @@ -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; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ RoomUserListComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(RoomUserListComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/projects/ucap-webmessenger-app/src/app/layouts/messenger/components/right-drawer/room-user-list.component.ts b/projects/ucap-webmessenger-app/src/app/layouts/messenger/components/right-drawer/room-user-list.component.ts new file mode 100644 index 0000000..35c695c --- /dev/null +++ b/projects/ucap-webmessenger-app/src/app/layouts/messenger/components/right-drawer/room-user-list.component.ts @@ -0,0 +1,172 @@ +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(); + + userInfoList: UserInfo[]; + userInfoListSubscription: Subscription; + + loginRes: LoginResponse; + sessionVerinfo: VersionInfo2Response; + + constructor( + private store: Store, + private sessionStorageService: SessionStorageService, + private dialogService: DialogService + ) { + this.loginRes = this.sessionStorageService.get( + KEY_LOGIN_RES_INFO + ); + this.sessionVerinfo = this.sessionStorageService.get( + 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[] = this.userInfoList.map( + userInfo => userInfo.seq + ); + if (!!result.selectedUserList && result.selectedUserList.length > 0) { + result.selectedUserList.forEach(user => { + if (userSeqs.indexOf(user.seq) < 0) { + 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 + }) + ); + } + } + } +} diff --git a/projects/ucap-webmessenger-app/src/app/layouts/messenger/dialogs/chat/create-chat.dialog.component.html b/projects/ucap-webmessenger-app/src/app/layouts/messenger/dialogs/chat/create-chat.dialog.component.html index 23a40c6..2ee7eae 100644 --- a/projects/ucap-webmessenger-app/src/app/layouts/messenger/dialogs/chat/create-chat.dialog.component.html +++ b/projects/ucap-webmessenger-app/src/app/layouts/messenger/dialogs/chat/create-chat.dialog.component.html @@ -34,9 +34,25 @@ > - group + + + + + + + -
+
-
+
-
-
- +
+
+
+ +
+
검색결과
@@ -98,10 +128,13 @@
@@ -112,20 +145,6 @@ chat
-
- {{ selectedUserList.length }}명 + {{ selectedUserList.length }}명
@@ -167,7 +188,12 @@ > No - diff --git a/projects/ucap-webmessenger-app/src/app/layouts/messenger/dialogs/chat/create-chat.dialog.component.scss b/projects/ucap-webmessenger-app/src/app/layouts/messenger/dialogs/chat/create-chat.dialog.component.scss index 711b0d9..d803389 100644 --- a/projects/ucap-webmessenger-app/src/app/layouts/messenger/dialogs/chat/create-chat.dialog.component.scss +++ b/projects/ucap-webmessenger-app/src/app/layouts/messenger/dialogs/chat/create-chat.dialog.component.scss @@ -6,21 +6,25 @@ ::ng-deep .dialog-org { .oraganization-tab { width: 100%; - height:380px; + height: 380px; border-bottom: 1px solid #dddddd; position: relative; .oraganization-tab-tree { display: inline-flex; width: 50%; - height:100% !important; + height: 100% !important; border-right: 1px solid #dddddd; overflow: auto; + .tab-tree-frame { + width: 100%; + height: 100%; + } } .select-list { display: inline-flex; flex-direction: column; width: 50%; - height:100% !important; + height: 100% !important; overflow: auto; .search-list { overflow: auto; @@ -33,12 +37,12 @@ .list-chip { height: 100px; width: 100%; - padding:10px; - border:1px solid #dddddd; + padding: 10px; + border: 1px solid #dddddd; overflow: auto; - background-color:#f9f9f9; + background-color: #f9f9f9; } -.mat-chip.mat-standard-chip .mat-chip-remove{ +.mat-chip.mat-standard-chip .mat-chip-remove { line-height: 24px; } .confirm-card { @@ -64,15 +68,42 @@ } } } + ::ng-deep .mat-dialog-container .mat-tab-body-wrapper { height: 380px; -} -.list-panel{ - overflow: auto; - height: calc(100% - 60px); - .group-expansion{ - .list-item{ - height:70px; - } + width: 100%; + .mat-tab-body { + width: 100%; + height: 100%; + .mat-tab-body-content { + width: 100%; + height: 100%; + } } } +.mat-tab-frame { + width: 100%; + height: 100%; + .list-panel { + width: 100%; + height: calc(100% - 60px); + .group-expansion { + .list-item { + height: 70px; + } + } + } +} +::ng-deep .mat-card > .mat-tab-labels { + border-bottom: 2px solid #dddddd; +} +::ng-deep .ps-content { + .cdk-virtual-scroll-viewport { + height: 100%; + } +} + +.list-item-frame { + width: 100%; + height: 100%; +} diff --git a/projects/ucap-webmessenger-app/src/app/layouts/messenger/dialogs/chat/create-chat.dialog.component.ts b/projects/ucap-webmessenger-app/src/app/layouts/messenger/dialogs/chat/create-chat.dialog.component.ts index 0881d26..a9bd462 100644 --- a/projects/ucap-webmessenger-app/src/app/layouts/messenger/dialogs/chat/create-chat.dialog.component.ts +++ b/projects/ucap-webmessenger-app/src/app/layouts/messenger/dialogs/chat/create-chat.dialog.component.ts @@ -48,6 +48,12 @@ import { UserInfoShort, UserInfo as RoomUserInfo } from '@ucap-webmessenger/protocol-room'; +import { + ConfirmDialogComponent, + ConfirmDialogResult, + ConfirmDialogData, + DialogService +} from '@ucap-webmessenger/ui'; export interface CreateChatDialogData { type?: string; @@ -62,7 +68,8 @@ export interface CreateChatDialogData { | UserInfoSS | UserInfoF | UserInfoDN - | RoomUserInfo)[]; + | RoomUserInfo + )[]; } export interface CreateChatDialogResult { @@ -72,7 +79,8 @@ export interface CreateChatDialogResult { | UserInfoSS | UserInfoF | UserInfoDN - | RoomUserInfo)[]; + | RoomUserInfo + )[]; selectedRoom?: RoomInfo; groupName?: string; oldGroup?: GroupDetailData; @@ -94,13 +102,16 @@ export class CreateChatDialogComponent implements OnInit, OnDestroy { private sessionStorageService: SessionStorageService, private queryProtocolService: QueryProtocolService, private formBuilder: FormBuilder, - private logger: NGXLogger + private logger: NGXLogger, + private dialogService: DialogService ) { this.sessionVerinfo = this.sessionStorageService.get( KEY_VER_INFO ); } + currentTabIndex: number; + UserSelectDialogType = UserSelectDialogType; loginRes: LoginResponse; @@ -132,7 +143,8 @@ export class CreateChatDialogComponent implements OnInit, OnDestroy { | UserInfoSS | UserInfoF | UserInfoDN - | RoomUserInfo)[] = []; + | RoomUserInfo + )[] = []; isShowSelectedUserList = true; selectedRoom: RoomInfo; @@ -227,6 +239,8 @@ export class CreateChatDialogComponent implements OnInit, OnDestroy { if (this.data.type === UserSelectDialogType.EditChatMember) { this.selectedUserList = this.data.curRoomUser; } + + this.currentTabIndex = 0; } ngOnDestroy(): void { @@ -274,6 +288,8 @@ export class CreateChatDialogComponent implements OnInit, OnDestroy { } onSelectedTabChange(tabChangeEvent: MatTabChangeEvent): void { + this.currentTabIndex = tabChangeEvent.index; + if (tabChangeEvent.index === 2) { this.selectedUserList = []; this.isShowSelectedUserList = false; @@ -366,6 +382,7 @@ export class CreateChatDialogComponent implements OnInit, OnDestroy { } } + /** 조직도 > 부서원 전체 선택 */ onCheckAllUser(params: { isChecked: boolean; userInfos: (UserInfo | UserInfoSS | UserInfoF | UserInfoDN)[]; @@ -404,6 +421,19 @@ export class CreateChatDialogComponent implements OnInit, OnDestroy { item => item.seq !== params.userInfo.seq ); } + console.log(this.selectedUserList); + } + onToggleUser(userInfo: UserInfo | UserInfoSS | UserInfoF | UserInfoDN) { + if ( + this.selectedUserList.filter(user => user.seq === userInfo.seq).length === + 0 + ) { + this.selectedUserList = [...this.selectedUserList, userInfo]; + } else { + this.selectedUserList = this.selectedUserList.filter( + item => item.seq !== userInfo.seq + ); + } } /** 대화방 > 대화방 선택 :: 해당 팝업에서는 대화방을 중복 선택하지 않는다 */ @@ -427,12 +457,13 @@ export class CreateChatDialogComponent implements OnInit, OnDestroy { } getCheckableRoom(roomInfo: RoomInfo) { - if (!!this.data.ignoreRoom && this.data.ignoreRoom.length > 0) { - return !( - this.data.ignoreRoom.filter(room => room.roomSeq === roomInfo.roomSeq) - .length > 0 - ); - } + // // 현재 방도 체크 전달 할수 있도록 수정. (끌어올리기 개념.) + // if (!!this.data.ignoreRoom && this.data.ignoreRoom.length > 0) { + // return !( + // this.data.ignoreRoom.filter(room => room.roomSeq === roomInfo.roomSeq) + // .length > 0 + // ); + // } return true; } getCheckedRoom(roomInfo: RoomInfo) { @@ -449,8 +480,41 @@ export class CreateChatDialogComponent implements OnInit, OnDestroy { ); } + getBtnValid() { + if (this.data.type === UserSelectDialogType.NewGroup) { + return this.inputForm.invalid; + } else { + return false; + } + } + /** 팝업의 선택 이벤트 전달. */ - onClickChoice(choice: boolean): void { + async onClickChoice(choice: boolean): Promise { + if (this.data.type === UserSelectDialogType.NewGroup) { + let cfmMsg = `새로운 그룹을 추가하시겠습니까?`; + if (this.selectedUserList.length === 0) { + cfmMsg += `
빈 그룹으로 생성됩니다.`; + } + const result = await this.dialogService.open< + ConfirmDialogComponent, + ConfirmDialogData, + ConfirmDialogResult + >(ConfirmDialogComponent, { + width: '400px', + data: { + title: 'Delete', + html: cfmMsg + } + }); + + if (!!result && !!result.choice && result.choice) { + this.doAction(choice); + } + } else { + this.doAction(choice); + } + } + doAction(choice: boolean) { this.dialogRef.close({ choice, selectedUserList: this.selectedUserList, diff --git a/projects/ucap-webmessenger-app/src/app/layouts/messenger/dialogs/chat/edit-chat-room.dialog.component.html b/projects/ucap-webmessenger-app/src/app/layouts/messenger/dialogs/chat/edit-chat-room.dialog.component.html index 6b205e6..8924fa5 100644 --- a/projects/ucap-webmessenger-app/src/app/layouts/messenger/dialogs/chat/edit-chat-room.dialog.component.html +++ b/projects/ucap-webmessenger-app/src/app/layouts/messenger/dialogs/chat/edit-chat-room.dialog.component.html @@ -5,7 +5,7 @@
- + + + {{ data.title }} + + + +

+
+
+ + + + diff --git a/projects/ucap-webmessenger-app/src/app/layouts/messenger/dialogs/chat/mass-detail.component.scss b/projects/ucap-webmessenger-app/src/app/layouts/messenger/dialogs/chat/mass-detail.component.scss new file mode 100644 index 0000000..9968576 --- /dev/null +++ b/projects/ucap-webmessenger-app/src/app/layouts/messenger/dialogs/chat/mass-detail.component.scss @@ -0,0 +1,25 @@ +::ng-deep .mat-card-header-tex { + margin: 0; +} +.confirm-card { + min-width: 500px; + .mat-card-header { + margin-bottom: 20px; + .mat-card-header-text { + .mat-card-title { + margin: 0 -16px; + } + } + } + .button-farm { + text-align: right; + .mat-primary { + margin-left: 4px; + } + } +} + +.contnets { + max-height: 500px; + word-break: break-word; +} diff --git a/projects/ucap-webmessenger-app/src/app/layouts/messenger/dialogs/chat/mass-detail.component.spec.ts b/projects/ucap-webmessenger-app/src/app/layouts/messenger/dialogs/chat/mass-detail.component.spec.ts new file mode 100644 index 0000000..bf54e62 --- /dev/null +++ b/projects/ucap-webmessenger-app/src/app/layouts/messenger/dialogs/chat/mass-detail.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { MassDetailComponent } from './mass-detail.component'; + +describe('MassDetailComponent', () => { + let component: MassDetailComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ MassDetailComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(MassDetailComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/projects/ucap-webmessenger-app/src/app/layouts/messenger/dialogs/chat/mass-detail.component.ts b/projects/ucap-webmessenger-app/src/app/layouts/messenger/dialogs/chat/mass-detail.component.ts new file mode 100644 index 0000000..d06b360 --- /dev/null +++ b/projects/ucap-webmessenger-app/src/app/layouts/messenger/dialogs/chat/mass-detail.component.ts @@ -0,0 +1,58 @@ +import { + Component, + OnInit, + Inject, + ElementRef, + AfterViewInit +} from '@angular/core'; +import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material'; +import { UCAP_NATIVE_SERVICE, NativeService } from '@ucap-webmessenger/native'; + +export interface MassDetailDialogData { + title: string; + contents: string; +} + +// tslint:disable-next-line: no-empty-interface +export interface MassDetailDialogResult {} + +@Component({ + selector: 'app-layout-messenger-mass-detail', + templateUrl: './mass-detail.component.html', + styleUrls: ['./mass-detail.component.scss'] +}) +export class MassDetailComponent implements OnInit, AfterViewInit { + constructor( + public dialogRef: MatDialogRef< + MassDetailDialogData, + MassDetailDialogResult + >, + @Inject(MAT_DIALOG_DATA) public data: MassDetailDialogData, + private elementRef: ElementRef, + @Inject(UCAP_NATIVE_SERVICE) private nativeService: NativeService + ) {} + + ngOnInit() {} + + ngAfterViewInit(): void { + if ( + !!this.elementRef.nativeElement && + !!this.elementRef.nativeElement.querySelector('a') + ) { + const elements = this.elementRef.nativeElement.querySelectorAll('a'); + elements.forEach(element => { + element.addEventListener('click', this.onClickEvent.bind(this)); + }); + } + } + + onClickEvent(event: MouseEvent) { + this.nativeService.openDefaultBrowser( + (event.target as HTMLAnchorElement).text + ); + } + + onClickConfirm(): void { + this.dialogRef.close(); + } +} diff --git a/projects/ucap-webmessenger-app/src/app/layouts/messenger/dialogs/group/edit-group.dialog.component.html b/projects/ucap-webmessenger-app/src/app/layouts/messenger/dialogs/group/edit-group.dialog.component.html index 06db2dd..24f3c32 100644 --- a/projects/ucap-webmessenger-app/src/app/layouts/messenger/dialogs/group/edit-group.dialog.component.html +++ b/projects/ucap-webmessenger-app/src/app/layouts/messenger/dialogs/group/edit-group.dialog.component.html @@ -28,4 +28,4 @@ Yes - + \ No newline at end of file diff --git a/projects/ucap-webmessenger-app/src/app/layouts/messenger/dialogs/group/edit-group.dialog.component.scss b/projects/ucap-webmessenger-app/src/app/layouts/messenger/dialogs/group/edit-group.dialog.component.scss index d6fb4a0..22d70b5 100644 --- a/projects/ucap-webmessenger-app/src/app/layouts/messenger/dialogs/group/edit-group.dialog.component.scss +++ b/projects/ucap-webmessenger-app/src/app/layouts/messenger/dialogs/group/edit-group.dialog.component.scss @@ -23,5 +23,4 @@ form{ .mat-form-field{ width:100%; } -} - +} \ No newline at end of file diff --git a/projects/ucap-webmessenger-app/src/app/layouts/messenger/dialogs/group/select-group.dialog.component.html b/projects/ucap-webmessenger-app/src/app/layouts/messenger/dialogs/group/select-group.dialog.component.html index afc155e..ee657ad 100644 --- a/projects/ucap-webmessenger-app/src/app/layouts/messenger/dialogs/group/select-group.dialog.component.html +++ b/projects/ucap-webmessenger-app/src/app/layouts/messenger/dialogs/group/select-group.dialog.component.html @@ -40,16 +40,18 @@
- - -
-
@@ -57,7 +59,10 @@ *ngFor="let groupBuddy of groupBuddyList$ | async" [value]="groupBuddy.group" > - {{ groupBuddy.group.name }} + {{ groupBuddy.group.name }} + ({{ groupBuddy.buddyList.length }}명) +
+ + + + + + diff --git a/projects/ucap-webmessenger-app/src/app/layouts/messenger/dialogs/settings/messenger-settings.dialog.component.scss b/projects/ucap-webmessenger-app/src/app/layouts/messenger/dialogs/settings/messenger-settings.dialog.component.scss new file mode 100644 index 0000000..df5512b --- /dev/null +++ b/projects/ucap-webmessenger-app/src/app/layouts/messenger/dialogs/settings/messenger-settings.dialog.component.scss @@ -0,0 +1,112 @@ +::ng-deep .setting-frame { + padding: 16px; + height: 100%; + min-width: 500px; + position: relative; + + .mat-dialog-container { + position: relative; + } + + .mat-card-header { + position: relative; + width: 100%; + border-bottom: 1px solid #dddddd; + margin-bottom: 12px; + } + + .mat-card-content { + flex: 0 0 auto; + display: flex; + align-items: flex-start; + height: calc(100% - 100px); + border-bottom: 1px solid #dddddd; + .setting-tab { + position: relative; + width: 100%; + height: 100%; + .mat-tab-group { + flex-direction: row; + .mat-tab-header { + width: 160px; + .mat-tab-labels { + flex-direction: column; + .mat-tab-label { + padding: 0 10px; + align-content: flex-start; + text-align: left; + align-items: self-start; + justify-content: flex-start; + } + .mat-ink-bar { + display: none; + } + } + } + .mat-tab-body-wrapper { + border-left: 1px solid #dddddd; + position: relative; + height: 100%; + padding: 0 0 10px 10px; + } + } + } + } + + .button-farm { + text-align: right; + position: absolute; + width: 100%; + bottom: 10px; + .mat-primary { + margin-left: 4px; + } + } +} + +::ng-deep .setting-tab { + .mat-tab-group { + position: relative; + height: 100%; + width: 100%; + .mat-tab-header { + width: 160px; + flex-flow: column; + .mat-tab-label-container { + .mat-tab-list { + .mat-tab-labels { + border-bottom: 0; + padding-right: 10px; + .mat-tab-label { + padding: 0 10px; + } + } + } + } + } + + .mat-tab-body-wrapper { + .mat-tab-body { + .mat-tab-body-conten { + position: relative; + width: 100%; + height: 100%; + .mat-list-base { + position: relative; + } + } + } + } + } +} + +::ng-deep .setting-category { + .mat-list-base { + position: relative; + .mat-list-item { + font-size: 15px; + } + .mat-divider { + } + } +} diff --git a/projects/ucap-webmessenger-app/src/app/layouts/messenger/dialogs/settings/messenger-settings.dialog.component.spec.ts b/projects/ucap-webmessenger-app/src/app/layouts/messenger/dialogs/settings/messenger-settings.dialog.component.spec.ts new file mode 100644 index 0000000..6656611 --- /dev/null +++ b/projects/ucap-webmessenger-app/src/app/layouts/messenger/dialogs/settings/messenger-settings.dialog.component.spec.ts @@ -0,0 +1,27 @@ +/* tslint:disable:no-unused-variable */ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { By } from '@angular/platform-browser'; +import { DebugElement } from '@angular/core'; + +import { MessengerSettingsDialogComponent } from './messenger-settings.dialog.component'; + +describe('MessengerSettingsDialogComponent', () => { + let component: MessengerSettingsDialogComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [MessengerSettingsDialogComponent] + }).compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(MessengerSettingsDialogComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/projects/ucap-webmessenger-app/src/app/layouts/messenger/dialogs/settings/messenger-settings.dialog.component.ts b/projects/ucap-webmessenger-app/src/app/layouts/messenger/dialogs/settings/messenger-settings.dialog.component.ts new file mode 100644 index 0000000..5f6a1ea --- /dev/null +++ b/projects/ucap-webmessenger-app/src/app/layouts/messenger/dialogs/settings/messenger-settings.dialog.component.ts @@ -0,0 +1,57 @@ +import { Component, OnInit, Inject, Renderer2 } from '@angular/core'; +import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material'; +import { KEY_LOGIN_RES_INFO } from '@app/types/login-res-info.type'; +import { KEY_VER_INFO } from '@app/types/ver-info.type'; +import { SessionStorageService } from '@ucap-webmessenger/web-storage'; + +import { Store } from '@ngrx/store'; + +import { DialogService } from '@ucap-webmessenger/ui'; +import { VersionInfo2Response } from '@ucap-webmessenger/api-public'; +import { LoginResponse } from '@ucap-webmessenger/protocol-authentication'; +import { map } from 'rxjs/operators'; +import { DOCUMENT } from '@angular/common'; + +export interface MessengerSettingsDialogData {} + +export interface MessengerSettingsDialogResult {} + +@Component({ + selector: 'app-messenger-settings-dialog', + templateUrl: './messenger-settings.dialog.component.html', + styleUrls: ['./messenger-settings.dialog.component.scss'] +}) +export class MessengerSettingsDialogComponent implements OnInit { + loginRes: LoginResponse; + sessionVerinfo: VersionInfo2Response; + + constructor( + public dialogRef: MatDialogRef< + MessengerSettingsDialogData, + MessengerSettingsDialogResult + >, + @Inject(MAT_DIALOG_DATA) public data: MessengerSettingsDialogData, + private dialogService: DialogService, + private sessionStorageService: SessionStorageService, + private store: Store, + @Inject(DOCUMENT) private document: Document, + private renderer2: Renderer2 + ) { + this.sessionVerinfo = this.sessionStorageService.get( + KEY_VER_INFO + ); + this.loginRes = this.sessionStorageService.get( + KEY_LOGIN_RES_INFO + ); + } + + ngOnInit() {} + + onSelectTheme(theme: string): void { + this.renderer2.setAttribute(this.document.body, 'class', theme); + } + + onClickChoice(choice: boolean): void { + this.dialogRef.close({}); + } +} diff --git a/projects/ucap-webmessenger-app/src/app/layouts/messenger/messenger.layout.module.ts b/projects/ucap-webmessenger-app/src/app/layouts/messenger/messenger.layout.module.ts index f6daeba..66fb9ec 100644 --- a/projects/ucap-webmessenger-app/src/app/layouts/messenger/messenger.layout.module.ts +++ b/projects/ucap-webmessenger-app/src/app/layouts/messenger/messenger.layout.module.ts @@ -22,7 +22,14 @@ 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, + MatTooltipModule +} from '@angular/material'; import { MatListModule } from '@angular/material/list'; import { MatChipsModule } from '@angular/material/chips'; @@ -37,6 +44,7 @@ import { UCapUiRoomModule } from '@ucap-webmessenger/ui-room'; import { UCapUiProfileModule } from '@ucap-webmessenger/ui-profile'; import { UCapUiGroupModule } from '@ucap-webmessenger/ui-group'; import { UCapUiOrganizationModule } from '@ucap-webmessenger/ui-organization'; +import { UCapUiSettingsModule } from '@ucap-webmessenger/ui-settings'; import { AppCommonLayoutModule } from '@app/layouts/common/common.layout.module'; @@ -70,6 +78,11 @@ import { DIALOGS } from './dialogs'; MatCheckboxModule, MatRadioModule, MatSelectModule, + MatTableModule, + MatSortModule, + MatPaginatorModule, + MatRippleModule, + MatTooltipModule, PerfectScrollbarModule, @@ -79,6 +92,7 @@ import { DIALOGS } from './dialogs'; UCapUiProfileModule, UCapUiGroupModule, UCapUiOrganizationModule, + UCapUiSettingsModule, AppCommonLayoutModule ], diff --git a/projects/ucap-webmessenger-app/src/app/layouts/native/components/top-bar.component.html b/projects/ucap-webmessenger-app/src/app/layouts/native/components/top-bar.component.html index 9dc1c69..8fae978 100644 --- a/projects/ucap-webmessenger-app/src/app/layouts/native/components/top-bar.component.html +++ b/projects/ucap-webmessenger-app/src/app/layouts/native/components/top-bar.component.html @@ -1,9 +1,60 @@
UCAP M Messenger
+
@@ -23,19 +84,45 @@ > - - - + + + - + -
diff --git a/projects/ucap-webmessenger-ui-chat/src/lib/components/form.component.ts b/projects/ucap-webmessenger-ui-chat/src/lib/components/form.component.ts index 0821586..bc575b8 100644 --- a/projects/ucap-webmessenger-ui-chat/src/lib/components/form.component.ts +++ b/projects/ucap-webmessenger-ui-chat/src/lib/components/form.component.ts @@ -1,70 +1,81 @@ -import { - Component, - OnInit, - Output, - EventEmitter, - ViewChild, - ElementRef, - Input -} from '@angular/core'; -import { NgForm } from '@angular/forms'; -import { FileUploadItem } from '@ucap-webmessenger/api-common'; -import { FileUploadQueueComponent } from '@ucap-webmessenger/ui'; - -@Component({ - selector: 'ucap-chat-form', - templateUrl: './form.component.html', - styleUrls: ['./form.component.scss'] -}) -export class FormComponent implements OnInit { - @Input() - fileUploadQueue: FileUploadQueueComponent; - - @Output() - send = new EventEmitter(); - - @Output() - sendFiles = new EventEmitter(); - - @ViewChild('replyForm', { static: false }) - replyForm: NgForm; - - @ViewChild('replyInput', { static: false }) - replyInput: ElementRef; - - @ViewChild('fileInput', { static: false }) - fileInput: ElementRef; - - constructor() {} - - ngOnInit() {} - - focus(): void { - this.replyInput.nativeElement.focus(); - } - - onSend(event: Event) { - event.preventDefault(); - - this.send.emit(this.replyForm.form.value.message); - this.replyForm.reset(); - } - - onClickFileInput() { - this.fileInput.nativeElement.click(); - } - - onChangeFileInput() { - const fileUploadItems = FileUploadItem.fromFiles( - this.fileInput.nativeElement.files - ); - - if (!!this.fileUploadQueue) { - this.fileUploadQueue.onFileSelected(fileUploadItems); - } - - this.sendFiles.emit(fileUploadItems); - - this.fileInput.nativeElement.value = ''; - } -} +import { + Component, + OnInit, + Output, + EventEmitter, + ViewChild, + ElementRef, + Input +} from '@angular/core'; +import { NgForm } from '@angular/forms'; +import { FileUploadItem } from '@ucap-webmessenger/api-common'; +import { FileUploadQueueComponent } from '@ucap-webmessenger/ui'; + +@Component({ + selector: 'ucap-chat-form', + templateUrl: './form.component.html', + styleUrls: ['./form.component.scss'] +}) +export class FormComponent implements OnInit { + @Input() + fileUploadQueue: FileUploadQueueComponent; + + @Output() + send = new EventEmitter(); + + @Output() + sendFiles = new EventEmitter(); + + @Output() + toggleStickerSelector = new EventEmitter(); + + @Output() + clearView = new EventEmitter(); + + @ViewChild('replyForm', { static: false }) + replyForm: NgForm; + + @ViewChild('replyInput', { static: false }) + replyInput: ElementRef; + + @ViewChild('fileInput', { static: false }) + fileInput: ElementRef; + + constructor() {} + + ngOnInit() {} + + focus(): void { + this.replyInput.nativeElement.focus(); + } + + onSend(event: Event) { + event.preventDefault(); + + this.send.emit(this.replyForm.form.value.message); + this.replyForm.reset(); + } + + onClickFileInput() { + this.clearView.emit(); + this.fileInput.nativeElement.click(); + } + + onChangeFileInput() { + const fileUploadItems = FileUploadItem.fromFiles( + this.fileInput.nativeElement.files + ); + + if (!!this.fileUploadQueue) { + this.fileUploadQueue.onFileSelected(fileUploadItems); + } + + this.sendFiles.emit(fileUploadItems); + + this.fileInput.nativeElement.value = ''; + } + + onClickStickerSelector() { + this.toggleStickerSelector.emit(); + } +} diff --git a/projects/ucap-webmessenger-ui-chat/src/lib/components/message-box/date-splitter.component.ts b/projects/ucap-webmessenger-ui-chat/src/lib/components/message-box/date-splitter.component.ts index 5605c29..9009f0d 100644 --- a/projects/ucap-webmessenger-ui-chat/src/lib/components/message-box/date-splitter.component.ts +++ b/projects/ucap-webmessenger-ui-chat/src/lib/components/message-box/date-splitter.component.ts @@ -1,11 +1,12 @@ import { Component, OnInit, Input } from '@angular/core'; import { Info, EventJson } from '@ucap-webmessenger/protocol-event'; import { DatePipe } from '@angular/common'; +import moment from 'moment'; @Component({ selector: 'ucap-chat-message-box-date-splitter', templateUrl: './date-splitter.component.html', - styleUrls: ['./date-splitter.component.scss'] + styleUrls: ['./date-splitter.component.scss'], }) export class DateSplitterComponent implements OnInit { @Input() @@ -17,7 +18,7 @@ export class DateSplitterComponent implements OnInit { ngOnInit() { this.dateInfo = this.datePipe.transform( - this.message.sendDate, + moment(this.message.sendDate).toDate(), 'yyyy.MM.dd EEE' ); } diff --git a/projects/ucap-webmessenger-ui-chat/src/lib/components/message-box/file.component.ts b/projects/ucap-webmessenger-ui-chat/src/lib/components/message-box/file.component.ts index 7526159..e8b1faf 100644 --- a/projects/ucap-webmessenger-ui-chat/src/lib/components/message-box/file.component.ts +++ b/projects/ucap-webmessenger-ui-chat/src/lib/components/message-box/file.component.ts @@ -42,7 +42,7 @@ export class FileComponent implements OnInit { getExpiredFile() { if ( !!this.eventInfoStatus && - this.eventInfoStatus.validFileBaseSeq < this.message.seq + this.eventInfoStatus.validFileBaseSeq <= this.message.seq ) { return false; } else { diff --git a/projects/ucap-webmessenger-ui-chat/src/lib/components/message-box/image.component.scss b/projects/ucap-webmessenger-ui-chat/src/lib/components/message-box/image.component.scss index d53cddf..7f520d9 100644 --- a/projects/ucap-webmessenger-ui-chat/src/lib/components/message-box/image.component.scss +++ b/projects/ucap-webmessenger-ui-chat/src/lib/components/message-box/image.component.scss @@ -1,3 +1,7 @@ .bubble-main{ padding:10px; + img{ + height:140px; + width:auto; + } } \ No newline at end of file diff --git a/projects/ucap-webmessenger-ui-chat/src/lib/components/message-box/mass.component.html b/projects/ucap-webmessenger-ui-chat/src/lib/components/message-box/mass.component.html index 60cb938..ec9326d 100644 --- a/projects/ucap-webmessenger-ui-chat/src/lib/components/message-box/mass.component.html +++ b/projects/ucap-webmessenger-ui-chat/src/lib/components/message-box/mass.component.html @@ -1,7 +1,7 @@
- + - {{ message.sendDate | date: 'short' }} + {{ moment(message.sendDate).toDate() | date: 'short' }}
diff --git a/projects/ucap-webmessenger-ui-chat/src/lib/components/message-box/mass.component.ts b/projects/ucap-webmessenger-ui-chat/src/lib/components/message-box/mass.component.ts index 0d29682..7c4053b 100644 --- a/projects/ucap-webmessenger-ui-chat/src/lib/components/message-box/mass.component.ts +++ b/projects/ucap-webmessenger-ui-chat/src/lib/components/message-box/mass.component.ts @@ -2,11 +2,12 @@ import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core'; import { Info, MassTextEventJson } from '@ucap-webmessenger/protocol-event'; import { NGXLogger } from 'ngx-logger'; import { StatusCode } from '@ucap-webmessenger/api'; +import moment from 'moment'; @Component({ selector: 'ucap-chat-message-box-mass', templateUrl: './mass.component.html', - styleUrls: ['./mass.component.scss'] + styleUrls: ['./mass.component.scss'], }) export class MassComponent implements OnInit { @Input() @@ -19,6 +20,8 @@ export class MassComponent implements OnInit { eventMassSeq: number; detailButteonShow = true; + moment = moment; + constructor(private logger: NGXLogger) {} ngOnInit() { diff --git a/projects/ucap-webmessenger-ui-chat/src/lib/components/message-box/sticker.component.html b/projects/ucap-webmessenger-ui-chat/src/lib/components/message-box/sticker.component.html index 1e244cb..5af9deb 100644 --- a/projects/ucap-webmessenger-ui-chat/src/lib/components/message-box/sticker.component.html +++ b/projects/ucap-webmessenger-ui-chat/src/lib/components/message-box/sticker.component.html @@ -6,9 +6,6 @@ onerror="this.src='assets/sticker/sticker_default.png'" /> -
  • +
  • diff --git a/projects/ucap-webmessenger-ui-chat/src/lib/components/message-box/sticker.component.ts b/projects/ucap-webmessenger-ui-chat/src/lib/components/message-box/sticker.component.ts index 03c18b7..c2975dd 100644 --- a/projects/ucap-webmessenger-ui-chat/src/lib/components/message-box/sticker.component.ts +++ b/projects/ucap-webmessenger-ui-chat/src/lib/components/message-box/sticker.component.ts @@ -1,28 +1,61 @@ -import { Component, OnInit, Input } from '@angular/core'; +import { + Component, + OnInit, + Input, + Inject, + ElementRef, + AfterViewInit +} from '@angular/core'; import { Info, StickerEventJson } from '@ucap-webmessenger/protocol-event'; import { NGXLogger } from 'ngx-logger'; import { StickerInfo } from '../../models/sticker-info.json'; +import { UCAP_NATIVE_SERVICE, NativeService } from '@ucap-webmessenger/native'; @Component({ selector: 'ucap-chat-message-box-sticker', templateUrl: './sticker.component.html', styleUrls: ['./sticker.component.scss'] }) -export class StickerComponent implements OnInit { +export class StickerComponent implements OnInit, AfterViewInit { @Input() message: Info; - contentJson?: StickerInfo; + contents: string; stickerUrl?: string; - constructor(private logger: NGXLogger) {} + constructor( + private logger: NGXLogger, + private elementRef: ElementRef, + @Inject(UCAP_NATIVE_SERVICE) private nativeService: NativeService + ) {} ngOnInit() { try { if (!!this.message.sentMessageJson.file) { this.stickerUrl = `assets/sticker/sticker_s_${this.message.sentMessageJson.file}.png`; } + if (!!this.message.sentMessageJson.chat) { + this.contents = this.message.sentMessageJson.chat; + } } catch (e) { this.logger.error(e); } } + + ngAfterViewInit(): void { + if ( + !!this.elementRef.nativeElement && + !!this.elementRef.nativeElement.querySelector('a') + ) { + const elements = this.elementRef.nativeElement.querySelectorAll('a'); + elements.forEach(element => { + element.addEventListener('click', this.onClickEvent.bind(this)); + }); + } + } + + onClickEvent(event: MouseEvent) { + this.nativeService.openDefaultBrowser( + (event.target as HTMLAnchorElement).text + ); + } } diff --git a/projects/ucap-webmessenger-ui-chat/src/lib/components/message-box/text.component.html b/projects/ucap-webmessenger-ui-chat/src/lib/components/message-box/text.component.html index 474d482..c9750ca 100644 --- a/projects/ucap-webmessenger-ui-chat/src/lib/components/message-box/text.component.html +++ b/projects/ucap-webmessenger-ui-chat/src/lib/components/message-box/text.component.html @@ -1,3 +1,3 @@
    - +
    diff --git a/projects/ucap-webmessenger-ui-chat/src/lib/components/message-box/text.component.scss b/projects/ucap-webmessenger-ui-chat/src/lib/components/message-box/text.component.scss index b75dae7..e207a63 100644 --- a/projects/ucap-webmessenger-ui-chat/src/lib/components/message-box/text.component.scss +++ b/projects/ucap-webmessenger-ui-chat/src/lib/components/message-box/text.component.scss @@ -1,9 +1,9 @@ .bubble-main { padding: 14px; - text-align:left; - span{ + text-align: left; + span { word-wrap: break-word; white-space: pre-wrap; - word-break: keep-all; + word-break: break-word; } -} \ No newline at end of file +} diff --git a/projects/ucap-webmessenger-ui-chat/src/lib/components/message-box/text.component.ts b/projects/ucap-webmessenger-ui-chat/src/lib/components/message-box/text.component.ts index 17482ad..5973e59 100644 --- a/projects/ucap-webmessenger-ui-chat/src/lib/components/message-box/text.component.ts +++ b/projects/ucap-webmessenger-ui-chat/src/lib/components/message-box/text.component.ts @@ -1,17 +1,45 @@ -import { Component, OnInit, Input } from '@angular/core'; +import { + Component, + OnInit, + Input, + ElementRef, + AfterViewInit, + Inject +} from '@angular/core'; import { Info, EventJson } from '@ucap-webmessenger/protocol-event'; +import { NativeService, UCAP_NATIVE_SERVICE } from '@ucap-webmessenger/native'; @Component({ selector: 'ucap-chat-message-box-text', templateUrl: './text.component.html', styleUrls: ['./text.component.scss'] }) -export class TextComponent implements OnInit { +export class TextComponent implements OnInit, AfterViewInit { @Input() message: Info; - test = `가




    바사`; - constructor() {} + constructor( + private elementRef: ElementRef, + @Inject(UCAP_NATIVE_SERVICE) private nativeService: NativeService + ) {} ngOnInit() {} + + ngAfterViewInit(): void { + if ( + !!this.elementRef.nativeElement && + !!this.elementRef.nativeElement.querySelector('a') + ) { + const elements = this.elementRef.nativeElement.querySelectorAll('a'); + elements.forEach(element => { + element.addEventListener('click', this.onClickEvent.bind(this)); + }); + } + } + + onClickEvent(event: MouseEvent) { + this.nativeService.openDefaultBrowser( + (event.target as HTMLAnchorElement).text + ); + } } diff --git a/projects/ucap-webmessenger-ui-chat/src/lib/components/message-box/video.component.html b/projects/ucap-webmessenger-ui-chat/src/lib/components/message-box/video.component.html index 7072870..d969a13 100644 --- a/projects/ucap-webmessenger-ui-chat/src/lib/components/message-box/video.component.html +++ b/projects/ucap-webmessenger-ui-chat/src/lib/components/message-box/video.component.html @@ -1,7 +1,5 @@
    - - -
    +
    +
    @@ -43,12 +43,14 @@ @@ -78,6 +80,7 @@ [base]="profileImageRoot" [path]="getUserProfile(message.senderSeq)" [default]="'assets/images/img_nophoto_50.png'" + (click)="onClickOpenProfile($event, getUerInfo(message.senderSeq))" /> + +
  • +
    + + +
    +
  • +
    + + +
  • +
    + + + + 내 프로필 + + + 즐겨찾기 + + ({{ node.countOfChildren }}명) + + {{ + node.groupDetail.name + }} + + ({{ node.countOfChildren }}명) + + - - - - - - - - - 즐겨찾기 - ({{ favoritBuddyList.length }}명) - - - - - - - - - - - - -
    {{ groupBuddy.group.name }}
    - ({{ groupBuddy.buddyList.length }}명) -
    - - - - - -
    - - - - -
    - + + + +
    +
      +
      +
      + +
      +
    +
  • +
    + + diff --git a/projects/ucap-webmessenger-ui-group/src/lib/components/expansion-panel.component.scss b/projects/ucap-webmessenger-ui-group/src/lib/components/expansion-panel.component.scss index 3ad0856..2763d73 100644 --- a/projects/ucap-webmessenger-ui-group/src/lib/components/expansion-panel.component.scss +++ b/projects/ucap-webmessenger-ui-group/src/lib/components/expansion-panel.component.scss @@ -1,66 +1,108 @@ @charset 'utf-8'; -:host { - display: flex; - flex: 1; - flex-direction: column; - - .more-spacer { - flex: 1 1 auto; +.group-tree { + ul, + li { + margin-top: 0; + margin-bottom: 0; + list-style-type: none; + margin-left: 10px; + } + .group-tree-node-invisible { + display: none; } } -::ng-deep .groupExpansionPanel .mat-expansion-panel-body { - padding: 0; -} -.mat-expansion-panel-header { - padding: 0 20px; - .mat-expansion-panel-header-title { - align-items: center; - font-size: 13px; - } - .mat-expansion-panel-header-description { - margin-right: 0; - } -} +.tree-node-frame { + border-bottom: 1px solid #dddddd; + height: 40px; -.mat-icon-button { - margin-right: 0; - width: inherit; + .tree-node-header { + width: 100%; + + .title-name { + display: inline-flex; + flex: 1 1 auto; + } + } + .mat-tree-node { + width: 100%; + &:hover { + background-color: #f4f4f4; + border: 1px solid #cccccc; + border-radius: 4px; + box-shadow: 0 1px 4px rgba(32, 33, 36, 0.1); + } + } } -.mat-icon { - font-size: 20px; -} -.groupList { - .mat-expansion-panel-header { - padding: 0 20px; - .mat-content { - color: #666666; - overflow: unset; - .panel-title{ - display:inline-flex; - .title-name{ - display:inline-flex; - flex:1 1 auto; - } - .number{ - margin-left:6px; - display: inline-flex; - flex: 0 0 auto; - } +.mat-tree-node { + &[aria-level='1'] { + position: relative; + widows: 100px; + height: 100%; + li { + margin-left: 0; + width: 100%; + height: 100%; + .mat-tree-node { + width: 100%; + height: 100%; } } } } -.box-more-spacer { - margin-right: 0; + +.mat-tree-node[aria-level='0'][node-type='Profile'] { + position: relative; + widows: 100px; + height: 100%; + li { + margin-left: 0; + width: 100%; + height: 100%; + .mat-tree-node { + width: 100%; + height: 100%; + } + } } -::ng-deep .mat-content{ - overflow: unset; -} +.path { + display: flex; + padding: 6px 4px; + align-items: center; + .btn-toggle { + padding: 0; + min-width: 0; + width: 20px; + height: 20px; + flex-shrink: 0; + line-height: 20px; + margin-right: 10px; + } + .group-check { + margin-left: auto; + margin-right: 16px; + } -.number{ - margin-left:6px; - display: inline-flex; - flex: 0 0 auto; - } \ No newline at end of file + .group-menu { + margin-left: auto; + opacity: 0.6; + } + + ul { + li:last-chlid { + border-bottom: 1px solid #dddddd; + } + } + .horizontal-line { + width: 10px; + height: 1px; + background-color: #dddddd; + display: inline-block; + vertical-align: middle; + margin-left: -10px; + } + + .dept-name { + padding-left: 10px; + } +} diff --git a/projects/ucap-webmessenger-ui-group/src/lib/components/expansion-panel.component.ts b/projects/ucap-webmessenger-ui-group/src/lib/components/expansion-panel.component.ts index bd1e596..13cfdb9 100644 --- a/projects/ucap-webmessenger-ui-group/src/lib/components/expansion-panel.component.ts +++ b/projects/ucap-webmessenger-ui-group/src/lib/components/expansion-panel.component.ts @@ -6,13 +6,16 @@ import { EventEmitter, ViewChild, ContentChild, - TemplateRef + TemplateRef, + AfterViewInit, + ChangeDetectorRef, + OnDestroy } from '@angular/core'; import { ucapAnimations } from '@ucap-webmessenger/ui'; import { GroupDetailData, UserInfo } from '@ucap-webmessenger/protocol-sync'; -import { MatAccordion } from '@angular/material'; +import { MatTreeFlattener, MatTree } from '@angular/material'; import { ExpansionPanelItemDirective } from '../directives/expansion-panel-item.directive'; import { UserInfoSS, @@ -20,6 +23,34 @@ import { UserInfoDN } from '@ucap-webmessenger/protocol-query'; import { NGXLogger } from 'ngx-logger'; +import { VirtualScrollTreeFlatDataSource } from '@ucap-webmessenger/ui'; +import { FlatTreeControl } from '@angular/cdk/tree'; +import { CdkVirtualScrollViewport } from '@angular/cdk/scrolling'; +import { PerfectScrollbarDirective } from 'ngx-perfect-scrollbar'; +import { Subscription } from 'rxjs'; + +enum NodeType { + None = 'None', + Favorit = 'Favorit', + Profile = 'Profile', + Buddy = 'Buddy' +} + +interface GroupNode { + nodeType: NodeType; + userInfo?: UserInfo; + groupDetail?: GroupDetailData; + children?: GroupNode[]; +} + +interface FlatNode { + expandable: boolean; + level: number; + nodeType: NodeType; + countOfChildren?: number; + userInfo?: UserInfo; + groupDetail?: GroupDetailData; +} @Component({ selector: 'ucap-group-expansion-panel', @@ -27,15 +58,84 @@ import { NGXLogger } from 'ngx-logger'; styleUrls: ['./expansion-panel.component.scss'], animations: ucapAnimations }) -export class ExpansionPanelComponent implements OnInit { +export class ExpansionPanelComponent + implements OnInit, OnDestroy, AfterViewInit { @Input() - groupBuddyList: { group: GroupDetailData; buddyList: UserInfo[] }[]; + set myProfileInfo(userInfo: UserInfo) { + if (!userInfo) { + return; + } + const groupNode: GroupNode = { + nodeType: NodeType.Profile, + userInfo, + children: [] + }; + + this.profileNodes = [groupNode]; + + this.refreshRootNodeList(); + } + @Input() - favoritBuddyList?: UserInfo[]; + set favoritBuddyList(userInfoList: UserInfo[]) { + if (!userInfoList || 0 === userInfoList.length) { + return; + } + const groupNode: GroupNode = { + nodeType: NodeType.Favorit, + children: [] + }; + + userInfoList.forEach(userInfo => { + groupNode.children.push({ + nodeType: NodeType.Favorit, + userInfo + }); + }); + + this.favoritNodes = [groupNode]; + this.refreshRootNodeList(); + } + @Input() - myProfileInfo?: UserInfo; + set groupBuddyList( + list: { group: GroupDetailData; buddyList: UserInfo[] }[] + ) { + if (!list || 0 === list.length) { + return; + } + + this.groupList = list; + + this.buddyNodes = []; + + for (const item of list) { + const groupNode: GroupNode = { + nodeType: NodeType.Buddy, + groupDetail: item.group, + children: [] + }; + + item.buddyList.sort((a, b) => + a.name < b.name ? -1 : a.name > b.name ? 1 : 0 + ); + + item.buddyList.forEach(userInfo => { + groupNode.children.push({ + nodeType: NodeType.Buddy, + groupDetail: item.group, + userInfo + }); + }); + + this.buddyNodes.push(groupNode); + } + this.refreshRootNodeList(); + } + @Input() checkable = false; + @Input() /** 선택된 사용자의 리스트 */ selectedUserList?: (UserInfo | UserInfoSS | UserInfoF | UserInfoDN)[] = []; @@ -54,22 +154,102 @@ export class ExpansionPanelComponent implements OnInit { @ContentChild(ExpansionPanelItemDirective, { read: TemplateRef, - static: true + static: false }) expansionPanelItemTemplateRef: TemplateRef; - @ViewChild('groupAccordion', { static: true }) groupAccordion: MatAccordion; + @ViewChild('groupTree', { static: false }) + groupTree: MatTree; - constructor(private logger: NGXLogger) {} + @ViewChild('cvsvGroup', { static: false }) + cvsvGroup: CdkVirtualScrollViewport; - ngOnInit() {} + @ViewChild(PerfectScrollbarDirective, { static: false }) + psDirectiveRef?: PerfectScrollbarDirective; + + NodeType = NodeType; + + profileNodes: GroupNode[] = []; + favoritNodes: GroupNode[] = []; + buddyNodes: GroupNode[] = []; + + rootNodeList: GroupNode[] = []; + treeControl: FlatTreeControl; + treeFlattener: MatTreeFlattener; + dataSource: VirtualScrollTreeFlatDataSource; + + groupList: { group: GroupDetailData; buddyList: UserInfo[] }[]; + + treeControlExpansionChangeSubscription: Subscription; + + constructor( + private changeDetectorRef: ChangeDetectorRef, + private logger: NGXLogger + ) { + this.treeControl = new FlatTreeControl( + node => node.level, + node => node.expandable + ); + + this.treeFlattener = new MatTreeFlattener( + (node: GroupNode, level: number) => { + return { + expandable: !!node.children && node.children.length > 0, + level, + nodeType: node.nodeType, + countOfChildren: + !!node.children && node.children.length > 0 + ? node.children.length + : 0, + userInfo: node.userInfo, + groupDetail: node.groupDetail + }; + }, + node => node.level, + node => node.expandable, + node => node.children + ); + + this.dataSource = new VirtualScrollTreeFlatDataSource( + this.treeControl, + this.treeFlattener + ); + } + + ngOnInit() { + this.treeControlExpansionChangeSubscription = this.treeControl.expansionModel.changed.subscribe( + () => { + this.psDirectiveRef.update(); + } + ); + } + + ngOnDestroy(): void { + if (!!this.treeControlExpansionChangeSubscription) { + this.treeControlExpansionChangeSubscription.unsubscribe(); + } + } + + ngAfterViewInit(): void { + this.dataSource.cdkVirtualScrollViewport = this.cvsvGroup; + } + + // hasChild = (_: number, node: FlatNode) => node.expandable; + isHeader = (_: number, node: FlatNode) => + NodeType.Profile !== node.nodeType && 0 === node.level; expandMore() { - this.groupAccordion.openAll(); + this.groupTree.treeControl.expandAll(); + if (!!this.psDirectiveRef) { + this.psDirectiveRef.scrollToTop(); + } } expandLess() { - this.groupAccordion.closeAll(); + this.groupTree.treeControl.collapseAll(); + if (!!this.psDirectiveRef) { + this.psDirectiveRef.scrollToTop(); + } } onClickMore(event: MouseEvent, group: GroupDetailData) { @@ -77,30 +257,34 @@ export class ExpansionPanelComponent implements OnInit { } /** 그룹리스트가 checkable 할 경우 checkbox 의 change 이벤트를 상위 컴포넌트로 전달한다. */ - onChangeCheck( - value: boolean, - groupBuddyList: { group: GroupDetailData; buddyList: UserInfo[] } - ) { - this.checkGroup.emit({ - isChecked: value, - groupBuddyList - }); + onChangeCheck(value: boolean, group: GroupDetailData, nodeType: NodeType) { + const groupInfos = this.groupList.filter( + groupInfo => groupInfo.group.seq === group.seq + ); + + if (groupInfos.length > 0) { + this.checkGroup.emit({ + isChecked: value, + groupBuddyList: groupInfos[0] + }); + } } /** 그룹리스트가 checkable 할 경우 checkbox 의 isChecked 를 관장하며, 하위 부서원들의 전체선택여부를 판단한다. */ - getCheckedGroup(groupBuddy: { - group: GroupDetailData; - buddyList: UserInfo[]; - }) { - if (groupBuddy.buddyList.length === 0) { + getCheckedGroup(group: GroupDetailData) { + if (!group || group === undefined) { return false; } + + if (group.userSeqs.length === 0) { + return false; + } + if (!!this.selectedUserList && this.selectedUserList.length > 0) { let allExist = true; - groupBuddy.buddyList.some(groupUser => { + group.userSeqs.some(seq => { if ( - this.selectedUserList.filter(item => item.seq === groupUser.seq) - .length === 0 + this.selectedUserList.filter(item => item.seq === seq).length === 0 ) { allExist = false; return true; @@ -110,4 +294,17 @@ export class ExpansionPanelComponent implements OnInit { } return false; } + + private refreshRootNodeList(): void { + this.rootNodeList = [ + ...this.profileNodes, + ...this.favoritNodes, + ...this.buddyNodes + ]; + this.dataSource.data = this.rootNodeList; + + if (!!this.psDirectiveRef) { + this.psDirectiveRef.scrollToTop(); + } + } } diff --git a/projects/ucap-webmessenger-ui-group/src/lib/ucap-ui-group.module.ts b/projects/ucap-webmessenger-ui-group/src/lib/ucap-ui-group.module.ts index 44be219..2c25817 100644 --- a/projects/ucap-webmessenger-ui-group/src/lib/ucap-ui-group.module.ts +++ b/projects/ucap-webmessenger-ui-group/src/lib/ucap-ui-group.module.ts @@ -4,13 +4,18 @@ import { ReactiveFormsModule } from '@angular/forms'; import { FlexLayoutModule } from '@angular/flex-layout'; +import { ScrollingModule } from '@angular/cdk/scrolling'; + +import { MatRippleModule, MatCheckboxModule } from '@angular/material'; import { MatButtonModule } from '@angular/material/button'; import { MatExpansionModule } from '@angular/material/expansion'; import { MatIconModule } from '@angular/material/icon'; +import { MatTreeModule } from '@angular/material/tree'; + +import { PerfectScrollbarModule } from 'ngx-perfect-scrollbar'; import { ExpansionPanelComponent } from './components/expansion-panel.component'; import { ExpansionPanelItemDirective } from './directives/expansion-panel-item.directive'; -import { MatCheckboxModule } from '@angular/material'; const COMPONENTS = [ExpansionPanelComponent]; const DIALOGS = []; @@ -22,10 +27,17 @@ const SERVICES = []; CommonModule, ReactiveFormsModule, FlexLayoutModule, + + ScrollingModule, + MatButtonModule, MatExpansionModule, MatIconModule, - MatCheckboxModule + MatTreeModule, + MatCheckboxModule, + MatRippleModule, + + PerfectScrollbarModule ], exports: [...COMPONENTS, ...DIRECTIVES], declarations: [...COMPONENTS, ...DIRECTIVES], diff --git a/projects/ucap-webmessenger-ui-organization/src/lib/components/tenant-search.component.html b/projects/ucap-webmessenger-ui-organization/src/lib/components/tenant-search.component.html index 78f847a..35b12ae 100644 --- a/projects/ucap-webmessenger-ui-organization/src/lib/components/tenant-search.component.html +++ b/projects/ucap-webmessenger-ui-organization/src/lib/components/tenant-search.component.html @@ -15,7 +15,7 @@ - {{ node.title }} -
    -
      + + + +
      -
      - +
      +
      +
      + +
    • +
      {{ node.name }}
      +
    • + + + +
      +
      +
      +
      +
    • +
      + + + {{ node.name }}
      -
    - - - + + + + + diff --git a/projects/ucap-webmessenger-ui-organization/src/lib/components/tree.component.scss b/projects/ucap-webmessenger-ui-organization/src/lib/components/tree.component.scss index 42a3c36..9d210d5 100644 --- a/projects/ucap-webmessenger-ui-organization/src/lib/components/tree.component.scss +++ b/projects/ucap-webmessenger-ui-organization/src/lib/components/tree.component.scss @@ -1,61 +1,93 @@ -@charset 'utf-8'; .organization-tree { - padding:10px; - ul, + padding: 5px; + + .tree-node-closer-container { + position: relative; + // border: 1px dotted grey; + // border-width: 0 0 1px 1px; + + .tree-node-closer-top { + width: 15px; + height: 40px; + position: absolute; + border: 1px dotted grey; + border-width: 0 0 1px 1px; + top: -40px; + // left: 20px; + } + .tree-node-closer-bottom { + width: 15px; + height: 40px; + position: absolute; + border: 1px dotted grey; + border-width: 0 0 1px 1px; + top: 0px; + // left: 20px; + } + + .tree-node-closer-top[sub-node] { + border-width: 0 0 0 1px; + } + .tree-node-closer-top[sub-node][last-node] { + border-width: 0 0 0 0; + } + + .tree-node-closer-bottom[expanded] { + border-width: 0 0 1px 0px; + } + .tree-node-closer-bottom[last-node] { + border-width: 0 0 1px 0px; + } + .tree-node-closer-bottom[sub-node] { + border-width: 0 0 0 1px; + } + .tree-node-closer-bottom[sub-node][last-node] { + border-width: 0 0 0 0; + } + } + li { margin-top: 0; margin-bottom: 0; list-style-type: none; - padding-left: 6px; } - .organization-tree-node-invisible { - display: none; - } -} -.mat-tree-node { - min-height: 30px; - font-size: 13px; - padding-left:20px; - margin-top:4px; - &:hover { - background-color: #f4f4f4; - border:1px solid #cccccc; - border-radius:4px; - box-shadow: 0 1px 4px rgba(32, 33, 36, 0.1); - } -} + // li:last-child { + // border-left: 1px solid white; + // margin-left: -41px; + // } + .tree-has-child { + height: 40px; + min-height: 40px; + li { + display: flex; + align-items: center; + cursor: pointer; + width: 100%; -.path { - //border: 1px solid #dddddd; - padding: 4px; - margin-top: 10px; - //box-shadow: 0 1px 4px rgba(32, 33, 36, 0.1); - + ul{ - li:last-chlid{ - border-bottom:1px solid #dddddd; + .tree-node-body { + .tree-node-expand-btn { + background-color: white; + } + } + } + } + + .tree-no-child { + height: 40px; + min-height: 40px; + font-size: 13px; + li { + display: flex; + align-items: center; + width: 100%; + height: 100%; + cursor: pointer; + + .tree-node-body { + padding-left: 40px; + } } } } -.mat-icon-button{ - padding: 0; - min-width: 0; - width: 20px; - height: 20px; - flex-shrink: 0; - line-height: 20px; - margin-right:10px; - .mat-icon-rtl-mirror{ - border: 1px solid #dddddd; - padding: 2px; - font-size: 14px; - min-width: 14px; - min-height: 14px; - line-height: 14px; - width:20px; - height:20px; - box-shadow: 0 2px 1px rgba(48, 48, 48, 0.2); - border-radius: 50%; - } -} diff --git a/projects/ucap-webmessenger-ui-organization/src/lib/components/tree.component.ts b/projects/ucap-webmessenger-ui-organization/src/lib/components/tree.component.ts index f542168..78e8ce0 100644 --- a/projects/ucap-webmessenger-ui-organization/src/lib/components/tree.component.ts +++ b/projects/ucap-webmessenger-ui-organization/src/lib/components/tree.component.ts @@ -6,136 +6,233 @@ import { ViewChild, Output, EventEmitter, - AfterViewInit + AfterViewInit, + OnDestroy } from '@angular/core'; -import { MatTreeNestedDataSource, MatTree } from '@angular/material'; -import { NestedTreeControl } from '@angular/cdk/tree'; -import { BehaviorSubject } from 'rxjs'; +import { MatTreeFlattener, MatTree } from '@angular/material'; import { NGXLogger } from 'ngx-logger'; import { DeptInfo } from '@ucap-webmessenger/protocol-query'; import { LoginResponse } from '@ucap-webmessenger/protocol-authentication'; +import { FlatTreeControl } from '@angular/cdk/tree'; +import { CdkVirtualScrollViewport } from '@angular/cdk/scrolling'; +import { VirtualScrollTreeFlatDataSource } from '@ucap-webmessenger/ui'; +import { ucapAnimations } from '@ucap-webmessenger/ui'; +import { trigger, transition, style, animate } from '@angular/animations'; +import { PerfectScrollbarDirective } from 'ngx-perfect-scrollbar'; +import { Subscription } from 'rxjs'; -export class OraganizationNode { - private childNodeBehaviorSubject: BehaviorSubject; - private childNodeList: OraganizationNode[]; +interface OrganizationNode { + deptInfo: DeptInfo; + name: string; + children?: OrganizationNode[]; +} - get title(): string { - return this.deptInfo.name; - } - - get children(): BehaviorSubject { - if (!this.childNodeBehaviorSubject) { - this.childNodeBehaviorSubject = new BehaviorSubject( - undefined === this.childNodeList ? [] : this.childNodeList - ); - } - return this.childNodeBehaviorSubject; - } - - constructor(public deptInfo: DeptInfo) {} - - addChild(childNode: OraganizationNode) { - if (!this.childNodeList) { - this.childNodeList = []; - } - this.childNodeList.push(childNode); - } +/** Flat node with expandable and level information */ +interface FlatNode { + expandable: boolean; + name: string; + level: number; + deptInfo: DeptInfo; } @Component({ selector: 'ucap-organization-tree', templateUrl: './tree.component.html', - styleUrls: ['./tree.component.scss'] + styleUrls: ['./tree.component.scss'], + animations: [ + ucapAnimations, + trigger('romvoeAdd', [ + transition('remove <=> add', [ + style({ + transform: `rotate(45deg)`, + opacity: 0 + }), + animate('.2s 0s ease-out') + ]) + ]) + ] }) -export class TreeComponent implements OnInit, AfterViewInit { +export class TreeComponent implements OnInit, OnDestroy, AfterViewInit { @Output() selected = new EventEmitter(); @Input() loginRes: LoginResponse; - @Input() - set oraganizationList(deptInfo: DeptInfo[]) { - const nodeMap = new Map(); - const rootNodeList: OraganizationNode[] = []; - const remainChildNodeList: OraganizationNode[] = []; - let myNode: OraganizationNode; - deptInfo.forEach(value => { - const node = new OraganizationNode(value); - if (nodeMap.has(value.seq)) { - this.logger.warn('duplicate seq', value.seq); + @Input() + set oraganizationList(deptInfoList: DeptInfo[]) { + if (!deptInfoList || 0 === deptInfoList.length) { + return; + } + const nodeMap = new Map(); + const rootNodeList: OrganizationNode[] = []; + const remainChildNodeList: OrganizationNode[] = []; + let myNode: OrganizationNode; + + deptInfoList.forEach(deptInfo => { + const node: OrganizationNode = { + deptInfo, + name: deptInfo.name, + children: [] + }; + if (nodeMap.has(deptInfo.seq)) { + this.logger.warn('duplicate seq', deptInfo.seq); return; } - nodeMap.set(value.seq, node); + nodeMap.set(deptInfo.seq, node); - if (value.seq === this.loginRes.departmentCode) { + if (deptInfo.seq === this.loginRes.departmentCode) { myNode = node; } - if (0 === value.parentSeq) { + if (0 === deptInfo.parentSeq) { rootNodeList.push(node); return; } - if (nodeMap.has(value.parentSeq)) { - nodeMap.get(value.parentSeq).addChild(node); + if (nodeMap.has(deptInfo.parentSeq)) { + nodeMap.get(deptInfo.parentSeq).children.push(node); } else { remainChildNodeList.push(node); } }); - remainChildNodeList.forEach(value => { - if (nodeMap.has(value.deptInfo.parentSeq)) { - nodeMap.get(value.deptInfo.parentSeq).addChild(value); + remainChildNodeList.forEach(node => { + if (nodeMap.has(node.deptInfo.parentSeq)) { + nodeMap.get(node.deptInfo.parentSeq).children.push(node); } }); - this.dataSource.data = rootNodeList; - // console.log('myNode', myNode); - // console.log('this.dataSource.data', this.dataSource.data[0]); - // this.treeControl.expandDescendants(this.dataSource.data[2]); - // console.log('this.dataSource', this.dataSource); - // console.log('this.dataSource.data', this.dataSource.data); - // console.log('this.treeControl', this.treeControl); - // console.log('this.treeControl.dataNodes', this.treeControl.dataNodes); - - // const myNode = this.treeControl.dataNodes.filter( - // node => node.deptInfo.seq === this.loginRes.departmentCode - // ); - // if (!!myNode && myNode.length > 0) { - // this.treeControl.expand(myNode[0]); - // } } - @ViewChild('orgranizationTree', { static: true }) - orgranizationTree: MatTree; + @ViewChild('cvsvOrganization', { static: false }) + cvsvOrganization: CdkVirtualScrollViewport; - levels = new Map(); - treeControl: NestedTreeControl; + @ViewChild('orgranizationTree', { static: false }) + orgranizationTree: MatTree; - dataSource: MatTreeNestedDataSource; + @ViewChild(PerfectScrollbarDirective, { static: false }) + psDirectiveRef?: PerfectScrollbarDirective; + + treeControl: FlatTreeControl; + treeFlattener: MatTreeFlattener; + dataSource: VirtualScrollTreeFlatDataSource; + + treeControlExpansionChangeSubscription: Subscription; constructor( private changeDetectorRef: ChangeDetectorRef, private logger: NGXLogger ) { - this.treeControl = new NestedTreeControl( - this.getChildren + this.treeControl = new FlatTreeControl( + node => node.level, + node => node.expandable ); - this.dataSource = new MatTreeNestedDataSource(); + this.treeFlattener = new MatTreeFlattener( + (node: OrganizationNode, level: number) => { + return { + expandable: !!node.children && node.children.length > 0, + name: node.name, + level, + deptInfo: node.deptInfo + }; + }, + node => node.level, + node => node.expandable, + node => node.children + ); + this.dataSource = new VirtualScrollTreeFlatDataSource< + OrganizationNode, + FlatNode + >(this.treeControl, this.treeFlattener); } - ngOnInit() {} + ngOnInit() { + this.treeControlExpansionChangeSubscription = this.treeControl.expansionModel.changed.subscribe( + () => { + this.psDirectiveRef.update(); + } + ); + } - ngAfterViewInit(): void {} + ngOnDestroy(): void { + this.logger.debug('-----------------------TreeComponent ngOnDestroy'); + if (!!this.treeControlExpansionChangeSubscription) { + this.treeControlExpansionChangeSubscription.unsubscribe(); + } + } - getChildren = (node: OraganizationNode) => node.children; + ngAfterViewInit(): void { + this.dataSource.cdkVirtualScrollViewport = this.cvsvOrganization; + } - hasChildren = (index: number, node: OraganizationNode) => - 0 < node.children.value.length; + hasChild = (_: number, node: FlatNode) => node.expandable; - onClickNode(node: OraganizationNode) { + isLastNode(node: FlatNode, depth: number): boolean { + const i = this.findNodeIndex(node, depth); + + if (-1 === i) { + return false; + } + + if (i === this.dataSource.expandedDataSubject.value.length - 1) { + return true; + } + + const n = this.dataSource.expandedDataSubject.value[i]; + + for ( + let idx = i + 1; + idx < this.dataSource.expandedDataSubject.value.length; + idx++ + ) { + const element = this.dataSource.expandedDataSubject.value[idx]; + if (n.level === element.level) { + return false; + } + if (n.level > element.level) { + return true; + } + } + return true; + } + + appendDivArray(level: number): number[] { + if (0 === level) { + return []; + } + + return Array.from({ length: level }, (_, i: number) => i); + } + + onClickNode(node: OrganizationNode) { this.selected.emit(node.deptInfo); } + + private findNodeIndex(node: FlatNode, depth: number): number { + if (!node) { + return -1; + } + const i = this.dataSource.expandedDataSubject.value.findIndex(n => { + return node.deptInfo.seq === n.deptInfo.seq; + }); + + if (0 === depth) { + return i; + } + return this.findNodeIndex(this.findParentNode(i), depth - 1); + } + + private findParentNode(index: number): FlatNode { + const node = this.dataSource.expandedDataSubject.value[index]; + + for (let idx = index - 1; idx >= 0; idx--) { + const n = this.dataSource.expandedDataSubject.value[idx]; + if (n.level === node.level - 1) { + return n; + } + } + return undefined; + } } diff --git a/projects/ucap-webmessenger-ui-organization/src/lib/ucap-ui-organization.module.ts b/projects/ucap-webmessenger-ui-organization/src/lib/ucap-ui-organization.module.ts index 14ee788..e51a5a0 100644 --- a/projects/ucap-webmessenger-ui-organization/src/lib/ucap-ui-organization.module.ts +++ b/projects/ucap-webmessenger-ui-organization/src/lib/ucap-ui-organization.module.ts @@ -2,14 +2,20 @@ import { NgModule, ModuleWithProviders } from '@angular/core'; import { CommonModule } from '@angular/common'; import { ReactiveFormsModule } from '@angular/forms'; +import { FlexLayoutModule } from '@angular/flex-layout'; + import { ScrollingModule } from '@angular/cdk/scrolling'; +import { MatRippleModule } from '@angular/material'; + import { MatButtonModule } from '@angular/material/button'; import { MatIconModule } from '@angular/material/icon'; import { MatInputModule } from '@angular/material/input'; import { MatSelectModule } from '@angular/material/select'; import { MatTreeModule } from '@angular/material/tree'; +import { PerfectScrollbarModule } from 'ngx-perfect-scrollbar'; + import { TenantSearchComponent } from './components/tenant-search.component'; import { TreeComponent } from './components/tree.component'; @@ -21,13 +27,17 @@ const SERVICES = []; CommonModule, ReactiveFormsModule, + FlexLayoutModule, ScrollingModule, + MatRippleModule, MatButtonModule, MatIconModule, MatInputModule, MatSelectModule, - MatTreeModule + MatTreeModule, + + PerfectScrollbarModule ], exports: [...COMPONENTS], declarations: [...COMPONENTS] diff --git a/projects/ucap-webmessenger-ui-profile/src/lib/components/my-profile-widget.component.html b/projects/ucap-webmessenger-ui-profile/src/lib/components/my-profile-widget.component.html new file mode 100644 index 0000000..5a20d38 --- /dev/null +++ b/projects/ucap-webmessenger-ui-profile/src/lib/components/my-profile-widget.component.html @@ -0,0 +1,12 @@ +
    + + + + 내프로필 +
    diff --git a/projects/ucap-webmessenger-ui-profile/src/lib/components/my-profile-widget.component.scss b/projects/ucap-webmessenger-ui-profile/src/lib/components/my-profile-widget.component.scss new file mode 100644 index 0000000..8dd8ce6 --- /dev/null +++ b/projects/ucap-webmessenger-ui-profile/src/lib/components/my-profile-widget.component.scss @@ -0,0 +1,26 @@ +.myprofile { + position: absolute; + display: flex; + flex-flow: column; + justify-content: center; + height: 80px; + width: 68px; + bottom: 10px; + color: #ffffff; + font-size: 11px; + text-align: center; + + .myprofile-img { + display: block; + border-radius: 10px; + height: 42px; + width: 42px; + background-color: #efefef; + align-self: center; + margin-bottom: 6px; + + .thumbnail { + border-radius: 10px; + } + } +} diff --git a/projects/ucap-webmessenger-ui-profile/src/lib/components/my-profile-widget.component.spec.ts b/projects/ucap-webmessenger-ui-profile/src/lib/components/my-profile-widget.component.spec.ts new file mode 100644 index 0000000..55d2b46 --- /dev/null +++ b/projects/ucap-webmessenger-ui-profile/src/lib/components/my-profile-widget.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { MyProfileWidgetComponent } from './my-profile-widget.component'; + +describe('MyProfileWidgetComponent', () => { + let component: MyProfileWidgetComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ MyProfileWidgetComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(MyProfileWidgetComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/projects/ucap-webmessenger-ui-profile/src/lib/components/my-profile-widget.component.ts b/projects/ucap-webmessenger-ui-profile/src/lib/components/my-profile-widget.component.ts new file mode 100644 index 0000000..8f0c6bb --- /dev/null +++ b/projects/ucap-webmessenger-ui-profile/src/lib/components/my-profile-widget.component.ts @@ -0,0 +1,38 @@ +import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core'; +import { UserInfo } from '@ucap-webmessenger/protocol-room'; +import { + UserInfoSS, + UserInfoF, + UserInfoDN +} from '@ucap-webmessenger/protocol-query'; + +@Component({ + selector: 'ucap-profile-my-profile-widget', + templateUrl: './my-profile-widget.component.html', + styleUrls: ['./my-profile-widget.component.scss'] +}) +export class MyProfileWidgetComponent implements OnInit { + @Input() + profileImageRoot: string; + @Input() + profileImageFile: string; + + @Output() + openProfile = new EventEmitter< + UserInfo | UserInfoSS | UserInfoF | UserInfoDN + >(); + + constructor() {} + + ngOnInit() {} + + onClickOpenProfile( + event: MouseEvent, + userInfo: UserInfo | UserInfoSS | UserInfoF | UserInfoDN + ) { + event.preventDefault(); + event.stopPropagation(); + + this.openProfile.emit(userInfo); + } +} diff --git a/projects/ucap-webmessenger-ui-profile/src/lib/components/profile.component.html b/projects/ucap-webmessenger-ui-profile/src/lib/components/profile.component.html new file mode 100644 index 0000000..05eeed8 --- /dev/null +++ b/projects/ucap-webmessenger-ui-profile/src/lib/components/profile.component.html @@ -0,0 +1,262 @@ + + + + {{ userInfo.name }} + {{ userInfo.grade }} + + {{ userInfo.deptName }} + + + +
    + +
    + +
    + + + + + + + + + + + + + + + + + + + + + + + +
    + +
      +
    • + + + + {{ userInfo.intro }} +
    • +
    • + + + + + {{ userInfo.email }} +
    • +
    • + + + + {{ userInfo.lineNumber }} +
    • +
    • + + + + + {{ userInfo.hpNumber }} +
    • +
    +
    + + +
    + + + + + + + +
    +
    +
    diff --git a/projects/ucap-webmessenger-ui-profile/src/lib/components/profile.component.scss b/projects/ucap-webmessenger-ui-profile/src/lib/components/profile.component.scss new file mode 100644 index 0000000..6c941d9 --- /dev/null +++ b/projects/ucap-webmessenger-ui-profile/src/lib/components/profile.component.scss @@ -0,0 +1,104 @@ +@mixin ellipsis($row) { + overflow: hidden; + text-overflow: ellipsis; + @if $row == 1 { + display: block; + white-space: nowrap; + word-wrap: normal; + } @else if $row >= 2 { + display: -webkit-box; + -webkit-line-clamp: $row; + -webkit-box-orient: vertical; + word-wrap: break-word; + } +} +::ng-deep .mat-card-header-text{ + width:100%; + .mat-card-subtitle{ + color: rgb(256, 256, 256, 0.7) !important; + text-align:center; + margin-top:10px !important; + } +} + +.example-card { + width: 400px; + padding: 0 0 20px; + position: relative; + .mat-card-header{ + justify-content: center; + padding-bottom: 40px; + background: #76d9c5; + /*background: linear-gradient(to right, #345385, #ef4c73);*/ + color: #ffffff; + padding-top: 20px; + width:100%; + .mat-card-title{ + margin-bottom: 12px; + max-width: 100%; + justify-content: center; + display: flex; + margin:0 20px; + span{ + @include ellipsis(1); + } + } + } + .mat-card-content{ + margin-top:-40px; + .profile-img{ + display:flex; + height:80px; + justify-content: center; + margin-bottom:20px; + img{ + widows: 80px; + height: 80px; + border-radius: 50%; + background-color:#efefef; + border:2px solid #ffffff; + } + } + .profile-option{ + display:flex; + padding:0 20px; + color:#ffffff; + margin-top: -100px; + height: 120px; + .btn-favorite{ + cursor: pointer; + .on{ + fill:yellow; + } + } + .btn-groupadd{ + margin-left:auto; + cursor: pointer; + svg{ + display:none; + &.on{ + display:block; + } + } + } + } + ul{ + padding:0 20px; + display:flex; + flex-flow: column; + margin-top:-20px; + li{ + display:inline-flex; + height:30px; + align-items: center; + flex-flow:row; + margin-bottom:20px; + + svg{ + margin-right:10px; + color:#777777; + } + } + } + } +} diff --git a/projects/ucap-webmessenger-ui-profile/src/lib/components/profile.component.spec.ts b/projects/ucap-webmessenger-ui-profile/src/lib/components/profile.component.spec.ts new file mode 100644 index 0000000..9401c7a --- /dev/null +++ b/projects/ucap-webmessenger-ui-profile/src/lib/components/profile.component.spec.ts @@ -0,0 +1,28 @@ +/* tslint:disable:no-unused-variable */ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { By } from '@angular/platform-browser'; +import { DebugElement } from '@angular/core'; + +import { ProfileComponent } from './profile.component'; + +describe('ProfileComponent', () => { + let component: ProfileComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ ProfileComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(ProfileComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/projects/ucap-webmessenger-ui-profile/src/lib/components/profile.component.ts b/projects/ucap-webmessenger-ui-profile/src/lib/components/profile.component.ts new file mode 100644 index 0000000..5a0c5fc --- /dev/null +++ b/projects/ucap-webmessenger-ui-profile/src/lib/components/profile.component.ts @@ -0,0 +1,76 @@ +import { Component, OnInit, Input, EventEmitter, Output } from '@angular/core'; + +import { UserInfo } from '@ucap-webmessenger/protocol-sync'; +import { + UserInfoSS, + UserInfoF, + UserInfoDN +} from '@ucap-webmessenger/protocol-query'; + +@Component({ + selector: 'ucap-profile-profile', + templateUrl: './profile.component.html', + styleUrls: ['./profile.component.scss'] +}) +export class ProfileComponent implements OnInit { + @Input() + profileImageRoot: string; + @Input() + isMe: boolean; + @Input() + isBuddy: boolean; + @Input() + isFavorit: boolean; + @Input() + userInfo: UserInfo | UserInfoF; + + @Output() + openChat = new EventEmitter(); + @Output() + toggleFavorit = new EventEmitter<{ + userInfo: UserInfo | UserInfoF; + isFavorit: boolean; + }>(); + @Output() + toggleBuddy = new EventEmitter<{ + userInfo: UserInfo | UserInfoF; + isBuddy: boolean; + }>(); + + constructor() {} + + ngOnInit() {} + + onClickOpenChat() { + this.openChat.emit(this.userInfo); + } + + onClickCall() {} + + onClickVideoConference() {} + + onClickMessage() {} + + onToggleFavorit() { + this.isFavorit = !this.isFavorit; + + this.toggleFavorit.emit({ + userInfo: this.userInfo, + isFavorit: this.isFavorit + }); + } + + onClickAddBuddy() { + this.toggleBuddy.emit({ + userInfo: this.userInfo, + isBuddy: true + }); + } + + onClickDelBuddy() { + this.toggleBuddy.emit({ + userInfo: this.userInfo, + isBuddy: false + }); + } +} diff --git a/projects/ucap-webmessenger-ui-profile/src/lib/components/user-list-item.component.html b/projects/ucap-webmessenger-ui-profile/src/lib/components/user-list-item.component.html index 45eb4a3..d258cc0 100644 --- a/projects/ucap-webmessenger-ui-profile/src/lib/components/user-list-item.component.html +++ b/projects/ucap-webmessenger-ui-profile/src/lib/components/user-list-item.component.html @@ -1,12 +1,7 @@ -
    +
    - {{ presence.pcStatus }} - +
    @@ -41,7 +37,7 @@ #checkbox [checked]="isChecked" (change)="onChangeCheck(checkbox.checked, userInfo)" - (click)="$event.stopPropagation()" + (click)="onClickCheck($event)" >
    diff --git a/projects/ucap-webmessenger-ui-profile/src/lib/components/user-list-item.component.ts b/projects/ucap-webmessenger-ui-profile/src/lib/components/user-list-item.component.ts index 0ba87db..be354e9 100644 --- a/projects/ucap-webmessenger-ui-profile/src/lib/components/user-list-item.component.ts +++ b/projects/ucap-webmessenger-ui-profile/src/lib/components/user-list-item.component.ts @@ -43,12 +43,19 @@ export class UserListItemComponent implements OnInit { @Input() /** 선택된 사용자의 리스트 */ selectedUserList?: (UserInfo | UserInfoSS | UserInfoF | UserInfoDN)[] = []; + @Input() + /** event bubbling fixed in custom tree */ + inTree = false; @Output() checkUser = new EventEmitter<{ isChecked: boolean; userInfo: UserInfo | UserInfoSS | UserInfoF | UserInfoDN; }>(); + @Output() + openProfile = new EventEmitter< + UserInfo | UserInfoSS | UserInfoF | UserInfoDN + >(); PresenceType = PresenceType; @@ -64,7 +71,7 @@ export class UserListItemComponent implements OnInit { let rtnClass = ''; switch (type) { case 'pc': - status = this.presence.pcStatus; + status = !!this.presence ? this.presence.pcStatus : undefined; break; } @@ -98,4 +105,19 @@ export class UserListItemComponent implements OnInit { userInfo }); } + onClickCheck(event: MouseEvent) { + if (!this.inTree) { + event.stopPropagation(); + } + } + + onClickOpenProfile( + event: MouseEvent, + userInfo: UserInfo | UserInfoSS | UserInfoF | UserInfoDN + ) { + event.preventDefault(); + event.stopPropagation(); + + this.openProfile.emit(userInfo); + } } diff --git a/projects/ucap-webmessenger-ui-profile/src/lib/ucap-ui-profile.module.ts b/projects/ucap-webmessenger-ui-profile/src/lib/ucap-ui-profile.module.ts index 6420bf4..3387eb5 100644 --- a/projects/ucap-webmessenger-ui-profile/src/lib/ucap-ui-profile.module.ts +++ b/projects/ucap-webmessenger-ui-profile/src/lib/ucap-ui-profile.module.ts @@ -1,3 +1,5 @@ +import { MatTooltipModule } from '@angular/material/tooltip'; +import { MatCardModule } from '@angular/material/card'; import { NgModule, ModuleWithProviders } from '@angular/core'; import { CommonModule } from '@angular/common'; @@ -11,8 +13,15 @@ import { UCapUiModule } from '@ucap-webmessenger/ui'; import { ListItemComponent } from './components/list-item.component'; import { UserListItemComponent } from './components/user-list-item.component'; +import { ProfileComponent } from './components/profile.component'; +import { MyProfileWidgetComponent } from './components/my-profile-widget.component'; -const COMPONENTS = [ListItemComponent, UserListItemComponent]; +const COMPONENTS = [ + ListItemComponent, + UserListItemComponent, + ProfileComponent, + MyProfileWidgetComponent +]; const SERVICES = []; @@ -24,6 +33,8 @@ const SERVICES = []; MatIconModule, MatRippleModule, MatCheckboxModule, + MatCardModule, + MatTooltipModule, UCapUiModule ], diff --git a/projects/ucap-webmessenger-ui-room/src/lib/components/list-item.component.html b/projects/ucap-webmessenger-ui-room/src/lib/components/list-item.component.html index b8599af..a4ef3ac 100644 --- a/projects/ucap-webmessenger-ui-room/src/lib/components/list-item.component.html +++ b/projects/ucap-webmessenger-ui-room/src/lib/components/list-item.component.html @@ -11,13 +11,22 @@ timer +
    {{ getRoomName(roomInfo) }}
    {{ roomInfo.joinUserCount }}명 diff --git a/projects/ucap-webmessenger-ui-room/src/lib/components/list-item.component.scss b/projects/ucap-webmessenger-ui-room/src/lib/components/list-item.component.scss index ae9b222..423d768 100644 --- a/projects/ucap-webmessenger-ui-room/src/lib/components/list-item.component.scss +++ b/projects/ucap-webmessenger-ui-room/src/lib/components/list-item.component.scss @@ -25,19 +25,19 @@ $thumbnail-msize: 40px; } .badge-timer { - position:absolute; + position: absolute; background-color: #ffffff; width: 18px; height: 18px; border-radius: 50%; bottom: 14px; left: 46px; - text-align:center; - .mat-icon{ - font-size:14px; - width: 18px; + text-align: center; + .mat-icon { + font-size: 14px; + width: 18px; height: 18px; - line-height:18px; + line-height: 18px; } } @@ -107,7 +107,7 @@ $thumbnail-msize: 40px; display: flex; margin: 0; padding: 0; - width: calc(100% - 60px); + .detail { flex-direction: column; width: calc(100% - 80px); @@ -131,7 +131,7 @@ $thumbnail-msize: 40px; font-size: 16px; color: #666666; margin-left: 4px; - line-height:unset; + line-height: unset; } .num { font-size: 12px; @@ -139,7 +139,6 @@ $thumbnail-msize: 40px; margin-left: 6px; border-radius: 3px; padding: 1px 6px; - background-color: #ef4c73; color: #ffffff; } } @@ -159,6 +158,14 @@ $thumbnail-msize: 40px; @include ellipsis(1); } } + + .num { + font-size: 18px; + font: bold; + flex: none; + text-align: center; + background-color: rgba($color: #666666, $alpha: 0.5); + } } .list-item { diff --git a/projects/ucap-webmessenger-ui-settings/README.md b/projects/ucap-webmessenger-ui-settings/README.md new file mode 100644 index 0000000..402cb1d --- /dev/null +++ b/projects/ucap-webmessenger-ui-settings/README.md @@ -0,0 +1,24 @@ +# UcapWebmessengerUiSettings + +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-ui-settings` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module --project ucap-webmessenger-ui-settings`. +> Note: Don't forget to add `--project ucap-webmessenger-ui-settings` or else it will be added to the default project in your `angular.json` file. + +## Build + +Run `ng build ucap-webmessenger-ui-settings` to build the project. The build artifacts will be stored in the `dist/` directory. + +## Publishing + +After building your library with `ng build ucap-webmessenger-ui-settings`, go to the dist folder `cd dist/ucap-webmessenger-ui-settings` and run `npm publish`. + +## Running unit tests + +Run `ng test ucap-webmessenger-ui-settings` 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). diff --git a/projects/ucap-webmessenger-electron-notification/karma.conf.js b/projects/ucap-webmessenger-ui-settings/karma.conf.js similarity index 96% rename from projects/ucap-webmessenger-electron-notification/karma.conf.js rename to projects/ucap-webmessenger-ui-settings/karma.conf.js index 2b6d790..44e8601 100644 --- a/projects/ucap-webmessenger-electron-notification/karma.conf.js +++ b/projects/ucap-webmessenger-ui-settings/karma.conf.js @@ -16,7 +16,7 @@ module.exports = function (config) { clearContext: false // leave Jasmine Spec Runner output visible in browser }, coverageIstanbulReporter: { - dir: require('path').join(__dirname, '../../coverage/ucap-webmessenger-electron-notification'), + dir: require('path').join(__dirname, '../../coverage/ucap-webmessenger-ui-settings'), reports: ['html', 'lcovonly', 'text-summary'], fixWebpackSourcePaths: true }, diff --git a/projects/ucap-webmessenger-electron-notification/ng-package.json b/projects/ucap-webmessenger-ui-settings/ng-package.json similarity index 65% rename from projects/ucap-webmessenger-electron-notification/ng-package.json rename to projects/ucap-webmessenger-ui-settings/ng-package.json index fc7aaf1..6fbd226 100644 --- a/projects/ucap-webmessenger-electron-notification/ng-package.json +++ b/projects/ucap-webmessenger-ui-settings/ng-package.json @@ -1,6 +1,6 @@ { "$schema": "../../node_modules/ng-packagr/ng-package.schema.json", - "dest": "../../dist/ucap-webmessenger-electron-notification", + "dest": "../../dist/ucap-webmessenger-ui-settings", "lib": { "entryFile": "src/public-api.ts" } diff --git a/projects/ucap-webmessenger-ui-settings/package.json b/projects/ucap-webmessenger-ui-settings/package.json new file mode 100644 index 0000000..d871cee --- /dev/null +++ b/projects/ucap-webmessenger-ui-settings/package.json @@ -0,0 +1,8 @@ +{ + "name": "@ucap-webmessenger/ui-settings", + "version": "0.0.1", + "peerDependencies": { + "@angular/common": "^8.2.11", + "@angular/core": "^8.2.11" + } +} diff --git a/projects/ucap-webmessenger-ui-settings/src/assets/timezone/en.json b/projects/ucap-webmessenger-ui-settings/src/assets/timezone/en.json new file mode 100644 index 0000000..f0d28cc --- /dev/null +++ b/projects/ucap-webmessenger-ui-settings/src/assets/timezone/en.json @@ -0,0 +1,1247 @@ +[ + { + "value": "Dateline Standard Time", + "abbr": "DST", + "offset": -12, + "isdst": false, + "text": "(UTC-12:00) International Date Line West", + "utc": ["Etc/GMT+12"] + }, + { + "value": "UTC-11", + "abbr": "U", + "offset": -11, + "isdst": false, + "text": "(UTC-11:00) Coordinated Universal Time-11", + "utc": ["Etc/GMT+11", "Pacific/Midway", "Pacific/Niue", "Pacific/Pago_Pago"] + }, + { + "value": "Hawaiian Standard Time", + "abbr": "HST", + "offset": -10, + "isdst": false, + "text": "(UTC-10:00) Hawaii", + "utc": [ + "Etc/GMT+10", + "Pacific/Honolulu", + "Pacific/Johnston", + "Pacific/Rarotonga", + "Pacific/Tahiti" + ] + }, + { + "value": "Alaskan Standard Time", + "abbr": "AKDT", + "offset": -8, + "isdst": true, + "text": "(UTC-09:00) Alaska", + "utc": [ + "America/Anchorage", + "America/Juneau", + "America/Nome", + "America/Sitka", + "America/Yakutat" + ] + }, + { + "value": "Pacific Standard Time (Mexico)", + "abbr": "PDT", + "offset": -7, + "isdst": true, + "text": "(UTC-08:00) Baja California", + "utc": ["America/Santa_Isabel"] + }, + { + "value": "Pacific Daylight Time", + "abbr": "PDT", + "offset": -7, + "isdst": true, + "text": "(UTC-07:00) Pacific Time (US & Canada)", + "utc": [ + "America/Dawson", + "America/Los_Angeles", + "America/Tijuana", + "America/Vancouver", + "America/Whitehorse" + ] + }, + { + "value": "Pacific Standard Time", + "abbr": "PST", + "offset": -8, + "isdst": false, + "text": "(UTC-08:00) Pacific Time (US & Canada)", + "utc": [ + "America/Dawson", + "America/Los_Angeles", + "America/Tijuana", + "America/Vancouver", + "America/Whitehorse", + "PST8PDT" + ] + }, + { + "value": "US Mountain Standard Time", + "abbr": "UMST", + "offset": -7, + "isdst": false, + "text": "(UTC-07:00) Arizona", + "utc": [ + "America/Creston", + "America/Dawson_Creek", + "America/Hermosillo", + "America/Phoenix", + "Etc/GMT+7" + ] + }, + { + "value": "Mountain Standard Time (Mexico)", + "abbr": "MDT", + "offset": -6, + "isdst": true, + "text": "(UTC-07:00) Chihuahua, La Paz, Mazatlan", + "utc": ["America/Chihuahua", "America/Mazatlan"] + }, + { + "value": "Mountain Standard Time", + "abbr": "MDT", + "offset": -6, + "isdst": true, + "text": "(UTC-07:00) Mountain Time (US & Canada)", + "utc": [ + "America/Boise", + "America/Cambridge_Bay", + "America/Denver", + "America/Edmonton", + "America/Inuvik", + "America/Ojinaga", + "America/Yellowknife", + "MST7MDT" + ] + }, + { + "value": "Central America Standard Time", + "abbr": "CAST", + "offset": -6, + "isdst": false, + "text": "(UTC-06:00) Central America", + "utc": [ + "America/Belize", + "America/Costa_Rica", + "America/El_Salvador", + "America/Guatemala", + "America/Managua", + "America/Tegucigalpa", + "Etc/GMT+6", + "Pacific/Galapagos" + ] + }, + { + "value": "Central Standard Time", + "abbr": "CDT", + "offset": -5, + "isdst": true, + "text": "(UTC-06:00) Central Time (US & Canada)", + "utc": [ + "America/Chicago", + "America/Indiana/Knox", + "America/Indiana/Tell_City", + "America/Matamoros", + "America/Menominee", + "America/North_Dakota/Beulah", + "America/North_Dakota/Center", + "America/North_Dakota/New_Salem", + "America/Rainy_River", + "America/Rankin_Inlet", + "America/Resolute", + "America/Winnipeg", + "CST6CDT" + ] + }, + { + "value": "Central Standard Time (Mexico)", + "abbr": "CDT", + "offset": -5, + "isdst": true, + "text": "(UTC-06:00) Guadalajara, Mexico City, Monterrey", + "utc": [ + "America/Bahia_Banderas", + "America/Cancun", + "America/Merida", + "America/Mexico_City", + "America/Monterrey" + ] + }, + { + "value": "Canada Central Standard Time", + "abbr": "CCST", + "offset": -6, + "isdst": false, + "text": "(UTC-06:00) Saskatchewan", + "utc": ["America/Regina", "America/Swift_Current"] + }, + { + "value": "SA Pacific Standard Time", + "abbr": "SPST", + "offset": -5, + "isdst": false, + "text": "(UTC-05:00) Bogota, Lima, Quito", + "utc": [ + "America/Bogota", + "America/Cayman", + "America/Coral_Harbour", + "America/Eirunepe", + "America/Guayaquil", + "America/Jamaica", + "America/Lima", + "America/Panama", + "America/Rio_Branco", + "Etc/GMT+5" + ] + }, + { + "value": "Eastern Standard Time", + "abbr": "EDT", + "offset": -4, + "isdst": true, + "text": "(UTC-05:00) Eastern Time (US & Canada)", + "utc": [ + "America/Detroit", + "America/Havana", + "America/Indiana/Petersburg", + "America/Indiana/Vincennes", + "America/Indiana/Winamac", + "America/Iqaluit", + "America/Kentucky/Monticello", + "America/Louisville", + "America/Montreal", + "America/Nassau", + "America/New_York", + "America/Nipigon", + "America/Pangnirtung", + "America/Port-au-Prince", + "America/Thunder_Bay", + "America/Toronto", + "EST5EDT" + ] + }, + { + "value": "US Eastern Standard Time", + "abbr": "UEDT", + "offset": -4, + "isdst": true, + "text": "(UTC-05:00) Indiana (East)", + "utc": [ + "America/Indiana/Marengo", + "America/Indiana/Vevay", + "America/Indianapolis" + ] + }, + { + "value": "Venezuela Standard Time", + "abbr": "VST", + "offset": -4.5, + "isdst": false, + "text": "(UTC-04:30) Caracas", + "utc": ["America/Caracas"] + }, + { + "value": "Paraguay Standard Time", + "abbr": "PYT", + "offset": -4, + "isdst": false, + "text": "(UTC-04:00) Asuncion", + "utc": ["America/Asuncion"] + }, + { + "value": "Atlantic Standard Time", + "abbr": "ADT", + "offset": -3, + "isdst": true, + "text": "(UTC-04:00) Atlantic Time (Canada)", + "utc": [ + "America/Glace_Bay", + "America/Goose_Bay", + "America/Halifax", + "America/Moncton", + "America/Thule", + "Atlantic/Bermuda" + ] + }, + { + "value": "Central Brazilian Standard Time", + "abbr": "CBST", + "offset": -4, + "isdst": false, + "text": "(UTC-04:00) Cuiaba", + "utc": ["America/Campo_Grande", "America/Cuiaba"] + }, + { + "value": "SA Western Standard Time", + "abbr": "SWST", + "offset": -4, + "isdst": false, + "text": "(UTC-04:00) Georgetown, La Paz, Manaus, San Juan", + "utc": [ + "America/Anguilla", + "America/Antigua", + "America/Aruba", + "America/Barbados", + "America/Blanc-Sablon", + "America/Boa_Vista", + "America/Curacao", + "America/Dominica", + "America/Grand_Turk", + "America/Grenada", + "America/Guadeloupe", + "America/Guyana", + "America/Kralendijk", + "America/La_Paz", + "America/Lower_Princes", + "America/Manaus", + "America/Marigot", + "America/Martinique", + "America/Montserrat", + "America/Port_of_Spain", + "America/Porto_Velho", + "America/Puerto_Rico", + "America/Santo_Domingo", + "America/St_Barthelemy", + "America/St_Kitts", + "America/St_Lucia", + "America/St_Thomas", + "America/St_Vincent", + "America/Tortola", + "Etc/GMT+4" + ] + }, + { + "value": "Pacific SA Standard Time", + "abbr": "PSST", + "offset": -4, + "isdst": false, + "text": "(UTC-04:00) Santiago", + "utc": ["America/Santiago", "Antarctica/Palmer"] + }, + { + "value": "Newfoundland Standard Time", + "abbr": "NDT", + "offset": -2.5, + "isdst": true, + "text": "(UTC-03:30) Newfoundland", + "utc": ["America/St_Johns"] + }, + { + "value": "E. South America Standard Time", + "abbr": "ESAST", + "offset": -3, + "isdst": false, + "text": "(UTC-03:00) Brasilia", + "utc": ["America/Sao_Paulo"] + }, + { + "value": "Argentina Standard Time", + "abbr": "AST", + "offset": -3, + "isdst": false, + "text": "(UTC-03:00) Buenos Aires", + "utc": [ + "America/Argentina/La_Rioja", + "America/Argentina/Rio_Gallegos", + "America/Argentina/Salta", + "America/Argentina/San_Juan", + "America/Argentina/San_Luis", + "America/Argentina/Tucuman", + "America/Argentina/Ushuaia", + "America/Buenos_Aires", + "America/Catamarca", + "America/Cordoba", + "America/Jujuy", + "America/Mendoza" + ] + }, + { + "value": "SA Eastern Standard Time", + "abbr": "SEST", + "offset": -3, + "isdst": false, + "text": "(UTC-03:00) Cayenne, Fortaleza", + "utc": [ + "America/Araguaina", + "America/Belem", + "America/Cayenne", + "America/Fortaleza", + "America/Maceio", + "America/Paramaribo", + "America/Recife", + "America/Santarem", + "Antarctica/Rothera", + "Atlantic/Stanley", + "Etc/GMT+3" + ] + }, + { + "value": "Greenland Standard Time", + "abbr": "GDT", + "offset": -3, + "isdst": true, + "text": "(UTC-03:00) Greenland", + "utc": ["America/Godthab"] + }, + { + "value": "Montevideo Standard Time", + "abbr": "MST", + "offset": -3, + "isdst": false, + "text": "(UTC-03:00) Montevideo", + "utc": ["America/Montevideo"] + }, + { + "value": "Bahia Standard Time", + "abbr": "BST", + "offset": -3, + "isdst": false, + "text": "(UTC-03:00) Salvador", + "utc": ["America/Bahia"] + }, + { + "value": "UTC-02", + "abbr": "U", + "offset": -2, + "isdst": false, + "text": "(UTC-02:00) Coordinated Universal Time-02", + "utc": ["America/Noronha", "Atlantic/South_Georgia", "Etc/GMT+2"] + }, + { + "value": "Mid-Atlantic Standard Time", + "abbr": "MDT", + "offset": -1, + "isdst": true, + "text": "(UTC-02:00) Mid-Atlantic - Old", + "utc": [] + }, + { + "value": "Azores Standard Time", + "abbr": "ADT", + "offset": 0, + "isdst": true, + "text": "(UTC-01:00) Azores", + "utc": ["America/Scoresbysund", "Atlantic/Azores"] + }, + { + "value": "Cape Verde Standard Time", + "abbr": "CVST", + "offset": -1, + "isdst": false, + "text": "(UTC-01:00) Cape Verde Is.", + "utc": ["Atlantic/Cape_Verde", "Etc/GMT+1"] + }, + { + "value": "Morocco Standard Time", + "abbr": "MDT", + "offset": 1, + "isdst": true, + "text": "(UTC) Casablanca", + "utc": ["Africa/Casablanca", "Africa/El_Aaiun"] + }, + { + "value": "UTC", + "abbr": "UTC", + "offset": 0, + "isdst": false, + "text": "(UTC) Coordinated Universal Time", + "utc": ["America/Danmarkshavn", "Etc/GMT"] + }, + { + "value": "GMT Standard Time", + "abbr": "GMT", + "offset": 0, + "isdst": false, + "text": "(UTC) Edinburgh, London", + "utc": [ + "Europe/Isle_of_Man", + "Europe/Guernsey", + "Europe/Jersey", + "Europe/London" + ] + }, + { + "value": "British Summer Time", + "abbr": "BST", + "offset": 1, + "isdst": true, + "text": "(UTC+01:00) Edinburgh, London", + "utc": [ + "Europe/Isle_of_Man", + "Europe/Guernsey", + "Europe/Jersey", + "Europe/London" + ] + }, + { + "value": "GMT Standard Time", + "abbr": "GDT", + "offset": 1, + "isdst": true, + "text": "(UTC) Dublin, Lisbon", + "utc": [ + "Atlantic/Canary", + "Atlantic/Faeroe", + "Atlantic/Madeira", + "Europe/Dublin", + "Europe/Lisbon" + ] + }, + { + "value": "Greenwich Standard Time", + "abbr": "GST", + "offset": 0, + "isdst": false, + "text": "(UTC) Monrovia, Reykjavik", + "utc": [ + "Africa/Abidjan", + "Africa/Accra", + "Africa/Bamako", + "Africa/Banjul", + "Africa/Bissau", + "Africa/Conakry", + "Africa/Dakar", + "Africa/Freetown", + "Africa/Lome", + "Africa/Monrovia", + "Africa/Nouakchott", + "Africa/Ouagadougou", + "Africa/Sao_Tome", + "Atlantic/Reykjavik", + "Atlantic/St_Helena" + ] + }, + { + "value": "W. Europe Standard Time", + "abbr": "WEDT", + "offset": 2, + "isdst": true, + "text": "(UTC+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna", + "utc": [ + "Arctic/Longyearbyen", + "Europe/Amsterdam", + "Europe/Andorra", + "Europe/Berlin", + "Europe/Busingen", + "Europe/Gibraltar", + "Europe/Luxembourg", + "Europe/Malta", + "Europe/Monaco", + "Europe/Oslo", + "Europe/Rome", + "Europe/San_Marino", + "Europe/Stockholm", + "Europe/Vaduz", + "Europe/Vatican", + "Europe/Vienna", + "Europe/Zurich" + ] + }, + { + "value": "Central Europe Standard Time", + "abbr": "CEDT", + "offset": 2, + "isdst": true, + "text": "(UTC+01:00) Belgrade, Bratislava, Budapest, Ljubljana, Prague", + "utc": [ + "Europe/Belgrade", + "Europe/Bratislava", + "Europe/Budapest", + "Europe/Ljubljana", + "Europe/Podgorica", + "Europe/Prague", + "Europe/Tirane" + ] + }, + { + "value": "Romance Standard Time", + "abbr": "RDT", + "offset": 2, + "isdst": true, + "text": "(UTC+01:00) Brussels, Copenhagen, Madrid, Paris", + "utc": [ + "Africa/Ceuta", + "Europe/Brussels", + "Europe/Copenhagen", + "Europe/Madrid", + "Europe/Paris" + ] + }, + { + "value": "Central European Standard Time", + "abbr": "CEDT", + "offset": 2, + "isdst": true, + "text": "(UTC+01:00) Sarajevo, Skopje, Warsaw, Zagreb", + "utc": [ + "Europe/Sarajevo", + "Europe/Skopje", + "Europe/Warsaw", + "Europe/Zagreb" + ] + }, + { + "value": "W. Central Africa Standard Time", + "abbr": "WCAST", + "offset": 1, + "isdst": false, + "text": "(UTC+01:00) West Central Africa", + "utc": [ + "Africa/Algiers", + "Africa/Bangui", + "Africa/Brazzaville", + "Africa/Douala", + "Africa/Kinshasa", + "Africa/Lagos", + "Africa/Libreville", + "Africa/Luanda", + "Africa/Malabo", + "Africa/Ndjamena", + "Africa/Niamey", + "Africa/Porto-Novo", + "Africa/Tunis", + "Etc/GMT-1" + ] + }, + { + "value": "Namibia Standard Time", + "abbr": "NST", + "offset": 1, + "isdst": false, + "text": "(UTC+01:00) Windhoek", + "utc": ["Africa/Windhoek"] + }, + { + "value": "GTB Standard Time", + "abbr": "GDT", + "offset": 3, + "isdst": true, + "text": "(UTC+02:00) Athens, Bucharest", + "utc": [ + "Asia/Nicosia", + "Europe/Athens", + "Europe/Bucharest", + "Europe/Chisinau" + ] + }, + { + "value": "Middle East Standard Time", + "abbr": "MEDT", + "offset": 3, + "isdst": true, + "text": "(UTC+02:00) Beirut", + "utc": ["Asia/Beirut"] + }, + { + "value": "Egypt Standard Time", + "abbr": "EST", + "offset": 2, + "isdst": false, + "text": "(UTC+02:00) Cairo", + "utc": ["Africa/Cairo"] + }, + { + "value": "Syria Standard Time", + "abbr": "SDT", + "offset": 3, + "isdst": true, + "text": "(UTC+02:00) Damascus", + "utc": ["Asia/Damascus"] + }, + { + "value": "E. Europe Standard Time", + "abbr": "EEDT", + "offset": 3, + "isdst": true, + "text": "(UTC+02:00) E. Europe", + "utc": [ + "Asia/Nicosia", + "Europe/Athens", + "Europe/Bucharest", + "Europe/Chisinau", + "Europe/Helsinki", + "Europe/Kiev", + "Europe/Mariehamn", + "Europe/Nicosia", + "Europe/Riga", + "Europe/Sofia", + "Europe/Tallinn", + "Europe/Uzhgorod", + "Europe/Vilnius", + "Europe/Zaporozhye" + ] + }, + { + "value": "South Africa Standard Time", + "abbr": "SAST", + "offset": 2, + "isdst": false, + "text": "(UTC+02:00) Harare, Pretoria", + "utc": [ + "Africa/Blantyre", + "Africa/Bujumbura", + "Africa/Gaborone", + "Africa/Harare", + "Africa/Johannesburg", + "Africa/Kigali", + "Africa/Lubumbashi", + "Africa/Lusaka", + "Africa/Maputo", + "Africa/Maseru", + "Africa/Mbabane", + "Etc/GMT-2" + ] + }, + { + "value": "FLE Standard Time", + "abbr": "FDT", + "offset": 3, + "isdst": true, + "text": "(UTC+02:00) Helsinki, Kyiv, Riga, Sofia, Tallinn, Vilnius", + "utc": [ + "Europe/Helsinki", + "Europe/Kiev", + "Europe/Mariehamn", + "Europe/Riga", + "Europe/Sofia", + "Europe/Tallinn", + "Europe/Uzhgorod", + "Europe/Vilnius", + "Europe/Zaporozhye" + ] + }, + { + "value": "Turkey Standard Time", + "abbr": "TDT", + "offset": 3, + "isdst": false, + "text": "(UTC+03:00) Istanbul", + "utc": ["Europe/Istanbul"] + }, + { + "value": "Israel Standard Time", + "abbr": "JDT", + "offset": 3, + "isdst": true, + "text": "(UTC+02:00) Jerusalem", + "utc": ["Asia/Jerusalem"] + }, + { + "value": "Libya Standard Time", + "abbr": "LST", + "offset": 2, + "isdst": false, + "text": "(UTC+02:00) Tripoli", + "utc": ["Africa/Tripoli"] + }, + { + "value": "Jordan Standard Time", + "abbr": "JST", + "offset": 3, + "isdst": false, + "text": "(UTC+03:00) Amman", + "utc": ["Asia/Amman"] + }, + { + "value": "Arabic Standard Time", + "abbr": "AST", + "offset": 3, + "isdst": false, + "text": "(UTC+03:00) Baghdad", + "utc": ["Asia/Baghdad"] + }, + { + "value": "Kaliningrad Standard Time", + "abbr": "KST", + "offset": 3, + "isdst": false, + "text": "(UTC+03:00) Kaliningrad, Minsk", + "utc": ["Europe/Kaliningrad", "Europe/Minsk"] + }, + { + "value": "Arab Standard Time", + "abbr": "AST", + "offset": 3, + "isdst": false, + "text": "(UTC+03:00) Kuwait, Riyadh", + "utc": [ + "Asia/Aden", + "Asia/Bahrain", + "Asia/Kuwait", + "Asia/Qatar", + "Asia/Riyadh" + ] + }, + { + "value": "E. Africa Standard Time", + "abbr": "EAST", + "offset": 3, + "isdst": false, + "text": "(UTC+03:00) Nairobi", + "utc": [ + "Africa/Addis_Ababa", + "Africa/Asmera", + "Africa/Dar_es_Salaam", + "Africa/Djibouti", + "Africa/Juba", + "Africa/Kampala", + "Africa/Khartoum", + "Africa/Mogadishu", + "Africa/Nairobi", + "Antarctica/Syowa", + "Etc/GMT-3", + "Indian/Antananarivo", + "Indian/Comoro", + "Indian/Mayotte" + ] + }, + { + "value": "Moscow Standard Time", + "abbr": "MSK", + "offset": 3, + "isdst": false, + "text": "(UTC+03:00) Moscow, St. Petersburg, Volgograd", + "utc": [ + "Europe/Kirov", + "Europe/Moscow", + "Europe/Simferopol", + "Europe/Volgograd" + ] + }, + { + "value": "Samara Time", + "abbr": "SAMT", + "offset": 4, + "isdst": false, + "text": "(UTC+04:00) Samara, Ulyanovsk, Saratov", + "utc": ["Europe/Astrakhan", "Europe/Samara", "Europe/Ulyanovsk"] + }, + { + "value": "Iran Standard Time", + "abbr": "IDT", + "offset": 4.5, + "isdst": true, + "text": "(UTC+03:30) Tehran", + "utc": ["Asia/Tehran"] + }, + { + "value": "Arabian Standard Time", + "abbr": "AST", + "offset": 4, + "isdst": false, + "text": "(UTC+04:00) Abu Dhabi, Muscat", + "utc": ["Asia/Dubai", "Asia/Muscat", "Etc/GMT-4"] + }, + { + "value": "Azerbaijan Standard Time", + "abbr": "ADT", + "offset": 5, + "isdst": true, + "text": "(UTC+04:00) Baku", + "utc": ["Asia/Baku"] + }, + { + "value": "Mauritius Standard Time", + "abbr": "MST", + "offset": 4, + "isdst": false, + "text": "(UTC+04:00) Port Louis", + "utc": ["Indian/Mahe", "Indian/Mauritius", "Indian/Reunion"] + }, + { + "value": "Georgian Standard Time", + "abbr": "GET", + "offset": 4, + "isdst": false, + "text": "(UTC+04:00) Tbilisi", + "utc": ["Asia/Tbilisi"] + }, + { + "value": "Caucasus Standard Time", + "abbr": "CST", + "offset": 4, + "isdst": false, + "text": "(UTC+04:00) Yerevan", + "utc": ["Asia/Yerevan"] + }, + { + "value": "Afghanistan Standard Time", + "abbr": "AST", + "offset": 4.5, + "isdst": false, + "text": "(UTC+04:30) Kabul", + "utc": ["Asia/Kabul"] + }, + { + "value": "West Asia Standard Time", + "abbr": "WAST", + "offset": 5, + "isdst": false, + "text": "(UTC+05:00) Ashgabat, Tashkent", + "utc": [ + "Antarctica/Mawson", + "Asia/Aqtau", + "Asia/Aqtobe", + "Asia/Ashgabat", + "Asia/Dushanbe", + "Asia/Oral", + "Asia/Samarkand", + "Asia/Tashkent", + "Etc/GMT-5", + "Indian/Kerguelen", + "Indian/Maldives" + ] + }, + { + "value": "Yekaterinburg Time", + "abbr": "YEKT", + "offset": 5, + "isdst": false, + "text": "(UTC+05:00) Yekaterinburg", + "utc": ["Asia/Yekaterinburg"] + }, + { + "value": "Pakistan Standard Time", + "abbr": "PKT", + "offset": 5, + "isdst": false, + "text": "(UTC+05:00) Islamabad, Karachi", + "utc": ["Asia/Karachi"] + }, + { + "value": "India Standard Time", + "abbr": "IST", + "offset": 5.5, + "isdst": false, + "text": "(UTC+05:30) Chennai, Kolkata, Mumbai, New Delhi", + "utc": ["Asia/Kolkata"] + }, + { + "value": "Sri Lanka Standard Time", + "abbr": "SLST", + "offset": 5.5, + "isdst": false, + "text": "(UTC+05:30) Sri Jayawardenepura", + "utc": ["Asia/Colombo"] + }, + { + "value": "Nepal Standard Time", + "abbr": "NST", + "offset": 5.75, + "isdst": false, + "text": "(UTC+05:45) Kathmandu", + "utc": ["Asia/Kathmandu"] + }, + { + "value": "Central Asia Standard Time", + "abbr": "CAST", + "offset": 6, + "isdst": false, + "text": "(UTC+06:00) Astana", + "utc": [ + "Antarctica/Vostok", + "Asia/Almaty", + "Asia/Bishkek", + "Asia/Qyzylorda", + "Asia/Urumqi", + "Etc/GMT-6", + "Indian/Chagos" + ] + }, + { + "value": "Bangladesh Standard Time", + "abbr": "BST", + "offset": 6, + "isdst": false, + "text": "(UTC+06:00) Dhaka", + "utc": ["Asia/Dhaka", "Asia/Thimphu"] + }, + { + "value": "Myanmar Standard Time", + "abbr": "MST", + "offset": 6.5, + "isdst": false, + "text": "(UTC+06:30) Yangon (Rangoon)", + "utc": ["Asia/Rangoon", "Indian/Cocos"] + }, + { + "value": "SE Asia Standard Time", + "abbr": "SAST", + "offset": 7, + "isdst": false, + "text": "(UTC+07:00) Bangkok, Hanoi, Jakarta", + "utc": [ + "Antarctica/Davis", + "Asia/Bangkok", + "Asia/Hovd", + "Asia/Jakarta", + "Asia/Phnom_Penh", + "Asia/Pontianak", + "Asia/Saigon", + "Asia/Vientiane", + "Etc/GMT-7", + "Indian/Christmas" + ] + }, + { + "value": "N. Central Asia Standard Time", + "abbr": "NCAST", + "offset": 7, + "isdst": false, + "text": "(UTC+07:00) Novosibirsk", + "utc": ["Asia/Novokuznetsk", "Asia/Novosibirsk", "Asia/Omsk"] + }, + { + "value": "China Standard Time", + "abbr": "CST", + "offset": 8, + "isdst": false, + "text": "(UTC+08:00) Beijing, Chongqing, Hong Kong, Urumqi", + "utc": ["Asia/Hong_Kong", "Asia/Macau", "Asia/Shanghai"] + }, + { + "value": "North Asia Standard Time", + "abbr": "NAST", + "offset": 8, + "isdst": false, + "text": "(UTC+08:00) Krasnoyarsk", + "utc": ["Asia/Krasnoyarsk"] + }, + { + "value": "Singapore Standard Time", + "abbr": "MPST", + "offset": 8, + "isdst": false, + "text": "(UTC+08:00) Kuala Lumpur, Singapore", + "utc": [ + "Asia/Brunei", + "Asia/Kuala_Lumpur", + "Asia/Kuching", + "Asia/Makassar", + "Asia/Manila", + "Asia/Singapore", + "Etc/GMT-8" + ] + }, + { + "value": "W. Australia Standard Time", + "abbr": "WAST", + "offset": 8, + "isdst": false, + "text": "(UTC+08:00) Perth", + "utc": ["Antarctica/Casey", "Australia/Perth"] + }, + { + "value": "Taipei Standard Time", + "abbr": "TST", + "offset": 8, + "isdst": false, + "text": "(UTC+08:00) Taipei", + "utc": ["Asia/Taipei"] + }, + { + "value": "Ulaanbaatar Standard Time", + "abbr": "UST", + "offset": 8, + "isdst": false, + "text": "(UTC+08:00) Ulaanbaatar", + "utc": ["Asia/Choibalsan", "Asia/Ulaanbaatar"] + }, + { + "value": "North Asia East Standard Time", + "abbr": "NAEST", + "offset": 8, + "isdst": false, + "text": "(UTC+08:00) Irkutsk", + "utc": ["Asia/Irkutsk"] + }, + { + "value": "Japan Standard Time", + "abbr": "JST", + "offset": 9, + "isdst": false, + "text": "(UTC+09:00) Osaka, Sapporo, Tokyo", + "utc": [ + "Asia/Dili", + "Asia/Jayapura", + "Asia/Tokyo", + "Etc/GMT-9", + "Pacific/Palau" + ] + }, + { + "value": "Korea Standard Time", + "abbr": "KST", + "offset": 9, + "isdst": false, + "text": "(UTC+09:00) Seoul", + "utc": ["Asia/Pyongyang", "Asia/Seoul"] + }, + { + "value": "Cen. Australia Standard Time", + "abbr": "CAST", + "offset": 9.5, + "isdst": false, + "text": "(UTC+09:30) Adelaide", + "utc": ["Australia/Adelaide", "Australia/Broken_Hill"] + }, + { + "value": "AUS Central Standard Time", + "abbr": "ACST", + "offset": 9.5, + "isdst": false, + "text": "(UTC+09:30) Darwin", + "utc": ["Australia/Darwin"] + }, + { + "value": "E. Australia Standard Time", + "abbr": "EAST", + "offset": 10, + "isdst": false, + "text": "(UTC+10:00) Brisbane", + "utc": ["Australia/Brisbane", "Australia/Lindeman"] + }, + { + "value": "AUS Eastern Standard Time", + "abbr": "AEST", + "offset": 10, + "isdst": false, + "text": "(UTC+10:00) Canberra, Melbourne, Sydney", + "utc": ["Australia/Melbourne", "Australia/Sydney"] + }, + { + "value": "West Pacific Standard Time", + "abbr": "WPST", + "offset": 10, + "isdst": false, + "text": "(UTC+10:00) Guam, Port Moresby", + "utc": [ + "Antarctica/DumontDUrville", + "Etc/GMT-10", + "Pacific/Guam", + "Pacific/Port_Moresby", + "Pacific/Saipan", + "Pacific/Truk" + ] + }, + { + "value": "Tasmania Standard Time", + "abbr": "TST", + "offset": 10, + "isdst": false, + "text": "(UTC+10:00) Hobart", + "utc": ["Australia/Currie", "Australia/Hobart"] + }, + { + "value": "Yakutsk Standard Time", + "abbr": "YST", + "offset": 9, + "isdst": false, + "text": "(UTC+09:00) Yakutsk", + "utc": ["Asia/Chita", "Asia/Khandyga", "Asia/Yakutsk"] + }, + { + "value": "Central Pacific Standard Time", + "abbr": "CPST", + "offset": 11, + "isdst": false, + "text": "(UTC+11:00) Solomon Is., New Caledonia", + "utc": [ + "Antarctica/Macquarie", + "Etc/GMT-11", + "Pacific/Efate", + "Pacific/Guadalcanal", + "Pacific/Kosrae", + "Pacific/Noumea", + "Pacific/Ponape" + ] + }, + { + "value": "Vladivostok Standard Time", + "abbr": "VST", + "offset": 11, + "isdst": false, + "text": "(UTC+11:00) Vladivostok", + "utc": ["Asia/Sakhalin", "Asia/Ust-Nera", "Asia/Vladivostok"] + }, + { + "value": "New Zealand Standard Time", + "abbr": "NZST", + "offset": 12, + "isdst": false, + "text": "(UTC+12:00) Auckland, Wellington", + "utc": ["Antarctica/McMurdo", "Pacific/Auckland"] + }, + { + "value": "UTC+12", + "abbr": "U", + "offset": 12, + "isdst": false, + "text": "(UTC+12:00) Coordinated Universal Time+12", + "utc": [ + "Etc/GMT-12", + "Pacific/Funafuti", + "Pacific/Kwajalein", + "Pacific/Majuro", + "Pacific/Nauru", + "Pacific/Tarawa", + "Pacific/Wake", + "Pacific/Wallis" + ] + }, + { + "value": "Fiji Standard Time", + "abbr": "FST", + "offset": 12, + "isdst": false, + "text": "(UTC+12:00) Fiji", + "utc": ["Pacific/Fiji"] + }, + { + "value": "Magadan Standard Time", + "abbr": "MST", + "offset": 12, + "isdst": false, + "text": "(UTC+12:00) Magadan", + "utc": [ + "Asia/Anadyr", + "Asia/Kamchatka", + "Asia/Magadan", + "Asia/Srednekolymsk" + ] + }, + { + "value": "Kamchatka Standard Time", + "abbr": "KDT", + "offset": 13, + "isdst": true, + "text": "(UTC+12:00) Petropavlovsk-Kamchatsky - Old", + "utc": ["Asia/Kamchatka"] + }, + { + "value": "Tonga Standard Time", + "abbr": "TST", + "offset": 13, + "isdst": false, + "text": "(UTC+13:00) Nuku'alofa", + "utc": [ + "Etc/GMT-13", + "Pacific/Enderbury", + "Pacific/Fakaofo", + "Pacific/Tongatapu" + ] + }, + { + "value": "Samoa Standard Time", + "abbr": "SST", + "offset": 13, + "isdst": false, + "text": "(UTC+13:00) Samoa", + "utc": ["Pacific/Apia"] + } +] diff --git a/projects/ucap-webmessenger-ui-settings/src/assets/timezone/ko.json b/projects/ucap-webmessenger-ui-settings/src/assets/timezone/ko.json new file mode 100644 index 0000000..f0d28cc --- /dev/null +++ b/projects/ucap-webmessenger-ui-settings/src/assets/timezone/ko.json @@ -0,0 +1,1247 @@ +[ + { + "value": "Dateline Standard Time", + "abbr": "DST", + "offset": -12, + "isdst": false, + "text": "(UTC-12:00) International Date Line West", + "utc": ["Etc/GMT+12"] + }, + { + "value": "UTC-11", + "abbr": "U", + "offset": -11, + "isdst": false, + "text": "(UTC-11:00) Coordinated Universal Time-11", + "utc": ["Etc/GMT+11", "Pacific/Midway", "Pacific/Niue", "Pacific/Pago_Pago"] + }, + { + "value": "Hawaiian Standard Time", + "abbr": "HST", + "offset": -10, + "isdst": false, + "text": "(UTC-10:00) Hawaii", + "utc": [ + "Etc/GMT+10", + "Pacific/Honolulu", + "Pacific/Johnston", + "Pacific/Rarotonga", + "Pacific/Tahiti" + ] + }, + { + "value": "Alaskan Standard Time", + "abbr": "AKDT", + "offset": -8, + "isdst": true, + "text": "(UTC-09:00) Alaska", + "utc": [ + "America/Anchorage", + "America/Juneau", + "America/Nome", + "America/Sitka", + "America/Yakutat" + ] + }, + { + "value": "Pacific Standard Time (Mexico)", + "abbr": "PDT", + "offset": -7, + "isdst": true, + "text": "(UTC-08:00) Baja California", + "utc": ["America/Santa_Isabel"] + }, + { + "value": "Pacific Daylight Time", + "abbr": "PDT", + "offset": -7, + "isdst": true, + "text": "(UTC-07:00) Pacific Time (US & Canada)", + "utc": [ + "America/Dawson", + "America/Los_Angeles", + "America/Tijuana", + "America/Vancouver", + "America/Whitehorse" + ] + }, + { + "value": "Pacific Standard Time", + "abbr": "PST", + "offset": -8, + "isdst": false, + "text": "(UTC-08:00) Pacific Time (US & Canada)", + "utc": [ + "America/Dawson", + "America/Los_Angeles", + "America/Tijuana", + "America/Vancouver", + "America/Whitehorse", + "PST8PDT" + ] + }, + { + "value": "US Mountain Standard Time", + "abbr": "UMST", + "offset": -7, + "isdst": false, + "text": "(UTC-07:00) Arizona", + "utc": [ + "America/Creston", + "America/Dawson_Creek", + "America/Hermosillo", + "America/Phoenix", + "Etc/GMT+7" + ] + }, + { + "value": "Mountain Standard Time (Mexico)", + "abbr": "MDT", + "offset": -6, + "isdst": true, + "text": "(UTC-07:00) Chihuahua, La Paz, Mazatlan", + "utc": ["America/Chihuahua", "America/Mazatlan"] + }, + { + "value": "Mountain Standard Time", + "abbr": "MDT", + "offset": -6, + "isdst": true, + "text": "(UTC-07:00) Mountain Time (US & Canada)", + "utc": [ + "America/Boise", + "America/Cambridge_Bay", + "America/Denver", + "America/Edmonton", + "America/Inuvik", + "America/Ojinaga", + "America/Yellowknife", + "MST7MDT" + ] + }, + { + "value": "Central America Standard Time", + "abbr": "CAST", + "offset": -6, + "isdst": false, + "text": "(UTC-06:00) Central America", + "utc": [ + "America/Belize", + "America/Costa_Rica", + "America/El_Salvador", + "America/Guatemala", + "America/Managua", + "America/Tegucigalpa", + "Etc/GMT+6", + "Pacific/Galapagos" + ] + }, + { + "value": "Central Standard Time", + "abbr": "CDT", + "offset": -5, + "isdst": true, + "text": "(UTC-06:00) Central Time (US & Canada)", + "utc": [ + "America/Chicago", + "America/Indiana/Knox", + "America/Indiana/Tell_City", + "America/Matamoros", + "America/Menominee", + "America/North_Dakota/Beulah", + "America/North_Dakota/Center", + "America/North_Dakota/New_Salem", + "America/Rainy_River", + "America/Rankin_Inlet", + "America/Resolute", + "America/Winnipeg", + "CST6CDT" + ] + }, + { + "value": "Central Standard Time (Mexico)", + "abbr": "CDT", + "offset": -5, + "isdst": true, + "text": "(UTC-06:00) Guadalajara, Mexico City, Monterrey", + "utc": [ + "America/Bahia_Banderas", + "America/Cancun", + "America/Merida", + "America/Mexico_City", + "America/Monterrey" + ] + }, + { + "value": "Canada Central Standard Time", + "abbr": "CCST", + "offset": -6, + "isdst": false, + "text": "(UTC-06:00) Saskatchewan", + "utc": ["America/Regina", "America/Swift_Current"] + }, + { + "value": "SA Pacific Standard Time", + "abbr": "SPST", + "offset": -5, + "isdst": false, + "text": "(UTC-05:00) Bogota, Lima, Quito", + "utc": [ + "America/Bogota", + "America/Cayman", + "America/Coral_Harbour", + "America/Eirunepe", + "America/Guayaquil", + "America/Jamaica", + "America/Lima", + "America/Panama", + "America/Rio_Branco", + "Etc/GMT+5" + ] + }, + { + "value": "Eastern Standard Time", + "abbr": "EDT", + "offset": -4, + "isdst": true, + "text": "(UTC-05:00) Eastern Time (US & Canada)", + "utc": [ + "America/Detroit", + "America/Havana", + "America/Indiana/Petersburg", + "America/Indiana/Vincennes", + "America/Indiana/Winamac", + "America/Iqaluit", + "America/Kentucky/Monticello", + "America/Louisville", + "America/Montreal", + "America/Nassau", + "America/New_York", + "America/Nipigon", + "America/Pangnirtung", + "America/Port-au-Prince", + "America/Thunder_Bay", + "America/Toronto", + "EST5EDT" + ] + }, + { + "value": "US Eastern Standard Time", + "abbr": "UEDT", + "offset": -4, + "isdst": true, + "text": "(UTC-05:00) Indiana (East)", + "utc": [ + "America/Indiana/Marengo", + "America/Indiana/Vevay", + "America/Indianapolis" + ] + }, + { + "value": "Venezuela Standard Time", + "abbr": "VST", + "offset": -4.5, + "isdst": false, + "text": "(UTC-04:30) Caracas", + "utc": ["America/Caracas"] + }, + { + "value": "Paraguay Standard Time", + "abbr": "PYT", + "offset": -4, + "isdst": false, + "text": "(UTC-04:00) Asuncion", + "utc": ["America/Asuncion"] + }, + { + "value": "Atlantic Standard Time", + "abbr": "ADT", + "offset": -3, + "isdst": true, + "text": "(UTC-04:00) Atlantic Time (Canada)", + "utc": [ + "America/Glace_Bay", + "America/Goose_Bay", + "America/Halifax", + "America/Moncton", + "America/Thule", + "Atlantic/Bermuda" + ] + }, + { + "value": "Central Brazilian Standard Time", + "abbr": "CBST", + "offset": -4, + "isdst": false, + "text": "(UTC-04:00) Cuiaba", + "utc": ["America/Campo_Grande", "America/Cuiaba"] + }, + { + "value": "SA Western Standard Time", + "abbr": "SWST", + "offset": -4, + "isdst": false, + "text": "(UTC-04:00) Georgetown, La Paz, Manaus, San Juan", + "utc": [ + "America/Anguilla", + "America/Antigua", + "America/Aruba", + "America/Barbados", + "America/Blanc-Sablon", + "America/Boa_Vista", + "America/Curacao", + "America/Dominica", + "America/Grand_Turk", + "America/Grenada", + "America/Guadeloupe", + "America/Guyana", + "America/Kralendijk", + "America/La_Paz", + "America/Lower_Princes", + "America/Manaus", + "America/Marigot", + "America/Martinique", + "America/Montserrat", + "America/Port_of_Spain", + "America/Porto_Velho", + "America/Puerto_Rico", + "America/Santo_Domingo", + "America/St_Barthelemy", + "America/St_Kitts", + "America/St_Lucia", + "America/St_Thomas", + "America/St_Vincent", + "America/Tortola", + "Etc/GMT+4" + ] + }, + { + "value": "Pacific SA Standard Time", + "abbr": "PSST", + "offset": -4, + "isdst": false, + "text": "(UTC-04:00) Santiago", + "utc": ["America/Santiago", "Antarctica/Palmer"] + }, + { + "value": "Newfoundland Standard Time", + "abbr": "NDT", + "offset": -2.5, + "isdst": true, + "text": "(UTC-03:30) Newfoundland", + "utc": ["America/St_Johns"] + }, + { + "value": "E. South America Standard Time", + "abbr": "ESAST", + "offset": -3, + "isdst": false, + "text": "(UTC-03:00) Brasilia", + "utc": ["America/Sao_Paulo"] + }, + { + "value": "Argentina Standard Time", + "abbr": "AST", + "offset": -3, + "isdst": false, + "text": "(UTC-03:00) Buenos Aires", + "utc": [ + "America/Argentina/La_Rioja", + "America/Argentina/Rio_Gallegos", + "America/Argentina/Salta", + "America/Argentina/San_Juan", + "America/Argentina/San_Luis", + "America/Argentina/Tucuman", + "America/Argentina/Ushuaia", + "America/Buenos_Aires", + "America/Catamarca", + "America/Cordoba", + "America/Jujuy", + "America/Mendoza" + ] + }, + { + "value": "SA Eastern Standard Time", + "abbr": "SEST", + "offset": -3, + "isdst": false, + "text": "(UTC-03:00) Cayenne, Fortaleza", + "utc": [ + "America/Araguaina", + "America/Belem", + "America/Cayenne", + "America/Fortaleza", + "America/Maceio", + "America/Paramaribo", + "America/Recife", + "America/Santarem", + "Antarctica/Rothera", + "Atlantic/Stanley", + "Etc/GMT+3" + ] + }, + { + "value": "Greenland Standard Time", + "abbr": "GDT", + "offset": -3, + "isdst": true, + "text": "(UTC-03:00) Greenland", + "utc": ["America/Godthab"] + }, + { + "value": "Montevideo Standard Time", + "abbr": "MST", + "offset": -3, + "isdst": false, + "text": "(UTC-03:00) Montevideo", + "utc": ["America/Montevideo"] + }, + { + "value": "Bahia Standard Time", + "abbr": "BST", + "offset": -3, + "isdst": false, + "text": "(UTC-03:00) Salvador", + "utc": ["America/Bahia"] + }, + { + "value": "UTC-02", + "abbr": "U", + "offset": -2, + "isdst": false, + "text": "(UTC-02:00) Coordinated Universal Time-02", + "utc": ["America/Noronha", "Atlantic/South_Georgia", "Etc/GMT+2"] + }, + { + "value": "Mid-Atlantic Standard Time", + "abbr": "MDT", + "offset": -1, + "isdst": true, + "text": "(UTC-02:00) Mid-Atlantic - Old", + "utc": [] + }, + { + "value": "Azores Standard Time", + "abbr": "ADT", + "offset": 0, + "isdst": true, + "text": "(UTC-01:00) Azores", + "utc": ["America/Scoresbysund", "Atlantic/Azores"] + }, + { + "value": "Cape Verde Standard Time", + "abbr": "CVST", + "offset": -1, + "isdst": false, + "text": "(UTC-01:00) Cape Verde Is.", + "utc": ["Atlantic/Cape_Verde", "Etc/GMT+1"] + }, + { + "value": "Morocco Standard Time", + "abbr": "MDT", + "offset": 1, + "isdst": true, + "text": "(UTC) Casablanca", + "utc": ["Africa/Casablanca", "Africa/El_Aaiun"] + }, + { + "value": "UTC", + "abbr": "UTC", + "offset": 0, + "isdst": false, + "text": "(UTC) Coordinated Universal Time", + "utc": ["America/Danmarkshavn", "Etc/GMT"] + }, + { + "value": "GMT Standard Time", + "abbr": "GMT", + "offset": 0, + "isdst": false, + "text": "(UTC) Edinburgh, London", + "utc": [ + "Europe/Isle_of_Man", + "Europe/Guernsey", + "Europe/Jersey", + "Europe/London" + ] + }, + { + "value": "British Summer Time", + "abbr": "BST", + "offset": 1, + "isdst": true, + "text": "(UTC+01:00) Edinburgh, London", + "utc": [ + "Europe/Isle_of_Man", + "Europe/Guernsey", + "Europe/Jersey", + "Europe/London" + ] + }, + { + "value": "GMT Standard Time", + "abbr": "GDT", + "offset": 1, + "isdst": true, + "text": "(UTC) Dublin, Lisbon", + "utc": [ + "Atlantic/Canary", + "Atlantic/Faeroe", + "Atlantic/Madeira", + "Europe/Dublin", + "Europe/Lisbon" + ] + }, + { + "value": "Greenwich Standard Time", + "abbr": "GST", + "offset": 0, + "isdst": false, + "text": "(UTC) Monrovia, Reykjavik", + "utc": [ + "Africa/Abidjan", + "Africa/Accra", + "Africa/Bamako", + "Africa/Banjul", + "Africa/Bissau", + "Africa/Conakry", + "Africa/Dakar", + "Africa/Freetown", + "Africa/Lome", + "Africa/Monrovia", + "Africa/Nouakchott", + "Africa/Ouagadougou", + "Africa/Sao_Tome", + "Atlantic/Reykjavik", + "Atlantic/St_Helena" + ] + }, + { + "value": "W. Europe Standard Time", + "abbr": "WEDT", + "offset": 2, + "isdst": true, + "text": "(UTC+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna", + "utc": [ + "Arctic/Longyearbyen", + "Europe/Amsterdam", + "Europe/Andorra", + "Europe/Berlin", + "Europe/Busingen", + "Europe/Gibraltar", + "Europe/Luxembourg", + "Europe/Malta", + "Europe/Monaco", + "Europe/Oslo", + "Europe/Rome", + "Europe/San_Marino", + "Europe/Stockholm", + "Europe/Vaduz", + "Europe/Vatican", + "Europe/Vienna", + "Europe/Zurich" + ] + }, + { + "value": "Central Europe Standard Time", + "abbr": "CEDT", + "offset": 2, + "isdst": true, + "text": "(UTC+01:00) Belgrade, Bratislava, Budapest, Ljubljana, Prague", + "utc": [ + "Europe/Belgrade", + "Europe/Bratislava", + "Europe/Budapest", + "Europe/Ljubljana", + "Europe/Podgorica", + "Europe/Prague", + "Europe/Tirane" + ] + }, + { + "value": "Romance Standard Time", + "abbr": "RDT", + "offset": 2, + "isdst": true, + "text": "(UTC+01:00) Brussels, Copenhagen, Madrid, Paris", + "utc": [ + "Africa/Ceuta", + "Europe/Brussels", + "Europe/Copenhagen", + "Europe/Madrid", + "Europe/Paris" + ] + }, + { + "value": "Central European Standard Time", + "abbr": "CEDT", + "offset": 2, + "isdst": true, + "text": "(UTC+01:00) Sarajevo, Skopje, Warsaw, Zagreb", + "utc": [ + "Europe/Sarajevo", + "Europe/Skopje", + "Europe/Warsaw", + "Europe/Zagreb" + ] + }, + { + "value": "W. Central Africa Standard Time", + "abbr": "WCAST", + "offset": 1, + "isdst": false, + "text": "(UTC+01:00) West Central Africa", + "utc": [ + "Africa/Algiers", + "Africa/Bangui", + "Africa/Brazzaville", + "Africa/Douala", + "Africa/Kinshasa", + "Africa/Lagos", + "Africa/Libreville", + "Africa/Luanda", + "Africa/Malabo", + "Africa/Ndjamena", + "Africa/Niamey", + "Africa/Porto-Novo", + "Africa/Tunis", + "Etc/GMT-1" + ] + }, + { + "value": "Namibia Standard Time", + "abbr": "NST", + "offset": 1, + "isdst": false, + "text": "(UTC+01:00) Windhoek", + "utc": ["Africa/Windhoek"] + }, + { + "value": "GTB Standard Time", + "abbr": "GDT", + "offset": 3, + "isdst": true, + "text": "(UTC+02:00) Athens, Bucharest", + "utc": [ + "Asia/Nicosia", + "Europe/Athens", + "Europe/Bucharest", + "Europe/Chisinau" + ] + }, + { + "value": "Middle East Standard Time", + "abbr": "MEDT", + "offset": 3, + "isdst": true, + "text": "(UTC+02:00) Beirut", + "utc": ["Asia/Beirut"] + }, + { + "value": "Egypt Standard Time", + "abbr": "EST", + "offset": 2, + "isdst": false, + "text": "(UTC+02:00) Cairo", + "utc": ["Africa/Cairo"] + }, + { + "value": "Syria Standard Time", + "abbr": "SDT", + "offset": 3, + "isdst": true, + "text": "(UTC+02:00) Damascus", + "utc": ["Asia/Damascus"] + }, + { + "value": "E. Europe Standard Time", + "abbr": "EEDT", + "offset": 3, + "isdst": true, + "text": "(UTC+02:00) E. Europe", + "utc": [ + "Asia/Nicosia", + "Europe/Athens", + "Europe/Bucharest", + "Europe/Chisinau", + "Europe/Helsinki", + "Europe/Kiev", + "Europe/Mariehamn", + "Europe/Nicosia", + "Europe/Riga", + "Europe/Sofia", + "Europe/Tallinn", + "Europe/Uzhgorod", + "Europe/Vilnius", + "Europe/Zaporozhye" + ] + }, + { + "value": "South Africa Standard Time", + "abbr": "SAST", + "offset": 2, + "isdst": false, + "text": "(UTC+02:00) Harare, Pretoria", + "utc": [ + "Africa/Blantyre", + "Africa/Bujumbura", + "Africa/Gaborone", + "Africa/Harare", + "Africa/Johannesburg", + "Africa/Kigali", + "Africa/Lubumbashi", + "Africa/Lusaka", + "Africa/Maputo", + "Africa/Maseru", + "Africa/Mbabane", + "Etc/GMT-2" + ] + }, + { + "value": "FLE Standard Time", + "abbr": "FDT", + "offset": 3, + "isdst": true, + "text": "(UTC+02:00) Helsinki, Kyiv, Riga, Sofia, Tallinn, Vilnius", + "utc": [ + "Europe/Helsinki", + "Europe/Kiev", + "Europe/Mariehamn", + "Europe/Riga", + "Europe/Sofia", + "Europe/Tallinn", + "Europe/Uzhgorod", + "Europe/Vilnius", + "Europe/Zaporozhye" + ] + }, + { + "value": "Turkey Standard Time", + "abbr": "TDT", + "offset": 3, + "isdst": false, + "text": "(UTC+03:00) Istanbul", + "utc": ["Europe/Istanbul"] + }, + { + "value": "Israel Standard Time", + "abbr": "JDT", + "offset": 3, + "isdst": true, + "text": "(UTC+02:00) Jerusalem", + "utc": ["Asia/Jerusalem"] + }, + { + "value": "Libya Standard Time", + "abbr": "LST", + "offset": 2, + "isdst": false, + "text": "(UTC+02:00) Tripoli", + "utc": ["Africa/Tripoli"] + }, + { + "value": "Jordan Standard Time", + "abbr": "JST", + "offset": 3, + "isdst": false, + "text": "(UTC+03:00) Amman", + "utc": ["Asia/Amman"] + }, + { + "value": "Arabic Standard Time", + "abbr": "AST", + "offset": 3, + "isdst": false, + "text": "(UTC+03:00) Baghdad", + "utc": ["Asia/Baghdad"] + }, + { + "value": "Kaliningrad Standard Time", + "abbr": "KST", + "offset": 3, + "isdst": false, + "text": "(UTC+03:00) Kaliningrad, Minsk", + "utc": ["Europe/Kaliningrad", "Europe/Minsk"] + }, + { + "value": "Arab Standard Time", + "abbr": "AST", + "offset": 3, + "isdst": false, + "text": "(UTC+03:00) Kuwait, Riyadh", + "utc": [ + "Asia/Aden", + "Asia/Bahrain", + "Asia/Kuwait", + "Asia/Qatar", + "Asia/Riyadh" + ] + }, + { + "value": "E. Africa Standard Time", + "abbr": "EAST", + "offset": 3, + "isdst": false, + "text": "(UTC+03:00) Nairobi", + "utc": [ + "Africa/Addis_Ababa", + "Africa/Asmera", + "Africa/Dar_es_Salaam", + "Africa/Djibouti", + "Africa/Juba", + "Africa/Kampala", + "Africa/Khartoum", + "Africa/Mogadishu", + "Africa/Nairobi", + "Antarctica/Syowa", + "Etc/GMT-3", + "Indian/Antananarivo", + "Indian/Comoro", + "Indian/Mayotte" + ] + }, + { + "value": "Moscow Standard Time", + "abbr": "MSK", + "offset": 3, + "isdst": false, + "text": "(UTC+03:00) Moscow, St. Petersburg, Volgograd", + "utc": [ + "Europe/Kirov", + "Europe/Moscow", + "Europe/Simferopol", + "Europe/Volgograd" + ] + }, + { + "value": "Samara Time", + "abbr": "SAMT", + "offset": 4, + "isdst": false, + "text": "(UTC+04:00) Samara, Ulyanovsk, Saratov", + "utc": ["Europe/Astrakhan", "Europe/Samara", "Europe/Ulyanovsk"] + }, + { + "value": "Iran Standard Time", + "abbr": "IDT", + "offset": 4.5, + "isdst": true, + "text": "(UTC+03:30) Tehran", + "utc": ["Asia/Tehran"] + }, + { + "value": "Arabian Standard Time", + "abbr": "AST", + "offset": 4, + "isdst": false, + "text": "(UTC+04:00) Abu Dhabi, Muscat", + "utc": ["Asia/Dubai", "Asia/Muscat", "Etc/GMT-4"] + }, + { + "value": "Azerbaijan Standard Time", + "abbr": "ADT", + "offset": 5, + "isdst": true, + "text": "(UTC+04:00) Baku", + "utc": ["Asia/Baku"] + }, + { + "value": "Mauritius Standard Time", + "abbr": "MST", + "offset": 4, + "isdst": false, + "text": "(UTC+04:00) Port Louis", + "utc": ["Indian/Mahe", "Indian/Mauritius", "Indian/Reunion"] + }, + { + "value": "Georgian Standard Time", + "abbr": "GET", + "offset": 4, + "isdst": false, + "text": "(UTC+04:00) Tbilisi", + "utc": ["Asia/Tbilisi"] + }, + { + "value": "Caucasus Standard Time", + "abbr": "CST", + "offset": 4, + "isdst": false, + "text": "(UTC+04:00) Yerevan", + "utc": ["Asia/Yerevan"] + }, + { + "value": "Afghanistan Standard Time", + "abbr": "AST", + "offset": 4.5, + "isdst": false, + "text": "(UTC+04:30) Kabul", + "utc": ["Asia/Kabul"] + }, + { + "value": "West Asia Standard Time", + "abbr": "WAST", + "offset": 5, + "isdst": false, + "text": "(UTC+05:00) Ashgabat, Tashkent", + "utc": [ + "Antarctica/Mawson", + "Asia/Aqtau", + "Asia/Aqtobe", + "Asia/Ashgabat", + "Asia/Dushanbe", + "Asia/Oral", + "Asia/Samarkand", + "Asia/Tashkent", + "Etc/GMT-5", + "Indian/Kerguelen", + "Indian/Maldives" + ] + }, + { + "value": "Yekaterinburg Time", + "abbr": "YEKT", + "offset": 5, + "isdst": false, + "text": "(UTC+05:00) Yekaterinburg", + "utc": ["Asia/Yekaterinburg"] + }, + { + "value": "Pakistan Standard Time", + "abbr": "PKT", + "offset": 5, + "isdst": false, + "text": "(UTC+05:00) Islamabad, Karachi", + "utc": ["Asia/Karachi"] + }, + { + "value": "India Standard Time", + "abbr": "IST", + "offset": 5.5, + "isdst": false, + "text": "(UTC+05:30) Chennai, Kolkata, Mumbai, New Delhi", + "utc": ["Asia/Kolkata"] + }, + { + "value": "Sri Lanka Standard Time", + "abbr": "SLST", + "offset": 5.5, + "isdst": false, + "text": "(UTC+05:30) Sri Jayawardenepura", + "utc": ["Asia/Colombo"] + }, + { + "value": "Nepal Standard Time", + "abbr": "NST", + "offset": 5.75, + "isdst": false, + "text": "(UTC+05:45) Kathmandu", + "utc": ["Asia/Kathmandu"] + }, + { + "value": "Central Asia Standard Time", + "abbr": "CAST", + "offset": 6, + "isdst": false, + "text": "(UTC+06:00) Astana", + "utc": [ + "Antarctica/Vostok", + "Asia/Almaty", + "Asia/Bishkek", + "Asia/Qyzylorda", + "Asia/Urumqi", + "Etc/GMT-6", + "Indian/Chagos" + ] + }, + { + "value": "Bangladesh Standard Time", + "abbr": "BST", + "offset": 6, + "isdst": false, + "text": "(UTC+06:00) Dhaka", + "utc": ["Asia/Dhaka", "Asia/Thimphu"] + }, + { + "value": "Myanmar Standard Time", + "abbr": "MST", + "offset": 6.5, + "isdst": false, + "text": "(UTC+06:30) Yangon (Rangoon)", + "utc": ["Asia/Rangoon", "Indian/Cocos"] + }, + { + "value": "SE Asia Standard Time", + "abbr": "SAST", + "offset": 7, + "isdst": false, + "text": "(UTC+07:00) Bangkok, Hanoi, Jakarta", + "utc": [ + "Antarctica/Davis", + "Asia/Bangkok", + "Asia/Hovd", + "Asia/Jakarta", + "Asia/Phnom_Penh", + "Asia/Pontianak", + "Asia/Saigon", + "Asia/Vientiane", + "Etc/GMT-7", + "Indian/Christmas" + ] + }, + { + "value": "N. Central Asia Standard Time", + "abbr": "NCAST", + "offset": 7, + "isdst": false, + "text": "(UTC+07:00) Novosibirsk", + "utc": ["Asia/Novokuznetsk", "Asia/Novosibirsk", "Asia/Omsk"] + }, + { + "value": "China Standard Time", + "abbr": "CST", + "offset": 8, + "isdst": false, + "text": "(UTC+08:00) Beijing, Chongqing, Hong Kong, Urumqi", + "utc": ["Asia/Hong_Kong", "Asia/Macau", "Asia/Shanghai"] + }, + { + "value": "North Asia Standard Time", + "abbr": "NAST", + "offset": 8, + "isdst": false, + "text": "(UTC+08:00) Krasnoyarsk", + "utc": ["Asia/Krasnoyarsk"] + }, + { + "value": "Singapore Standard Time", + "abbr": "MPST", + "offset": 8, + "isdst": false, + "text": "(UTC+08:00) Kuala Lumpur, Singapore", + "utc": [ + "Asia/Brunei", + "Asia/Kuala_Lumpur", + "Asia/Kuching", + "Asia/Makassar", + "Asia/Manila", + "Asia/Singapore", + "Etc/GMT-8" + ] + }, + { + "value": "W. Australia Standard Time", + "abbr": "WAST", + "offset": 8, + "isdst": false, + "text": "(UTC+08:00) Perth", + "utc": ["Antarctica/Casey", "Australia/Perth"] + }, + { + "value": "Taipei Standard Time", + "abbr": "TST", + "offset": 8, + "isdst": false, + "text": "(UTC+08:00) Taipei", + "utc": ["Asia/Taipei"] + }, + { + "value": "Ulaanbaatar Standard Time", + "abbr": "UST", + "offset": 8, + "isdst": false, + "text": "(UTC+08:00) Ulaanbaatar", + "utc": ["Asia/Choibalsan", "Asia/Ulaanbaatar"] + }, + { + "value": "North Asia East Standard Time", + "abbr": "NAEST", + "offset": 8, + "isdst": false, + "text": "(UTC+08:00) Irkutsk", + "utc": ["Asia/Irkutsk"] + }, + { + "value": "Japan Standard Time", + "abbr": "JST", + "offset": 9, + "isdst": false, + "text": "(UTC+09:00) Osaka, Sapporo, Tokyo", + "utc": [ + "Asia/Dili", + "Asia/Jayapura", + "Asia/Tokyo", + "Etc/GMT-9", + "Pacific/Palau" + ] + }, + { + "value": "Korea Standard Time", + "abbr": "KST", + "offset": 9, + "isdst": false, + "text": "(UTC+09:00) Seoul", + "utc": ["Asia/Pyongyang", "Asia/Seoul"] + }, + { + "value": "Cen. Australia Standard Time", + "abbr": "CAST", + "offset": 9.5, + "isdst": false, + "text": "(UTC+09:30) Adelaide", + "utc": ["Australia/Adelaide", "Australia/Broken_Hill"] + }, + { + "value": "AUS Central Standard Time", + "abbr": "ACST", + "offset": 9.5, + "isdst": false, + "text": "(UTC+09:30) Darwin", + "utc": ["Australia/Darwin"] + }, + { + "value": "E. Australia Standard Time", + "abbr": "EAST", + "offset": 10, + "isdst": false, + "text": "(UTC+10:00) Brisbane", + "utc": ["Australia/Brisbane", "Australia/Lindeman"] + }, + { + "value": "AUS Eastern Standard Time", + "abbr": "AEST", + "offset": 10, + "isdst": false, + "text": "(UTC+10:00) Canberra, Melbourne, Sydney", + "utc": ["Australia/Melbourne", "Australia/Sydney"] + }, + { + "value": "West Pacific Standard Time", + "abbr": "WPST", + "offset": 10, + "isdst": false, + "text": "(UTC+10:00) Guam, Port Moresby", + "utc": [ + "Antarctica/DumontDUrville", + "Etc/GMT-10", + "Pacific/Guam", + "Pacific/Port_Moresby", + "Pacific/Saipan", + "Pacific/Truk" + ] + }, + { + "value": "Tasmania Standard Time", + "abbr": "TST", + "offset": 10, + "isdst": false, + "text": "(UTC+10:00) Hobart", + "utc": ["Australia/Currie", "Australia/Hobart"] + }, + { + "value": "Yakutsk Standard Time", + "abbr": "YST", + "offset": 9, + "isdst": false, + "text": "(UTC+09:00) Yakutsk", + "utc": ["Asia/Chita", "Asia/Khandyga", "Asia/Yakutsk"] + }, + { + "value": "Central Pacific Standard Time", + "abbr": "CPST", + "offset": 11, + "isdst": false, + "text": "(UTC+11:00) Solomon Is., New Caledonia", + "utc": [ + "Antarctica/Macquarie", + "Etc/GMT-11", + "Pacific/Efate", + "Pacific/Guadalcanal", + "Pacific/Kosrae", + "Pacific/Noumea", + "Pacific/Ponape" + ] + }, + { + "value": "Vladivostok Standard Time", + "abbr": "VST", + "offset": 11, + "isdst": false, + "text": "(UTC+11:00) Vladivostok", + "utc": ["Asia/Sakhalin", "Asia/Ust-Nera", "Asia/Vladivostok"] + }, + { + "value": "New Zealand Standard Time", + "abbr": "NZST", + "offset": 12, + "isdst": false, + "text": "(UTC+12:00) Auckland, Wellington", + "utc": ["Antarctica/McMurdo", "Pacific/Auckland"] + }, + { + "value": "UTC+12", + "abbr": "U", + "offset": 12, + "isdst": false, + "text": "(UTC+12:00) Coordinated Universal Time+12", + "utc": [ + "Etc/GMT-12", + "Pacific/Funafuti", + "Pacific/Kwajalein", + "Pacific/Majuro", + "Pacific/Nauru", + "Pacific/Tarawa", + "Pacific/Wake", + "Pacific/Wallis" + ] + }, + { + "value": "Fiji Standard Time", + "abbr": "FST", + "offset": 12, + "isdst": false, + "text": "(UTC+12:00) Fiji", + "utc": ["Pacific/Fiji"] + }, + { + "value": "Magadan Standard Time", + "abbr": "MST", + "offset": 12, + "isdst": false, + "text": "(UTC+12:00) Magadan", + "utc": [ + "Asia/Anadyr", + "Asia/Kamchatka", + "Asia/Magadan", + "Asia/Srednekolymsk" + ] + }, + { + "value": "Kamchatka Standard Time", + "abbr": "KDT", + "offset": 13, + "isdst": true, + "text": "(UTC+12:00) Petropavlovsk-Kamchatsky - Old", + "utc": ["Asia/Kamchatka"] + }, + { + "value": "Tonga Standard Time", + "abbr": "TST", + "offset": 13, + "isdst": false, + "text": "(UTC+13:00) Nuku'alofa", + "utc": [ + "Etc/GMT-13", + "Pacific/Enderbury", + "Pacific/Fakaofo", + "Pacific/Tongatapu" + ] + }, + { + "value": "Samoa Standard Time", + "abbr": "SST", + "offset": 13, + "isdst": false, + "text": "(UTC+13:00) Samoa", + "utc": ["Pacific/Apia"] + } +] diff --git a/projects/ucap-webmessenger-ui-settings/src/lib/components/call.component.html b/projects/ucap-webmessenger-ui-settings/src/lib/components/call.component.html new file mode 100644 index 0000000..938018d --- /dev/null +++ b/projects/ucap-webmessenger-ui-settings/src/lib/components/call.component.html @@ -0,0 +1,63 @@ +
    + +

    오디오 장치

    + + 발표자 + + + + + 배너 및 전자 메일 + + + 배너 + + + 끔 + + + + + + + 마이크 + + + + + 배너 및 전자 메일 + + + 배너 + + + 끔 + + + + + + + + +

    카메라

    + + 알림 소리 + + + + + 모두 + + + 통화, 채팅 + + + 끔 + + + + + +
    +
    diff --git a/projects/ucap-webmessenger-ui-settings/src/lib/components/call.component.scss b/projects/ucap-webmessenger-ui-settings/src/lib/components/call.component.scss new file mode 100644 index 0000000..bd43512 --- /dev/null +++ b/projects/ucap-webmessenger-ui-settings/src/lib/components/call.component.scss @@ -0,0 +1,7 @@ +.item-title { + width: 25rem; +} + +.item-input { + width: 20rem; +} diff --git a/projects/ucap-webmessenger-ui-settings/src/lib/components/call.component.spec.ts b/projects/ucap-webmessenger-ui-settings/src/lib/components/call.component.spec.ts new file mode 100644 index 0000000..0e3c6d9 --- /dev/null +++ b/projects/ucap-webmessenger-ui-settings/src/lib/components/call.component.spec.ts @@ -0,0 +1,24 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { CallComponent } from './call.component'; + +describe('Settings::CallComponent', () => { + let component: CallComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [CallComponent] + }).compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(CallComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/projects/ucap-webmessenger-ui-settings/src/lib/components/call.component.ts b/projects/ucap-webmessenger-ui-settings/src/lib/components/call.component.ts new file mode 100644 index 0000000..3802393 --- /dev/null +++ b/projects/ucap-webmessenger-ui-settings/src/lib/components/call.component.ts @@ -0,0 +1,20 @@ +import { Component, OnInit, ChangeDetectorRef } from '@angular/core'; +import { FormGroup, FormBuilder } from '@angular/forms'; + +@Component({ + selector: 'ucap-settings-call', + templateUrl: './call.component.html', + styleUrls: ['./call.component.scss'] +}) +export class CallComponent implements OnInit { + loginForm: FormGroup; + + constructor( + private formBuilder: FormBuilder, + private changeDetectorRef: ChangeDetectorRef + ) {} + + ngOnInit() {} + + onClickLogin() {} +} diff --git a/projects/ucap-webmessenger-ui-settings/src/lib/components/device.component.html b/projects/ucap-webmessenger-ui-settings/src/lib/components/device.component.html new file mode 100644 index 0000000..938018d --- /dev/null +++ b/projects/ucap-webmessenger-ui-settings/src/lib/components/device.component.html @@ -0,0 +1,63 @@ +
    + +

    오디오 장치

    + + 발표자 + + + + + 배너 및 전자 메일 + + + 배너 + + + 끔 + + + + + + + 마이크 + + + + + 배너 및 전자 메일 + + + 배너 + + + 끔 + + + + + + + + +

    카메라

    + + 알림 소리 + + + + + 모두 + + + 통화, 채팅 + + + 끔 + + + + + +
    +
    diff --git a/projects/ucap-webmessenger-ui-settings/src/lib/components/device.component.scss b/projects/ucap-webmessenger-ui-settings/src/lib/components/device.component.scss new file mode 100644 index 0000000..bd43512 --- /dev/null +++ b/projects/ucap-webmessenger-ui-settings/src/lib/components/device.component.scss @@ -0,0 +1,7 @@ +.item-title { + width: 25rem; +} + +.item-input { + width: 20rem; +} diff --git a/projects/ucap-webmessenger-ui-settings/src/lib/components/device.component.spec.ts b/projects/ucap-webmessenger-ui-settings/src/lib/components/device.component.spec.ts new file mode 100644 index 0000000..e5caf65 --- /dev/null +++ b/projects/ucap-webmessenger-ui-settings/src/lib/components/device.component.spec.ts @@ -0,0 +1,24 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { DeviceComponent } from './device.component'; + +describe('Settings::DeviceComponent', () => { + let component: DeviceComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [DeviceComponent] + }).compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(DeviceComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/projects/ucap-webmessenger-ui-settings/src/lib/components/device.component.ts b/projects/ucap-webmessenger-ui-settings/src/lib/components/device.component.ts new file mode 100644 index 0000000..d47c430 --- /dev/null +++ b/projects/ucap-webmessenger-ui-settings/src/lib/components/device.component.ts @@ -0,0 +1,20 @@ +import { Component, OnInit, ChangeDetectorRef } from '@angular/core'; +import { FormGroup, FormBuilder } from '@angular/forms'; + +@Component({ + selector: 'ucap-settings-device', + templateUrl: './device.component.html', + styleUrls: ['./device.component.scss'] +}) +export class DeviceComponent implements OnInit { + loginForm: FormGroup; + + constructor( + private formBuilder: FormBuilder, + private changeDetectorRef: ChangeDetectorRef + ) {} + + ngOnInit() {} + + onClickLogin() {} +} diff --git a/projects/ucap-webmessenger-ui-settings/src/lib/components/general.component.html b/projects/ucap-webmessenger-ui-settings/src/lib/components/general.component.html new file mode 100644 index 0000000..4535a16 --- /dev/null +++ b/projects/ucap-webmessenger-ui-settings/src/lib/components/general.component.html @@ -0,0 +1,89 @@ +
    + +

    테마

    + + + + + +
    +
    기본값
    +
    +
    + + +
    +
    LG Red
    +
    +
    +
    +
    + + + +

    응용 프로그램

    + + 응용 프로그램 자동 시작 + + + 백그라운드에서 응용 프로그램 열기 + + + 닫을 시 응용 프로그램을 계속 실행 + + + + +

    로그인

    + + 실행 시 자동 로그인 + + + + +

    언어

    + + + + + 한국어 (대한민국) + + + 영어 (미국) + + + + + + + +

    시간대

    + + + + + 한국어 (대한민국) + + + 영어 (미국) + + + + +
    +
    diff --git a/projects/ucap-webmessenger-ui-settings/src/lib/components/general.component.scss b/projects/ucap-webmessenger-ui-settings/src/lib/components/general.component.scss new file mode 100644 index 0000000..ae9410d --- /dev/null +++ b/projects/ucap-webmessenger-ui-settings/src/lib/components/general.component.scss @@ -0,0 +1,72 @@ +::ng-deep .mat-list-base { + .theme-select.mat-list-item { + position: relative; + height: 160px; + .mat-list-item-content { + flex-direction: column; + } + } +} + +::ng-deep .theme-list { + position: relative; + display: flex; + flex-flow: row; + width: 100%; + margin: 10px; + height: auto !important; + .mat-tab-header { + position: relative; + width: 100% !important; + .mat-tab-labels { + position: relative; + width: 100%; + flex-flow: row !important; + .mat-tab-label { + width: 140px; + height: 120px; + .mat-tab-label-content { + position: relative; + flex-flow: column; + width: 100%; + } + } + } + .mat-ink-bar { + display: none; + } + } + .mat-tab-body-wrapper { + border-left: none; + } +} + +.theme-item { + width: 140px; + height: 98px; + margin-right: 10px; + border: 1px solid #dddddd; + background-size: 100% auto; + background-repeat: no-repeat; + opacity: 0.7; +} +.theme-box { + width: 140px; + height: 98px; + border: 1px solid #dddddd; + background-size: 100% auto; + background-repeat: no-repeat; + &.default-theme { + background-image: url('../../../../ucap-webmessenger-app/src/assets/images/theme/theme-default.png'); + } + &.lg-red-theme { + background-image: url('../../../../ucap-webmessenger-app/src/assets/images/theme/theme-lgRed.png'); + } +} + +.brightness { + position: relative; + width: 100%; + display: flex; + flex-direction: row; +} diff --git a/projects/ucap-webmessenger-ui-settings/src/lib/components/general.component.spec.ts b/projects/ucap-webmessenger-ui-settings/src/lib/components/general.component.spec.ts new file mode 100644 index 0000000..d6a5178 --- /dev/null +++ b/projects/ucap-webmessenger-ui-settings/src/lib/components/general.component.spec.ts @@ -0,0 +1,24 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { GeneralComponent } from './general.component'; + +describe('Settings::GeneralComponent', () => { + let component: GeneralComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [GeneralComponent] + }).compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(GeneralComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/projects/ucap-webmessenger-ui-settings/src/lib/components/general.component.ts b/projects/ucap-webmessenger-ui-settings/src/lib/components/general.component.ts new file mode 100644 index 0000000..409cf3c --- /dev/null +++ b/projects/ucap-webmessenger-ui-settings/src/lib/components/general.component.ts @@ -0,0 +1,46 @@ +import { + Component, + OnInit, + ChangeDetectorRef, + Output, + EventEmitter +} from '@angular/core'; +import { FormGroup, FormBuilder } from '@angular/forms'; +import { MatTabChangeEvent } from '@angular/material'; + +@Component({ + selector: 'ucap-settings-general', + templateUrl: './general.component.html', + styleUrls: ['./general.component.scss'] +}) +export class GeneralComponent implements OnInit { + loginForm: FormGroup; + + @Output() + selectTheme = new EventEmitter(); + + constructor( + private formBuilder: FormBuilder, + private changeDetectorRef: ChangeDetectorRef + ) {} + + ngOnInit() {} + + onSelectedTabChange(e: MatTabChangeEvent) { + let theme = 'theme-default'; + switch (e.index) { + case 0: + theme = 'theme-default'; + break; + case 1: + theme = 'theme-lgRed'; + break; + default: + break; + } + + this.selectTheme.emit(theme); + } + + onClickLogin() {} +} diff --git a/projects/ucap-webmessenger-ui-settings/src/lib/components/notification.component.html b/projects/ucap-webmessenger-ui-settings/src/lib/components/notification.component.html new file mode 100644 index 0000000..8da42f0 --- /dev/null +++ b/projects/ucap-webmessenger-ui-settings/src/lib/components/notification.component.html @@ -0,0 +1,81 @@ +
    + +

    메시지

    + + 채팅 메시지 + + + + + 배너 및 전자 메일 + + + 배너 + + + 끔 + + + + + + + 내가 시작한 대화에 답장 + + + + + 배너 및 전자 메일 + + + 배너 + + + 끔 + + + + + + + + +

    기타

    + + 알림 소리 + + + + + 모두 + + + 통화, 채팅 + + + 끔 + + + + + + + 부재 중 활동 전자 메일 + + + + + 배너 및 전자 메일 + + + 배너 + + + 끔 + + + + + +
    +
    diff --git a/projects/ucap-webmessenger-ui-settings/src/lib/components/notification.component.scss b/projects/ucap-webmessenger-ui-settings/src/lib/components/notification.component.scss new file mode 100644 index 0000000..bd43512 --- /dev/null +++ b/projects/ucap-webmessenger-ui-settings/src/lib/components/notification.component.scss @@ -0,0 +1,7 @@ +.item-title { + width: 25rem; +} + +.item-input { + width: 20rem; +} diff --git a/projects/ucap-webmessenger-ui-settings/src/lib/components/notification.component.spec.ts b/projects/ucap-webmessenger-ui-settings/src/lib/components/notification.component.spec.ts new file mode 100644 index 0000000..e398431 --- /dev/null +++ b/projects/ucap-webmessenger-ui-settings/src/lib/components/notification.component.spec.ts @@ -0,0 +1,24 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { NotificationComponent } from './notification.component'; + +describe('Settings::NotificationComponent', () => { + let component: NotificationComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [NotificationComponent] + }).compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(NotificationComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/projects/ucap-webmessenger-ui-settings/src/lib/components/notification.component.ts b/projects/ucap-webmessenger-ui-settings/src/lib/components/notification.component.ts new file mode 100644 index 0000000..e3674d6 --- /dev/null +++ b/projects/ucap-webmessenger-ui-settings/src/lib/components/notification.component.ts @@ -0,0 +1,20 @@ +import { Component, OnInit, ChangeDetectorRef } from '@angular/core'; +import { FormGroup, FormBuilder } from '@angular/forms'; + +@Component({ + selector: 'ucap-settings-notification', + templateUrl: './notification.component.html', + styleUrls: ['./notification.component.scss'] +}) +export class NotificationComponent implements OnInit { + loginForm: FormGroup; + + constructor( + private formBuilder: FormBuilder, + private changeDetectorRef: ChangeDetectorRef + ) {} + + ngOnInit() {} + + onClickLogin() {} +} diff --git a/projects/ucap-webmessenger-ui-settings/src/lib/components/permission.component.html b/projects/ucap-webmessenger-ui-settings/src/lib/components/permission.component.html new file mode 100644 index 0000000..689a772 --- /dev/null +++ b/projects/ucap-webmessenger-ui-settings/src/lib/components/permission.component.html @@ -0,0 +1,27 @@ +
    + +

    사용 권한

    + + 미디어 + + + + + + 마이크 + + + + + + + +

    카메라

    + + 알림 소리 + + + + +
    +
    diff --git a/projects/ucap-webmessenger-ui-settings/src/lib/components/permission.component.scss b/projects/ucap-webmessenger-ui-settings/src/lib/components/permission.component.scss new file mode 100644 index 0000000..bd43512 --- /dev/null +++ b/projects/ucap-webmessenger-ui-settings/src/lib/components/permission.component.scss @@ -0,0 +1,7 @@ +.item-title { + width: 25rem; +} + +.item-input { + width: 20rem; +} diff --git a/projects/ucap-webmessenger-ui-settings/src/lib/components/permission.component.spec.ts b/projects/ucap-webmessenger-ui-settings/src/lib/components/permission.component.spec.ts new file mode 100644 index 0000000..54ef1ee --- /dev/null +++ b/projects/ucap-webmessenger-ui-settings/src/lib/components/permission.component.spec.ts @@ -0,0 +1,24 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { PermissionComponent } from './permission.component'; + +describe('Settings::PermissionComponent', () => { + let component: PermissionComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [PermissionComponent] + }).compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(PermissionComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/projects/ucap-webmessenger-ui-settings/src/lib/components/permission.component.ts b/projects/ucap-webmessenger-ui-settings/src/lib/components/permission.component.ts new file mode 100644 index 0000000..38da4c1 --- /dev/null +++ b/projects/ucap-webmessenger-ui-settings/src/lib/components/permission.component.ts @@ -0,0 +1,20 @@ +import { Component, OnInit, ChangeDetectorRef } from '@angular/core'; +import { FormGroup, FormBuilder } from '@angular/forms'; + +@Component({ + selector: 'ucap-settings-permission', + templateUrl: './permission.component.html', + styleUrls: ['./permission.component.scss'] +}) +export class PermissionComponent implements OnInit { + loginForm: FormGroup; + + constructor( + private formBuilder: FormBuilder, + private changeDetectorRef: ChangeDetectorRef + ) {} + + ngOnInit() {} + + onClickLogin() {} +} diff --git a/projects/ucap-webmessenger-ui-settings/src/lib/components/privacy.component.html b/projects/ucap-webmessenger-ui-settings/src/lib/components/privacy.component.html new file mode 100644 index 0000000..5a8a9dd --- /dev/null +++ b/projects/ucap-webmessenger-ui-settings/src/lib/components/privacy.component.html @@ -0,0 +1,15 @@ +
    + +

    방해 금지

    + + 상태를 방해 금지로 바꿉니다. + + + + +

    응용 프로그램

    + + 에러 자동 보고 + +
    +
    diff --git a/projects/ucap-webmessenger-ui-settings/src/lib/components/privacy.component.scss b/projects/ucap-webmessenger-ui-settings/src/lib/components/privacy.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/projects/ucap-webmessenger-ui-settings/src/lib/components/privacy.component.spec.ts b/projects/ucap-webmessenger-ui-settings/src/lib/components/privacy.component.spec.ts new file mode 100644 index 0000000..bddbec4 --- /dev/null +++ b/projects/ucap-webmessenger-ui-settings/src/lib/components/privacy.component.spec.ts @@ -0,0 +1,24 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { PrivacyComponent } from './privacy.component'; + +describe('Settings::PrivacyComponent', () => { + let component: PrivacyComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [PrivacyComponent] + }).compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(PrivacyComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/projects/ucap-webmessenger-ui-settings/src/lib/components/privacy.component.ts b/projects/ucap-webmessenger-ui-settings/src/lib/components/privacy.component.ts new file mode 100644 index 0000000..d7de28d --- /dev/null +++ b/projects/ucap-webmessenger-ui-settings/src/lib/components/privacy.component.ts @@ -0,0 +1,20 @@ +import { Component, OnInit, ChangeDetectorRef } from '@angular/core'; +import { FormGroup, FormBuilder } from '@angular/forms'; + +@Component({ + selector: 'ucap-settings-privacy', + templateUrl: './privacy.component.html', + styleUrls: ['./privacy.component.scss'] +}) +export class PrivacyComponent implements OnInit { + loginForm: FormGroup; + + constructor( + private formBuilder: FormBuilder, + private changeDetectorRef: ChangeDetectorRef + ) {} + + ngOnInit() {} + + onClickLogin() {} +} diff --git a/projects/ucap-webmessenger-ui-settings/src/lib/ucap-ui-settings.module.ts b/projects/ucap-webmessenger-ui-settings/src/lib/ucap-ui-settings.module.ts new file mode 100644 index 0000000..285eda3 --- /dev/null +++ b/projects/ucap-webmessenger-ui-settings/src/lib/ucap-ui-settings.module.ts @@ -0,0 +1,53 @@ +import { NgModule, ModuleWithProviders } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { ReactiveFormsModule } from '@angular/forms'; + +import { FlexLayoutModule } from '@angular/flex-layout'; + +import { MatCheckboxModule } from '@angular/material/checkbox'; +import { MatFormFieldModule } from '@angular/material/form-field'; +import { MatListModule } from '@angular/material/list'; +import { MatSelectModule } from '@angular/material/select'; +import { MatSlideToggleModule } from '@angular/material/slide-toggle'; +import { MatTabsModule } from '@angular/material/tabs'; + +import { CallComponent } from './components/call.component'; +import { DeviceComponent } from './components/device.component'; +import { GeneralComponent } from './components/general.component'; +import { NotificationComponent } from './components/notification.component'; +import { PermissionComponent } from './components/permission.component'; +import { PrivacyComponent } from './components/privacy.component'; + +const COMPONENTS = [ + CallComponent, + DeviceComponent, + GeneralComponent, + NotificationComponent, + PermissionComponent, + PrivacyComponent +]; +const SERVICES = []; + +@NgModule({ + imports: [ + CommonModule, + ReactiveFormsModule, + FlexLayoutModule, + MatCheckboxModule, + MatFormFieldModule, + MatListModule, + MatSelectModule, + MatSlideToggleModule, + MatTabsModule + ], + exports: [...COMPONENTS], + declarations: [...COMPONENTS] +}) +export class UCapUiSettingsModule { + public static forRoot(): ModuleWithProviders { + return { + ngModule: UCapUiSettingsModule, + providers: [...SERVICES] + }; + } +} diff --git a/projects/ucap-webmessenger-ui-settings/src/public-api.ts b/projects/ucap-webmessenger-ui-settings/src/public-api.ts new file mode 100644 index 0000000..93dc960 --- /dev/null +++ b/projects/ucap-webmessenger-ui-settings/src/public-api.ts @@ -0,0 +1,7 @@ +/* + * Public API Surface of ucap-webmessenger-ui-settings + */ + +export * from './lib/components/general.component'; + +export * from './lib/ucap-ui-settings.module'; diff --git a/projects/ucap-webmessenger-ui-settings/src/test.ts b/projects/ucap-webmessenger-ui-settings/src/test.ts new file mode 100644 index 0000000..978c64f --- /dev/null +++ b/projects/ucap-webmessenger-ui-settings/src/test.ts @@ -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); diff --git a/projects/ucap-webmessenger-electron-notification/tsconfig.lib.json b/projects/ucap-webmessenger-ui-settings/tsconfig.lib.json similarity index 100% rename from projects/ucap-webmessenger-electron-notification/tsconfig.lib.json rename to projects/ucap-webmessenger-ui-settings/tsconfig.lib.json diff --git a/projects/ucap-webmessenger-ui-settings/tsconfig.spec.json b/projects/ucap-webmessenger-ui-settings/tsconfig.spec.json new file mode 100644 index 0000000..16da33d --- /dev/null +++ b/projects/ucap-webmessenger-ui-settings/tsconfig.spec.json @@ -0,0 +1,17 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": "../../out-tsc/spec", + "types": [ + "jasmine", + "node" + ] + }, + "files": [ + "src/test.ts" + ], + "include": [ + "**/*.spec.ts", + "**/*.d.ts" + ] +} diff --git a/projects/ucap-webmessenger-ui-settings/tslint.json b/projects/ucap-webmessenger-ui-settings/tslint.json new file mode 100644 index 0000000..a91f162 --- /dev/null +++ b/projects/ucap-webmessenger-ui-settings/tslint.json @@ -0,0 +1,17 @@ +{ + "extends": "../../tslint.json", + "rules": { + "directive-selector": [ + true, + "attribute", + "ucapSettings", + "camelCase" + ], + "component-selector": [ + true, + "element", + "ucap-settings", + "kebab-case" + ] + } +} diff --git a/projects/ucap-webmessenger-ui/src/assets/scss/partials/_general.scss b/projects/ucap-webmessenger-ui/src/assets/scss/partials/_general.scss index c643d73..6f6a662 100644 --- a/projects/ucap-webmessenger-ui/src/assets/scss/partials/_general.scss +++ b/projects/ucap-webmessenger-ui/src/assets/scss/partials/_general.scss @@ -1,70 +1,74 @@ -// ----------------------------------------------------------------------------------------------------- -// @ Body scroll lock -// ----------------------------------------------------------------------------------------------------- -html, -body { - display: flex; - flex: 1 0 auto; - width: 100%; - height: 100%; - max-height: 100%; - min-height: 100%; - margin: 0; - padding: 0; - overflow: hidden; -} - -// ----------------------------------------------------------------------------------------------------- -// @ Boxed body -// ----------------------------------------------------------------------------------------------------- -body { - // Boxed - &.boxed { - max-width: 1200px; - margin: 0 auto; - - @include mat-elevation(8); - } -} - -/*----------------------------------------------------------------*/ -/* @ Text rendering & box sizing -/*----------------------------------------------------------------*/ -* { - text-rendering: optimizeLegibility; - -o-text-rendering: optimizeLegibility; - -ms-text-rendering: optimizeLegibility; - -moz-text-rendering: optimizeLegibility; - -webkit-text-rendering: optimizeLegibility; - -webkit-tap-highlight-color: transparent; - box-sizing: border-box; - - &:before, - &:after { - box-sizing: border-box; - } - - // Remove focus outline - &:focus { - outline: none; - } -} - -// ----------------------------------------------------------------------------------------------------- -// @ Responsive images -// ----------------------------------------------------------------------------------------------------- - -img { - max-width: 100%; - height: auto; - vertical-align: top; - border: none; -} - -// ----------------------------------------------------------------------------------------------------- -// @ Input -// ----------------------------------------------------------------------------------------------------- -input { - border: none; - padding: 0 16px; -} +// ----------------------------------------------------------------------------------------------------- +// @ Body scroll lock +// ----------------------------------------------------------------------------------------------------- +html, +body { + display: flex; + flex: 1 0 auto; + width: 100%; + height: 100%; + max-height: 100%; + min-height: 100%; + margin: 0; + padding: 0; + overflow: hidden; +} + +// ----------------------------------------------------------------------------------------------------- +// @ Boxed body +// ----------------------------------------------------------------------------------------------------- +body { + // Boxed + &.boxed { + max-width: 1200px; + margin: 0 auto; + + @include mat-elevation(8); + } +} + +/*----------------------------------------------------------------*/ +/* @ Text rendering & box sizing +/*----------------------------------------------------------------*/ +* { + text-rendering: optimizeLegibility; + -o-text-rendering: optimizeLegibility; + -ms-text-rendering: optimizeLegibility; + -moz-text-rendering: optimizeLegibility; + -webkit-text-rendering: optimizeLegibility; + -webkit-tap-highlight-color: transparent; + box-sizing: border-box; + + &:before, + &:after { + box-sizing: border-box; + } + + // Remove focus outline + &:focus { + outline: none; + } +} + +// ----------------------------------------------------------------------------------------------------- +// @ Responsive images +// ----------------------------------------------------------------------------------------------------- + +img { + max-width: 100%; + height: auto; + vertical-align: top; + border: none; +} + +// ----------------------------------------------------------------------------------------------------- +// @ Input +// ----------------------------------------------------------------------------------------------------- +input { + border: none; + padding: 0 16px; +} + +a { + cursor: pointer; +} diff --git a/projects/ucap-webmessenger-ui/src/assets/scss/partials/_presence.scss b/projects/ucap-webmessenger-ui/src/assets/scss/partials/_presence.scss index 2b3edec..f7f8677 100644 --- a/projects/ucap-webmessenger-ui/src/assets/scss/partials/_presence.scss +++ b/projects/ucap-webmessenger-ui/src/assets/scss/partials/_presence.scss @@ -8,7 +8,7 @@ margin-right: 4px; border-radius: 100px; } -.presence{ +.presence { @extend %presence; &.pcOn { background-color: #28ad66; @@ -16,7 +16,7 @@ &.pcOut { background-color: #f35b5b; } - & .pcOff { + &.pcOff { background-color: #a29f9f; } &.pcOther { diff --git a/projects/ucap-webmessenger-ui/src/lib/animations/index.ts b/projects/ucap-webmessenger-ui/src/lib/animations/index.ts index 84f249b..ba6c095 100644 --- a/projects/ucap-webmessenger-ui/src/lib/animations/index.ts +++ b/projects/ucap-webmessenger-ui/src/lib/animations/index.ts @@ -47,15 +47,21 @@ export const ucapAnimations = [ transition( 'void => 50', - query('@*', [stagger('50ms', [animateChild()])], { optional: true }) + query('@*', [stagger('50ms', [animateChild()])], { + optional: true + }) ), transition( 'void => 100', - query('@*', [stagger('100ms', [animateChild()])], { optional: true }) + query('@*', [stagger('100ms', [animateChild()])], { + optional: true + }) ), transition( 'void => 200', - query('@*', [stagger('200ms', [animateChild()])], { optional: true }) + query('@*', [stagger('200ms', [animateChild()])], { + optional: true + }) ) ]), @@ -551,6 +557,24 @@ export const ucapAnimations = [ ) ]), + trigger('treeToggler', [ + state( + '0, void', + style({ + opacity: 0 + }) + ), + state( + '1, *', + style({ + opacity: 1 + }) + ), + transition('1 => 0', animate('300ms ease-out')), + transition('0 => 1', animate('300ms ease-in')), + transition('void <=> *', animate('300ms ease-in')) + ]), + /** * Floating ACtion Button Animation. */ diff --git a/projects/ucap-webmessenger-ui/src/lib/components/expansion-panel.component.html b/projects/ucap-webmessenger-ui/src/lib/components/expansion-panel.component.html new file mode 100644 index 0000000..8c675cd --- /dev/null +++ b/projects/ucap-webmessenger-ui/src/lib/components/expansion-panel.component.html @@ -0,0 +1 @@ +
    diff --git a/projects/ucap-webmessenger-ui/src/lib/components/expansion-panel.component.scss b/projects/ucap-webmessenger-ui/src/lib/components/expansion-panel.component.scss new file mode 100644 index 0000000..5719c2a --- /dev/null +++ b/projects/ucap-webmessenger-ui/src/lib/components/expansion-panel.component.scss @@ -0,0 +1,4 @@ +.ucap-expansion-panel-container { + width: 100%; + height: 100%; +} diff --git a/projects/ucap-webmessenger-ui/src/lib/components/expansion-panel.component.spec.ts b/projects/ucap-webmessenger-ui/src/lib/components/expansion-panel.component.spec.ts new file mode 100644 index 0000000..48e6712 --- /dev/null +++ b/projects/ucap-webmessenger-ui/src/lib/components/expansion-panel.component.spec.ts @@ -0,0 +1,27 @@ +/* tslint:disable:no-unused-variable */ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { By } from '@angular/platform-browser'; +import { DebugElement } from '@angular/core'; + +import { ExpansionPanelComponent } from './expansion-panel.component'; + +describe('ExpansionPanelComponent', () => { + let component: ExpansionPanelComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ExpansionPanelComponent] + }).compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(ExpansionPanelComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/projects/ucap-webmessenger-ui/src/lib/components/expansion-panel.component.ts b/projects/ucap-webmessenger-ui/src/lib/components/expansion-panel.component.ts new file mode 100644 index 0000000..66fa997 --- /dev/null +++ b/projects/ucap-webmessenger-ui/src/lib/components/expansion-panel.component.ts @@ -0,0 +1,12 @@ +import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core'; + +@Component({ + selector: 'ucap-expansion-panel', + templateUrl: './expansion-panel.component.html', + styleUrls: ['./expansion-panel.component.scss'] +}) +export class ExpansionPanelComponent implements OnInit { + constructor() {} + + ngOnInit() {} +} diff --git a/projects/ucap-webmessenger-ui/src/lib/components/file-upload-queue.component.html b/projects/ucap-webmessenger-ui/src/lib/components/file-upload-queue.component.html index edf37d5..765e886 100644 --- a/projects/ucap-webmessenger-ui/src/lib/components/file-upload-queue.component.html +++ b/projects/ucap-webmessenger-ui/src/lib/components/file-upload-queue.component.html @@ -1,25 +1,23 @@
    -
    -
    -
    - image -
    -
    {{ fileUploadItem.file.name }}
    +
    +
    + + + + + + + +
    {{ fileUploadItem.file.name }}
    -
    - + +
    +
    @@ -28,4 +26,4 @@
    여기에 파일을 Drop하시면 업로드 됩니다.
    -
    +
    \ No newline at end of file diff --git a/projects/ucap-webmessenger-ui/src/lib/components/file-upload-queue.component.scss b/projects/ucap-webmessenger-ui/src/lib/components/file-upload-queue.component.scss index ae2e16e..ad4f3f5 100644 --- a/projects/ucap-webmessenger-ui/src/lib/components/file-upload-queue.component.scss +++ b/projects/ucap-webmessenger-ui/src/lib/components/file-upload-queue.component.scss @@ -1,4 +1,41 @@ +@mixin ellipsis($row) { + overflow: hidden; + text-overflow: ellipsis; + @if $row == 1 { + display: block; + white-space: nowrap; + word-wrap: normal; + } @else if $row >= 2 { + display: -webkit-box; + -webkit-line-clamp: $row; + -webkit-box-orient: vertical; + word-wrap: break-word; + } +} + .ucap-file-upload-queue-container { width: 100%; height: 100%; + .file-upload-item { + min-width: 200px; + margin: 0 1%; + margin-bottom: 10px; + width: 48%; + border-radius: 3px; + background-color:#f9f9f9; + border:1px solid #dddddd; + .file-upload-info { + padding: 10px; + svg { + margin-right: 6px; + } + .file-upload-name { + height: 20px; + @include ellipsis(2); + } + } + .file-upload-progress { + padding: 6px 10px; + } + } } diff --git a/projects/ucap-webmessenger-ui/src/lib/components/file-viewer.component.html b/projects/ucap-webmessenger-ui/src/lib/components/file-viewer.component.html index 4d38e2f..772d4c8 100644 --- a/projects/ucap-webmessenger-ui/src/lib/components/file-viewer.component.html +++ b/projects/ucap-webmessenger-ui/src/lib/components/file-viewer.component.html @@ -6,35 +6,35 @@ *ngSwitchCase="FileViewerType.Document" [fileInfo]="fileInfo" [fileDownloadUrl]="fileDownloadUrl" - (download)="onDownload()" + (download)="onDownload($event)" (closed)="onClosedViewer()" >
    diff --git a/projects/ucap-webmessenger-ui/src/lib/components/file-viewer.component.ts b/projects/ucap-webmessenger-ui/src/lib/components/file-viewer.component.ts index 51ce68c..246c72b 100644 --- a/projects/ucap-webmessenger-ui/src/lib/components/file-viewer.component.ts +++ b/projects/ucap-webmessenger-ui/src/lib/components/file-viewer.component.ts @@ -3,12 +3,13 @@ import { ucapAnimations } from '../animations'; import { FileEventJson } from '@ucap-webmessenger/protocol-event'; import { FileViewerType } from '../types/file-viewer.type'; import { FileType } from '@ucap-webmessenger/protocol-file'; +import { FileDownloadItem } from '@ucap-webmessenger/api-common'; @Component({ selector: 'ucap-file-viewer', templateUrl: './file-viewer.component.html', styleUrls: ['./file-viewer.component.scss'], - animations: ucapAnimations + animations: ucapAnimations, }) export class FileViewerComponent implements OnInit { @Input() @@ -18,7 +19,7 @@ export class FileViewerComponent implements OnInit { fileDownloadUrl: string; @Output() - download = new EventEmitter(); + download = new EventEmitter(); @Output() closed = new EventEmitter(); @@ -44,8 +45,8 @@ export class FileViewerComponent implements OnInit { return FileViewerType.Binary; } } - onDownload(): void { - this.download.emit(); + onDownload(fileDownloadItem: FileDownloadItem): void { + this.download.emit(fileDownloadItem); } onClosedViewer(): void { diff --git a/projects/ucap-webmessenger-ui/src/lib/components/file-viewer/binary-viewer.component.html b/projects/ucap-webmessenger-ui/src/lib/components/file-viewer/binary-viewer.component.html index 5474125..0ded2cb 100644 --- a/projects/ucap-webmessenger-ui/src/lib/components/file-viewer/binary-viewer.component.html +++ b/projects/ucap-webmessenger-ui/src/lib/components/file-viewer/binary-viewer.component.html @@ -1,6 +1,22 @@
    - - attachment + + + + + {{ fileInfo.fileName }} @@ -12,18 +28,56 @@ aria-label="" (click)="onClickDownload()" > - get_app + + + - + +
    +
    + +
    +
    -
    -
    +
    +
    +
    +
    -
    +
    미리보기를 지원하지 않는 파일입니다.
    - + +
    +
    + +
    +
    (); @Output() - download = new EventEmitter(); + download = new EventEmitter(); + + fileDownloadItem: FileDownloadItem; constructor() {} ngOnInit() {} onClickDownload(): void { - this.download.emit(); + this.fileDownloadItem = new FileDownloadItem(); + this.download.emit(this.fileDownloadItem); } onClickClose(): void { diff --git a/projects/ucap-webmessenger-ui/src/lib/components/file-viewer/sound-viewer.component.html b/projects/ucap-webmessenger-ui/src/lib/components/file-viewer/sound-viewer.component.html index fbe086a..20aae80 100644 --- a/projects/ucap-webmessenger-ui/src/lib/components/file-viewer/sound-viewer.component.html +++ b/projects/ucap-webmessenger-ui/src/lib/components/file-viewer/sound-viewer.component.html @@ -5,23 +5,43 @@ + +
    +
    + +
    +
    - music_note -
    -
    - - -
    -
    -
    - {{ currentTime | ucapSecondsToMinutes }} +
    + music_note
    - - - -
    - {{ duration | ucapSecondsToMinutes }} + + +
    +
    +
    + {{ currentTime | ucapSecondsToMinutes }} +
    + + + +
    + {{ duration | ucapSecondsToMinutes }} +
    -
    +
    \ No newline at end of file diff --git a/projects/ucap-webmessenger-ui/src/lib/components/file-viewer/sound-viewer.component.scss b/projects/ucap-webmessenger-ui/src/lib/components/file-viewer/sound-viewer.component.scss index 31b6cb6..22290b5 100644 --- a/projects/ucap-webmessenger-ui/src/lib/components/file-viewer/sound-viewer.component.scss +++ b/projects/ucap-webmessenger-ui/src/lib/components/file-viewer/sound-viewer.component.scss @@ -4,40 +4,73 @@ .ucap-sound-viewer-header { width: 100%; - height: 50px; + height: 60px; + box-shadow: 0 3px 6px rgba(0, 0, 0, 0.6); + background-color: #333333; .ucap-sound-viewer-icon { + margin-right: 10px; } .ucap-sound-viewer-title { + font-size:16px; + } + .stroke-bar { + width: 1px; + height: 30px; + background-color: rgba(256, 256, 256, 0.3); + margin: 0 10px; + } + .ucap-sound-viewer-action { + &:hover { + opacity: 0.7; + } } } .ucap-sound-viewer-body { position: relative; - background-color: white; width: 100%; - height: 100%; - padding-bottom: 70px; + height: calc(100% - 60px); - .ucap-sound-viewer-sound-icon { - width: 100%; - height: calc(100% - 60px); - } - .ucap-sound-viewer-sound-time { - width: 100%; - height: 30px; - } - .ucap-sound-viewer-sound-controls { - width: 100%; - height: 30px; - - .ucap-sound-viewer-sound-time-current { - padding-left: 30px; + .circle-box{ + display:flex; + width:140px; + height:140px; + border-radius:50%; + justify-content: center; + align-items: center; + border:2px solid #ffffff; + background-color:rgba(256, 256, 256, 0.7); + .mat-icon{ + font-size: 100px; + height: 100px; + width: 100px; } + } - .ucap-sound-viewer-sound-time-total { - padding-right: 30px; + .ucap-sound-viewer-sound-icon{ + width: 100%; + height: calc(100% - 80px); + } + .viewer-bottom{ + background-color: #212121; + color:#ffffff; + .ucap-sound-viewer-sound-time { + width: 100%; + height: 30px; + } + .ucap-sound-viewer-sound-controls { + width: 100%; + height: 50px; + + .ucap-sound-viewer-sound-time-current { + padding-left: 30px; + } + + .ucap-sound-viewer-sound-time-total { + padding-right: 30px; + } } } } @@ -45,9 +78,22 @@ flex: 1 1 auto; } .ucap-sound-viewer-action { + .mat-icon{ + font-size: 40px; + width: 100%; + height: 100%; + line-height:40px; + } } } mat-slider { - width: 95%; + width: 94%; } + +::ng-deep .mat-slider-horizontal .mat-slider-track-background{ + background-color: #999999 !important; +} +::ng-deep .mat-slider-min-value:not(.mat-slider-thumb-label-showing) .mat-slider-thumb{ + border-color: #999999 !important; +} \ No newline at end of file diff --git a/projects/ucap-webmessenger-ui/src/lib/components/file-viewer/sound-viewer.component.ts b/projects/ucap-webmessenger-ui/src/lib/components/file-viewer/sound-viewer.component.ts index c2ae0ff..ab1ed25 100644 --- a/projects/ucap-webmessenger-ui/src/lib/components/file-viewer/sound-viewer.component.ts +++ b/projects/ucap-webmessenger-ui/src/lib/components/file-viewer/sound-viewer.component.ts @@ -5,17 +5,18 @@ import { Output, EventEmitter, ViewChild, - ElementRef + ElementRef, } from '@angular/core'; import { ucapAnimations } from '../../animations'; import { FileEventJson } from '@ucap-webmessenger/protocol-event'; import { MatSlider, MatSliderChange } from '@angular/material'; +import { FileDownloadItem } from '@ucap-webmessenger/api-common'; @Component({ selector: 'ucap-sound-viewer', templateUrl: './sound-viewer.component.html', styleUrls: ['./sound-viewer.component.scss'], - animations: ucapAnimations + animations: ucapAnimations, }) export class SoundViewerComponent implements OnInit { @Input() @@ -25,7 +26,7 @@ export class SoundViewerComponent implements OnInit { fileDownloadUrl: string; @Output() - download = new EventEmitter(); + download = new EventEmitter(); @Output() closed = new EventEmitter(); @@ -41,6 +42,7 @@ export class SoundViewerComponent implements OnInit { currentTime = 0; volume = 0.1; loading = false; + fileDownloadItem: FileDownloadItem; constructor() {} @@ -90,7 +92,8 @@ export class SoundViewerComponent implements OnInit { } onClickDownload(): void { - this.download.emit(); + this.fileDownloadItem = new FileDownloadItem(); + this.download.emit(this.fileDownloadItem); } onClickClose(): void { diff --git a/projects/ucap-webmessenger-ui/src/lib/components/file-viewer/video-viewer.component.html b/projects/ucap-webmessenger-ui/src/lib/components/file-viewer/video-viewer.component.html index 28ea7bb..9c1e66e 100644 --- a/projects/ucap-webmessenger-ui/src/lib/components/file-viewer/video-viewer.component.html +++ b/projects/ucap-webmessenger-ui/src/lib/components/file-viewer/video-viewer.component.html @@ -1,6 +1,27 @@
    - video_label + + + + + + + + + + + {{ fileInfo.fileName }} - + +
    +
    + +
    +
    -
    - +
    - -
    -
    -
    - {{ currentTime | ucapSecondsToMinutes }} + +
    - - - -
    - {{ duration | ucapSecondsToMinutes }} +
    + {{ currentTime | ucapSecondsToMinutes }} +
    + + + +
    + {{ duration | ucapSecondsToMinutes }} +
    diff --git a/projects/ucap-webmessenger-ui/src/lib/components/file-viewer/video-viewer.component.scss b/projects/ucap-webmessenger-ui/src/lib/components/file-viewer/video-viewer.component.scss index 8f7be76..e77e2bb 100644 --- a/projects/ucap-webmessenger-ui/src/lib/components/file-viewer/video-viewer.component.scss +++ b/projects/ucap-webmessenger-ui/src/lib/components/file-viewer/video-viewer.component.scss @@ -4,40 +4,57 @@ .ucap-video-viewer-header { width: 100%; - height: 50px; + height: 60px; + box-shadow: 0 3px 6px rgba(0, 0, 0, 0.6); + background-color: #333333; .ucap-video-viewer-icon { + margin-right: 10px; } .ucap-video-viewer-title { + font-size:16px; + } + .stroke-bar { + width: 1px; + height: 30px; + background-color: rgba(256, 256, 256, 0.3); + margin: 0 10px; + } + .ucap-image-viewer-action { + &:hover { + opacity: 0.7; + } } } .ucap-video-viewer-body { position: relative; - background-color: white; width: 100%; - height: 100%; - padding-bottom: 70px; + height: calc(100% - 60px); .ucap-video-viewer-video-icon { width: 100%; - height: calc(100% - 60px); + height: calc(100% - 80px); } - .ucap-video-viewer-video-time { - width: 100%; - height: 30px; - } - .ucap-video-viewer-video-controls { - width: 100%; - height: 30px; - - .ucap-video-viewer-video-time-current { - padding-left: 30px; + .viewer-bottom{ + background-color: #212121; + color:#ffffff; + .ucap-video-viewer-video-time { + width: 100%; + height: 30px; } + .ucap-video-viewer-video-controls { + width: 100%; + height: 50px; - .ucap-video-viewer-video-time-total { - padding-right: 30px; + .ucap-video-viewer-video-time-current { + padding-left: 30px; + } + + .ucap-video-viewer-video-time-total { + padding-right: 30px; + } } } } @@ -45,9 +62,22 @@ flex: 1 1 auto; } .ucap-video-viewer-action { + .mat-icon{ + font-size: 40px; + width: 100%; + height: 100%; + line-height:40px; + } } } mat-slider { - width: 95%; + width: 94%; } + +::ng-deep .mat-slider-horizontal .mat-slider-track-background{ + background-color: #999999 !important; +} +::ng-deep .mat-slider-min-value:not(.mat-slider-thumb-label-showing) .mat-slider-thumb{ + border-color: #999999 !important; +} \ No newline at end of file diff --git a/projects/ucap-webmessenger-ui/src/lib/components/file-viewer/video-viewer.component.ts b/projects/ucap-webmessenger-ui/src/lib/components/file-viewer/video-viewer.component.ts index 2259508..9eed043 100644 --- a/projects/ucap-webmessenger-ui/src/lib/components/file-viewer/video-viewer.component.ts +++ b/projects/ucap-webmessenger-ui/src/lib/components/file-viewer/video-viewer.component.ts @@ -5,17 +5,18 @@ import { Output, EventEmitter, ViewChild, - ElementRef + ElementRef, } from '@angular/core'; import { ucapAnimations } from '../../animations'; import { FileEventJson } from '@ucap-webmessenger/protocol-event'; import { MatSlider, MatSliderChange } from '@angular/material'; +import { FileDownloadItem } from '@ucap-webmessenger/api-common'; @Component({ selector: 'ucap-video-viewer', templateUrl: './video-viewer.component.html', styleUrls: ['./video-viewer.component.scss'], - animations: ucapAnimations + animations: ucapAnimations, }) export class VideoViewerComponent implements OnInit { @Input() @@ -25,7 +26,7 @@ export class VideoViewerComponent implements OnInit { fileDownloadUrl: string; @Output() - download = new EventEmitter(); + download = new EventEmitter(); @Output() closed = new EventEmitter(); @@ -41,6 +42,7 @@ export class VideoViewerComponent implements OnInit { currentTime = 0; volume = 0.1; loading = false; + fileDownloadItem: FileDownloadItem; constructor() {} @@ -90,7 +92,8 @@ export class VideoViewerComponent implements OnInit { } onClickDownload(): void { - this.download.emit(); + this.fileDownloadItem = new FileDownloadItem(); + this.download.emit(this.fileDownloadItem); } onClickClose(): void { diff --git a/projects/ucap-webmessenger-ui/src/lib/components/float-action-button.component.html b/projects/ucap-webmessenger-ui/src/lib/components/float-action-button.component.html index 9811169..9d812f2 100644 --- a/projects/ucap-webmessenger-ui/src/lib/components/float-action-button.component.html +++ b/projects/ucap-webmessenger-ui/src/lib/components/float-action-button.component.html @@ -3,7 +3,7 @@ *ngIf="fabTogglerState === 'active'" (click)="onToggleFab()" >
    -
    +
    diff --git a/projects/ucap-webmessenger-ui/src/lib/components/float-action-button.component.scss b/projects/ucap-webmessenger-ui/src/lib/components/float-action-button.component.scss index 164c51e..068e4aa 100644 --- a/projects/ucap-webmessenger-ui/src/lib/components/float-action-button.component.scss +++ b/projects/ucap-webmessenger-ui/src/lib/components/float-action-button.component.scss @@ -1,7 +1,7 @@ .fab-container { position: absolute; bottom: 15px; - right: 15px; + right: 40px; z-index: 100; display: flex; flex-direction: column-reverse; diff --git a/projects/ucap-webmessenger-ui/src/lib/components/sticker-selector.component.html b/projects/ucap-webmessenger-ui/src/lib/components/sticker-selector.component.html new file mode 100644 index 0000000..604c287 --- /dev/null +++ b/projects/ucap-webmessenger-ui/src/lib/components/sticker-selector.component.html @@ -0,0 +1,39 @@ +
    + +
    +
    + + + + + +
    +
    + +
    +
    +
    +
    +
    diff --git a/projects/ucap-webmessenger-ui/src/lib/components/sticker-selector.component.scss b/projects/ucap-webmessenger-ui/src/lib/components/sticker-selector.component.scss new file mode 100644 index 0000000..b85f3e7 --- /dev/null +++ b/projects/ucap-webmessenger-ui/src/lib/components/sticker-selector.component.scss @@ -0,0 +1,8 @@ +.sticker-selector { + height: 200px; + overflow: auto; +} + +.sticker-item { + cursor: pointer; +} diff --git a/projects/ucap-webmessenger-ui/src/lib/components/sticker-selector.component.spec.ts b/projects/ucap-webmessenger-ui/src/lib/components/sticker-selector.component.spec.ts new file mode 100644 index 0000000..a5b654b --- /dev/null +++ b/projects/ucap-webmessenger-ui/src/lib/components/sticker-selector.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { StickerSelectorComponent } from './sticker-selector.component'; + +describe('StickerSelectorComponent', () => { + let component: StickerSelectorComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ StickerSelectorComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(StickerSelectorComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/projects/ucap-webmessenger-ui/src/lib/components/sticker-selector.component.ts b/projects/ucap-webmessenger-ui/src/lib/components/sticker-selector.component.ts new file mode 100644 index 0000000..2f3ce9f --- /dev/null +++ b/projects/ucap-webmessenger-ui/src/lib/components/sticker-selector.component.ts @@ -0,0 +1,91 @@ +import { Component, OnInit, Output, EventEmitter } from '@angular/core'; +import { + StickerInfo, + StickerFilesInfo, + StickerUtil, + StickerMap +} from '@ucap-webmessenger/core'; +import { LocalStorageService } from '@ucap-webmessenger/web-storage'; +import { KEY_STICKER_HISTORY } from '@app/types'; + +@Component({ + selector: 'ucap-sticker-selector', + templateUrl: './sticker-selector.component.html', + styleUrls: ['./sticker-selector.component.scss'] +}) +export class StickerSelectorComponent implements OnInit { + @Output() + selectedSticker = new EventEmitter(); + + stickerBasePath = 'assets/sticker/'; + stickerInfoList: StickerInfo[] = []; + stickerFileInfoList: StickerFilesInfo[] = []; + currentSticker: StickerFilesInfo; + + currentTabIndex: number; + + constructor(private localStorageService: LocalStorageService) {} + + ngOnInit() { + this.stickerInfoList = StickerUtil.getStickerInfoList(); + this.currentTabIndex = 0; + } + + onSelectedIndexChange(value: number) { + this.currentTabIndex = value; + } + + getStickerTitleImage( + stickerInfo: StickerInfo, + hover: boolean, + tabIndex: number + ) { + if (this.currentTabIndex === tabIndex) { + return this.stickerBasePath + stickerInfo.iconPathOn; + } + + if (!hover) { + return this.stickerBasePath + stickerInfo.iconPath; + } else { + return this.stickerBasePath + stickerInfo.iconPathOn; + } + } + + getStickerInfos(stickerInfo: StickerInfo) { + if (stickerInfo.index === '00') { + const rtnArray: StickerFilesInfo[] = []; + const history = this.localStorageService.get( + KEY_STICKER_HISTORY + ); + if (!!history && history.length > 0) { + history.forEach(sticker => { + const arr: string[] = sticker.split('_'); + if (arr.length === 2) { + const sInfo: StickerInfo[] = StickerMap.filter( + s => s.index === arr[0] + ); + if (!!sInfo && sInfo.length > 0) { + rtnArray.push( + ...sInfo[0].fileInfos.filter( + fileInfo => fileInfo.index === sticker + ) + ); + } + } + }); + } + return rtnArray; + } else { + return stickerInfo.fileInfos; + } + } + + getStickerContentsImage(sticker: StickerFilesInfo) { + return this.stickerBasePath + sticker.path; + } + + onClickSelectSticker(sticker: StickerFilesInfo) { + this.currentSticker = sticker; + this.selectedSticker.emit(sticker); + } +} diff --git a/projects/ucap-webmessenger-ui/src/lib/data-source/virtual-scroll-tree-flat.data-source.ts b/projects/ucap-webmessenger-ui/src/lib/data-source/virtual-scroll-tree-flat.data-source.ts new file mode 100644 index 0000000..d73a138 --- /dev/null +++ b/projects/ucap-webmessenger-ui/src/lib/data-source/virtual-scroll-tree-flat.data-source.ts @@ -0,0 +1,132 @@ +import { CollectionViewer, DataSource } from '@angular/cdk/collections'; +import { FlatTreeControl } from '@angular/cdk/tree'; +import { + BehaviorSubject, + merge, + Observable, + Subject, + Subscription +} from 'rxjs'; +import { map, share } from 'rxjs/operators'; +import { MatTreeFlattener } from '@angular/material'; +import { CdkVirtualScrollViewport } from '@angular/cdk/scrolling'; + +export class VirtualScrollTreeFlatDataSource extends DataSource { + private flattenedDataSubject = new BehaviorSubject([]); + + expandedDataSubject = new BehaviorSubject([]); + expandedData$: Observable; + + private connectSubject: Subject; + private dataChangeSubscription: Subscription; + private rangeChangeSubscription: Subscription; + + private rangeSubject: BehaviorSubject<{ + start: number; + end: number; + }>; + + // tslint:disable-next-line: variable-name + private _cdkVirtualScrollViewport: CdkVirtualScrollViewport; + set cdkVirtualScrollViewport( + cdkVirtualScrollViewport: CdkVirtualScrollViewport + ) { + if (!cdkVirtualScrollViewport) { + return; + } + this._cdkVirtualScrollViewport = cdkVirtualScrollViewport; + this.rangeSubject = new BehaviorSubject<{ start: number; end: number }>({ + start: 0, + end: 1 + }); + + this.rangeChangeSubscription = cdkVirtualScrollViewport.renderedRangeStream.subscribe( + range => { + this.rangeSubject.next({ + start: range.start, + end: range.end + }); + if (!!this.connectSubject) { + this.connectSubject.next( + this.expandedDataSubject.value.slice( + this.rangeSubject.value.start, + this.rangeSubject.value.end + ) + ); + } + } + ); + } + + // tslint:disable-next-line: variable-name + private _data: BehaviorSubject; + get data() { + return this._data.value; + } + set data(value: T[]) { + this._data.next(value); + this.flattenedDataSubject.next(this.treeFlattener.flattenNodes(this.data)); + this.treeControl.dataNodes = this.flattenedDataSubject.value; + } + + constructor( + private treeControl: FlatTreeControl, + private treeFlattener: MatTreeFlattener, + initialData: T[] = [] + ) { + super(); + this._data = new BehaviorSubject(initialData); + this.expandedData$ = this.expandedDataSubject.asObservable().pipe(share()); + } + + connect(collectionViewer: CollectionViewer): Observable { + this.connectSubject = new Subject(); + + this.dataChangeSubscription = merge( + collectionViewer.viewChange, + this.treeControl.expansionModel.changed, + this.flattenedDataSubject + ) + .pipe( + map(() => { + this.expandedDataSubject.next( + this.treeFlattener.expandFlattenedNodes( + this.flattenedDataSubject.value, + this.treeControl + ) + ); + + return !this.rangeSubject + ? this.expandedDataSubject.value + : this.expandedDataSubject.value.slice( + this.rangeSubject.value.start, + this.rangeSubject.value.end + ); + }) + ) + .subscribe(datas => { + this.connectSubject.next(datas); + if (!!this._cdkVirtualScrollViewport) { + this._cdkVirtualScrollViewport.checkViewportSize(); + } + }); + + return this.connectSubject.asObservable(); + } + + disconnect() { + console.log('VirtualScrollTreeFlatDataSource disconnect'); + if (!!this.connectSubject) { + this.connectSubject.next(); + this.connectSubject.unsubscribe(); + } + + if (!!this.dataChangeSubscription) { + this.dataChangeSubscription.unsubscribe(); + } + + if (!!this.rangeChangeSubscription) { + this.rangeChangeSubscription.unsubscribe(); + } + } +} diff --git a/projects/ucap-webmessenger-ui/src/lib/dialogs/alert.dialog.component.html b/projects/ucap-webmessenger-ui/src/lib/dialogs/alert.dialog.component.html index 0ab17f2..9973e3b 100644 --- a/projects/ucap-webmessenger-ui/src/lib/dialogs/alert.dialog.component.html +++ b/projects/ucap-webmessenger-ui/src/lib/dialogs/alert.dialog.component.html @@ -9,7 +9,7 @@
    - diff --git a/projects/ucap-webmessenger-ui/src/lib/directives/cdk-virtual-scroll-viewport-patch.directive.ts b/projects/ucap-webmessenger-ui/src/lib/directives/cdk-virtual-scroll-viewport-patch.directive.ts new file mode 100644 index 0000000..bc45b33 --- /dev/null +++ b/projects/ucap-webmessenger-ui/src/lib/directives/cdk-virtual-scroll-viewport-patch.directive.ts @@ -0,0 +1,30 @@ +import { Directive, OnInit, OnDestroy, Self, Inject } from '@angular/core'; +import { Subject, fromEvent } from 'rxjs'; +import { CdkVirtualScrollViewport } from '@angular/cdk/scrolling'; +import { debounceTime, takeUntil } from 'rxjs/operators'; + +@Directive({ + // tslint:disable-next-line: directive-selector + selector: 'cdk-virtual-scroll-viewport' +}) +export class CdkVirtualScrollViewportPatchDirective + implements OnInit, OnDestroy { + protected readonly destroySubject = new Subject(); + + constructor( + @Self() + @Inject(CdkVirtualScrollViewport) + private readonly viewportComponent: CdkVirtualScrollViewport + ) {} + + ngOnInit() { + fromEvent(window, 'resize') + .pipe(debounceTime(10), takeUntil(this.destroySubject)) + .subscribe(() => this.viewportComponent.checkViewportSize()); + } + + ngOnDestroy() { + this.destroySubject.next(); + this.destroySubject.complete(); + } +} diff --git a/projects/ucap-webmessenger-ui/src/lib/directives/file-upload-for.directive.ts b/projects/ucap-webmessenger-ui/src/lib/directives/file-upload-for.directive.ts index df56bee..072f145 100644 --- a/projects/ucap-webmessenger-ui/src/lib/directives/file-upload-for.directive.ts +++ b/projects/ucap-webmessenger-ui/src/lib/directives/file-upload-for.directive.ts @@ -15,6 +15,12 @@ import { CommonApiService } from '@ucap-webmessenger/api-common'; import { FileUtil } from '@ucap-webmessenger/core'; +import { DialogService } from '../services/dialog.service'; +import { + AlertDialogComponent, + AlertDialogResult, + AlertDialogData +} from '../dialogs/alert.dialog.component'; @Directive({ selector: 'input[ucapFileUploadFor], div[ucapFileUploadFor]' @@ -40,7 +46,8 @@ export class FileUploadForDirective implements AfterViewInit { constructor( private commonApiService: CommonApiService, private elementRef: ElementRef, - private logger: NGXLogger + private logger: NGXLogger, + private dialogService: DialogService ) {} ngAfterViewInit(): void {} @@ -66,11 +73,11 @@ export class FileUploadForDirective implements AfterViewInit { return; } - if (this.fileUploadQueue.isEventInElement(event)) { - event.dataTransfer.dropEffect = 'copy'; - } else { - event.dataTransfer.dropEffect = 'none'; - } + // if (this.fileUploadQueue.isEventInElement(event)) { + // event.dataTransfer.dropEffect = 'copy'; + // } else { + // event.dataTransfer.dropEffect = 'none'; + // } event.preventDefault(); } @@ -103,17 +110,32 @@ export class FileUploadForDirective implements AfterViewInit { } const files: FileList = event.dataTransfer.files; - if ( - !this.commonApiService.acceptableExtensionForFileTalk( - FileUtil.getExtensions(files) - ) - ) { + const checkExt = this.commonApiService.acceptableExtensionForFileTalk( + FileUtil.getExtensions(files) + ); + if (!checkExt.accept) { this.logger.debug('window:drop not acceptable'); if (!!this.fileUploadQueue) { this.fileUploadQueue.onDragLeave(); } this.elementRef.nativeElement.value = ''; this.dragOver = false; + + this.dialogService.open< + AlertDialogComponent, + AlertDialogData, + AlertDialogResult + >(AlertDialogComponent, { + data: { + title: 'Alert', + html: `지원하지 않는 파일형식입니다.${ + checkExt.reject.length > 0 + ? '
    (' + checkExt.reject.join(',') + ')' + : '' + }` + } + }); + return; } diff --git a/projects/ucap-webmessenger-ui/src/lib/pipes/dates.pipe.spec.ts b/projects/ucap-webmessenger-ui/src/lib/pipes/dates.pipe.spec.ts deleted file mode 100644 index 8104bdc..0000000 --- a/projects/ucap-webmessenger-ui/src/lib/pipes/dates.pipe.spec.ts +++ /dev/null @@ -1,11 +0,0 @@ -/* tslint:disable:no-unused-variable */ - -import { TestBed, async } from '@angular/core/testing'; -import { DatesPipe } from './dates.pipe'; - -describe('Pipe: Datese', () => { - it('create an instance', () => { - let pipe = new DatesPipe(); - expect(pipe).toBeTruthy(); - }); -}); diff --git a/projects/ucap-webmessenger-ui/src/lib/pipes/dates.pipe.ts b/projects/ucap-webmessenger-ui/src/lib/pipes/dates.pipe.ts index ba604ac..cf90efd 100644 --- a/projects/ucap-webmessenger-ui/src/lib/pipes/dates.pipe.ts +++ b/projects/ucap-webmessenger-ui/src/lib/pipes/dates.pipe.ts @@ -1,8 +1,9 @@ import { Pipe, PipeTransform } from '@angular/core'; import { StringUtil } from '../utils/string.util'; +import moment from 'moment'; @Pipe({ - name: 'dateToStringChatList' + name: 'dateToStringChatList', }) export class DateToStringForChatRoomListPipe implements PipeTransform { transform(value: any): string { @@ -10,7 +11,7 @@ export class DateToStringForChatRoomListPipe implements PipeTransform { const yesterDate = new Date(curDate.getTime() - 1 * 24 * 60 * 60 * 1000); let date: Date; if (typeof value === 'string') { - date = new Date(value.toString()); + date = moment(value.toString()).toDate(); } else if (value instanceof Date) { date = value; } else { @@ -36,3 +37,18 @@ export class DateToStringForChatRoomListPipe implements PipeTransform { } } } + +@Pipe({ + name: 'dateToStringFormat', +}) +export class DateToStringFormatPipe implements PipeTransform { + transform(value: any, format?: string): string { + const date = moment(value.toString()).toDate(); + + if (!!format) { + return StringUtil.dateFormat(date, format); + } else { + return StringUtil.dateFormat(date, 'YYYY.MM.DD'); + } + } +} diff --git a/projects/ucap-webmessenger-ui/src/lib/pipes/linefeed.pipe.spec.ts b/projects/ucap-webmessenger-ui/src/lib/pipes/linefeed.pipe.spec.ts deleted file mode 100644 index 69dabff..0000000 --- a/projects/ucap-webmessenger-ui/src/lib/pipes/linefeed.pipe.spec.ts +++ /dev/null @@ -1,11 +0,0 @@ -/* tslint:disable:no-unused-variable */ - -import { TestBed, async } from '@angular/core/testing'; -import { LinefeedPipe } from './linefeed.pipe'; - -describe('Pipe: Linefeede', () => { - it('create an instance', () => { - let pipe = new LinefeedPipe(); - expect(pipe).toBeTruthy(); - }); -}); diff --git a/projects/ucap-webmessenger-ui/src/lib/pipes/linky.pipe.ts b/projects/ucap-webmessenger-ui/src/lib/pipes/linky.pipe.ts new file mode 100644 index 0000000..02c9421 --- /dev/null +++ b/projects/ucap-webmessenger-ui/src/lib/pipes/linky.pipe.ts @@ -0,0 +1,22 @@ +import { Pipe, PipeTransform } from '@angular/core'; +import { Autolinker, AutolinkerConfig } from 'autolinker'; + +@Pipe({ name: 'linky' }) +export class LinkyPipe implements PipeTransform { + transform(value: string, options?: AutolinkerConfig): string { + options = { + email: false, + phone: false, + stripPrefix: false, + // newWindow: false, + replaceFn: match => { + if (match.getType() === 'url') { + return '' + match.getAnchorHref() + ''; + // return true; + } + }, + ...options + }; + return Autolinker.link(value, options); + } +} diff --git a/projects/ucap-webmessenger-ui/src/lib/services/splash-screen.service.spec.ts b/projects/ucap-webmessenger-ui/src/lib/services/splash-screen.service.spec.ts new file mode 100644 index 0000000..97fb5eb --- /dev/null +++ b/projects/ucap-webmessenger-ui/src/lib/services/splash-screen.service.spec.ts @@ -0,0 +1,12 @@ +import { TestBed } from '@angular/core/testing'; + +import { BottomSheetService } from './bottom-sheet.service'; + +describe('ui::BottomSheetService', () => { + beforeEach(() => TestBed.configureTestingModule({})); + + it('should be created', () => { + const service: BottomSheetService = TestBed.get(BottomSheetService); + expect(service).toBeTruthy(); + }); +}); diff --git a/projects/ucap-webmessenger-ui/src/lib/services/splash-screen.service.ts b/projects/ucap-webmessenger-ui/src/lib/services/splash-screen.service.ts new file mode 100644 index 0000000..70307ef --- /dev/null +++ b/projects/ucap-webmessenger-ui/src/lib/services/splash-screen.service.ts @@ -0,0 +1,88 @@ +import { Injectable, Inject } from '@angular/core'; +import { + animate, + AnimationBuilder, + AnimationPlayer, + style +} from '@angular/animations'; +import { DOCUMENT } from '@angular/common'; +import { Router, NavigationEnd } from '@angular/router'; +import { filter, take } from 'rxjs/operators'; + +@Injectable({ + providedIn: 'root' +}) +export class SplashScreenService { + splashScreenEl: any; + player: AnimationPlayer; + + public constructor( + private animationBuilder: AnimationBuilder, + @Inject(DOCUMENT) private document: Document, + private router: Router + ) { + this.init(); + } + + private init(): void { + // Get the splash screen element + this.splashScreenEl = this.document.body.querySelector('#splash-screen'); + + // If the splash screen element exists... + if (this.splashScreenEl) { + // Hide it on the first NavigationEnd event + this.router.events + .pipe( + filter(event => event instanceof NavigationEnd), + take(1) + ) + .subscribe(() => { + setTimeout(() => { + this.hide(); + }); + }); + } + } + + /** + * Show the splash screen + */ + show(): void { + this.player = this.animationBuilder + .build([ + style({ + opacity: '0', + zIndex: '99999' + }), + animate('400ms ease', style({ opacity: '1' })) + ]) + .create(this.splashScreenEl); + + setTimeout(() => { + this.player.play(); + }, 0); + } + + /** + * Hide the splash screen + */ + hide(): void { + this.player = this.animationBuilder + .build([ + style({ opacity: '1' }), + animate( + '700ms ease', + style({ + opacity: '0', + display: 'none', + zIndex: '-10' + }) + ) + ]) + .create(this.splashScreenEl); + + setTimeout(() => { + this.player.play(); + }, 0); + } +} diff --git a/projects/ucap-webmessenger-ui/src/lib/ucap-ui.module.ts b/projects/ucap-webmessenger-ui/src/lib/ucap-ui.module.ts index 6fa1b1a..e8485cc 100644 --- a/projects/ucap-webmessenger-ui/src/lib/ucap-ui.module.ts +++ b/projects/ucap-webmessenger-ui/src/lib/ucap-ui.module.ts @@ -18,6 +18,7 @@ import { DragDropModule } from '@angular/cdk/drag-drop'; import { FileUploadQueueComponent } from './components/file-upload-queue.component'; import { FloatActionButtonComponent } from './components/float-action-button.component'; import { FileViewerComponent } from './components/file-viewer.component'; +import { ExpansionPanelComponent } from './components/expansion-panel.component'; import { BinaryViewerComponent } from './components/file-viewer/binary-viewer.component'; import { DocumentViewerComponent } from './components/file-viewer/document-viewer.component'; @@ -29,23 +30,33 @@ import { BottomSheetService } from './services/bottom-sheet.service'; import { ClipboardService } from './services/clipboard.service'; import { DialogService } from './services/dialog.service'; import { SnackBarService } from './services/snack-bar.service'; +import { SplashScreenService } from './services/splash-screen.service'; import { ClickOutsideDirective } from './directives/click-outside.directive'; import { FileUploadForDirective } from './directives/file-upload-for.directive'; import { ImageDirective } from './directives/image.directive'; +import { CdkVirtualScrollViewportPatchDirective } from './directives/cdk-virtual-scroll-viewport-patch.directive'; import { AlertDialogComponent } from './dialogs/alert.dialog.component'; import { ConfirmDialogComponent } from './dialogs/confirm.dialog.component'; import { BytesPipe } from './pipes/bytes.pipe'; import { LinefeedToHtmlPipe, HtmlToLinefeedPipe } from './pipes/linefeed.pipe'; -import { DateToStringForChatRoomListPipe } from './pipes/dates.pipe'; +import { + DateToStringForChatRoomListPipe, + DateToStringFormatPipe +} from './pipes/dates.pipe'; import { SecondsToMinutesPipe } from './pipes/seconds-to-minutes.pipe'; +import { LinkyPipe } from './pipes/linky.pipe'; +import { StickerSelectorComponent } from './components/sticker-selector.component'; +import { MatTabsModule } from '@angular/material'; const COMPONENTS = [ FileUploadQueueComponent, FloatActionButtonComponent, FileViewerComponent, + ExpansionPanelComponent, + StickerSelectorComponent, BinaryViewerComponent, DocumentViewerComponent, @@ -57,20 +68,24 @@ const DIALOGS = [AlertDialogComponent, ConfirmDialogComponent]; const DIRECTIVES = [ ClickOutsideDirective, FileUploadForDirective, - ImageDirective + ImageDirective, + CdkVirtualScrollViewportPatchDirective ]; const PIPES = [ BytesPipe, LinefeedToHtmlPipe, HtmlToLinefeedPipe, DateToStringForChatRoomListPipe, - SecondsToMinutesPipe + DateToStringFormatPipe, + SecondsToMinutesPipe, + LinkyPipe ]; const SERVICES = [ BottomSheetService, ClipboardService, DialogService, - SnackBarService + SnackBarService, + SplashScreenService ]; @NgModule({ @@ -86,6 +101,7 @@ const SERVICES = [ MatSnackBarModule, MatToolbarModule, MatTooltipModule, + MatTabsModule, DragDropModule ], exports: [...COMPONENTS, ...DIRECTIVES, ...PIPES], diff --git a/projects/ucap-webmessenger-ui/src/lib/utils/string.util.ts b/projects/ucap-webmessenger-ui/src/lib/utils/string.util.ts index 6318164..dceff78 100644 --- a/projects/ucap-webmessenger-ui/src/lib/utils/string.util.ts +++ b/projects/ucap-webmessenger-ui/src/lib/utils/string.util.ts @@ -2,7 +2,7 @@ import { EventType, EventJson, FileEventJson, - MassTextEventJson + MassTextEventJson, } from '@ucap-webmessenger/protocol-event'; import { FileType } from '@ucap-webmessenger/protocol-file'; @@ -79,7 +79,7 @@ export class StringUtil { '수요일', '목요일', '금요일', - '토요일' + '토요일', ]; const weekKorShortName = ['일', '월', '화', '수', '목', '금', '토']; @@ -91,56 +91,62 @@ export class StringUtil { 'Wednesday', 'Thursday', 'Friday', - 'Saturday' + 'Saturday', ]; const weekEngShortName = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']; - return f.replace(/(yyyy|yy|MM|dd|KS|KL|ES|EL|HH|hh|mm|ss|a\/p)/gi, $1 => { - switch ($1) { - case 'yyyy': - return date.getFullYear().toString(); // 년 (4자리) + return f.replace( + /(YYYY|yyyy|YY|yy|MM|DD|dd|KS|KL|ES|EL|HH|hh|mm|ss|a\/p)/gi, + $1 => { + switch ($1) { + case 'YYYY': + case 'yyyy': + return date.getFullYear().toString(); // 년 (4자리) - case 'yy': - return StringUtil.zeroFill(date.getFullYear() % 1000, 2); // 년 (2자리) + case 'YY': + case 'yy': + return StringUtil.zeroFill(date.getFullYear() % 1000, 2); // 년 (2자리) - case 'MM': - return StringUtil.zeroFill(date.getMonth() + 1, 2); // 월 (2자리) + case 'MM': + return StringUtil.zeroFill(date.getMonth() + 1, 2); // 월 (2자리) - case 'dd': - return StringUtil.zeroFill(date.getDate(), 2); // 일 (2자리) + case 'DD': + case 'dd': + return StringUtil.zeroFill(date.getDate(), 2); // 일 (2자리) - case 'KS': - return weekKorShortName[date.getDay()]; // 요일 (짧은 한글) + case 'KS': + return weekKorShortName[date.getDay()]; // 요일 (짧은 한글) - case 'KL': - return weekKorName[date.getDay()]; // 요일 (긴 한글) + case 'KL': + return weekKorName[date.getDay()]; // 요일 (긴 한글) - case 'ES': - return weekEngShortName[date.getDay()]; // 요일 (짧은 영어) + case 'ES': + return weekEngShortName[date.getDay()]; // 요일 (짧은 영어) - case 'EL': - return weekEngName[date.getDay()]; // 요일 (긴 영어) + case 'EL': + return weekEngName[date.getDay()]; // 요일 (긴 영어) - case 'HH': - return StringUtil.zeroFill(date.getHours(), 2); // 시간 (24시간 기준, 2자리) + case 'HH': + return StringUtil.zeroFill(date.getHours(), 2); // 시간 (24시간 기준, 2자리) - case 'hh': - return StringUtil.zeroFill(date.getHours() % 12, 2); // 시간 (12시간 기준, 2자리) + case 'hh': + return StringUtil.zeroFill(date.getHours() % 12, 2); // 시간 (12시간 기준, 2자리) - case 'mm': - return StringUtil.zeroFill(date.getMinutes(), 2); // 분 (2자리) + case 'mm': + return StringUtil.zeroFill(date.getMinutes(), 2); // 분 (2자리) - case 'ss': - return StringUtil.zeroFill(date.getSeconds(), 2); // 초 (2자리) + case 'ss': + return StringUtil.zeroFill(date.getSeconds(), 2); // 초 (2자리) - case 'a/p': - return date.getHours() < 12 ? '오전' : '오후'; // 오전/오후 구분 + case 'a/p': + return date.getHours() < 12 ? '오전' : '오후'; // 오전/오후 구분 - default: - return $1; + default: + return $1; + } } - }); + ); } public static convertFinalEventMessage( diff --git a/projects/ucap-webmessenger-ui/src/public-api.ts b/projects/ucap-webmessenger-ui/src/public-api.ts index db8b49e..6ffe333 100644 --- a/projects/ucap-webmessenger-ui/src/public-api.ts +++ b/projects/ucap-webmessenger-ui/src/public-api.ts @@ -13,6 +13,8 @@ export * from './lib/components/file-upload-queue.component'; export * from './lib/components/file-viewer.component'; export * from './lib/components/float-action-button.component'; +export * from './lib/data-source/virtual-scroll-tree-flat.data-source'; + export * from './lib/dialogs/alert.dialog.component'; export * from './lib/dialogs/confirm.dialog.component'; @@ -24,6 +26,7 @@ export * from './lib/services/bottom-sheet.service'; export * from './lib/services/clipboard.service'; export * from './lib/services/dialog.service'; export * from './lib/services/snack-bar.service'; +export * from './lib/services/splash-screen.service'; export * from './lib/types/file-viewer.type'; diff --git a/tsconfig.json b/tsconfig.json index 18fcd29..db8767b 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -11,11 +11,10 @@ "module": "esnext", "moduleResolution": "node", "importHelpers": true, - "target": "es5", + "target": "es2015", "typeRoots": ["node_modules/@types"], "lib": ["es2018", "dom"], "paths": { - "@app/*": ["projects/ucap-webmessenger-app/src/app/*"], "@ucap-webmessenger/core": [ "projects/ucap-webmessenger-core/src/public-api" ], @@ -31,6 +30,9 @@ "@ucap-webmessenger/api-external": [ "projects/ucap-webmessenger-api-external/src/public-api" ], + "@ucap-webmessenger/api-message": [ + "projects/ucap-webmessenger-api-message/src/public-api" + ], "@ucap-webmessenger/pi": ["projects/ucap-webmessenger-pi/src/public-api"], "@ucap-webmessenger/ui": ["projects/ucap-webmessenger-ui/src/public-api"], "@ucap-webmessenger/ui-account": [ @@ -54,6 +56,9 @@ "@ucap-webmessenger/ui-profile": [ "projects/ucap-webmessenger-ui-profile/src/public-api" ], + "@ucap-webmessenger/ui-settings": [ + "projects/ucap-webmessenger-ui-settings/src/public-api" + ], "@ucap-webmessenger/protocol": [ "projects/ucap-webmessenger-protocol/src/public-api" ], @@ -126,11 +131,15 @@ "@ucap-webmessenger/util": [ "projects/ucap-webmessenger-util/src/public-api" ], + "@app/*": ["projects/ucap-webmessenger-app/src/app/*"], "@ucap-webmessenger/electron-core": [ - "projects/ucap-webmessenger-electron-core/src/public-api" + "electron-projects/ucap-webmessenger-electron-core/src/public-api" ], "@ucap-webmessenger/electron-notification": [ - "projects/ucap-webmessenger-electron-notification/src/public-api" + "electron-projects/ucap-webmessenger-electron-notification/src/public-api" + ], + "@ucap-webmessenger/electron": [ + "electron-projects/ucap-webmessenger-electron/src/public-api" ] } },