diff --git a/.storybook/main.js b/.storybook/main.js index b315022..d64e832 100644 --- a/.storybook/main.js +++ b/.storybook/main.js @@ -14,7 +14,23 @@ module.exports = { rule.use.push({ loader: 'sass-resources-loader', options: { - resources: [path.join(__dirname, 'styles.scss')] + resources: [ + path.join( + __dirname, + '..', + 'node_modules', + '@angular/material/prebuilt-themes', + 'indigo-pink.css' + ), + path.join( + __dirname, + '..', + 'node_modules', + 'perfect-scrollbar/css', + 'perfect-scrollbar.css' + ), + path.join(__dirname, 'styles.scss') + ] } }); } diff --git a/.storybook/preview-head.html b/.storybook/preview-head.html new file mode 100644 index 0000000..6c041c7 --- /dev/null +++ b/.storybook/preview-head.html @@ -0,0 +1,6 @@ + + + diff --git a/.storybook/tsconfig.json b/.storybook/tsconfig.json index fea73af..c10a15c 100644 --- a/.storybook/tsconfig.json +++ b/.storybook/tsconfig.json @@ -1,6 +1,7 @@ { "extends": "../tsconfig.json", "compilerOptions": { + "emitDecoratorMetadata": true, "types": ["node"] }, "exclude": [ diff --git a/angular.json b/angular.json index 6435907..dff1cee 100644 --- a/angular.json +++ b/angular.json @@ -1264,6 +1264,49 @@ } } }, + "ui-material": { + "projectType": "library", + "schematics": { + "@schematics/angular:component": { + "style": "scss" + } + }, + "root": "projects/ui-material", + "sourceRoot": "projects/ui-material/src", + "prefix": "lib", + "architect": { + "build": { + "builder": "@angular-devkit/build-ng-packagr:build", + "options": { + "tsConfig": "projects/ui-material/tsconfig.lib.json", + "project": "projects/ui-material/ng-package.json" + }, + "configurations": { + "production": { + "tsConfig": "projects/ui-material/tsconfig.lib.prod.json" + } + } + }, + "test": { + "builder": "@angular-devkit/build-angular:karma", + "options": { + "main": "projects/ui-material/src/test.ts", + "tsConfig": "projects/ui-material/tsconfig.spec.json", + "karmaConfig": "projects/ui-material/karma.conf.js" + } + }, + "lint": { + "builder": "@angular-devkit/build-angular:tslint", + "options": { + "tsConfig": [ + "projects/ui-material/tsconfig.lib.json", + "projects/ui-material/tsconfig.spec.json" + ], + "exclude": ["**/node_modules/**"] + } + } + } + }, "ui": { "projectType": "library", "schematics": { diff --git a/package-lock.json b/package-lock.json index 435954a..a3d7176 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3503,18 +3503,18 @@ "dev": true }, "@ucap/ng-store-authentication": { - "version": "file:pack/ucap-ng-store-authentication-0.0.10.tgz", - "integrity": "sha512-71Jzg9oYSQ89nShT3F64Mfy4edAbmc/vH/0pbPtT0S4zVH/ZMiC11xnocDQTzAKKtP1kXdNGJt/wv1ZbjMNUQQ==", + "version": "file:pack/ucap-ng-store-authentication-0.0.11.tgz", + "integrity": "sha512-YwLMW+GIR3Rs7LaP+1xOH9KLI5jlpZx8oS7Zl32m6Wbym4ModIcGh21rRrqFhNXky4s9zl+ziaTRpFNCKJRgng==", "dev": true }, "@ucap/ng-store-chat": { - "version": "file:pack/ucap-ng-store-chat-0.0.8.tgz", - "integrity": "sha512-f/Smoy/A97JV2Tsd7IIAeQcNRrthxKT+S01PrVyzjNktDvcxOurnIXGacytU9sfkEMP2rOFCuWKv5p21rvVg6g==", + "version": "file:pack/ucap-ng-store-chat-0.0.13.tgz", + "integrity": "sha512-o+BCCSMxneUenRHEW47sSY22+Zt3lyr202Lg4bub9OVRbW5CVohHez8H+JwK+w+Lf8KbqG32V1ZjKLGclTpboA==", "dev": true }, "@ucap/ng-store-group": { - "version": "file:pack/ucap-ng-store-group-0.0.9.tgz", - "integrity": "sha512-KJ4E/kZECAkT6zwA1FiDCrhGevCx9so2Knz08kU49broquZQlOtbV70tPj1fA0XBnaY3hL7uUKXqvAfC7OXj0g==", + "version": "file:pack/ucap-ng-store-group-0.0.14.tgz", + "integrity": "sha512-sUmdHO7TD5B33DMAoEnelvqbLXTsWPnK2HC8XQ0FdlfGyUtf3kGpwS4BxduUi5wiZckR3hfuBdpCShIhf/qmeQ==", "dev": true }, "@ucap/ng-store-organization": { @@ -3523,33 +3523,39 @@ "dev": true }, "@ucap/ng-ui": { - "version": "file:pack/ucap-ng-ui-0.0.11.tgz", - "integrity": "sha512-Vrl6LFQyBwju76RALrF0/dH9p+PJ4nX33dy99QSx6RUJHQ80C0qAmO/DFS1Ln0LZaDc4KoYIHTAOLvX4WLHS5w==", + "version": "file:pack/ucap-ng-ui-0.0.19.tgz", + "integrity": "sha512-UuZSzWM4tBR+e5Z/1PFdNenHS00Pn4K7dTafIicG29YjHE5sTXXRqjDCVrKNxJQoMSEPWjUj7qnTgYwP2U83Vg==", "dev": true }, "@ucap/ng-ui-authentication": { - "version": "file:pack/ucap-ng-ui-authentication-0.0.20.tgz", - "integrity": "sha512-1FhqwODVL51NC39mwi/2MECMQiyM+qXAlVp2/BrvN+piXXRz/qp62Iwyf/jww+N8aVCe3dqbktJl/tuPacm4/Q==", + "version": "file:pack/ucap-ng-ui-authentication-0.0.24.tgz", + "integrity": "sha512-6QMJ8dieTnbPANsBzg2Ll3HH5q6Bzl2iSM19yHq8Ct7XOmElrYqrEZmxbDyYO+aCXIAwd2t7vu+rTsHfz3XOQg==", "dev": true }, "@ucap/ng-ui-chat": { - "version": "file:pack/ucap-ng-ui-chat-0.0.3.tgz", - "integrity": "sha512-RRw533PNi0vVCxH1QiogOkJEC/dWGsSFtK3hdJ/ZlcPCT7G81FnnXVY3HPIzu1MhxnSb7KfVJLZhx2RFEfEXWA==", + "version": "file:pack/ucap-ng-ui-chat-0.0.9.tgz", + "integrity": "sha512-6qvzcTuylkxVjsqajsLW15laOyOskxVMy238/Ju1yYvwCRyHygwS1i67APoG5tv+SWu+l38f9uWIqzfy7WYHkQ==", "dev": true }, "@ucap/ng-ui-group": { - "version": "file:pack/ucap-ng-ui-group-0.0.30.tgz", - "integrity": "sha512-LJXwWZ4anO/ScpI+c6IUfwjmcW9tocQq86/cHi8m6SaQwaMq3jltlN2x8WLzRefd72KysLyJHZrX5L1zMLcXog==", + "version": "file:pack/ucap-ng-ui-group-0.0.33.tgz", + "integrity": "sha512-c//Jq00drbMGE3Cgwlh19ScXllGERX2eMVWkVjm311Y8HN9oBBT6Aq2uCM23/76P866oNrhecVDfDHgGYzPRjA==", + "dev": true + }, + "@ucap/ng-ui-material": { + "version": "file:pack/ucap-ng-ui-material-0.0.4.tgz", + "integrity": "sha512-ySPULAbP+nQ65hBG2VWZ2H5Hr7muuTGGNXs6A+S3lsxLaW452wM3GNyUBhvUopr8LaSsoOPpp4nK1JeC0fG6pA==", "dev": true }, "@ucap/ng-ui-organization": { - "version": "file:pack/ucap-ng-ui-organization-0.0.27.tgz", - "integrity": "sha512-BC0Jxoxia/+Kho+1oAXE+7+K9iXLhVYVWPVCmmzSRGYGrIZu1skNzzKCNZh6WxYOr7LAJ6ZOp+FgYDfKS7iHMg==", + "version": "file:pack/ucap-ng-ui-organization-0.0.55.tgz", + "integrity": "sha512-vfpKd3fbd+I0Od8aB2nIFfjuI7wj3Ziu/uiTEmZxKwZy7uZrNYm59BPbctKW3AQsQ4UtnLofhlBbAA7e9pT80Q==", "dev": true }, "@ucap/ng-ui-skin-default": { "version": "file:pack/ucap-ng-ui-skin-default-0.0.1.tgz", - "integrity": "sha512-kfbbfHZ2b1mQL5SflvM9xn86d53NFEx3yTCaQSx16VSEetbQAtb6Qp1/VedDxK6NcWHp+s/Msw5cfuypN1gwug==" + "integrity": "sha512-+lHYAzbnyyWh6hf+Ui7vP/ibyGJXuDUO++82jOiOsnPMCl17hkCCag8vQcB/aVgl0iHmebiPshnsL3CptJfeAg==", + "dev": true }, "@ucap/ng-web-socket": { "version": "file:pack/ucap-ng-web-socket-0.0.2.tgz", @@ -3592,9 +3598,9 @@ "dev": true }, "@ucap/protocol-file": { - "version": "0.0.4", - "resolved": "https://nexus.loafle.net/repository/npm-all/@ucap/protocol-file/-/protocol-file-0.0.4.tgz", - "integrity": "sha512-oyne/wiKsEsLzJY9VJUO85AwLtgfq0Dt7RyFLThoqquz6O7lCuWszdtvggAJTgn+XM+nF4hczw2Qm2jwjjCZgQ==", + "version": "0.0.5", + "resolved": "https://nexus.loafle.net/repository/npm-all/@ucap/protocol-file/-/protocol-file-0.0.5.tgz", + "integrity": "sha512-3XRwtlpcrm2oZeckoOzzAUcqADPCGbgdEb4psfNnphTbGX9nYaBUTpWuLYwD3tVe7Wg4fytaHemcAu8yVZUANw==", "dev": true }, "@ucap/protocol-group": { @@ -3604,9 +3610,9 @@ "dev": true }, "@ucap/protocol-info": { - "version": "0.0.5", - "resolved": "https://nexus.loafle.net/repository/npm-all/@ucap/protocol-info/-/protocol-info-0.0.5.tgz", - "integrity": "sha512-C2+cJrxdUNLVt3E1a54tCpTmEYE16sUGNvdJGUPywbvLAhjWf71ECjGr16bTMcPr/PxmzjZBu9M2Of39sqngOQ==", + "version": "0.0.6", + "resolved": "https://nexus.loafle.net/repository/npm-all/@ucap/protocol-info/-/protocol-info-0.0.6.tgz", + "integrity": "sha512-qpt0jfmHDyaMGyADzaDMKbbkfD04yEC0u4KDyoMdjnTi0RXA6cilDRGr9TW/bezB9OxS40yNLK6REfh7aSmcUA==", "dev": true }, "@ucap/protocol-inner": { diff --git a/package.json b/package.json index a042fec..05c532e 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "ng": "ng", "start": "ng serve", "build": "ng build", - "build:all": "npm-run-all -s build:logger build:core build:util:all build:api:all build:protocol:all build:native:all build:store:all build:ui:all build:ui-skin:all", + "build:all": "npm-run-all -s build:logger build:core build:util:all build:api:all build:protocol:all build:native:all build:store:all build:ui-material:all build:ui:all build:ui-skin:all", "build:api:all": "npm-run-all -s build:api-common build:api-external build:api-message build:api-prompt build:api-public build:pi", "build:api-common": "node ./scripts/build.js api-common", "build:api-external": "node ./scripts/build.js api-external", @@ -45,15 +45,17 @@ "build:store-chat": "node ./scripts/build.js store-chat", "build:store-group": "node ./scripts/build.js store-group", "build:store-organization": "node ./scripts/build.js store-organization", + "build:ui-material:all": "npm-run-all -s build:ui-material", + "build:ui-material": "node ./scripts/build.js ui-material useScssBundle", "build:ui:all": "npm-run-all -s build:ui build:ui-organization build:ui-authentication build:ui-group build:ui-chat", - "build:ui": "node ./scripts/build.js ui", - "build:ui-organization": "node ./scripts/build.js ui-organization", - "build:ui-authentication": "node ./scripts/build.js ui-authentication", - "build:ui-group": "node ./scripts/build.js ui-group", - "build:ui-chat": "node ./scripts/build.js ui-chat", + "build:ui": "node ./scripts/build.js ui useScssBundle", + "build:ui-organization": "node ./scripts/build.js ui-organization useScssBundle", + "build:ui-authentication": "node ./scripts/build.js ui-authentication useScssBundle", + "build:ui-group": "node ./scripts/build.js ui-group useScssBundle", + "build:ui-chat": "node ./scripts/build.js ui-chat useScssBundle", "build:ui-skin:all": "npm-run-all -s build:ui-skin-default", "build:ui-skin-default": "node ./scripts/build.js ui-skin-default useScssBundle", - "publish:all": "npm-run-all -s publish:logger publish:core publish:util:all publish:api:all publish:protocol:all publish:native:all publish:store:all publish:ui:all publish:ui-skin:all", + "publish:all": "npm-run-all -s publish:logger publish:core publish:util:all publish:api:all publish:protocol:all publish:native:all publish:store:all publish:ui-material:all publish:ui:all publish:ui-skin:all", "publish:api:all": "npm-run-all -s publish:api-common publish:api-external publish:api-message publish:api-prompt publish:api-public publish:pi", "publish:api-common": "cd ./dist/api-common && npm publish", "publish:api-external": "cd ./dist/api-external && npm publish", @@ -92,6 +94,8 @@ "publish:store-chat": "cd ./dist/store-chat && npm publish", "publish:store-group": "cd ./dist/store-group && npm publish", "publish:store-organization": "cd ./dist/store-organization && npm publish", + "publish:ui-material:all": "npm-run-all -s publish:ui-material", + "publish:ui-material": "cd ./dist/ui-material && npm publish", "publish:ui:all": "npm-run-all -s publish:ui publish:ui-organization publish:ui-authentication publish:ui-group publish:ui-chat", "publish:ui": "cd ./dist/ui && npm publish", "publish:ui-organization": "cd ./dist/ui-organization && npm publish", @@ -180,15 +184,16 @@ "@ucap/ng-protocol-status": "file:pack/ucap-ng-protocol-status-0.0.3.tgz", "@ucap/ng-protocol-sync": "file:pack/ucap-ng-protocol-sync-0.0.3.tgz", "@ucap/ng-protocol-umg": "file:pack/ucap-ng-protocol-umg-0.0.3.tgz", - "@ucap/ng-store-authentication": "file:pack/ucap-ng-store-authentication-0.0.10.tgz", - "@ucap/ng-store-chat": "file:pack/ucap-ng-store-chat-0.0.8.tgz", - "@ucap/ng-store-group": "file:pack/ucap-ng-store-group-0.0.9.tgz", + "@ucap/ng-store-authentication": "file:pack/ucap-ng-store-authentication-0.0.11.tgz", + "@ucap/ng-store-chat": "file:pack/ucap-ng-store-chat-0.0.13.tgz", + "@ucap/ng-store-group": "file:pack/ucap-ng-store-group-0.0.14.tgz", "@ucap/ng-store-organization": "file:pack/ucap-ng-store-organization-0.0.8.tgz", - "@ucap/ng-ui": "file:pack/ucap-ng-ui-0.0.11.tgz", - "@ucap/ng-ui-authentication": "file:pack/ucap-ng-ui-authentication-0.0.20.tgz", - "@ucap/ng-ui-chat": "file:pack/ucap-ng-ui-chat-0.0.3.tgz", - "@ucap/ng-ui-group": "file:pack/ucap-ng-ui-group-0.0.30.tgz", - "@ucap/ng-ui-organization": "file:pack/ucap-ng-ui-organization-0.0.27.tgz", + "@ucap/ng-ui": "file:pack/ucap-ng-ui-0.0.19.tgz", + "@ucap/ng-ui-authentication": "file:pack/ucap-ng-ui-authentication-0.0.24.tgz", + "@ucap/ng-ui-chat": "file:pack/ucap-ng-ui-chat-0.0.9.tgz", + "@ucap/ng-ui-group": "file:pack/ucap-ng-ui-group-0.0.33.tgz", + "@ucap/ng-ui-material": "file:pack/ucap-ng-ui-material-0.0.4.tgz", + "@ucap/ng-ui-organization": "file:pack/ucap-ng-ui-organization-0.0.55.tgz", "@ucap/ng-ui-skin-default": "file:pack/ucap-ng-ui-skin-default-0.0.1.tgz", "@ucap/ng-web-socket": "file:pack/ucap-ng-web-socket-0.0.2.tgz", "@ucap/ng-web-storage": "file:pack/ucap-ng-web-storage-0.0.3.tgz", @@ -197,9 +202,9 @@ "@ucap/protocol-authentication": "~0.0.5", "@ucap/protocol-buddy": "~0.0.5", "@ucap/protocol-event": "~0.0.5", - "@ucap/protocol-file": "~0.0.4", + "@ucap/protocol-file": "~0.0.5", "@ucap/protocol-group": "~0.0.5", - "@ucap/protocol-info": "~0.0.5", + "@ucap/protocol-info": "~0.0.6", "@ucap/protocol-inner": "~0.0.4", "@ucap/protocol-option": "~0.0.7", "@ucap/protocol-ping": "~0.0.4", diff --git a/projects/store-authentication/ng-package.json b/projects/store-authentication/ng-package.json index fe22ca3..b791a0d 100644 --- a/projects/store-authentication/ng-package.json +++ b/projects/store-authentication/ng-package.json @@ -11,10 +11,12 @@ "@ucap/api-external": "@ucap/api-external", "@ucap/pi": "@ucap/pi", "@ucap/protocol-authentication": "@ucap/protocol-authentication", + "@ucap/protocol-info": "@ucap/protocol-info", "@ucap/protocol-option": "@ucap/protocol-option", "@ucap/protocol-query": "@ucap/protocol-query", "@ucap/ng-pi": "@ucap/ng-pi", "@ucap/ng-protocol-authentication": "@ucap/ng-protocol-authentication", + "@ucap/ng-protocol-info": "@ucap/ng-protocol-info", "@ucap/ng-protocol-option": "@ucap/ng-protocol-option", "@ucap/ng-protocol-query": "@ucap/ng-protocol-query" } diff --git a/projects/store-authentication/package.json b/projects/store-authentication/package.json index 320e52a..0da71fe 100644 --- a/projects/store-authentication/package.json +++ b/projects/store-authentication/package.json @@ -1,6 +1,6 @@ { "name": "@ucap/ng-store-authentication", - "version": "0.0.10", + "version": "0.0.11", "publishConfig": { "registry": "https://nexus.loafle.net/repository/npm-ucap/" }, @@ -17,10 +17,12 @@ "@ucap/protocol-authentication": "~0.0.1", "@ucap/protocol-option": "~0.0.1", "@ucap/protocol-query": "~0.0.1", + "@ucap/protocol-info": "~0.0.1", "@ucap/ng-pi": "~0.0.1", "@ucap/ng-protocol-authentication": "~0.0.1", "@ucap/ng-protocol-option": "~0.0.1", "@ucap/ng-protocol-query": "~0.0.1", + "@ucap/ng-protocol-info": "~0.0.1", "rxjs": "~6.5.4", "tslib": "^1.10.0" } diff --git a/projects/store-authentication/src/lib/store/login/actions.ts b/projects/store-authentication/src/lib/store/login/actions.ts index c8c9078..40024cc 100644 --- a/projects/store-authentication/src/lib/store/login/actions.ts +++ b/projects/store-authentication/src/lib/store/login/actions.ts @@ -7,6 +7,7 @@ import { LoginResponse, LogoutResponse } from '@ucap/protocol-authentication'; +import { UserResponse, UserRequest } from '@ucap/protocol-info'; /** * request of web login @@ -106,3 +107,29 @@ export const sessionDestroyed = createAction( '[ucap::authentication::login] session Destroyed', props<{ error: any }>() ); + +/** + * info user request + */ +export const infoUser = createAction( + '[ucap::authentication::login] Info User', + props<{ req: UserRequest }>() +); + +/** + * Success of info user request + */ +export const infoUserSuccess = createAction( + '[ucap::authentication::login] Info User Success', + props<{ + res: UserResponse; + }>() +); + +/** + * Failure of info user request + */ +export const infoUserFailure = createAction( + '[ucap::authentication::login] Info User Failure', + props<{ error: any }>() +); diff --git a/projects/store-authentication/src/lib/store/login/effects.ts b/projects/store-authentication/src/lib/store/login/effects.ts index 3d1bbb0..ca404d7 100644 --- a/projects/store-authentication/src/lib/store/login/effects.ts +++ b/projects/store-authentication/src/lib/store/login/effects.ts @@ -1,5 +1,5 @@ import { of } from 'rxjs'; -import { catchError, map, switchMap } from 'rxjs/operators'; +import { catchError, map, switchMap, exhaustMap } from 'rxjs/operators'; import { Injectable } from '@angular/core'; @@ -7,26 +7,52 @@ import { Actions, ofType, createEffect } from '@ngrx/effects'; import { PiService } from '@ucap/ng-pi'; import { AuthenticationProtocolService } from '@ucap/ng-protocol-authentication'; +import { InfoProtocolService } from '@ucap/ng-protocol-info'; -import { logout, logoutSuccess } from './actions'; +import { + logout, + logoutSuccess, + infoUser, + infoUserSuccess, + infoUserFailure +} from './actions'; +import { UserResponse } from '@ucap/protocol-info'; @Injectable() export class Effects { logout$ = createEffect(() => { return this.actions$.pipe( ofType(logout), - switchMap(action => { + switchMap((action) => { return this.authenticationProtocolService.logout({}).pipe( - map(res => logoutSuccess({ res })), - catchError(error => of(error)) + map((res) => logoutSuccess({ res })), + catchError((error) => of(error)) ); }) ); }); + infoUser$ = createEffect(() => + this.actions$.pipe( + ofType(infoUser), + map((action) => action.req), + exhaustMap((req) => + this.infoProtocolService.user(req).pipe( + map((res: UserResponse) => { + return infoUserSuccess({ + res + }); + }), + catchError((error) => of(infoUserFailure({ error }))) + ) + ) + ) + ); + constructor( private actions$: Actions, private piService: PiService, - private authenticationProtocolService: AuthenticationProtocolService + private authenticationProtocolService: AuthenticationProtocolService, + private infoProtocolService: InfoProtocolService ) {} } diff --git a/projects/store-authentication/src/lib/store/login/reducers.ts b/projects/store-authentication/src/lib/store/login/reducers.ts index aee7688..1f12c05 100644 --- a/projects/store-authentication/src/lib/store/login/reducers.ts +++ b/projects/store-authentication/src/lib/store/login/reducers.ts @@ -1,7 +1,8 @@ import { createReducer, on } from '@ngrx/store'; import { initialState } from './state'; -import { loginSuccess, logoutSuccess } from './actions'; +import { loginSuccess, logoutSuccess, infoUserSuccess } from './actions'; +import { UserInfoUpdateType } from '@ucap/protocol-info'; export const reducer = createReducer( initialState, @@ -16,5 +17,41 @@ export const reducer = createReducer( return { ...initialState }; + }), + + on(infoUserSuccess, (state, action) => { + let loginRes = { + ...state.loginRes + }; + + switch (action.res.type) { + case UserInfoUpdateType.Image: + loginRes = { + ...loginRes + }; + break; + case UserInfoUpdateType.Intro: + loginRes = { + ...loginRes, + userInfo: { + ...loginRes.userInfo, + intro: action.res.info + } + }; + break; + case UserInfoUpdateType.TelephoneVisible: + loginRes = { + ...loginRes + }; + break; + default: + break; + } + return { + ...state, + loginRes: { + ...loginRes + } + }; }) ); diff --git a/projects/store-chat/package.json b/projects/store-chat/package.json index 4830cda..604968b 100644 --- a/projects/store-chat/package.json +++ b/projects/store-chat/package.json @@ -1,6 +1,6 @@ { "name": "@ucap/ng-store-chat", - "version": "0.0.8", + "version": "0.0.13", "publishConfig": { "registry": "https://nexus.loafle.net/repository/npm-ucap/" }, diff --git a/projects/store-chat/src/lib/config/module-config.ts b/projects/store-chat/src/lib/config/module-config.ts index d158cc6..e8a2321 100644 --- a/projects/store-chat/src/lib/config/module-config.ts +++ b/projects/store-chat/src/lib/config/module-config.ts @@ -1,4 +1,7 @@ import { ModuleConfig as CoreModuleConfig } from '@ucap/core'; // tslint:disable-next-line: no-empty-interface -export interface ModuleConfig extends CoreModuleConfig {} +export interface ModuleConfig extends CoreModuleConfig { + eventRequestInitCount?: number; + eventRequestDefaultCount?: number; +} diff --git a/projects/store-chat/src/lib/store/chatting/actions.ts b/projects/store-chat/src/lib/store/chatting/actions.ts index 856cdad..55cbfff 100644 --- a/projects/store-chat/src/lib/store/chatting/actions.ts +++ b/projects/store-chat/src/lib/store/chatting/actions.ts @@ -15,7 +15,8 @@ import { ReadNotification, CancelNotification, DelNotification, - EventJson + EventJson, + ReadResponse } from '@ucap/protocol-event'; import { @@ -40,7 +41,7 @@ export const eventsSuccess = createAction( props<{ eventInfoList: Info[]; res: EventInfoResponse; - remainInfo: boolean; + remainEvent: boolean; }>() ); /** @@ -48,7 +49,7 @@ export const eventsSuccess = createAction( */ export const eventsFailure = createAction( '[ucap::chat::chatting] events Failure', - props<{ error: any }>() + props<{ roomId: string; error: any }>() ); /** @@ -74,7 +75,7 @@ export const fileInfosSuccess = createAction( */ export const fileInfosFailure = createAction( '[ucap::chat::chatting] fileInfos Failure', - props<{ error: any }>() + props<{ roomId: string; error: any }>() ); /** @@ -84,3 +85,23 @@ export const addEvent = createAction( '[ucap::chat::chatting] addEvent', props<{ req: FileInfoRequest }>() ); + +export const read = createAction( + '[ucap::chat::chatting] read', + props() +); + +export const readSuccess = createAction( + '[ucap::chat::chatting] read Success', + props() +); + +// export const readNotification = createAction( +// '[ucap::chat::chatting] Read Notification', +// props() +// ); + +export const readFailure = createAction( + '[ucap::chat::chatting] read Failure', + props<{ error: any }>() +); diff --git a/projects/store-chat/src/lib/store/chatting/effects.ts b/projects/store-chat/src/lib/store/chatting/effects.ts index 7161314..f2553e9 100644 --- a/projects/store-chat/src/lib/store/chatting/effects.ts +++ b/projects/store-chat/src/lib/store/chatting/effects.ts @@ -5,33 +5,165 @@ import { map, catchError, exhaustMap, - withLatestFrom + debounceTime } from 'rxjs/operators'; -import { Injectable } from '@angular/core'; +import { Injectable, Inject } from '@angular/core'; -import { Store, select } from '@ngrx/store'; +import { Store } from '@ngrx/store'; import { Actions, createEffect, ofType } from '@ngrx/effects'; -import { - RoomInfo, - UpdateResponse, - OpenResponse, - ExitResponse, - Open3Response, - RoomType, - InviteResponse, - UpdateTimerSetResponse, - ExitForcingResponse -} from '@ucap/protocol-room'; - +import { EventProtocolService } from '@ucap/ng-protocol-event'; import { RoomProtocolService } from '@ucap/ng-protocol-room'; +import { FileProtocolService } from '@ucap/ng-protocol-file'; + +import * as roomActions from '../room/actions'; +import { + events, + eventsFailure, + eventsSuccess, + read, + readFailure, + readSuccess, + fileInfos, + fileInfosFailure, + fileInfosSuccess +} from './actions'; + +import { InfoRequest, ReadResponse, FileType } from '@ucap/protocol-event'; + +import { ModuleConfig } from '../../config/module-config'; +import { _MODULE_CONFIG } from '../../config/token'; @Injectable() export class Effects { + selectedRoom$ = createEffect( + () => { + return this.actions$.pipe( + ofType(roomActions.selectedRoom), + debounceTime(300), + tap((action) => { + const requestCount = this.moduleConfig?.eventRequestInitCount || 50; + const req: InfoRequest = { + roomId: action.roomId, + baseSeq: 0, + requestCount + }; + + this.store.dispatch(events({ req })); + }) + ); + }, + { dispatch: false } + ); + + events$ = createEffect( + () => { + return this.actions$.pipe( + ofType(events), + map((action) => action.req), + switchMap((req) => { + return this.eventProtocolService.info(req).pipe( + map((res) => { + if (!!res && !!res.res) { + const infoList = res.infoList; + + this.store.dispatch( + eventsSuccess({ + eventInfoList: infoList, + res: res.res, + remainEvent: + infoList.length === req.requestCount ? true : false + }) + ); + + if (req.baseSeq === 0) { + // 최초 이벤트 목록 조회. + + // SSVC_TYPE_EVENT_READ_REQ 수행. + const maxSeq = Math.max.apply( + Math, + infoList.map((v) => v.seq) + ); + this.store.dispatch( + read({ + roomId: req.roomId, + lastReadSeq: Number(maxSeq) + }) + ); + + // File 정보 수집. + this.store.dispatch( + fileInfos({ + req: { + roomId: res.res.roomId, + // { 파일타입 } cf) I : 이미지 V: 동영상 F: 파일 "" 빈값이면 모든 타입을 내려줌 + type: FileType.All + } + }) + ); + } else { + } + } + }), + catchError((error) => + of(eventsFailure({ roomId: req.roomId, error })) + ) + ); + }) + ); + }, + { dispatch: false } + ); + + read$ = createEffect( + () => { + return this.actions$.pipe( + ofType(read), + exhaustMap((req) => + this.eventProtocolService.read(req).pipe( + map((res: ReadResponse) => { + this.store.dispatch(readSuccess(res)); + }), + catchError((error) => of(readFailure({ error }))) + ) + ) + ); + }, + { dispatch: false } + ); + + fileInfos$ = createEffect( + () => { + return this.actions$.pipe( + ofType(fileInfos), + switchMap((action) => { + return this.fileProtocolService.info(action.req).pipe( + map((res) => { + this.store.dispatch( + fileInfosSuccess({ + fileInfoList: res.fileInfos, + fileInfoCheckList: res.fileInfoChecks, + res: res.res + }) + ); + }), + catchError((error) => + of(fileInfosFailure({ roomId: action.req.roomId, error })) + ) + ); + }) + ); + }, + { dispatch: false } + ); + constructor( private actions$: Actions, private store: Store, - private roomProtocolService: RoomProtocolService + @Inject(_MODULE_CONFIG) private moduleConfig: ModuleConfig, + private roomProtocolService: RoomProtocolService, + private eventProtocolService: EventProtocolService, + private fileProtocolService: FileProtocolService ) {} } diff --git a/projects/store-chat/src/lib/store/chatting/reducers.ts b/projects/store-chat/src/lib/store/chatting/reducers.ts index 1364143..b79e0f5 100644 --- a/projects/store-chat/src/lib/store/chatting/reducers.ts +++ b/projects/store-chat/src/lib/store/chatting/reducers.ts @@ -1,5 +1,167 @@ import { createReducer, on } from '@ngrx/store'; -import { initialState, adapterChatting } from './state'; +import { + initialState, + adapterChatting, + adapterEventList, + Chatting, + adapterFileInfoList, + adapterFileInfoCheckList +} from './state'; -export const reducer = createReducer(initialState); +import * as roomActions from '../room/actions'; +import { + eventsSuccess, + eventsFailure, + readSuccess, + fileInfosSuccess, + fileInfosFailure +} from './actions'; + +export const reducer = createReducer( + initialState, + + on(roomActions.selectedRoom, (state, action) => { + return { + ...state, + activeRoomId: action.roomId + }; + }), + + on(roomActions.clearSelectedRoom, (state, action) => { + if (action.roomId === state.activeRoomId) { + return { + ...state, + activeRoomId: null + }; + } else { + return state; + } + }), + + on(eventsSuccess, (state, action) => { + const roomId = action.res.roomId; + + const chatting = state.chattings.entities[roomId] || {}; + let trgtChatting: Chatting = { + roomId, + + eventListProcessing: false, + eventList: adapterEventList.getInitialState(), + eventStatus: null, + remainEvent: false, + + fileInfoListProcessing: false, + fileInfoList: adapterFileInfoList.getInitialState(), + fileInfoCheckList: adapterFileInfoCheckList.getInitialState(), + fileInfoSyncDate: '', + ...chatting + }; + + trgtChatting = { + ...trgtChatting, + eventList: adapterEventList.upsertMany(action.eventInfoList, { + ...trgtChatting.eventList + }), + eventStatus: action.res, + remainEvent: action.remainEvent, + eventListProcessing: false + }; + + return { + ...state, + chattings: adapterChatting.upsertOne(trgtChatting, { + ...state.chattings + }) + }; + }), + + on(eventsFailure, (state, action) => { + const roomId = action.roomId; + + const chatting = state.chattings.entities[roomId]; + let trgtChatting: Chatting; + if (!!chatting) { + trgtChatting = { + ...chatting, + eventListProcessing: false + }; + } + + return { + ...state, + chattings: adapterChatting.upsertOne(trgtChatting, { + ...state.chattings + }) + }; + }), + + on(fileInfosSuccess, (state, action) => { + const roomId = action.res?.roomId; + + if (!roomId) { + return state; + } + + const chatting = state.chattings.entities[roomId] || {}; + let trgtChatting: Chatting = { + roomId, + + eventListProcessing: false, + eventList: adapterEventList.getInitialState(), + eventStatus: null, + remainEvent: false, + + fileInfoListProcessing: false, + fileInfoList: adapterFileInfoList.getInitialState(), + fileInfoCheckList: adapterFileInfoCheckList.getInitialState(), + fileInfoSyncDate: '', + ...chatting + }; + + const fileInfoList = action.fileInfoList; + const fileInfoCheckList = action.fileInfoCheckList; + + trgtChatting = { + ...trgtChatting, + fileInfoList: !!fileInfoList + ? adapterFileInfoList.upsertMany(fileInfoList, { + ...trgtChatting.fileInfoList + }) + : trgtChatting.fileInfoList, + fileInfoCheckList: !!fileInfoCheckList + ? adapterFileInfoCheckList.upsertMany(fileInfoCheckList, { + ...trgtChatting.fileInfoCheckList + }) + : trgtChatting.fileInfoCheckList, + fileInfoListProcessing: false + }; + + return { + ...state, + chattings: adapterChatting.upsertOne(trgtChatting, { + ...state.chattings + }) + }; + }), + + on(fileInfosFailure, (state, action) => { + const roomId = action.roomId; + + const chatting = state.chattings.entities[roomId]; + let trgtChatting: Chatting; + if (!!chatting) { + trgtChatting = { + ...chatting, + fileInfoListProcessing: false + }; + } + + return { + ...state, + chattings: adapterChatting.upsertOne(trgtChatting, { + ...state.chattings + }) + }; + }) +); diff --git a/projects/store-chat/src/lib/store/chatting/state.ts b/projects/store-chat/src/lib/store/chatting/state.ts index 13d072d..a5cc03e 100644 --- a/projects/store-chat/src/lib/store/chatting/state.ts +++ b/projects/store-chat/src/lib/store/chatting/state.ts @@ -10,19 +10,19 @@ export interface FileInfoListState extends EntityState {} export interface FileInfoCheckListState extends EntityState {} export const adapterEventList = createEntityAdapter>({ - selectId: info => info.seq, + selectId: (info) => info.seq, sortComparer: (a, b) => { return a.seq - b.seq; } }); export const adapterFileInfoList = createEntityAdapter({ - selectId: info => info.seq, + selectId: (info) => info.seq, sortComparer: (a, b) => { return b.seq - a.seq; } }); export const adapterFileInfoCheckList = createEntityAdapter({ - selectId: info => info.seq, + selectId: (info) => info.seq, sortComparer: (a, b) => { return b.seq - a.seq; } @@ -65,7 +65,7 @@ export interface Chatting { eventListProcessing?: boolean; eventList?: EventListState; eventStatus?: InfoResponse | null; - remainEvent?: false; + remainEvent?: boolean; fileInfoListProcessing?: boolean; fileInfoList?: FileInfoListState; @@ -76,9 +76,11 @@ export interface Chatting { export interface ChattingState extends EntityState {} export const adapterChatting = createEntityAdapter({ - selectId: chatting => chatting.roomId + selectId: (chatting) => chatting.roomId }); +const chattingInitialState: ChattingState = adapterChatting.getInitialState({}); + const { selectAll: selectAllForChatting, selectEntities: selectEntitiesForChatting, @@ -86,26 +88,14 @@ const { selectTotal: selectTotalForChatting } = adapterChatting.getSelectors(); -const chattingInitialState: ChattingState = adapterChatting.getInitialState({ - roomId: undefined, - - eventListProcessing: false, - eventList: eventListInitialState, - eventStatus: undefined, - remainEvent: false, - - fileInfoListProcessing: false, - fileInfoList: fileInfoListInitialState, - fileInfoCheckList: fileInfoCheckListInitialState, - fileInfoSyncDate: undefined -}); - export interface State { chattings: ChattingState; + activeRoomId: string | null; } export const initialState: State = { - chattings: chattingInitialState + chattings: chattingInitialState, + activeRoomId: null }; export function selectors(selector: Selector) { @@ -115,46 +105,55 @@ export function selectors(selector: Selector) { ); const selectChatting = createSelector( - selector, - selectEntitiesForChatting, - (state: State, entities: Dictionary, roomId: string) => - entities && entities[roomId] + selectChattings, + (state: ChattingState, roomId: string) => { + return state.entities && state.entities[roomId]; + } ); const selectChattingEventListProcessing = createSelector( selectChatting, - state => state.eventListProcessing + (state) => state.eventListProcessing ); const selectChattingEventList = createSelector( - selectChatting, - state => state.eventList + selectChattings, + (state: ChattingState, roomId: string) => { + const chatting = state.entities && state.entities[roomId]; + if (!!chatting) { + return chatting?.eventList; + } else { + return adapterEventList.getInitialState(); + } + } ); const selectChattingEventStatus = createSelector( selectChatting, - state => state.eventStatus + (state) => state.eventStatus ); const selectChattingRemainEvent = createSelector( selectChatting, - state => state.remainEvent + (state) => state.remainEvent ); const selectChattingFileInfoListProcessing = createSelector( selectChatting, - state => state.fileInfoListProcessing + (state) => state.fileInfoListProcessing ); const selectChattingFileInfoList = createSelector( selectChatting, - state => state.fileInfoList + (state) => state.fileInfoList ); const selectChattingFileInfoCheckList = createSelector( selectChatting, - state => state.fileInfoCheckList + (state) => state.fileInfoCheckList ); const selectChattingFileInfoSyncDate = createSelector( selectChatting, - state => state.fileInfoSyncDate + (state) => state.fileInfoSyncDate ); return { + activeRoomId: createSelector(selector, (state) => state.activeRoomId), + chattings: createSelector(selectChattings, selectAllForChatting), chatting: selectChatting, diff --git a/projects/store-chat/src/lib/store/room/actions.ts b/projects/store-chat/src/lib/store/room/actions.ts index 56780c6..8f70ad3 100644 --- a/projects/store-chat/src/lib/store/room/actions.ts +++ b/projects/store-chat/src/lib/store/room/actions.ts @@ -26,6 +26,21 @@ import { UserInfoShort } from '@ucap/protocol-room'; +/** + * retrieve selected Room. + */ +export const selectedRoom = createAction( + '[ucap::chat::selectedRoom] selected room', + props<{ roomId: string; localeCode: LocaleCode }>() +); +/** + * clear selected Room. + */ +export const clearSelectedRoom = createAction( + '[ucap::chat::clearSelectedRoom] clear Selected Room', + props<{ roomId: string }>() +); + /** * retrieve list of room information and list of user information per room */ diff --git a/projects/store-chat/src/lib/store/room/effects.ts b/projects/store-chat/src/lib/store/room/effects.ts index ae3ded9..af07dd6 100644 --- a/projects/store-chat/src/lib/store/room/effects.ts +++ b/projects/store-chat/src/lib/store/room/effects.ts @@ -4,7 +4,9 @@ import { map, switchMap, exhaustMap, - withLatestFrom + withLatestFrom, + tap, + debounceTime } from 'rxjs/operators'; import { Injectable } from '@angular/core'; @@ -21,7 +23,8 @@ import { UpdateResponse, InviteResponse, ExitForcingResponse, - UpdateTimerSetResponse + UpdateTimerSetResponse, + InfoRequest } from '@ucap/protocol-room'; import { RoomProtocolService } from '@ucap/ng-protocol-room'; @@ -73,7 +76,8 @@ import { rooms2Failure, delMulti, delMultiSuccess, - delMultiFailure + delMultiFailure, + selectedRoom } from './actions'; @Injectable() @@ -85,6 +89,29 @@ export class Effects { ); }); + selectedRoom$ = createEffect( + () => { + return this.actions$.pipe( + ofType(selectedRoom), + debounceTime(300), + tap((action) => { + const req: InfoRequest = { + ...action, + isDetail: false + }; + + console.log(req); + + // retrieve room info + this.store.dispatch(room({ req })); + + // retrieve event info >> chatting.effect.selectedRoom$ + }) + ); + }, + { dispatch: false } + ); + rooms$ = createEffect(() => { return this.actions$.pipe( ofType(rooms), diff --git a/projects/store-chat/src/lib/store/room/reducers.ts b/projects/store-chat/src/lib/store/room/reducers.ts index 7a2b2b2..44174c1 100644 --- a/projects/store-chat/src/lib/store/room/reducers.ts +++ b/projects/store-chat/src/lib/store/room/reducers.ts @@ -26,6 +26,7 @@ import { delMultiSuccess, updateSuccess } from './actions'; +import { userInfo } from 'os'; export const reducer = createReducer( initialState, @@ -214,7 +215,9 @@ export const reducer = createReducer( return { ...state, rooms: adapterRoom.removeOne(roomId, { ...state.rooms }), - roomUsers: adapterRoomUser.removeOne(roomId, { ...state.roomUsers }), + roomUsers: adapterRoomUser.removeOne(roomId, { + ...state.roomUsers + }), roomUsersShort: adapterRoomUserShort.removeOne(roomId, { ...state.roomUsersShort }) @@ -231,10 +234,72 @@ export const reducer = createReducer( return { ...state, rooms: adapterRoom.removeMany(roomIds, { ...state.rooms }), - roomUsers: adapterRoomUser.removeMany(roomIds, { ...state.roomUsers }), + roomUsers: adapterRoomUser.removeMany(roomIds, { + ...state.roomUsers + }), roomUsersShort: adapterRoomUserShort.removeMany(roomIds, { ...state.roomUsersShort }) }; + }), + + /** + * [Chatting Action watching.] + */ + on(chattingActions.readSuccess, (state, action) => { + const roomId = action.roomId; + const trgtUserSeq = action.SENDER_SEQ; + + if (!roomId || !trgtUserSeq) { + return state; + } + + let roomUser: RoomUserMap = state.roomUsers.entities[roomId]; + if (!!roomUser) { + roomUser = { + ...roomUser, + userInfos: state.roomUsers.entities[roomId].userInfos.map( + (roomUserInfo) => { + if (roomUserInfo.seq === Number(trgtUserSeq)) { + return { + ...roomUserInfo, + lastReadEventSeq: action.lastReadSeq + }; + } else { + return roomUserInfo; + } + } + ) + }; + } + let roomUserShort: RoomUserShortMap = state.roomUsersShort.entities[roomId]; + if (!!roomUserShort) { + roomUserShort = { + ...roomUserShort, + userInfos: state.roomUsersShort.entities[roomId].userInfos.map( + (roomUserInfo) => { + if (roomUserInfo.seq === Number(trgtUserSeq)) { + return { ...roomUserInfo, lastReadEventSeq: action.lastReadSeq }; + } else { + return roomUserInfo; + } + } + ) + }; + } + + return { + ...state, + roomUsers: !!roomUser + ? adapterRoomUser.upsertOne(roomUser, { + ...state.roomUsers + }) + : state.roomUsers, + roomUsersShort: !!roomUserShort + ? adapterRoomUserShort.upsertOne(roomUserShort, { + ...state.roomUsersShort + }) + : state.roomUsersShort + }; }) ); diff --git a/projects/store-chat/src/lib/store/room/state.ts b/projects/store-chat/src/lib/store/room/state.ts index c45ee79..8402240 100644 --- a/projects/store-chat/src/lib/store/room/state.ts +++ b/projects/store-chat/src/lib/store/room/state.ts @@ -101,9 +101,9 @@ export function selectors(selector: Selector) { rooms: createSelector(selectRooms, selectAllForRoom), room: createSelector( selectRooms, - selectEntitiesForRoom, - (roomState: RoomState, entities: Dictionary, roomId: string) => - entities && entities[roomId] + (roomState: RoomState, roomId: string) => { + return roomState.entities && roomState.entities[roomId]; + } ), roomsSyncDate: createSelector( selectRooms, @@ -112,12 +112,9 @@ export function selectors(selector: Selector) { roomUsers: createSelector(selectRoomUsers, selectAllForRoomUser), roomUser: createSelector( selectRoomUsers, - selectEntitiesForRoomUser, - ( - roomUserState: RoomUserState, - entities: Dictionary, - roomId: string - ) => entities && entities[roomId] + (roomUserState: RoomUserState, roomId: string) => { + return roomUserState.entities && roomUserState.entities[roomId]; + } ), roomUsersShort: createSelector( selectRoomUsersShort, @@ -125,12 +122,11 @@ export function selectors(selector: Selector) { ), roomUserShort: createSelector( selectRoomUsersShort, - selectEntitiesForRoomUserShort, - ( - roomUserShortState: RoomUserShortState, - entities: Dictionary, - roomId: string - ) => entities && entities[roomId] + (roomUserShortState: RoomUserShortState, roomId: string) => { + return ( + roomUserShortState.entities && roomUserShortState.entities[roomId] + ); + } ), unreadTotal: createSelector( selectRooms, diff --git a/projects/store-group/ng-package.json b/projects/store-group/ng-package.json index 4396113..5679a33 100644 --- a/projects/store-group/ng-package.json +++ b/projects/store-group/ng-package.json @@ -14,9 +14,11 @@ "@ucap/protocol-group": "@ucap/protocol-group", "@ucap/protocol-buddy": "@ucap/protocol-buddy", "@ucap/protocol-query": "@ucap/protocol-query", + "@ucap/protocol-info": "@ucap/protocol-info", "@ucap/ng-protocol-buddy": "@ucap/ng-protocol-buddy", "@ucap/ng-protocol-group": "@ucap/ng-protocol-group", "@ucap/ng-protocol-sync": "@ucap/ng-protocol-sync", + "@ucap/ng-protocol-info": "@ucap/ng-protocol-info", "@ucap/ng-store-organization": "@ucap/ng-store-organization", "@ucap/ng-store-authentication": "@ucap/ng-store-authentication" } diff --git a/projects/store-group/package.json b/projects/store-group/package.json index f7e089f..86133cc 100644 --- a/projects/store-group/package.json +++ b/projects/store-group/package.json @@ -1,6 +1,6 @@ { "name": "@ucap/ng-store-group", - "version": "0.0.9", + "version": "0.0.14", "publishConfig": { "registry": "https://nexus.loafle.net/repository/npm-ucap/" }, @@ -12,11 +12,13 @@ "@ucap/protocol-group": "~0.0.1", "@ucap/protocol-query": "~0.0.1", "@ucap/protocol-sync": "~0.0.1", + "@ucap/protocol-info": "~0.0.1", "@ucap/ng-protocol-buddy": "~0.0.1", "@ucap/ng-protocol-group": "~0.0.1", "@ucap/ng-protocol-sync": "~0.0.1", "@ucap/ng-store-organization": "~0.0.1", "@ucap/ng-store-authentication": "~0.0.1", + "@ucap/ng-protocol-info": "~0.0.1", "tslib": "^1.10.0" } } diff --git a/projects/store-group/src/lib/store/buddy/actions.ts b/projects/store-group/src/lib/store/buddy/actions.ts index 6530c4b..dfef27a 100644 --- a/projects/store-group/src/lib/store/buddy/actions.ts +++ b/projects/store-group/src/lib/store/buddy/actions.ts @@ -9,6 +9,10 @@ import { UpdateRequest as BuddyUpdateRequest, UpdateResponse as BuddyUpdateResponse } from '@ucap/protocol-buddy'; +import { + UserNicknameRequest as NicknameRequest, + UserNicknameResponse as NicknameResponse +} from '@ucap/protocol-info'; /** * retrieve list of buddy @@ -116,3 +120,25 @@ export const updateFailure = createAction( '[ucap::group::buddy] update Failure', props<{ error: any }>() ); + +/** + * 동료 닉네임 변경 + */ +export const nickname = createAction( + '[ucap::group::buddy] user nickname', + props<{ req: NicknameRequest }>() +); +/** + * Success of update request + */ +export const nicknameSuccess = createAction( + '[ucap::group::buddy] user nickname Success', + props<{ res: NicknameResponse }>() +); +/** + * Failure of update request + */ +export const nicknameFailure = createAction( + '[ucap::group::buddy] user nickname Failure', + props<{ error: any }>() +); diff --git a/projects/store-group/src/lib/store/buddy/effects.ts b/projects/store-group/src/lib/store/buddy/effects.ts index 132382f..2a561fa 100644 --- a/projects/store-group/src/lib/store/buddy/effects.ts +++ b/projects/store-group/src/lib/store/buddy/effects.ts @@ -19,6 +19,11 @@ import { UpdateResponse as BuddyUpdateResponse } from '@ucap/protocol-buddy'; +import { + UserNicknameRequest as NicknameRequest, + UserNicknameResponse as NicknameResponse +} from '@ucap/protocol-info'; + import { SyncProtocolService } from '@ucap/ng-protocol-sync'; import { BuddyProtocolService } from '@ucap/ng-protocol-buddy'; @@ -43,6 +48,9 @@ import { update, updateSuccess, updateFailure, + nickname, + nicknameSuccess, + nicknameFailure, delAndClear } from './actions'; @@ -50,6 +58,7 @@ import { BuddySelector, GroupSelector } from '../state'; import { ModuleConfig } from '../../config/module-config'; import { _MODULE_CONFIG } from '../../config/token'; +import { InfoProtocolService } from '@ucap/ng-protocol-info'; @Injectable() export class Effects { @@ -126,7 +135,7 @@ export class Effects { ), tap(([req, groupList, myDeptUserList]) => { for (const group of groupList) { - if (group.userSeqs.indexOf(String(req.seq)) > -1) { + if (group.userSeqs.indexOf(req.seq as any) > -1) { // 소속부서(내부서) 고정그룹 사용시 소속부서원을 삭제하지 않는다. if ( !!this.moduleConfig.useMyDeptGroup && @@ -145,7 +154,7 @@ export class Effects { groupSeq: group.seq, groupName: group.name, userSeqs: group.userSeqs.filter( - (userSeq) => userSeq !== String(req.seq) + (userSeq) => userSeq !== (req.seq as any) ) } }) @@ -158,8 +167,9 @@ export class Effects { if ( !!this.moduleConfig.useMyDeptGroup && this.moduleConfig.useMyDeptGroup && + !!myDeptUserList && myDeptUserList.filter( - (deptUser) => deptUser.seq === String(req.seq) + (deptUser) => deptUser.seq === (req.seq as any) ).length > 0 ) { // skip;; @@ -198,6 +208,21 @@ export class Effects { ) ); + nickname$ = createEffect(() => + this.actions$.pipe( + ofType(nickname), + map((action) => action.req), + exhaustMap((req) => + this.infoProtocolService.userNickname(req).pipe( + map((res: NicknameResponse) => { + return nicknameSuccess({ res }); + }), + catchError((error) => of(nicknameFailure({ error }))) + ) + ) + ) + ); + groupCreateSuccess$ = createEffect( () => { return this.actions$.pipe( @@ -215,7 +240,7 @@ export class Effects { } const index = buddyList.findIndex( - (b) => String(b.seq) === userSeq + (b) => b.seq === Number(userSeq) ); if (-1 < index) { addBuddyList.push(userSeq); @@ -251,7 +276,7 @@ export class Effects { } const index = buddyList.findIndex( - (b) => String(b.seq) === userSeq + (b) => b.seq === Number(userSeq) ); if (-1 < index) { addBuddyList.push(userSeq); @@ -284,6 +309,7 @@ export class Effects { private store: Store, @Inject(_MODULE_CONFIG) private moduleConfig: ModuleConfig, private syncProtocolService: SyncProtocolService, - private buddyProtocolService: BuddyProtocolService + private buddyProtocolService: BuddyProtocolService, + private infoProtocolService: InfoProtocolService ) {} } diff --git a/projects/store-group/src/lib/store/buddy/reducers.ts b/projects/store-group/src/lib/store/buddy/reducers.ts index 6539566..84ebf9b 100644 --- a/projects/store-group/src/lib/store/buddy/reducers.ts +++ b/projects/store-group/src/lib/store/buddy/reducers.ts @@ -3,7 +3,12 @@ import { createReducer, on } from '@ngrx/store'; import { UserInfo } from '@ucap/protocol-sync'; import { initialState, adapterBuddy } from './state'; -import { buddy2Success, delSuccess, updateSuccess } from './actions'; +import { + buddy2Success, + delSuccess, + updateSuccess, + nicknameSuccess +} from './actions'; export const reducer = createReducer( initialState, @@ -34,6 +39,19 @@ export const reducer = createReducer( isFavorit: res.isFavorit }; + return { + ...state, + buddies: adapterBuddy.upsertOne(userInfo, { ...state.buddies }) + }; + }), + + on(nicknameSuccess, (state, action) => { + const res = action.res; + const userInfo: UserInfo = { + ...state.buddies.entities[res.userSeq], + nickName: res.nickname + }; + return { ...state, buddies: adapterBuddy.upsertOne(userInfo, { ...state.buddies }) diff --git a/projects/store-group/src/lib/store/group/effects.ts b/projects/store-group/src/lib/store/group/effects.ts index 880e526..39af7f4 100644 --- a/projects/store-group/src/lib/store/group/effects.ts +++ b/projects/store-group/src/lib/store/group/effects.ts @@ -128,69 +128,68 @@ export class Effects { ) ); - updateMember$ = createEffect( - () => { - return this.actions$.pipe( - ofType(updateMember), - withLatestFrom( - this.store.pipe(select(GroupSelector.groups)), - this.store.pipe(select(DepartmentSelector.myDepartmentUserInfoList)) // 내 부서원 비교. - ), - switchMap(([action, groupList, myDeptUserList]) => { - const targetGroup = action.targetGroup; - const targetUserSeqs = action.targetUserSeqs; + updateMember$ = createEffect(() => { + return this.actions$.pipe( + ofType(updateMember), + withLatestFrom( + this.store.pipe(select(GroupSelector.groups)), + this.store.pipe(select(DepartmentSelector.myDepartmentUserInfoList)) // 내 부서원 비교. + ), + switchMap(([action, groupList, myDeptUserList]) => { + const targetGroup = action.targetGroup; + const targetUserSeqs = action.targetUserSeqs as any; - // Del Buddy - let userSeqsForDelete: string[] = targetGroup.userSeqs.filter( - (v) => targetUserSeqs.indexOf(v) < 0 + // Del Buddy + let userSeqsForDelete: string[] = targetGroup.userSeqs.filter( + (v) => targetUserSeqs.indexOf(v + '') < 0 + ); + + // 소속부서(내부서) 고정그룹 사용시 소속부서원을 삭제하지 않는다. + if ( + !!this.moduleConfig.useMyDeptGroup && + this.moduleConfig.useMyDeptGroup && + !!myDeptUserList && + myDeptUserList.length > 0 + ) { + userSeqsForDelete = userSeqsForDelete.filter( + (delbuddy) => + myDeptUserList.filter((deptUser) => deptUser.seq === delbuddy) + .length === 0 ); + } + userSeqsForDelete = userSeqsForDelete.filter((delbuddy) => { + let exist = false; - // 소속부서(내부서) 고정그룹 사용시 소속부서원을 삭제하지 않는다. - if ( - !!this.moduleConfig.useMyDeptGroup && - this.moduleConfig.useMyDeptGroup - ) { - userSeqsForDelete = userSeqsForDelete.filter( - (delbuddy) => - myDeptUserList.filter((deptUser) => deptUser.seq === delbuddy) - .length === 0 - ); - } - userSeqsForDelete = userSeqsForDelete.filter((delbuddy) => { - let exist = false; - - for (const group of groupList) { - if ( - group.seq !== targetGroup.seq && - group.userSeqs.filter((v) => v === delbuddy).length > 0 - ) { - exist = true; - break; - } + for (const group of groupList) { + if ( + group.seq !== targetGroup.seq && + group.userSeqs.filter((v) => v === delbuddy).length > 0 + ) { + exist = true; + break; } + } - return !exist; - }); + return !exist; + }); - return [ - update({ - req: { - groupSeq: targetGroup.seq, - groupName: targetGroup.name, - userSeqs: targetUserSeqs - } - }), - updateMemberSuccess({ - targetGroup, - targetUserSeqs, - userSeqsForDelete - }) - ]; - }) - ); - }, - { dispatch: false } - ); + return [ + update({ + req: { + groupSeq: targetGroup.seq, + groupName: targetGroup.name, + userSeqs: targetUserSeqs + } + }), + updateMemberSuccess({ + targetGroup, + targetUserSeqs, + userSeqsForDelete + }) + ]; + }) + ); + }); moveMember$ = createEffect(() => this.actions$.pipe( diff --git a/projects/ui-authentication/ng-package.json b/projects/ui-authentication/ng-package.json index 29fe59a..a9fdb60 100644 --- a/projects/ui-authentication/ng-package.json +++ b/projects/ui-authentication/ng-package.json @@ -3,6 +3,7 @@ "dest": "../../dist/ui-authentication", "lib": { "entryFile": "src/public-api.ts", + "styleIncludePaths": ["./src/assets/scss"], "umdModuleIds": { "moment": "moment", "@ucap/pi": "@ucap/pi", diff --git a/projects/ui-authentication/package.json b/projects/ui-authentication/package.json index 7b0f7f5..d8a2712 100644 --- a/projects/ui-authentication/package.json +++ b/projects/ui-authentication/package.json @@ -1,6 +1,6 @@ { "name": "@ucap/ng-ui-authentication", - "version": "0.0.20", + "version": "0.0.24", "publishConfig": { "registry": "https://nexus.loafle.net/repository/npm-ucap/" }, @@ -10,9 +10,10 @@ "@angular/core": "^9.0.2", "@angular/material": "^9.0.0", "@ucap/core": "~0.0.1", - "@ucap/uc-scss": "~0.0.1", + "@ucap/ui-scss": "~0.0.1", "@ucap/ng-i18n": "~0.0.1", "@ucap/ng-ui": "~0.0.1", + "@ucap/ng-ui-material": "~0.0.1", "tslib": "^1.10.0" } } diff --git a/projects/ui-authentication/scss-bundle.config.json b/projects/ui-authentication/scss-bundle.config.json new file mode 100644 index 0000000..8f3861a --- /dev/null +++ b/projects/ui-authentication/scss-bundle.config.json @@ -0,0 +1,11 @@ +{ + "bundlerOptions": { + "entryFile": "./projects/ui-authentication/src/assets/scss/_theme.scss", + "rootDir": "./projects/ui-authentication/src/assets/scss/", + "outFile": "./dist/ui-authentication/_theme.scss", + "dedupeGlobs": [], + "includePaths": [], + "ignoreImports": ["~@ucap/.*", "~@angular/.*"], + "logLevel": "silent" + } +} diff --git a/projects/ui-authentication/src/assets/scss/_theme.scss b/projects/ui-authentication/src/assets/scss/_theme.scss new file mode 100644 index 0000000..1be06c2 --- /dev/null +++ b/projects/ui-authentication/src/assets/scss/_theme.scss @@ -0,0 +1,2 @@ +@import '../../lib/components/change-password.component.theme.scss'; +@import '../../lib/components/login.component.theme.scss'; diff --git a/projects/ui-authentication/src/lib/components/change-password.component.scss b/projects/ui-authentication/src/lib/components/change-password.component.scss index b8e7250..bfc264c 100644 --- a/projects/ui-authentication/src/lib/components/change-password.component.scss +++ b/projects/ui-authentication/src/lib/components/change-password.component.scss @@ -30,8 +30,11 @@ } .separator { - font-size: 15px; - font-weight: 600; + font: { + size: 15px; + weight: 600; + } + margin: 24px auto; position: relative; overflow: hidden; diff --git a/projects/ui-authentication/src/lib/components/change-password.component.stories.ts b/projects/ui-authentication/src/lib/components/change-password.component.stories.ts index 0f1f78c..2c8e828 100644 --- a/projects/ui-authentication/src/lib/components/change-password.component.stories.ts +++ b/projects/ui-authentication/src/lib/components/change-password.component.stories.ts @@ -2,58 +2,17 @@ import { moduleMetadata } from '@storybook/angular'; import { action } from '@storybook/addon-actions'; import { linkTo } from '@storybook/addon-links'; -import { ChangePasswordComponent } from './change-password.component'; -import { AuthenticationUiModule } from '../authentication-ui.module'; -import { FormBuilder, ReactiveFormsModule } from '@angular/forms'; -import { ChangeDetectorRef } from '@angular/core'; -import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; import { BrowserModule } from '@angular/platform-browser'; -import { CommonModule } from '@angular/common'; -import { MatButtonModule } from '@angular/material/button'; -import { MatCheckboxModule } from '@angular/material/checkbox'; -import { MatFormFieldModule } from '@angular/material/form-field'; -import { MatIconModule } from '@angular/material/icon'; -import { MatInputModule } from '@angular/material/input'; -import { MatProgressSpinnerModule } from '@angular/material/progress-spinner'; -import { MatSelectModule } from '@angular/material/select'; -import { I18nService, UCAP_I18N_NAMESPACE, I18nModule } from '@ucap/ng-i18n'; -import { LogService } from '@ucap/logger'; -import { Company } from '@ucap/api-external'; +import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; -export default { - title: 'ChangePasswordComponent', - decorators: [ - moduleMetadata({ - imports: [ - BrowserModule, - BrowserAnimationsModule, +import { FormBuilder } from '@angular/forms'; - CommonModule, - ReactiveFormsModule, +import { LogService } from '@ucap/ng-logger'; +import { I18nService, UCAP_I18N_NAMESPACE } from '@ucap/ng-i18n'; - MatButtonModule, - MatCheckboxModule, - MatFormFieldModule, - MatIconModule, - MatInputModule, - MatProgressSpinnerModule, - MatSelectModule, +import { AuthenticationUiModule } from '../authentication-ui.module'; - I18nModule - ], - providers: [ - AuthenticationUiModule, - { provide: FormBuilder, useValue: new FormBuilder() }, - { provide: I18nService, useValue: new I18nService(new LogService({})) }, - { - provide: UCAP_I18N_NAMESPACE, - useValue: 'authentication' - } - ] - }) - ], - excludeStories: /.*Data$/ -}; +import { ChangePasswordComponent } from './change-password.component'; export const actionsData = { changePassword: action('changePassword') @@ -61,6 +20,25 @@ export const actionsData = { export const inputData = {}; +export default { + title: 'ui-authentication::ChangePasswordComponent', + component: ChangePasswordComponent, + decorators: [ + moduleMetadata({ + imports: [BrowserModule, BrowserAnimationsModule, AuthenticationUiModule], + providers: [ + { provide: FormBuilder, useClass: FormBuilder }, + { provide: LogService, useValue: new LogService({}) }, + { provide: I18nService, useClass: I18nService }, + { + provide: UCAP_I18N_NAMESPACE, + useValue: 'authentication' + } + ] + }) + ] +}; + export const Default = () => ({ component: ChangePasswordComponent, props: { diff --git a/projects/ui-authentication/src/lib/components/change-password.component.theme.scss b/projects/ui-authentication/src/lib/components/change-password.component.theme.scss new file mode 100644 index 0000000..45a8bfd --- /dev/null +++ b/projects/ui-authentication/src/lib/components/change-password.component.theme.scss @@ -0,0 +1,20 @@ +@import '~@ucap/ng-ui-material/material'; + +@mixin ucap-authentication-change-password-theme($theme) { + $is-dark-theme: map-get($theme, is-dark); + $primary: map-get($theme, primary); + $accent: map-get($theme, accent); + $warn: map-get($theme, warn); + $background: map-get($theme, background); + $foreground: map-get($theme, foreground); + + .ucap-authentication-change-password-container { + border-color: mat-color($foreground, secondary-text); + } +} + +@mixin ucap-authentication-change-password-typography($config) { + .ucap-authentication-change-password-container { + font-family: mat-font-family($config); + } +} diff --git a/projects/ui-authentication/src/lib/components/login.component.scss b/projects/ui-authentication/src/lib/components/login.component.scss index 4725c2a..93956ea 100644 --- a/projects/ui-authentication/src/lib/components/login.component.scss +++ b/projects/ui-authentication/src/lib/components/login.component.scss @@ -1,4 +1,4 @@ -@import '~@ucap/ui-scss/ucap'; +@import '~@ucap/ng-ui-material/material'; .ucap-authentication-login-container { top: 0; @@ -9,7 +9,9 @@ background-color: rgba(255, 255, 255, 1); border-radius: 0px; - font-size: 14px; + font: { + size: 14px; + } text-align: center; @@ -52,7 +54,9 @@ display: block; border-radius: 0; line-height: 50px; - font-size: 1.1em; + font: { + size: 1.1em; + } } } } diff --git a/projects/ui-authentication/src/lib/components/login.component.stories.ts b/projects/ui-authentication/src/lib/components/login.component.stories.ts index 0e854db..8fbcb91 100644 --- a/projects/ui-authentication/src/lib/components/login.component.stories.ts +++ b/projects/ui-authentication/src/lib/components/login.component.stories.ts @@ -5,40 +5,42 @@ import { linkTo } from '@storybook/addon-links'; import { BrowserModule } from '@angular/platform-browser'; import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; -import { LogService } from '@ucap/logger'; import { Company } from '@ucap/api-external'; +import { LogService } from '@ucap/ng-logger'; import { I18nService, UCAP_I18N_NAMESPACE } from '@ucap/ng-i18n'; import { AuthenticationUiModule } from '../authentication-ui.module'; + import { LoginComponent } from './login.component'; +const actionsData = { + login: action('login') +}; + +const inputData = { + companyList: [ + { companyName: 'LG CNS', companyCode: 'GUC100' }, + { companyName: 'LG UCAP', companyCode: 'GUC101' } + ] as Company[] +}; + export default { - title: 'LoginComponent', + title: 'ui-authentication::LoginComponent', + component: LoginComponent, decorators: [ moduleMetadata({ imports: [BrowserModule, BrowserAnimationsModule, AuthenticationUiModule], providers: [ - { provide: I18nService, useValue: new I18nService(new LogService({})) }, + { provide: LogService, useValue: new LogService({}) }, + { provide: I18nService, useClass: I18nService }, { provide: UCAP_I18N_NAMESPACE, useValue: 'authentication' } ] }) - ], - excludeStories: /.*Data$/ -}; - -export const actionsData = { - login: action('login') -}; - -export const inputData = { - companyList: [ - { companyName: 'LG CNS', companyCode: 'GUC100' }, - { companyName: 'LG UCAP', companyCode: 'GUC101' } - ] as Company[] + ] }; export const Default = () => ({ @@ -55,7 +57,6 @@ export const InputContents = () => ({ companyList: inputData.companyList, companyCode: 'GUC100', loginId: 'test-loginid', - // loginPw: '111111', login: actionsData.login } }); diff --git a/projects/ui-authentication/src/lib/components/login.component.theme.scss b/projects/ui-authentication/src/lib/components/login.component.theme.scss new file mode 100644 index 0000000..ec75c7a --- /dev/null +++ b/projects/ui-authentication/src/lib/components/login.component.theme.scss @@ -0,0 +1,20 @@ +@import '~@ucap/ng-ui-material/material'; + +@mixin ucap-authentication-login-theme($theme) { + $is-dark-theme: map-get($theme, is-dark); + $primary: map-get($theme, primary); + $accent: map-get($theme, accent); + $warn: map-get($theme, warn); + $background: map-get($theme, background); + $foreground: map-get($theme, foreground); + + .ucap-authentication-login-container { + border-color: mat-color($foreground, secondary-text); + } +} + +@mixin ucap-authentication-login-typography($config) { + .ucap-authentication-login-container { + font-family: mat-font-family($config); + } +} diff --git a/projects/ui-chat/ng-package.json b/projects/ui-chat/ng-package.json index 11948c6..b98dadd 100644 --- a/projects/ui-chat/ng-package.json +++ b/projects/ui-chat/ng-package.json @@ -3,11 +3,13 @@ "dest": "../../dist/ui-chat", "lib": { "entryFile": "src/public-api.ts", + "styleIncludePaths": ["./src/assets/scss"], "umdModuleIds": { "ngx-perfect-scrollbar": "ngx-perfect-scrollbar", "@ucap/core": "@ucap/core", "@ucap/protocol-room": "@ucap/protocol-room", "@ucap/ng-logger": "@ucap/ng-logger", + "@ucap/ng-i18n": "@ucap/ng-i18n", "@ucap/ng-ui": "@ucap/ng-ui" } } diff --git a/projects/ui-chat/package.json b/projects/ui-chat/package.json index ba74523..7f6f527 100644 --- a/projects/ui-chat/package.json +++ b/projects/ui-chat/package.json @@ -1,6 +1,6 @@ { "name": "@ucap/ng-ui-chat", - "version": "0.0.3", + "version": "0.0.9", "publishConfig": { "registry": "https://nexus.loafle.net/repository/npm-ucap/" }, @@ -11,8 +11,10 @@ "@angular/material": "^9.0.0", "@ucap/core": "~0.0.1", "@ucap/protocol-room": "~0.0.1", - "@ucap/uc-scss": "~0.0.1", + "@ucap/ui-scss": "~0.0.1", "@ucap/ng-ui": "~0.0.1", + "@ucap/ng-ui-material": "~0.0.1", + "@ucap/ng-ui-organization": "~0.0.1", "tslib": "^1.10.0" } } diff --git a/projects/ui-chat/scss-bundle.config.json b/projects/ui-chat/scss-bundle.config.json new file mode 100644 index 0000000..e6e0ada --- /dev/null +++ b/projects/ui-chat/scss-bundle.config.json @@ -0,0 +1,11 @@ +{ + "bundlerOptions": { + "entryFile": "./projects/ui-chat/src/assets/scss/_theme.scss", + "rootDir": "./projects/ui-chat/src/assets/scss/", + "outFile": "./dist/ui-chat/_theme.scss", + "dedupeGlobs": [], + "includePaths": [], + "ignoreImports": ["~@ucap/.*", "~@angular/.*"], + "logLevel": "silent" + } +} diff --git a/projects/ui-chat/src/assets/scss/_theme.scss b/projects/ui-chat/src/assets/scss/_theme.scss new file mode 100644 index 0000000..6f2172d --- /dev/null +++ b/projects/ui-chat/src/assets/scss/_theme.scss @@ -0,0 +1,2 @@ +@import '../../lib/components/room-expansion.component.theme.scss'; +@import '../../lib/components/room-list-item-01.component.theme.scss'; diff --git a/projects/ui-chat/src/lib/chat-ui.module.ts b/projects/ui-chat/src/lib/chat-ui.module.ts index 7669d28..39a0559 100644 --- a/projects/ui-chat/src/lib/chat-ui.module.ts +++ b/projects/ui-chat/src/lib/chat-ui.module.ts @@ -28,8 +28,48 @@ import { RoomExpansionNodeDirective } from './components/room-expansion.component'; import { RoomListItem01Component } from './components/room-list-item-01.component'; +import { InformationComponent } from './components/message-box/information.component'; +import { TextComponent } from './components/message-box/text.component'; +import { FileComponent } from './components/message-box/file.component'; +import { AttachFileComponent } from './components/message-box/attach-file.component'; +import { ImageComponent } from './components/message-box/image.component'; +import { VideoComponent } from './components/message-box/video.component'; +import { StickerComponent } from './components/message-box/sticker.component'; +import { MassComponent } from './components/message-box/mass.component'; +import { ScheduleComponent } from './components/message-box/schedule.component'; +import { VideoConferenceComponent } from './components/message-box/video-conference.component'; +import { TranslationComponent } from './components/message-box/translation.component'; +import { MassTranslationComponent } from './components/message-box/mass-translation.component'; +import { RecallComponent } from './components/message-box/recall.component'; +import { ReadHereComponent } from './components/message-box/read-here.component'; +import { DateSplitterComponent } from './components/message-box/date-splitter.component'; +import { SmsComponent } from './components/message-box/sms.component'; +import { ReplyComponent } from './components/message-box/reply.component'; -const COMPONENTS = [RoomExpansionComponent, RoomListItem01Component]; +const COMPONENTS = [ + RoomExpansionComponent, + RoomListItem01Component, + + InformationComponent, + TextComponent, + FileComponent, + AttachFileComponent, + ImageComponent, + VideoComponent, + StickerComponent, + MassComponent, + ScheduleComponent, + VideoConferenceComponent, + TranslationComponent, + MassTranslationComponent, + RecallComponent, + + ReadHereComponent, + DateSplitterComponent, + + SmsComponent, + ReplyComponent +]; const DIALOGS = []; const PIPES = []; const DIRECTIVES = [RoomExpansionHeaderDirective, RoomExpansionNodeDirective]; diff --git a/projects/ui-chat/src/lib/components/message-box/attach-file.component.html b/projects/ui-chat/src/lib/components/message-box/attach-file.component.html new file mode 100644 index 0000000..3afaee4 --- /dev/null +++ b/projects/ui-chat/src/lib/components/message-box/attach-file.component.html @@ -0,0 +1,37 @@ +
+ + +
+
+
+
    +
  • + {{ fileInfo.fileName }} +
  • +
  • + {{ fileInfo.attachmentRegDate | ucapDate }} +
  • +
+
+
+
    +
  • + +
  • +
  • + +
  • +
  • + +
  • +
+
+
+ 프로그레스 영역 +
diff --git a/projects/ui-chat/src/lib/components/message-box/attach-file.component.scss b/projects/ui-chat/src/lib/components/message-box/attach-file.component.scss new file mode 100644 index 0000000..2aa05cb --- /dev/null +++ b/projects/ui-chat/src/lib/components/message-box/attach-file.component.scss @@ -0,0 +1,126 @@ +// $tablet-s-width: 768px; + +// .bubble-main { +// display: flex; +// flex-direction: row; +// padding: 14px; +// min-width: 300px; +// .file-img { +// display: inline-flex; +// width: 50px; +// height: 50px; +// float: left; +// margin-right: 14px; +// background-repeat: no-repeat; +// &.doc { +// background-image: url(/assets/images/file/icon_talk_doc.png); +// &.disable { +// background-image: url(/assets/images/file/icon_talk_doc_d.png); +// } +// } +// &.exe { +// background-image: url(/assets/images/file/icon_talk_exe.png); +// &.disable { +// background-image: url(/assets/images/file/icon_talk_exe_d.png); +// } +// } +// &.file { +// background-image: url(/assets/images/file/icon_talk_file.png); +// &.disable { +// background-image: url(/assets/images/file/icon_talk_file_d.png); +// } +// } +// &.hwp { +// background-image: url(/assets/images/file/icon_talk_hwp.png); +// &.disable { +// background-image: url(/assets/images/file/icon_talk_hwp_d.png); +// } +// } +// &.ppt, +// &.pptx { +// background-image: url(/assets/images/file/icon_talk_ppt.png); +// &.disable { +// background-image: url(/assets/images/file/icon_talk_ppt_d.png); +// } +// } +// &.xls, +// &.xlsm, +// &.xlsx { +// background-image: url(/assets/images/file/icon_talk_xls.png); +// &.disable { +// background-image: url(/assets/images/file/icon_talk_xls_d.png); +// } +// } +// &.zip { +// background-image: url(/assets/images/file/icon_talk_zip.png); +// &.disable { +// background-image: url(/assets/images/file/icon_talk_doc_d.png); +// } +// } +// } +// .file-info { +// display: inline-flex; +// flex-direction: column; +// text-align: left; +// float: left; +// line-height: 1.6em; +// .file-name { +// font-size: 1em; +// font-weight: bold; +// display: inline-flex; +// } +// .file-size { +// display: inline-flex; +// font-size: 11px; +// color: #666666; +// } +// .file-ext { +// font-size: 12px; +// color: #848d95; +// } +// } +// } +// .btn-box { +// width: 100%; +// height: 40px; +// border-top: 1px solid #dddddd; +// display: flex; +// width: 100%; +// text-align: center; +// font-size: 1em; +// ul { +// width: 100%; +// li { +// width: 50%; +// height: 100%; +// display: inline-block; +// text-align: center; +// align-items: center; +// border-right: 1px solid #dddddd; +// @media screen and (max-width: #{$tablet-s-width}) { +// width: 30%; +// } +// &:last-child { +// border-right: none; +// @media screen and (max-width: #{$tablet-s-width}) { +// width: 70%; +// } +// } +// .mat-button { +// width: 100%; +// display: block; +// height: 100%; +// font-size: 1em; +// } +// } +// &.expired { +// li { +// width: 100%; +// white-space: nowrap; +// color: #999999; +// align-items: center; +// line-height: 40px; +// } +// } +// } +// } diff --git a/projects/ui-chat/src/lib/components/message-box/attach-file.component.spec.ts b/projects/ui-chat/src/lib/components/message-box/attach-file.component.spec.ts new file mode 100644 index 0000000..3f9a97b --- /dev/null +++ b/projects/ui-chat/src/lib/components/message-box/attach-file.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 { AttachFileComponent } from './attach-file.component'; + +describe('AttachFileComponent', () => { + let component: AttachFileComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ AttachFileComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(AttachFileComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/projects/ui-chat/src/lib/components/message-box/attach-file.component.ts b/projects/ui-chat/src/lib/components/message-box/attach-file.component.ts new file mode 100644 index 0000000..df974ca --- /dev/null +++ b/projects/ui-chat/src/lib/components/message-box/attach-file.component.ts @@ -0,0 +1,35 @@ +import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core'; +import { FileEventJson } from '@ucap/protocol-event'; + +@Component({ + selector: 'ucap-chat-message-box-attach-file', + templateUrl: './attach-file.component.html', + styleUrls: ['./attach-file.component.scss'] +}) +export class AttachFileComponent implements OnInit { + @Input() + fileInfo: FileEventJson; + + @Input() + expired = false; + + @Output() + save = new EventEmitter(); + + @Output() + openViewer = new EventEmitter(); + + constructor() {} + + ngOnInit() {} + + onClickSave() { + this.save.emit('save'); + } + onClickSaveAs() { + this.save.emit('saveAs'); + } + onClickOpenViewer() { + this.openViewer.emit(); + } +} diff --git a/projects/ui-chat/src/lib/components/message-box/date-splitter.component.html b/projects/ui-chat/src/lib/components/message-box/date-splitter.component.html new file mode 100644 index 0000000..e7c0791 --- /dev/null +++ b/projects/ui-chat/src/lib/components/message-box/date-splitter.component.html @@ -0,0 +1,5 @@ +
+ {{ + this.message.sendDate | ucapDate: 'L dddd' + }} +
diff --git a/projects/ui-chat/src/lib/components/message-box/date-splitter.component.scss b/projects/ui-chat/src/lib/components/message-box/date-splitter.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/projects/ui-chat/src/lib/components/message-box/date-splitter.component.spec.ts b/projects/ui-chat/src/lib/components/message-box/date-splitter.component.spec.ts new file mode 100644 index 0000000..8a326da --- /dev/null +++ b/projects/ui-chat/src/lib/components/message-box/date-splitter.component.spec.ts @@ -0,0 +1,24 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { DateSplitterComponent } from './date-splitter.component'; + +describe('Chat::MessageBox::DateSplitterComponent', () => { + let component: DateSplitterComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [DateSplitterComponent] + }).compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(DateSplitterComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/projects/ui-chat/src/lib/components/message-box/date-splitter.component.ts b/projects/ui-chat/src/lib/components/message-box/date-splitter.component.ts new file mode 100644 index 0000000..a478df3 --- /dev/null +++ b/projects/ui-chat/src/lib/components/message-box/date-splitter.component.ts @@ -0,0 +1,16 @@ +import { Component, OnInit, Input } from '@angular/core'; +import { Info, EventJson } from '@ucap/protocol-event'; + +@Component({ + selector: 'ucap-chat-message-box-date-splitter', + templateUrl: './date-splitter.component.html', + styleUrls: ['./date-splitter.component.scss'] +}) +export class DateSplitterComponent implements OnInit { + @Input() + message: Info; + + constructor() {} + + ngOnInit() {} +} diff --git a/projects/ui-chat/src/lib/components/message-box/file.component.html b/projects/ui-chat/src/lib/components/message-box/file.component.html new file mode 100644 index 0000000..d1c63a8 --- /dev/null +++ b/projects/ui-chat/src/lib/components/message-box/file.component.html @@ -0,0 +1,41 @@ + + + + + + + + + + + + + diff --git a/projects/ui-chat/src/lib/components/message-box/file.component.scss b/projects/ui-chat/src/lib/components/message-box/file.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/projects/ui-chat/src/lib/components/message-box/file.component.spec.ts b/projects/ui-chat/src/lib/components/message-box/file.component.spec.ts new file mode 100644 index 0000000..2cde53a --- /dev/null +++ b/projects/ui-chat/src/lib/components/message-box/file.component.spec.ts @@ -0,0 +1,24 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { FileComponent } from './file.component'; + +describe('Chat::MessageBox::FileComponent', () => { + let component: FileComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [FileComponent] + }).compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(FileComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/projects/ui-chat/src/lib/components/message-box/file.component.ts b/projects/ui-chat/src/lib/components/message-box/file.component.ts new file mode 100644 index 0000000..6a37e17 --- /dev/null +++ b/projects/ui-chat/src/lib/components/message-box/file.component.ts @@ -0,0 +1,71 @@ +import { Component, OnInit, Output, Input, EventEmitter } from '@angular/core'; +import { FileType, Info, FileEventJson } from '@ucap/protocol-event'; +import { RoomInfo } from '@ucap/protocol-room'; +import { FileDownloadItem, StatusCode } from '@ucap/api'; + +@Component({ + selector: 'ucap-chat-message-box-file', + templateUrl: './file.component.html', + styleUrls: ['./file.component.scss'] +}) +export class FileComponent implements OnInit { + @Input() + message: Info; + + @Input() + roomInfo: RoomInfo; + + @Output() + save = new EventEmitter<{ + fileInfo: FileEventJson; + fileDownloadItem: FileDownloadItem; + type: string; + }>(); + @Output() + fileViewer = new EventEmitter(); + + fileInfo?: FileEventJson; + fileDownloadItem: FileDownloadItem; + errorMessage?: string; + FileType = FileType; + + constructor() {} + + ngOnInit() { + if (StatusCode.Success === this.message.sentMessageJson.statusCode) { + this.fileInfo = this.message.sentMessageJson; + } else { + this.errorMessage = + this.message.sentMessageJson.errorMessage || '[Error] System Error!!'; + } + + this.fileDownloadItem = new FileDownloadItem(); + } + + getExpiredFile() { + if ( + !!this.roomInfo && + this.roomInfo.expiredFileStdSeq <= this.message.seq + ) { + return false; + } else { + return true; + } + } + + onClickFileViewer(fileInfo: FileEventJson) { + if (!this.getExpiredFile()) { + this.fileViewer.emit(fileInfo); + } + } + + onSave(value: string) { + if (!this.getExpiredFile()) { + this.save.emit({ + fileInfo: this.fileInfo, + fileDownloadItem: this.fileDownloadItem, + type: value + }); + } + } +} diff --git a/projects/ui-chat/src/lib/components/message-box/image.component.html b/projects/ui-chat/src/lib/components/message-box/image.component.html new file mode 100644 index 0000000..65240f9 --- /dev/null +++ b/projects/ui-chat/src/lib/components/message-box/image.component.html @@ -0,0 +1,10 @@ +
+
+ 만기된 파일입니다. +
+ +
diff --git a/projects/ui-chat/src/lib/components/message-box/image.component.scss b/projects/ui-chat/src/lib/components/message-box/image.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/projects/ui-chat/src/lib/components/message-box/image.component.spec.ts b/projects/ui-chat/src/lib/components/message-box/image.component.spec.ts new file mode 100644 index 0000000..5198038 --- /dev/null +++ b/projects/ui-chat/src/lib/components/message-box/image.component.spec.ts @@ -0,0 +1,24 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ImageComponent } from './image.component'; + +describe('Chat::MessageBox::ImageComponent', () => { + let component: ImageComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ImageComponent] + }).compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(ImageComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/projects/ui-chat/src/lib/components/message-box/image.component.ts b/projects/ui-chat/src/lib/components/message-box/image.component.ts new file mode 100644 index 0000000..841ed4c --- /dev/null +++ b/projects/ui-chat/src/lib/components/message-box/image.component.ts @@ -0,0 +1,35 @@ +import { Component, OnInit, Input } from '@angular/core'; +import { FileEventJson } from '@ucap/protocol-event'; + +@Component({ + selector: 'ucap-chat-message-box-image', + templateUrl: './image.component.html', + styleUrls: ['./image.component.scss'] +}) +export class ImageComponent implements OnInit { + @Input() + fileInfo: FileEventJson; + @Input() + expired = false; + + showExpired = false; + + constructor() {} + + ngOnInit() {} + + mouseEnter(event: MouseEvent): void { + if (this.expired) { + this.showExpired = true; + } + event.stopPropagation(); + event.preventDefault(); + } + mouseLeave(event: MouseEvent): void { + if (this.expired) { + this.showExpired = false; + } + event.stopPropagation(); + event.preventDefault(); + } +} diff --git a/projects/ui-chat/src/lib/components/message-box/index.ts b/projects/ui-chat/src/lib/components/message-box/index.ts new file mode 100644 index 0000000..629702f --- /dev/null +++ b/projects/ui-chat/src/lib/components/message-box/index.ts @@ -0,0 +1,39 @@ +import { InformationComponent } from './information.component'; +import { TextComponent } from './text.component'; +import { FileComponent } from './file.component'; +import { AttachFileComponent } from './attach-file.component'; +import { ImageComponent } from './image.component'; +import { VideoComponent } from './video.component'; +import { StickerComponent } from './sticker.component'; +import { MassComponent } from './mass.component'; +import { ScheduleComponent } from './schedule.component'; +import { VideoConferenceComponent } from './video-conference.component'; +import { TranslationComponent } from './translation.component'; +import { MassTranslationComponent } from './mass-translation.component'; +import { RecallComponent } from './recall.component'; +import { SmsComponent } from './sms.component'; +import { ReplyComponent } from './reply.component'; +import { ReadHereComponent } from './read-here.component'; +import { DateSplitterComponent } from './date-splitter.component'; + +export const COMPONENTS = [ + InformationComponent, + TextComponent, + FileComponent, + AttachFileComponent, + ImageComponent, + VideoComponent, + StickerComponent, + MassComponent, + ScheduleComponent, + VideoConferenceComponent, + TranslationComponent, + MassTranslationComponent, + RecallComponent, + + ReadHereComponent, + DateSplitterComponent, + + SmsComponent, + ReplyComponent +]; diff --git a/projects/ui-chat/src/lib/components/message-box/information.component.html b/projects/ui-chat/src/lib/components/message-box/information.component.html new file mode 100644 index 0000000..ba02149 --- /dev/null +++ b/projects/ui-chat/src/lib/components/message-box/information.component.html @@ -0,0 +1,88 @@ +
+ + + {{ getI18nForSir(getOwnerForJoinEventJson()) }}이 + {{ getI18nForSir(getInviterForJoinEventJson()) }}을 초대했습니다. + + + + {{ message.sentMessage }}님이 퇴장하셨습니다. + + + + {{ message.exitForcingRequestUserName }}님이 {{ message.sentMessage }}님을 + 퇴장 시키셨습니다. + + + + {{ getRequesterForRenameRoom() }}님이 대화방명을 '{{ + getRoomNameForRenameRoom() + }}'으로 변경하셨습니다. + + + + {{ message.sentMessage }} + + + {{ senderName }}님이 타이머를 설정하였습니다. ({{ + getCalcTimerForGuideForRoomTimerChanged() + }}) + + + + {{ message.sentMessage }}님이 대화내용을 캡쳐하였습니다. + + + +
+ + diff --git a/projects/ui-chat/src/lib/components/message-box/information.component.scss b/projects/ui-chat/src/lib/components/message-box/information.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/projects/ui-chat/src/lib/components/message-box/information.component.spec.ts b/projects/ui-chat/src/lib/components/message-box/information.component.spec.ts new file mode 100644 index 0000000..0536b85 --- /dev/null +++ b/projects/ui-chat/src/lib/components/message-box/information.component.spec.ts @@ -0,0 +1,24 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { InformationComponent } from './information.component'; + +describe('Chat::MessageBox::InformationComponent', () => { + let component: InformationComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [InformationComponent] + }).compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(InformationComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/projects/ui-chat/src/lib/components/message-box/information.component.ts b/projects/ui-chat/src/lib/components/message-box/information.component.ts new file mode 100644 index 0000000..debeed2 --- /dev/null +++ b/projects/ui-chat/src/lib/components/message-box/information.component.ts @@ -0,0 +1,134 @@ +import { Component, OnInit, Input } from '@angular/core'; +import { + EventType, + Info, + EventJson, + RenameRoomEventJson, + GuideForRoomTimerChangedEventJson, + JoinEventJson +} from '@ucap/protocol-event'; +import { TranslateService } from '@ucap/ng-ui-organization'; + +@Component({ + selector: 'ucap-chat-message-box-information', + templateUrl: './information.component.html', + styleUrls: ['./information.component.scss'] +}) +export class InformationComponent implements OnInit { + @Input() + message: Info; + + @Input() + senderName?: string; + + EventType = EventType; + + constructor(private translateService: TranslateService) {} + + ngOnInit() {} + + getI18nForSir(names: string | string[]) { + if (Array.isArray(names)) { + const inviter: string[] = []; + + // names.forEach((userName, idx) => { + // inviter.push( + // this.translateService.instant('common.messages.sirWith', { + // sir: userName + // }) + // ); + // }); + names.forEach((userName, idx) => { + inviter.push(userName); + }); + + return inviter.join(','); + } else { + // return this.translateService.instant('common.messages.sirWith', { + // sir: names + // }); + return names; + } + } + + getOwnerForJoinEventJson() { + return (this.message.sentMessageJson as JoinEventJson).owner; + } + getInviterForJoinEventJson() { + return (this.message.sentMessageJson as JoinEventJson).inviter; + } + getCalcTimerForGuideForRoomTimerChanged() { + const millisec = + Number( + (this.message.sentMessageJson as GuideForRoomTimerChangedEventJson).time + ) * 1000; + // const langs = this.translateService.instant([ + // 'common.units.hourFrom', + // 'common.units.minute', + // 'common.units.second' + // ]); + + // switch (millisec) { + // case 5000: + // return `5 ${langs['common.units.second']}`; + // case 10000: + // return `10 ${langs['common.units.second']}`; + // case 30000: + // return `30 ${langs['common.units.second']}`; + // case 60000: + // return `1 ${langs['common.units.minute']}`; + // case 300000: + // return `5 ${langs['common.units.minute']}`; + // case 600000: + // return `10 ${langs['common.units.minute']}`; + // case 1800000: + // return `30 ${langs['common.units.minute']}`; + // case 3600000: + // return `1 ${langs['common.units.hourFrom']}`; + // case 21600000: + // return `6 ${langs['common.units.hourFrom']}`; + // case 43200000: + // return `12 ${langs['common.units.hourFrom']}`; + // case 86400000: + // return `24 ${langs['common.units.hourFrom']}`; + // default: + // return `0 ${langs['common.units.second']}`; + // } + + const langs = ['초', '분', '시간']; + + switch (millisec) { + case 5000: + return `5 ${langs[0]}`; + case 10000: + return `10 ${langs[0]}`; + case 30000: + return `30 ${langs[0]}`; + case 60000: + return `1 ${langs[1]}`; + case 300000: + return `5 ${langs[1]}`; + case 600000: + return `10 ${langs[1]}`; + case 1800000: + return `30 ${langs[1]}`; + case 3600000: + return `1 ${langs[2]}`; + case 21600000: + return `6 ${langs[2]}`; + case 43200000: + return `12 ${langs[2]}`; + case 86400000: + return `24 ${langs[2]}`; + default: + return `0 ${langs[0]}`; + } + } + + getRequesterForRenameRoom() { + return (this.message.sentMessageJson as RenameRoomEventJson).requester; + } + getRoomNameForRenameRoom() { + return (this.message.sentMessageJson as RenameRoomEventJson).roomName; + } +} diff --git a/projects/ui-chat/src/lib/components/message-box/mass-translation.component.html b/projects/ui-chat/src/lib/components/message-box/mass-translation.component.html new file mode 100644 index 0000000..ae520ee --- /dev/null +++ b/projects/ui-chat/src/lib/components/message-box/mass-translation.component.html @@ -0,0 +1,44 @@ +
+
+
+ {{ message.sentMessageJson.destLocale }} + + +
+
+
+
    +
  • + +
  • +
  • + +
  • +
+
diff --git a/projects/ui-chat/src/lib/components/message-box/mass-translation.component.scss b/projects/ui-chat/src/lib/components/message-box/mass-translation.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/projects/ui-chat/src/lib/components/message-box/mass-translation.component.spec.ts b/projects/ui-chat/src/lib/components/message-box/mass-translation.component.spec.ts new file mode 100644 index 0000000..b775edf --- /dev/null +++ b/projects/ui-chat/src/lib/components/message-box/mass-translation.component.spec.ts @@ -0,0 +1,24 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { MassTranslationComponent } from './mass-translation.component'; + +describe('Chat::MessageBox::MassTranslationComponent', () => { + let component: MassTranslationComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [MassTranslationComponent] + }).compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(MassTranslationComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/projects/ui-chat/src/lib/components/message-box/mass-translation.component.ts b/projects/ui-chat/src/lib/components/message-box/mass-translation.component.ts new file mode 100644 index 0000000..c8952a7 --- /dev/null +++ b/projects/ui-chat/src/lib/components/message-box/mass-translation.component.ts @@ -0,0 +1,73 @@ +import { + Component, + OnInit, + Input, + Output, + EventEmitter, + AfterViewInit, + ElementRef, + Inject +} from '@angular/core'; +import { Info, MassTranslationEventJson } from '@ucap/protocol-event'; + +@Component({ + selector: 'ucap-chat-message-box-mass-translation', + templateUrl: './mass-translation.component.html', + styleUrls: ['./mass-translation.component.scss'] +}) +export class MassTranslationComponent implements OnInit, AfterViewInit { + @Input() + message: Info; + + @Input() + translationSimpleview: boolean; + + @Input() + isMe: boolean; + + @Output() + massTranslationDetail = new EventEmitter<{ + message: Info; + contentsType: string; + }>(); + + @Output() + contextMenu = new EventEmitter<{ + event: MouseEvent; + type: string; + }>(); + + @Output() + openLink = new EventEmitter(); + + constructor(private elementRef: ElementRef) {} + + 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.openLink.emit((event.target as HTMLAnchorElement).text); + } + + onClickMassDetail(contentsType: string) { + this.massTranslationDetail.emit({ + message: this.message, + contentsType + }); + } + + onContextMenuMessage(event: MouseEvent, type: string) { + this.contextMenu.emit({ event, type }); + } +} diff --git a/projects/ui-chat/src/lib/components/message-box/mass.component.html b/projects/ui-chat/src/lib/components/message-box/mass.component.html new file mode 100644 index 0000000..0e97ee2 --- /dev/null +++ b/projects/ui-chat/src/lib/components/message-box/mass.component.html @@ -0,0 +1,12 @@ +
+ + +
+
+ +
diff --git a/projects/ui-chat/src/lib/components/message-box/mass.component.scss b/projects/ui-chat/src/lib/components/message-box/mass.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/projects/ui-chat/src/lib/components/message-box/mass.component.spec.ts b/projects/ui-chat/src/lib/components/message-box/mass.component.spec.ts new file mode 100644 index 0000000..638ad02 --- /dev/null +++ b/projects/ui-chat/src/lib/components/message-box/mass.component.spec.ts @@ -0,0 +1,24 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { MassComponent } from './mass.component'; + +describe('Chat::MessageBox::MassComponent', () => { + let component: MassComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [MassComponent] + }).compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(MassComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/projects/ui-chat/src/lib/components/message-box/mass.component.ts b/projects/ui-chat/src/lib/components/message-box/mass.component.ts new file mode 100644 index 0000000..df55f91 --- /dev/null +++ b/projects/ui-chat/src/lib/components/message-box/mass.component.ts @@ -0,0 +1,74 @@ +import { + Component, + OnInit, + Input, + Output, + EventEmitter, + ElementRef, + AfterViewInit, + Inject +} from '@angular/core'; +import { Info, MassTextEventJson } from '@ucap/protocol-event'; +import { StatusCode } from '@ucap/api'; + +@Component({ + selector: 'ucap-chat-message-box-mass', + templateUrl: './mass.component.html', + styleUrls: ['./mass.component.scss'] +}) +export class MassComponent implements OnInit, AfterViewInit { + @Input() + message: Info; + + @Output() + massDetail = new EventEmitter(); + + @Output() + openLink = new EventEmitter(); + + content: string; + eventMassSeq: number; + detailButteonShow = true; + + constructor(private elementRef: ElementRef) {} + + ngOnInit() { + try { + if (StatusCode.Success === this.message.sentMessageJson.statusCode) { + this.content = this.message.sentMessageJson.content; + } else { + this.content = + this.message.sentMessageJson.errorMessage || '[Error] System Error!!'; + this.detailButteonShow = false; + } + + if (!!this.message.sentMessageJson.massSeq) { + this.eventMassSeq = this.message.sentMessageJson.massSeq; + } else { + this.detailButteonShow = false; + } + } catch (e) { + this.detailButteonShow = false; + } + } + + 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.openLink.emit((event.target as HTMLAnchorElement).text); + } + + onClickDetailView() { + this.massDetail.emit(this.eventMassSeq); + } +} diff --git a/projects/ui-chat/src/lib/components/message-box/read-here.component.html b/projects/ui-chat/src/lib/components/message-box/read-here.component.html new file mode 100644 index 0000000..daff627 --- /dev/null +++ b/projects/ui-chat/src/lib/components/message-box/read-here.component.html @@ -0,0 +1,3 @@ +
+ 여기까지 읽었습니다 +
diff --git a/projects/ui-chat/src/lib/components/message-box/read-here.component.scss b/projects/ui-chat/src/lib/components/message-box/read-here.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/projects/ui-chat/src/lib/components/message-box/read-here.component.spec.ts b/projects/ui-chat/src/lib/components/message-box/read-here.component.spec.ts new file mode 100644 index 0000000..17691f5 --- /dev/null +++ b/projects/ui-chat/src/lib/components/message-box/read-here.component.spec.ts @@ -0,0 +1,24 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ReadHereComponent } from './read-here.component'; + +describe('Chat::MessageBox::ReadHereComponent', () => { + let component: ReadHereComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ReadHereComponent] + }).compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(ReadHereComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/projects/ui-chat/src/lib/components/message-box/read-here.component.ts b/projects/ui-chat/src/lib/components/message-box/read-here.component.ts new file mode 100644 index 0000000..74cb1b1 --- /dev/null +++ b/projects/ui-chat/src/lib/components/message-box/read-here.component.ts @@ -0,0 +1,12 @@ +import { Component, OnInit } from '@angular/core'; + +@Component({ + selector: 'ucap-chat-message-box-read-here', + templateUrl: './read-here.component.html', + styleUrls: ['./read-here.component.scss'] +}) +export class ReadHereComponent implements OnInit { + constructor() {} + + ngOnInit() {} +} diff --git a/projects/ui-chat/src/lib/components/message-box/recall.component.html b/projects/ui-chat/src/lib/components/message-box/recall.component.html new file mode 100644 index 0000000..f84fdcc --- /dev/null +++ b/projects/ui-chat/src/lib/components/message-box/recall.component.html @@ -0,0 +1,4 @@ +
+ redo + 회수된 메시지 +
diff --git a/projects/ui-chat/src/lib/components/message-box/recall.component.scss b/projects/ui-chat/src/lib/components/message-box/recall.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/projects/ui-chat/src/lib/components/message-box/recall.component.spec.ts b/projects/ui-chat/src/lib/components/message-box/recall.component.spec.ts new file mode 100644 index 0000000..0ef9e65 --- /dev/null +++ b/projects/ui-chat/src/lib/components/message-box/recall.component.spec.ts @@ -0,0 +1,24 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { RecallComponent } from './recall.component'; + +describe('Chat::MessageBox::RecallComponent', () => { + let component: RecallComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [RecallComponent] + }).compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(RecallComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/projects/ui-chat/src/lib/components/message-box/recall.component.ts b/projects/ui-chat/src/lib/components/message-box/recall.component.ts new file mode 100644 index 0000000..bb6553b --- /dev/null +++ b/projects/ui-chat/src/lib/components/message-box/recall.component.ts @@ -0,0 +1,12 @@ +import { Component, OnInit } from '@angular/core'; + +@Component({ + selector: 'ucap-chat-message-box-recall', + templateUrl: './recall.component.html', + styleUrls: ['./recall.component.scss'] +}) +export class RecallComponent implements OnInit { + constructor() {} + + ngOnInit() {} +} diff --git a/projects/ui-chat/src/lib/components/message-box/reply.component.html b/projects/ui-chat/src/lib/components/message-box/reply.component.html new file mode 100644 index 0000000..19a0bfc --- /dev/null +++ b/projects/ui-chat/src/lib/components/message-box/reply.component.html @@ -0,0 +1,14 @@ +
+
+
    +
  • 나에게 답장
  • +
  • + 올려 놓았습니다. 확인해 보시기 바랍니다. +
  • +
+
+
+ + 네 감사합니다. 수고가 많으시네요. 오늘 중으로 확인해 보겠습니다. +
+
diff --git a/projects/ui-chat/src/lib/components/message-box/reply.component.scss b/projects/ui-chat/src/lib/components/message-box/reply.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/projects/ui-chat/src/lib/components/message-box/reply.component.spec.ts b/projects/ui-chat/src/lib/components/message-box/reply.component.spec.ts new file mode 100644 index 0000000..c5894c3 --- /dev/null +++ b/projects/ui-chat/src/lib/components/message-box/reply.component.spec.ts @@ -0,0 +1,24 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { TextComponent } from './text.component'; + +describe('Chat::MessageBox::TextComponent', () => { + let component: TextComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [TextComponent] + }).compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(TextComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/projects/ui-chat/src/lib/components/message-box/reply.component.ts b/projects/ui-chat/src/lib/components/message-box/reply.component.ts new file mode 100644 index 0000000..039eca0 --- /dev/null +++ b/projects/ui-chat/src/lib/components/message-box/reply.component.ts @@ -0,0 +1,21 @@ +import { + Component, + OnInit, + Input, + ElementRef, + AfterViewInit, + Inject +} from '@angular/core'; + +@Component({ + selector: 'ucap-chat-message-box-reply', + templateUrl: './reply.component.html', + styleUrls: ['./reply.component.scss'] +}) +export class ReplyComponent implements OnInit, AfterViewInit { + constructor(private elementRef: ElementRef) {} + + ngOnInit() {} + + ngAfterViewInit(): void {} +} diff --git a/projects/ui-chat/src/lib/components/message-box/schedule.component.html b/projects/ui-chat/src/lib/components/message-box/schedule.component.html new file mode 100644 index 0000000..fff45f2 --- /dev/null +++ b/projects/ui-chat/src/lib/components/message-box/schedule.component.html @@ -0,0 +1,38 @@ +
+
+ + + + {{ 'chat.event.scheduleTypeNew' | ucapI18n }} + + + {{ 'chat.event.scheduleTypeUpdate' | ucapI18n }} + + + {{ 'chat.event.scheduleTypeDelete' | ucapI18n }} + + + + {{ getAlertLeftTime() }} + + + +
+
    +
  • + 마곡 E14동 906호 +
  • +
  • + 2020.05.23 9:30 ~ 2020.05.23 11:30 +
  • +
  • + {{ message.sentMessageJson.title }} + {{ message.sentMessageJson.contents }} +
  • +
+
+
+ +
diff --git a/projects/ui-chat/src/lib/components/message-box/schedule.component.scss b/projects/ui-chat/src/lib/components/message-box/schedule.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/projects/ui-chat/src/lib/components/message-box/schedule.component.spec.ts b/projects/ui-chat/src/lib/components/message-box/schedule.component.spec.ts new file mode 100644 index 0000000..b9e1a66 --- /dev/null +++ b/projects/ui-chat/src/lib/components/message-box/schedule.component.spec.ts @@ -0,0 +1,24 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ScheduleComponent } from './schedule.component'; + +describe('Chat::MessageBox::ScheduleComponent', () => { + let component: ScheduleComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ScheduleComponent] + }).compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(ScheduleComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/projects/ui-chat/src/lib/components/message-box/schedule.component.ts b/projects/ui-chat/src/lib/components/message-box/schedule.component.ts new file mode 100644 index 0000000..98b9712 --- /dev/null +++ b/projects/ui-chat/src/lib/components/message-box/schedule.component.ts @@ -0,0 +1,64 @@ +import { Component, OnInit, Input } from '@angular/core'; +import { Info, PlanEventJson, PlanContentType } from '@ucap/protocol-event'; +import { TranslateService } from '@ucap/ng-ui-organization'; + +import moment from 'moment'; + +@Component({ + selector: 'ucap-chat-message-box-schedule', + templateUrl: './schedule.component.html', + styleUrls: ['./schedule.component.scss'] +}) +export class ScheduleComponent implements OnInit { + @Input() + message: Info; + + PlanContentType = PlanContentType; + date: any; + endDate: any; + + constructor(private translateService: TranslateService) {} + + ngOnInit() { + if (!!this.message && !!this.message.sentMessageJson) { + if (!!this.message.sentMessageJson.date) { + let strDate = this.message.sentMessageJson.date + .replace(/ /g, '') + .replace(/\n/g, '') + .replace(/(\([월,화,수,목,금,토,일]\))/g, ''); + if (strDate.indexOf('오전') > -1) { + strDate = strDate.replace('오전', ' '); + } else if (strDate.indexOf('오후') > -1) { + strDate = strDate.replace('오후', ' '); + const arr = strDate.split(' '); + const h = Number(arr[1].split(':')[0]) + 12; + strDate = arr[0] + ' ' + h + ':' + arr[1].split(':')[1]; + } + + this.date = moment(strDate).toDate(); + if (this.date === 'Invalid Date') { + this.date = this.message.sentMessageJson.date.replace(/\n/g, ''); + } + } + } + } + + onClickSave(): void {} + + getAlertLeftTime(): string { + let content = this.message.sentMessageJson.contents; + if (content.indexOf('PLAN_CONTENTS_MINUTE') > -1) { + content = content.replace('PLAN_CONTENTS_MINUTE', '분'); + } else if (content.indexOf('PLAN_CONTENTS_HOUR') > -1) { + content = content.replace('PLAN_CONTENTS_HOUR', '시간'); + } + + if (content.indexOf('PLAN_CONTENTS_AFTER') > -1) { + content = content.replace('PLAN_CONTENTS_AFTER', ' 전 알림'); + } + + content = '[이벤트] ' + content; + + return content; + } +} diff --git a/projects/ui-chat/src/lib/components/message-box/sms.component.html b/projects/ui-chat/src/lib/components/message-box/sms.component.html new file mode 100644 index 0000000..a16d272 --- /dev/null +++ b/projects/ui-chat/src/lib/components/message-box/sms.component.html @@ -0,0 +1,9 @@ +
+
+ SMS +
+
+ SMS 내용 공간입니다. 내용을 보여주세요 SMS 내용 공간입니다. 내용을 + 보여주세요 SMS 내용 공간입니다. 내용을 보여주세요 +
+
diff --git a/projects/ui-chat/src/lib/components/message-box/sms.component.scss b/projects/ui-chat/src/lib/components/message-box/sms.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/projects/ui-chat/src/lib/components/message-box/sms.component.spec.ts b/projects/ui-chat/src/lib/components/message-box/sms.component.spec.ts new file mode 100644 index 0000000..c5894c3 --- /dev/null +++ b/projects/ui-chat/src/lib/components/message-box/sms.component.spec.ts @@ -0,0 +1,24 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { TextComponent } from './text.component'; + +describe('Chat::MessageBox::TextComponent', () => { + let component: TextComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [TextComponent] + }).compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(TextComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/projects/ui-chat/src/lib/components/message-box/sms.component.ts b/projects/ui-chat/src/lib/components/message-box/sms.component.ts new file mode 100644 index 0000000..90834ee --- /dev/null +++ b/projects/ui-chat/src/lib/components/message-box/sms.component.ts @@ -0,0 +1,21 @@ +import { + Component, + OnInit, + Input, + ElementRef, + AfterViewInit, + Inject +} from '@angular/core'; + +@Component({ + selector: 'ucap-chat-message-box-sms', + templateUrl: './sms.component.html', + styleUrls: ['./sms.component.scss'] +}) +export class SmsComponent implements OnInit, AfterViewInit { + constructor(private elementRef: ElementRef) {} + + ngOnInit() {} + + ngAfterViewInit(): void {} +} diff --git a/projects/ui-chat/src/lib/components/message-box/sticker.component.html b/projects/ui-chat/src/lib/components/message-box/sticker.component.html new file mode 100644 index 0000000..e68be27 --- /dev/null +++ b/projects/ui-chat/src/lib/components/message-box/sticker.component.html @@ -0,0 +1,11 @@ +
+
    +
  • + +
  • +
  • +
+
diff --git a/projects/ui-chat/src/lib/components/message-box/sticker.component.scss b/projects/ui-chat/src/lib/components/message-box/sticker.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/projects/ui-chat/src/lib/components/message-box/sticker.component.spec.ts b/projects/ui-chat/src/lib/components/message-box/sticker.component.spec.ts new file mode 100644 index 0000000..f6522fd --- /dev/null +++ b/projects/ui-chat/src/lib/components/message-box/sticker.component.spec.ts @@ -0,0 +1,24 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { StickerComponent } from './sticker.component'; + +describe('Chat::MessageBox::StickerComponent', () => { + let component: StickerComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [StickerComponent] + }).compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(StickerComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/projects/ui-chat/src/lib/components/message-box/sticker.component.ts b/projects/ui-chat/src/lib/components/message-box/sticker.component.ts new file mode 100644 index 0000000..d2e5295 --- /dev/null +++ b/projects/ui-chat/src/lib/components/message-box/sticker.component.ts @@ -0,0 +1,54 @@ +import { + Component, + OnInit, + Input, + ElementRef, + AfterViewInit, + EventEmitter, + Output +} from '@angular/core'; +import { Info, StickerEventJson } from '@ucap/protocol-event'; + +@Component({ + selector: 'ucap-chat-message-box-sticker', + templateUrl: './sticker.component.html', + styleUrls: ['./sticker.component.scss'] +}) +export class StickerComponent implements OnInit, AfterViewInit { + @Input() + message: Info; + + @Input() + stickerUrl?: string; + + @Input() + stickerDefaultImagePath: string; + + @Output() + openLink = new EventEmitter(); + + contents: string; + constructor(private elementRef: ElementRef) {} + + ngOnInit() { + if (!!this.message.sentMessageJson?.chat) { + this.contents = this.message.sentMessageJson.chat; + } + } + + 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.openLink.emit((event.target as HTMLAnchorElement).text); + } +} diff --git a/projects/ui-chat/src/lib/components/message-box/text.component.html b/projects/ui-chat/src/lib/components/message-box/text.component.html new file mode 100644 index 0000000..bce0ecc --- /dev/null +++ b/projects/ui-chat/src/lib/components/message-box/text.component.html @@ -0,0 +1,3 @@ +
+ +
diff --git a/projects/ui-chat/src/lib/components/message-box/text.component.scss b/projects/ui-chat/src/lib/components/message-box/text.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/projects/ui-chat/src/lib/components/message-box/text.component.spec.ts b/projects/ui-chat/src/lib/components/message-box/text.component.spec.ts new file mode 100644 index 0000000..c5894c3 --- /dev/null +++ b/projects/ui-chat/src/lib/components/message-box/text.component.spec.ts @@ -0,0 +1,24 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { TextComponent } from './text.component'; + +describe('Chat::MessageBox::TextComponent', () => { + let component: TextComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [TextComponent] + }).compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(TextComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/projects/ui-chat/src/lib/components/message-box/text.component.ts b/projects/ui-chat/src/lib/components/message-box/text.component.ts new file mode 100644 index 0000000..de9c3a8 --- /dev/null +++ b/projects/ui-chat/src/lib/components/message-box/text.component.ts @@ -0,0 +1,43 @@ +import { + Component, + OnInit, + Input, + ElementRef, + AfterViewInit, + Output, + EventEmitter +} from '@angular/core'; +import { Info, EventJson } from '@ucap/protocol-event'; + +@Component({ + selector: 'ucap-chat-message-box-text', + templateUrl: './text.component.html', + styleUrls: ['./text.component.scss'] +}) +export class TextComponent implements OnInit, AfterViewInit { + @Input() + message: Info; + + @Output() + openLink = new EventEmitter(); + + constructor(private elementRef: ElementRef) {} + + 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.openLink.emit((event.target as HTMLAnchorElement).text); + } +} diff --git a/projects/ui-chat/src/lib/components/message-box/translation.component.html b/projects/ui-chat/src/lib/components/message-box/translation.component.html new file mode 100644 index 0000000..64f065a --- /dev/null +++ b/projects/ui-chat/src/lib/components/message-box/translation.component.html @@ -0,0 +1,20 @@ +
+
+ +
+ +
+
+ {{ message.sentMessageJson.locale }} + +
+
diff --git a/projects/ui-chat/src/lib/components/message-box/translation.component.scss b/projects/ui-chat/src/lib/components/message-box/translation.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/projects/ui-chat/src/lib/components/message-box/translation.component.spec.ts b/projects/ui-chat/src/lib/components/message-box/translation.component.spec.ts new file mode 100644 index 0000000..2382d23 --- /dev/null +++ b/projects/ui-chat/src/lib/components/message-box/translation.component.spec.ts @@ -0,0 +1,24 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { TranslationComponent } from './translation.component'; + +describe('Chat::MessageBox::TranslationComponent', () => { + let component: TranslationComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [TranslationComponent] + }).compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(TranslationComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/projects/ui-chat/src/lib/components/message-box/translation.component.ts b/projects/ui-chat/src/lib/components/message-box/translation.component.ts new file mode 100644 index 0000000..19fe408 --- /dev/null +++ b/projects/ui-chat/src/lib/components/message-box/translation.component.ts @@ -0,0 +1,65 @@ +import { + Component, + OnInit, + Input, + EventEmitter, + Output, + AfterViewInit, + ElementRef +} from '@angular/core'; +import { Info, TranslationEventJson } from '@ucap/protocol-event'; + +@Component({ + selector: 'ucap-chat-message-box-translation', + templateUrl: './translation.component.html', + styleUrls: ['./translation.component.scss'] +}) +export class TranslationComponent implements OnInit, AfterViewInit { + @Input() + message: Info; + + @Input() + translationSimpleview: boolean; + + @Input() + isMe: boolean; + + @Input() + stickerUrl?: string; + + @Input() + stickerDefaultImagePath: string; + + @Output() + contextMenu = new EventEmitter<{ + event: MouseEvent; + type: string; + }>(); + + @Output() + openLink = new EventEmitter(); + + constructor(private elementRef: ElementRef) {} + + 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.openLink.emit((event.target as HTMLAnchorElement).text); + } + + onContextMenuMessage(event: MouseEvent, type: string) { + this.contextMenu.emit({ event, type }); + } +} diff --git a/projects/ui-chat/src/lib/components/message-box/video-conference.component.html b/projects/ui-chat/src/lib/components/message-box/video-conference.component.html new file mode 100644 index 0000000..6d4f036 --- /dev/null +++ b/projects/ui-chat/src/lib/components/message-box/video-conference.component.html @@ -0,0 +1,54 @@ +
+
+ + + + {{ 'conference.videoConferenceTypeNow' | ucapI18n }} + + + {{ 'conference.videoConferenceTypeNew' | ucapI18n }} + + + {{ 'conference.videoConferenceTypeUpdate' | ucapI18n }} + + + {{ 'conference.videoConferenceTypeDelete' | ucapI18n }} + + + +
+
    +
  • + {{ + 'conference.videoConferenceRegister' | ucapI18n + }} + {{ message.sentMessageJson.register }} +
  • +
  • + {{ + 'conference.videoConferenceAttendee' | ucapI18n + }} + {{ message.sentMessageJson.attendee }} +
  • +
  • + {{ message.sentMessageJson.startDate | ucapDate }} ~ + {{ message.sentMessageJson.endDate | ucapDate }} +
  • +
+
+
+
    +
  • + +
  • +
  • + +
  • +
+
diff --git a/projects/ui-chat/src/lib/components/message-box/video-conference.component.scss b/projects/ui-chat/src/lib/components/message-box/video-conference.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/projects/ui-chat/src/lib/components/message-box/video-conference.component.spec.ts b/projects/ui-chat/src/lib/components/message-box/video-conference.component.spec.ts new file mode 100644 index 0000000..ce70c6c --- /dev/null +++ b/projects/ui-chat/src/lib/components/message-box/video-conference.component.spec.ts @@ -0,0 +1,24 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { VideoConferenceComponent } from './video-conference.component'; + +describe('Chat::MessageBox::VideoConferenceComponent', () => { + let component: VideoConferenceComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [VideoConferenceComponent] + }).compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(VideoConferenceComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/projects/ui-chat/src/lib/components/message-box/video-conference.component.ts b/projects/ui-chat/src/lib/components/message-box/video-conference.component.ts new file mode 100644 index 0000000..7ee330d --- /dev/null +++ b/projects/ui-chat/src/lib/components/message-box/video-conference.component.ts @@ -0,0 +1,40 @@ +import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core'; +import { + VideoConferenceEventJson, + VideoConferenceContentsType, + Info +} from '@ucap/protocol-event'; +import { AuthResponse } from '@ucap/protocol-query'; + +@Component({ + selector: 'ucap-chat-message-box-video-conference', + templateUrl: './video-conference.component.html', + styleUrls: ['./video-conference.component.scss'] +}) +export class VideoConferenceComponent implements OnInit { + @Input() + message: Info; + + @Input() + canVideoConference: boolean; + + @Output() + conferenceDetail = new EventEmitter(); + + @Output() + conferenceJoin = new EventEmitter(); + + VideoConferenceContentsType = VideoConferenceContentsType; + + constructor() {} + + ngOnInit() {} + + onClickDetailView() { + this.conferenceDetail.emit(this.message.sentMessageJson); + } + + onClickEnjoyConference() { + this.conferenceJoin.emit(this.message.sentMessageJson); + } +} diff --git a/projects/ui-chat/src/lib/components/message-box/video.component.html b/projects/ui-chat/src/lib/components/message-box/video.component.html new file mode 100644 index 0000000..67e4b77 --- /dev/null +++ b/projects/ui-chat/src/lib/components/message-box/video.component.html @@ -0,0 +1,41 @@ +
+
+ +
+
+
+
+
    +
  • + {{ fileInfo.fileName }} +
  • +
  • + 2020.01.01 ~ 2020.12.12 +
  • +
+
+
+
    +
  • + +
  • +
  • + +
  • +
  • + +
  • +
+
+
+ 프로그레스 영역 +
diff --git a/projects/ui-chat/src/lib/components/message-box/video.component.scss b/projects/ui-chat/src/lib/components/message-box/video.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/projects/ui-chat/src/lib/components/message-box/video.component.spec.ts b/projects/ui-chat/src/lib/components/message-box/video.component.spec.ts new file mode 100644 index 0000000..e67079a --- /dev/null +++ b/projects/ui-chat/src/lib/components/message-box/video.component.spec.ts @@ -0,0 +1,24 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { VideoComponent } from './video.component'; + +describe('Chat::MessageBox::VideoComponent', () => { + let component: VideoComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [VideoComponent] + }).compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(VideoComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/projects/ui-chat/src/lib/components/message-box/video.component.ts b/projects/ui-chat/src/lib/components/message-box/video.component.ts new file mode 100644 index 0000000..987bad2 --- /dev/null +++ b/projects/ui-chat/src/lib/components/message-box/video.component.ts @@ -0,0 +1,33 @@ +import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core'; +import { FileEventJson } from '@ucap/protocol-event'; + +@Component({ + selector: 'ucap-chat-message-box-video', + templateUrl: './video.component.html', + styleUrls: ['./video.component.scss'] +}) +export class VideoComponent implements OnInit { + @Input() + fileInfo: FileEventJson; + @Input() + expired = false; + + @Output() + save = new EventEmitter(); + @Output() + openViewer = new EventEmitter(); + + constructor() {} + + ngOnInit() {} + + onClickSave() { + this.save.emit('save'); + } + onClickSaveAs() { + this.save.emit('saveAs'); + } + onClickOpenViewer() { + this.openViewer.emit(); + } +} diff --git a/projects/ui-chat/src/lib/components/room-expansion.component.stories.ts b/projects/ui-chat/src/lib/components/room-expansion.component.stories.ts new file mode 100644 index 0000000..de148e3 --- /dev/null +++ b/projects/ui-chat/src/lib/components/room-expansion.component.stories.ts @@ -0,0 +1,26 @@ +import { moduleMetadata } from '@storybook/angular'; +import { action } from '@storybook/addon-actions'; +import { linkTo } from '@storybook/addon-links'; + +import { BrowserModule } from '@angular/platform-browser'; +import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; + +import { ChatUiModule } from '../chat-ui.module'; + +import { RoomExpansionComponent } from './room-expansion.component'; + +export default { + title: 'ui-chat::RoomExpansionComponent', + component: RoomExpansionComponent, + decorators: [ + moduleMetadata({ + imports: [BrowserModule, BrowserAnimationsModule, ChatUiModule], + providers: [] + }) + ] +}; + +export const Default = () => ({ + component: RoomExpansionComponent, + props: {} +}); diff --git a/projects/ui-chat/src/lib/components/room-expansion.component.theme.scss b/projects/ui-chat/src/lib/components/room-expansion.component.theme.scss new file mode 100644 index 0000000..ccf1255 --- /dev/null +++ b/projects/ui-chat/src/lib/components/room-expansion.component.theme.scss @@ -0,0 +1,20 @@ +@import '~@ucap/ng-ui-material/material'; + +@mixin ucap-chat-room-expansion-theme($theme) { + $is-dark-theme: map-get($theme, is-dark); + $primary: map-get($theme, primary); + $accent: map-get($theme, accent); + $warn: map-get($theme, warn); + $background: map-get($theme, background); + $foreground: map-get($theme, foreground); + + .ucap-chat-room-expansion-container { + border-color: mat-color($foreground, secondary-text); + } +} + +@mixin ucap-chat-room-expansion-typography($config) { + .ucap-chat-room-expansion-container { + font-family: mat-font-family($config); + } +} diff --git a/projects/ui-chat/src/lib/components/room-list-item-01.component.stories.ts b/projects/ui-chat/src/lib/components/room-list-item-01.component.stories.ts new file mode 100644 index 0000000..1c3d93a --- /dev/null +++ b/projects/ui-chat/src/lib/components/room-list-item-01.component.stories.ts @@ -0,0 +1,26 @@ +import { moduleMetadata } from '@storybook/angular'; +import { action } from '@storybook/addon-actions'; +import { linkTo } from '@storybook/addon-links'; + +import { BrowserModule } from '@angular/platform-browser'; +import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; + +import { ChatUiModule } from '../chat-ui.module'; + +import { RoomListItem01Component } from './room-list-item-01.component'; + +export default { + title: 'ui-chat::RoomListItem01Component', + component: RoomListItem01Component, + decorators: [ + moduleMetadata({ + imports: [BrowserModule, BrowserAnimationsModule, ChatUiModule], + providers: [] + }) + ] +}; + +export const Default = () => ({ + component: RoomListItem01Component, + props: {} +}); diff --git a/projects/ui-chat/src/lib/components/room-list-item-01.component.theme.scss b/projects/ui-chat/src/lib/components/room-list-item-01.component.theme.scss new file mode 100644 index 0000000..a5fe508 --- /dev/null +++ b/projects/ui-chat/src/lib/components/room-list-item-01.component.theme.scss @@ -0,0 +1,20 @@ +@import '~@ucap/ng-ui-material/material'; + +@mixin ucap-chat-room-list-item-01-theme($theme) { + $is-dark-theme: map-get($theme, is-dark); + $primary: map-get($theme, primary); + $accent: map-get($theme, accent); + $warn: map-get($theme, warn); + $background: map-get($theme, background); + $foreground: map-get($theme, foreground); + + .ucap-chat-room-list-item-01-container { + border-color: mat-color($foreground, secondary-text); + } +} + +@mixin ucap-chat-room-list-item-01-typography($config) { + .ucap-chat-room-list-item-01-container { + font-family: mat-font-family($config); + } +} diff --git a/projects/ui-group/ng-package.json b/projects/ui-group/ng-package.json index 8462562..ba3ffd9 100644 --- a/projects/ui-group/ng-package.json +++ b/projects/ui-group/ng-package.json @@ -3,6 +3,7 @@ "dest": "../../dist/ui-group", "lib": { "entryFile": "src/public-api.ts", + "styleIncludePaths": ["./src/assets/scss"], "umdModuleIds": { "ngx-perfect-scrollbar": "ngx-perfect-scrollbar", "@ucap/core": "@ucap/core", diff --git a/projects/ui-group/package.json b/projects/ui-group/package.json index c6bbe73..0fde3b2 100644 --- a/projects/ui-group/package.json +++ b/projects/ui-group/package.json @@ -1,6 +1,6 @@ { "name": "@ucap/ng-ui-group", - "version": "0.0.30", + "version": "0.0.33", "publishConfig": { "registry": "https://nexus.loafle.net/repository/npm-ucap/" }, @@ -10,8 +10,9 @@ "@angular/core": "^9.0.2", "@angular/material": "^9.0.0", "@ucap/core": "~0.0.1", - "@ucap/uc-scss": "~0.0.1", + "@ucap/ui-scss": "~0.0.1", "@ucap/ng-ui": "~0.0.1", + "@ucap/ng-ui-material": "~0.0.1", "tslib": "^1.10.0" } } diff --git a/projects/ui-group/scss-bundle.config.json b/projects/ui-group/scss-bundle.config.json new file mode 100644 index 0000000..cede2cf --- /dev/null +++ b/projects/ui-group/scss-bundle.config.json @@ -0,0 +1,11 @@ +{ + "bundlerOptions": { + "entryFile": "./projects/ui-group/src/assets/scss/_theme.scss", + "rootDir": "./projects/ui-group/src/assets/scss/", + "outFile": "./dist/ui-group/_theme.scss", + "dedupeGlobs": [], + "includePaths": [], + "ignoreImports": ["~@ucap/.*", "~@angular/.*"], + "logLevel": "silent" + } +} diff --git a/projects/ui-group/src/assets/scss/_theme.scss b/projects/ui-group/src/assets/scss/_theme.scss new file mode 100644 index 0000000..49200e8 --- /dev/null +++ b/projects/ui-group/src/assets/scss/_theme.scss @@ -0,0 +1 @@ +@import '../../lib/components/expansion.component.theme.scss'; diff --git a/projects/ui-group/src/lib/components/expansion.component.scss b/projects/ui-group/src/lib/components/expansion.component.scss index 425fdbd..cbc5e38 100644 --- a/projects/ui-group/src/lib/components/expansion.component.scss +++ b/projects/ui-group/src/lib/components/expansion.component.scss @@ -4,3 +4,22 @@ absolute ); } +.ucap-clickable { + display: flex; + min-height: 60px; + border-top: 10px solid #f1f2f6; + border-bottom: 1px solid #cccccc; + li { + width: 100%; + .path { + display: flex; + flex-direction: row; + justify-content: space-between; + align-items: center; + .group-info { + justify-self: self-start; + flex-grow: 1; + } + } + } +} diff --git a/projects/ui-group/src/lib/components/expansion.component.stories.ts b/projects/ui-group/src/lib/components/expansion.component.stories.ts index 6b76402..0f6ff1d 100644 --- a/projects/ui-group/src/lib/components/expansion.component.stories.ts +++ b/projects/ui-group/src/lib/components/expansion.component.stories.ts @@ -1,16 +1,26 @@ +import { moduleMetadata } from '@storybook/angular'; import { action } from '@storybook/addon-actions'; import { linkTo } from '@storybook/addon-links'; +import { BrowserModule } from '@angular/platform-browser'; +import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; + +import { GroupUiModule } from '../group-ui.module'; + import { ExpansionComponent } from './expansion.component'; export default { - title: 'ExpansionComponent', - component: ExpansionComponent + title: 'ui-group::ExpansionComponent', + component: ExpansionComponent, + decorators: [ + moduleMetadata({ + imports: [BrowserModule, BrowserAnimationsModule, GroupUiModule], + providers: [] + }) + ] }; -export const Text = () => ({ +export const Default = () => ({ component: ExpansionComponent, - props: { - text: 'Hello ExpansionComponent' - } + props: {} }); diff --git a/projects/ui-group/src/lib/components/expansion.component.theme.scss b/projects/ui-group/src/lib/components/expansion.component.theme.scss new file mode 100644 index 0000000..173f242 --- /dev/null +++ b/projects/ui-group/src/lib/components/expansion.component.theme.scss @@ -0,0 +1,20 @@ +@import '~@ucap/ng-ui-material/material'; + +@mixin ucap-group-expansion-theme($theme) { + $is-dark-theme: map-get($theme, is-dark); + $primary: map-get($theme, primary); + $accent: map-get($theme, accent); + $warn: map-get($theme, warn); + $background: map-get($theme, background); + $foreground: map-get($theme, foreground); + + .ucap-group-expansion-container { + border-color: mat-color($foreground, secondary-text); + } +} + +@mixin ucap-group-expansion-typography($config) { + .ucap-group-expansion-container { + font-family: mat-font-family($config); + } +} diff --git a/projects/ui-material/README.md b/projects/ui-material/README.md new file mode 100644 index 0000000..7824743 --- /dev/null +++ b/projects/ui-material/README.md @@ -0,0 +1,24 @@ +# UiSkinDefault + +This library was generated with [Angular CLI](https://github.com/angular/angular-cli) version 9.0.6. + +## Code scaffolding + +Run `ng generate component component-name --project ui-skin-default` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module --project ui-skin-default`. +> Note: Don't forget to add `--project ui-skin-default` or else it will be added to the default project in your `angular.json` file. + +## Build + +Run `ng build ui-skin-default` to build the project. The build artifacts will be stored in the `dist/` directory. + +## Publishing + +After building your library with `ng build ui-skin-default`, go to the dist folder `cd dist/ui-skin-default` and run `npm publish`. + +## Running unit tests + +Run `ng test ui-skin-default` 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/ui-material/karma.conf.js b/projects/ui-material/karma.conf.js new file mode 100644 index 0000000..912d8e8 --- /dev/null +++ b/projects/ui-material/karma.conf.js @@ -0,0 +1,32 @@ +// Karma configuration file, see link for more information +// https://karma-runner.github.io/1.0/config/configuration-file.html + +module.exports = function (config) { + config.set({ + basePath: '', + frameworks: ['jasmine', '@angular-devkit/build-angular'], + plugins: [ + require('karma-jasmine'), + require('karma-chrome-launcher'), + require('karma-jasmine-html-reporter'), + require('karma-coverage-istanbul-reporter'), + require('@angular-devkit/build-angular/plugins/karma') + ], + client: { + clearContext: false // leave Jasmine Spec Runner output visible in browser + }, + coverageIstanbulReporter: { + dir: require('path').join(__dirname, '../../coverage/ui-skin-default'), + 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/ui-material/ng-package.json b/projects/ui-material/ng-package.json new file mode 100644 index 0000000..2f25bdb --- /dev/null +++ b/projects/ui-material/ng-package.json @@ -0,0 +1,8 @@ +{ + "$schema": "../../node_modules/ng-packagr/ng-package.schema.json", + "dest": "../../dist/ui-material", + "lib": { + "entryFile": "src/public-api.ts", + "styleIncludePaths": ["./src/assets/scss"] + } +} diff --git a/projects/ui-material/package.json b/projects/ui-material/package.json new file mode 100644 index 0000000..850ef64 --- /dev/null +++ b/projects/ui-material/package.json @@ -0,0 +1,10 @@ +{ + "name": "@ucap/ng-ui-material", + "version": "0.0.4", + "publishConfig": { + "registry": "https://nexus.loafle.net/repository/npm-ucap/" + }, + "peerDependencies": { + "@ucap/ui-scss": "~0.0.1" + } +} diff --git a/projects/ui-material/scss-bundle.config.json b/projects/ui-material/scss-bundle.config.json new file mode 100644 index 0000000..2a6dfb0 --- /dev/null +++ b/projects/ui-material/scss-bundle.config.json @@ -0,0 +1,11 @@ +{ + "bundlerOptions": { + "entryFile": "./projects/ui-material/src/assets/scss/_material.scss", + "rootDir": "./projects/ui-material/src/assets/scss/", + "outFile": "./dist/ui-material/_material.scss", + "dedupeGlobs": [], + "includePaths": [], + "ignoreImports": ["~@ucap/.*", "~@angular/.*"], + "logLevel": "silent" + } +} diff --git a/projects/ui-material/src/assets/scss/_material.scss b/projects/ui-material/src/assets/scss/_material.scss new file mode 100644 index 0000000..5589d58 --- /dev/null +++ b/projects/ui-material/src/assets/scss/_material.scss @@ -0,0 +1,12 @@ +// Material theming tools +@import '~@angular/material/theming'; + +// Include core Angular Material styles +@include mat-core(); + +@import '~@ucap/ui-scss/ucap'; + +@import 'component/button'; +@import 'component/expansion-panel'; +@import 'component/form-field'; +@import 'component/select'; diff --git a/projects/ui-material/src/assets/scss/component/_button.scss b/projects/ui-material/src/assets/scss/component/_button.scss new file mode 100644 index 0000000..b64c71f --- /dev/null +++ b/projects/ui-material/src/assets/scss/component/_button.scss @@ -0,0 +1,13 @@ +@mixin ucapMatButton( + $min-width, + $height, + $border-radius, + $line-height, + $padding: 0 +) { + min-width: $min-width; + height: $height; + border-radius: $border-radius; + line-height: $line-height; + padding: $padding; +} diff --git a/projects/ui-material/src/assets/scss/component/_expansion-panel.scss b/projects/ui-material/src/assets/scss/component/_expansion-panel.scss new file mode 100644 index 0000000..1c0a3a7 --- /dev/null +++ b/projects/ui-material/src/assets/scss/component/_expansion-panel.scss @@ -0,0 +1,53 @@ +@mixin ucapMatExpansionPanel( + $header-height, + $content-body-padding, + $header-content-order: 0, + $header-indicator-order: 1 +) { + &.mat-expansion-panel-spacing { + margin: 10px 0; + } + .mat-expansion-panel-header { + height: $header-height !important; + padding: 0 17px; + font: { + size: 12px !important; + } + .mat-content { + align-items: center; + order: $header-content-order; + @if $header-content-order == 1 { + margin-left: 18px; + } + span { + margin-left: 6px; + font: { + size: 13px; + } + strong { + color: #e42f66; + } + &.mat-button-wrapper { + font: { + size: 24px; + } + + vertical-align: bottom; + margin: 0; + } + } + } + .mat-expansion-indicator { + align-items: center; + order: $header-indicator-order; + &:after { + vertical-align: super; + } + } + } + .mat-expansion-panel-content { + .mat-expansion-panel-body { + padding: $content-body-padding; + } + } +} diff --git a/projects/ui-material/src/assets/scss/component/_form-field.scss b/projects/ui-material/src/assets/scss/component/_form-field.scss new file mode 100644 index 0000000..b94d821 --- /dev/null +++ b/projects/ui-material/src/assets/scss/component/_form-field.scss @@ -0,0 +1,20 @@ +@mixin ucapMatFormField( + $border: 1px solid #cccccc, + $border-radius: 0, + $width: 100%, + $max-width, + $min-width, + $height, + $line-height, + $background-color: white +) { + border: $border; + border-radius: $border-radius + px; + width: $width; + max-width: $max-width; + min-width: $min-width; + height: $height; + line-height: $line-height; + background-color: $background-color; + @content; +} diff --git a/projects/ui-material/src/assets/scss/component/_select.scss b/projects/ui-material/src/assets/scss/component/_select.scss new file mode 100644 index 0000000..d37ebf3 --- /dev/null +++ b/projects/ui-material/src/assets/scss/component/_select.scss @@ -0,0 +1,5 @@ +@mixin ucapMatSelect($height, $padding) { + height: $height; + line-height: $height; + padding: $padding; +} diff --git a/projects/ui-material/src/public-api.ts b/projects/ui-material/src/public-api.ts new file mode 100644 index 0000000..f96b861 --- /dev/null +++ b/projects/ui-material/src/public-api.ts @@ -0,0 +1,5 @@ +/* + * Public API Surface of ui-material + */ + +export const MATERIAL_NAME = 'material'; diff --git a/projects/ui-material/src/test.ts b/projects/ui-material/src/test.ts new file mode 100644 index 0000000..303b32a --- /dev/null +++ b/projects/ui-material/src/test.ts @@ -0,0 +1,26 @@ +// 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: { + context(path: string, deep?: boolean, filter?: RegExp): { + keys(): string[]; + (id: string): T; + }; +}; + +// 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/ui-material/tsconfig.lib.json b/projects/ui-material/tsconfig.lib.json new file mode 100644 index 0000000..4b5d4af --- /dev/null +++ b/projects/ui-material/tsconfig.lib.json @@ -0,0 +1,23 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": "../../out-tsc/lib", + "target": "es2015", + "declaration": true, + "inlineSources": true, + "types": [], + "lib": [ + "dom", + "es2018" + ] + }, + "angularCompilerOptions": { + "skipTemplateCodegen": true, + "strictMetadataEmit": true, + "enableResourceInlining": true + }, + "exclude": [ + "src/test.ts", + "**/*.spec.ts" + ] +} diff --git a/projects/ui-material/tsconfig.lib.prod.json b/projects/ui-material/tsconfig.lib.prod.json new file mode 100644 index 0000000..cbae794 --- /dev/null +++ b/projects/ui-material/tsconfig.lib.prod.json @@ -0,0 +1,6 @@ +{ + "extends": "./tsconfig.lib.json", + "angularCompilerOptions": { + "enableIvy": false + } +} diff --git a/projects/ui-material/tsconfig.spec.json b/projects/ui-material/tsconfig.spec.json new file mode 100644 index 0000000..16da33d --- /dev/null +++ b/projects/ui-material/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/ui-material/tslint.json b/projects/ui-material/tslint.json new file mode 100644 index 0000000..124133f --- /dev/null +++ b/projects/ui-material/tslint.json @@ -0,0 +1,17 @@ +{ + "extends": "../../tslint.json", + "rules": { + "directive-selector": [ + true, + "attribute", + "lib", + "camelCase" + ], + "component-selector": [ + true, + "element", + "lib", + "kebab-case" + ] + } +} diff --git a/projects/ui-organization/ng-package.json b/projects/ui-organization/ng-package.json index cafcd99..5abf0cf 100644 --- a/projects/ui-organization/ng-package.json +++ b/projects/ui-organization/ng-package.json @@ -3,10 +3,13 @@ "dest": "../../dist/ui-organization", "lib": { "entryFile": "src/public-api.ts", + "styleIncludePaths": ["./src/assets/scss"], "umdModuleIds": { "ngx-perfect-scrollbar": "ngx-perfect-scrollbar", "@ucap/core": "@ucap/core", + "@ucap/api": "@ucap/api", "@ucap/ng-logger": "@ucap/ng-logger", + "@ucap/ng-i18n": "@ucap/ng-i18n", "@ucap/ng-ui": "@ucap/ng-ui" } } diff --git a/projects/ui-organization/package.json b/projects/ui-organization/package.json index 5cacbe3..47b595c 100644 --- a/projects/ui-organization/package.json +++ b/projects/ui-organization/package.json @@ -1,6 +1,6 @@ { "name": "@ucap/ng-ui-organization", - "version": "0.0.27", + "version": "0.0.55", "publishConfig": { "registry": "https://nexus.loafle.net/repository/npm-ucap/" }, @@ -10,8 +10,9 @@ "@angular/core": "^9.0.2", "@angular/material": "^9.0.0", "@ucap/core": "~0.0.1", - "@ucap/uc-scss": "~0.0.1", + "@ucap/ui-scss": "~0.0.1", "@ucap/ng-ui": "~0.0.1", + "@ucap/ng-ui-material": "~0.0.1", "tslib": "^1.10.0" } } diff --git a/projects/ui-organization/scss-bundle.config.json b/projects/ui-organization/scss-bundle.config.json new file mode 100644 index 0000000..34eaf90 --- /dev/null +++ b/projects/ui-organization/scss-bundle.config.json @@ -0,0 +1,11 @@ +{ + "bundlerOptions": { + "entryFile": "./projects/ui-organization/src/assets/scss/_theme.scss", + "rootDir": "./projects/ui-organization/src/assets/scss/", + "outFile": "./dist/ui-organization/_theme.scss", + "dedupeGlobs": [], + "includePaths": [], + "ignoreImports": ["~@ucap/.*", "~@angular/.*"], + "logLevel": "silent" + } +} diff --git a/projects/ui-organization/src/assets/scss/_theme.scss b/projects/ui-organization/src/assets/scss/_theme.scss new file mode 100644 index 0000000..addfa91 --- /dev/null +++ b/projects/ui-organization/src/assets/scss/_theme.scss @@ -0,0 +1,5 @@ +@import '../../lib/components/profile-01.component.theme.scss'; +@import '../../lib/components/profile-list-item-01.component.theme.scss'; +@import '../../lib/components/profile-list.component.theme.scss'; +@import '../../lib/components/search-for-tenant.component.theme.scss'; +@import '../../lib/components/tree.component.theme.scss'; diff --git a/projects/ui-organization/src/lib/components/profile-01.component.html b/projects/ui-organization/src/lib/components/profile-01.component.html index de5cd6e..1ffb2a4 100644 --- a/projects/ui-organization/src/lib/components/profile-01.component.html +++ b/projects/ui-organization/src/lib/components/profile-01.component.html @@ -2,72 +2,118 @@