From 176eb2bbd65c4f8a93632d6347c6fb4b0ccdbed9 Mon Sep 17 00:00:00 2001 From: Park Byung Eun Date: Thu, 28 May 2020 21:52:25 +0900 Subject: [PATCH] 0528 sync --- package-lock.json | 37 ++--- package.json | 14 +- projects/core/package.json | 2 +- projects/core/src/lib/utils/params.util.ts | 24 +++ projects/core/src/lib/utils/sticker.util.ts | 27 ++-- projects/core/src/public-api.ts | 1 + projects/store-chat/package.json | 2 +- .../src/lib/store/chatting/actions.ts | 40 ++++- .../src/lib/store/chatting/effects.ts | 103 ++++++++++++- .../src/lib/store/chatting/reducers.ts | 27 +++- .../store-chat/src/lib/store/room/actions.ts | 14 ++ .../store-chat/src/lib/store/room/effects.ts | 99 ++++++++++--- .../store-chat/src/lib/store/room/reducers.ts | 133 ++++++++++++++++- .../store-chat/src/lib/store/room/state.ts | 8 +- .../store-chat/src/lib/utils/chat.util.ts | 138 ++++++++++++++++++ projects/ui-authentication/package.json | 2 +- .../src/lib/components/login.component.html | 92 +++++++----- projects/ui-chat/package.json | 2 +- projects/ui-chat/src/lib/chat-ui.module.ts | 2 +- .../message-box/file.component.html | 7 +- .../message-box/information.component.html | 81 +++------- .../message-box/information.component.ts | 95 ++++-------- .../message-box/sticker.component.html | 7 +- .../message-box/sticker.component.ts | 12 +- projects/ui-organization/package.json | 2 +- .../profile-list-item-01.component.scss | 14 +- .../profile-list-item-01.component.ts | 6 +- .../profile-list-item-02.component.html | 41 ++++++ .../profile-list-item-02.component.scss | 113 ++++++++++++++ .../profile-list-item-02.component.spec.ts | 25 ++++ .../profile-list-item-02.component.stories.ts | 68 +++++++++ .../profile-list-item-02.component.theme.scss | 24 +++ .../profile-list-item-02.component.ts | 62 ++++++++ .../components/profile-list.component.html | 2 +- .../profile-selection-01.component.html | 38 ++--- .../profile-selection-01.component.scss | 5 + .../profile-selection-01.component.ts | 98 ++++++------- .../search-for-tenant.component.html | 1 + .../search-for-tenant.component.scss | 4 +- .../search-for-tenant.component.stories.ts | 1 - .../components/search-for-tenant.component.ts | 3 + .../src/lib/components/tree.component.html | 16 +- .../src/lib/components/tree.component.ts | 82 ++++++++--- .../src/lib/organization-ui.module.ts | 14 +- .../src/lib/utils/presence.util.ts | 2 +- 45 files changed, 1230 insertions(+), 360 deletions(-) create mode 100644 projects/core/src/lib/utils/params.util.ts create mode 100644 projects/store-chat/src/lib/utils/chat.util.ts create mode 100644 projects/ui-organization/src/lib/components/profile-list-item-02.component.html create mode 100644 projects/ui-organization/src/lib/components/profile-list-item-02.component.scss create mode 100644 projects/ui-organization/src/lib/components/profile-list-item-02.component.spec.ts create mode 100644 projects/ui-organization/src/lib/components/profile-list-item-02.component.stories.ts create mode 100644 projects/ui-organization/src/lib/components/profile-list-item-02.component.theme.scss create mode 100644 projects/ui-organization/src/lib/components/profile-list-item-02.component.ts diff --git a/package-lock.json b/package-lock.json index a3d7176..3f22159 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3314,9 +3314,9 @@ "dev": true }, "@ucap/api-common": { - "version": "0.0.3", - "resolved": "https://nexus.loafle.net/repository/npm-all/@ucap/api-common/-/api-common-0.0.3.tgz", - "integrity": "sha512-rifcCToIXdWZb9R3UXu2bXDqj/KBX3xfxHPFgx+Wp1TBUh6d+xszNYN7+mZbDKKSOYUgpVeuaF8leKkTwXUh9g==", + "version": "0.0.5", + "resolved": "https://nexus.loafle.net/repository/npm-all/@ucap/api-common/-/api-common-0.0.5.tgz", + "integrity": "sha512-7V/Ea4FbLIKE+/ti414Spm6PQS3ZDcsHTZStLLYkMQrU7x+GbrGnHGOcvzzAQtE2SmpoNd3q6JzoYY+CK1eCkA==", "dev": true }, "@ucap/api-external": { @@ -3393,8 +3393,8 @@ "dev": true }, "@ucap/ng-core": { - "version": "file:pack/ucap-ng-core-0.0.1.tgz", - "integrity": "sha512-okuTcVh/9VkF9dA1d/nsPuLL8ft2+4E77mgqfuPI2mI6IA7udQpC+hdMtyqtAN4LmT39iF1VGFv7UJYRK7fN7w==", + "version": "file:pack/ucap-ng-core-0.0.7.tgz", + "integrity": "sha512-ZC6LE3A0bg+REGbzDI/i1ad7mGpKsw6X0UtZ+Q8TUthHNv0DfWEieHFCgfYTRY1u022XyQ4ViOsrq9KunU1vfw==", "dev": true }, "@ucap/ng-i18n": { @@ -3508,8 +3508,8 @@ "dev": true }, "@ucap/ng-store-chat": { - "version": "file:pack/ucap-ng-store-chat-0.0.13.tgz", - "integrity": "sha512-o+BCCSMxneUenRHEW47sSY22+Zt3lyr202Lg4bub9OVRbW5CVohHez8H+JwK+w+Lf8KbqG32V1ZjKLGclTpboA==", + "version": "file:pack/ucap-ng-store-chat-0.0.16.tgz", + "integrity": "sha512-Rwupo2Gqa+4+0ANBZLtup+mdlTU42Tj5gkGnJJ86Vylo4xQcdR+PUdedWZ/lG7DyzrfBc8ON80aUPRikpWUCow==", "dev": true }, "@ucap/ng-store-group": { @@ -3528,13 +3528,8 @@ "dev": true }, "@ucap/ng-ui-authentication": { - "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.9.tgz", - "integrity": "sha512-6qvzcTuylkxVjsqajsLW15laOyOskxVMy238/Ju1yYvwCRyHygwS1i67APoG5tv+SWu+l38f9uWIqzfy7WYHkQ==", + "version": "file:pack/ucap-ng-ui-authentication-0.0.25.tgz", + "integrity": "sha512-/KgMR8JHcnOm+XwMQVhHGud61Hivi/fX0NucxUglsOguYiWL6Ms61FdRezB3wuKs5h/5+zI4QIWLdWdT8GT/Dg==", "dev": true }, "@ucap/ng-ui-group": { @@ -3544,13 +3539,7 @@ }, "@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.55.tgz", - "integrity": "sha512-vfpKd3fbd+I0Od8aB2nIFfjuI7wj3Ziu/uiTEmZxKwZy7uZrNYm59BPbctKW3AQsQ4UtnLofhlBbAA7e9pT80Q==", - "dev": true + "integrity": "sha512-ySPULAbP+nQ65hBG2VWZ2H5Hr7muuTGGNXs6A+S3lsxLaW452wM3GNyUBhvUopr8LaSsoOPpp4nK1JeC0fG6pA==" }, "@ucap/ng-ui-skin-default": { "version": "file:pack/ucap-ng-ui-skin-default-0.0.1.tgz", @@ -3640,9 +3629,9 @@ "dev": true }, "@ucap/protocol-room": { - "version": "0.0.5", - "resolved": "https://nexus.loafle.net/repository/npm-all/@ucap/protocol-room/-/protocol-room-0.0.5.tgz", - "integrity": "sha512-RSzLtnz5JVeDz9Y8gP17+LO6OG2NtLIPpW+JuHnqhfJyB93v2QmqqK5T7NbGYok72jRp4m7cJZEp1tLNYCKcmA==", + "version": "0.0.6", + "resolved": "https://nexus.loafle.net/repository/npm-all/@ucap/protocol-room/-/protocol-room-0.0.6.tgz", + "integrity": "sha512-PaEztUnZgmsH/Vo4JijJxpu9DBSA4SuIBW7y+L8BcBdPtzl49jBolm08+S9vgIr8cf9MtONdU37Al+uOTVki2g==", "dev": true }, "@ucap/protocol-service": { diff --git a/package.json b/package.json index 05c532e..80d691c 100644 --- a/package.json +++ b/package.json @@ -148,7 +148,7 @@ "@types/moment-timezone": "^0.5.12", "@types/node": "^12.12.30", "@ucap/api": "~0.0.1", - "@ucap/api-common": "~0.0.1", + "@ucap/api-common": "~0.0.5", "@ucap/api-external": "~0.0.2", "@ucap/api-message": "~0.0.1", "@ucap/api-prompt": "~0.0.1", @@ -162,7 +162,7 @@ "@ucap/ng-api-message": "file:pack/ucap-ng-api-message-0.0.1.tgz", "@ucap/ng-api-prompt": "file:pack/ucap-ng-api-prompt-0.0.1.tgz", "@ucap/ng-api-public": "file:pack/ucap-ng-api-public-0.0.1.tgz", - "@ucap/ng-core": "file:pack/ucap-ng-core-0.0.1.tgz", + "@ucap/ng-core": "file:pack/ucap-ng-core-0.0.7.tgz", "@ucap/ng-i18n": "file:pack/ucap-ng-i18n-0.0.6.tgz", "@ucap/ng-logger": "file:pack/ucap-ng-logger-0.0.2.tgz", "@ucap/ng-native": "file:pack/ucap-ng-native-0.0.1.tgz", @@ -185,15 +185,15 @@ "@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.11.tgz", - "@ucap/ng-store-chat": "file:pack/ucap-ng-store-chat-0.0.13.tgz", + "@ucap/ng-store-chat": "file:pack/ucap-ng-store-chat-0.0.16.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.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-authentication": "file:pack/ucap-ng-ui-authentication-0.0.25.tgz", + "@ucap/ng-ui-chat": "file:pack/ucap-ng-ui-chat-0.0.12.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-organization": "file:pack/ucap-ng-ui-organization-0.0.83.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", @@ -209,7 +209,7 @@ "@ucap/protocol-option": "~0.0.7", "@ucap/protocol-ping": "~0.0.4", "@ucap/protocol-query": "~0.0.5", - "@ucap/protocol-room": "~0.0.5", + "@ucap/protocol-room": "~0.0.6", "@ucap/protocol-service": "~0.0.4", "@ucap/protocol-status": "~0.0.5", "@ucap/protocol-sync": "~0.0.4", diff --git a/projects/core/package.json b/projects/core/package.json index 57d2918..cb84913 100644 --- a/projects/core/package.json +++ b/projects/core/package.json @@ -1,6 +1,6 @@ { "name": "@ucap/ng-core", - "version": "0.0.1", + "version": "0.0.7", "publishConfig": { "registry": "https://nexus.loafle.net/repository/npm-ucap/" }, diff --git a/projects/core/src/lib/utils/params.util.ts b/projects/core/src/lib/utils/params.util.ts new file mode 100644 index 0000000..2755d5b --- /dev/null +++ b/projects/core/src/lib/utils/params.util.ts @@ -0,0 +1,24 @@ +import { Params } from '@angular/router'; + +export class ParamsUtil { + static getParameter(params: Params, key: string, defaultValue: T): T { + const v = params[key]; + if (undefined === v) { + if (undefined !== defaultValue) { + return defaultValue; + } + return undefined; + } + + switch (typeof defaultValue) { + case 'boolean': + return ((v as string).toLowerCase() === 'true' ? true : false) as any; + case 'number': + return Number(v) as any; + default: + break; + } + + return v; + } +} diff --git a/projects/core/src/lib/utils/sticker.util.ts b/projects/core/src/lib/utils/sticker.util.ts index 0ebee84..a7717af 100644 --- a/projects/core/src/lib/utils/sticker.util.ts +++ b/projects/core/src/lib/utils/sticker.util.ts @@ -10,6 +10,7 @@ export interface StickerFilesInfo { index: string; path: string; } +export const KEY_STICKER_HISTORY = 'ucap::Sticker_History'; export const StickerMap: StickerInfo[] = [ { index: '00', @@ -138,15 +139,18 @@ export const StickerMap: StickerInfo[] = [ } ]; -const ActiveAndOrdering: string[] = ['00', '01', '02', '03', '04', '05']; +export const ActiveAndOrdering: string[] = ['00', '01', '02', '03', '04', '05']; export class StickerUtil { - static getStickerInfoList(): StickerInfo[] { + static getStickerInfoList( + stickerMap: StickerInfo[] = StickerMap, + activeAndOrdering: string[] = ActiveAndOrdering + ): StickerInfo[] { const rtnStickerList: StickerInfo[] = []; - ActiveAndOrdering.forEach(idx => { - const stickerInfos: StickerInfo[] = StickerMap.filter( - sticker => sticker.index === idx && sticker.useYn + activeAndOrdering.forEach((idx) => { + const stickerInfos: StickerInfo[] = stickerMap.filter( + (sticker) => sticker.index === idx && sticker.useYn ); if (!!stickerInfos && stickerInfos.length > 0) { @@ -156,17 +160,4 @@ export class StickerUtil { return rtnStickerList; } - - static getStickerInfoSub(index: string): StickerFilesInfo[] { - const stickerFilesList: StickerFilesInfo[] = []; - const stickerInfos: StickerInfo[] = StickerMap.filter( - sticker => sticker.index === index && sticker.useYn - ); - - if (!!stickerInfos && stickerInfos.length > 0) { - stickerFilesList.concat(stickerInfos[0].fileInfos); - } - - return stickerFilesList; - } } diff --git a/projects/core/src/public-api.ts b/projects/core/src/public-api.ts index 027abf5..3157385 100644 --- a/projects/core/src/public-api.ts +++ b/projects/core/src/public-api.ts @@ -2,6 +2,7 @@ * Public API Surface of core */ +export * from './lib/utils/params.util'; export * from './lib/utils/sticker.util'; export * from './lib/utils/string.util'; export * from './lib/utils/window.util'; diff --git a/projects/store-chat/package.json b/projects/store-chat/package.json index 604968b..1727fba 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.13", + "version": "0.0.16", "publishConfig": { "registry": "https://nexus.loafle.net/repository/npm-ucap/" }, diff --git a/projects/store-chat/src/lib/store/chatting/actions.ts b/projects/store-chat/src/lib/store/chatting/actions.ts index 55cbfff..d98a703 100644 --- a/projects/store-chat/src/lib/store/chatting/actions.ts +++ b/projects/store-chat/src/lib/store/chatting/actions.ts @@ -83,7 +83,22 @@ export const fileInfosFailure = createAction( */ export const addEvent = createAction( '[ucap::chat::chatting] addEvent', - props<{ req: FileInfoRequest }>() + props<{ + roomId: string; + info: Info; + SVC_TYPE?: number; + SSVC_TYPE?: number; + }>() +); +/** + * add new event Success. + */ +export const addEventSuccess = createAction( + '[ucap::chat::chatting] addEvent Success', + props<{ + roomId: string; + info: Info; + }>() ); export const read = createAction( @@ -105,3 +120,26 @@ export const readFailure = createAction( '[ucap::chat::chatting] read Failure', props<{ error: any }>() ); + +export const send = createAction( + '[ucap::chat::chatting] Send', + props<{ senderSeq: string; req: SendEventRequest }>() +); + +export const sendSuccess = createAction( + '[ucap::chat::chatting] Send Success', + props<{ + senderSeq: string; + res: SendEventResponse; + }>() +); + +export const sendFailure = createAction( + '[ucap::chat::chatting] Send Failure', + props<{ error: any }>() +); + +export const sendNotification = createAction( + '[ucap::chat::chatting] Send Notification', + props<{ noti: SendNotification }>() +); diff --git a/projects/store-chat/src/lib/store/chatting/effects.ts b/projects/store-chat/src/lib/store/chatting/effects.ts index f2553e9..ce36b6b 100644 --- a/projects/store-chat/src/lib/store/chatting/effects.ts +++ b/projects/store-chat/src/lib/store/chatting/effects.ts @@ -5,13 +5,16 @@ import { map, catchError, exhaustMap, + concatMap, + withLatestFrom, debounceTime } from 'rxjs/operators'; import { Injectable, Inject } from '@angular/core'; -import { Store } from '@ngrx/store'; +import { Store, select } from '@ngrx/store'; import { Actions, createEffect, ofType } from '@ngrx/effects'; +import { Dictionary } from '@ngrx/entity'; import { EventProtocolService } from '@ucap/ng-protocol-event'; import { RoomProtocolService } from '@ucap/ng-protocol-room'; @@ -27,13 +30,24 @@ import { readSuccess, fileInfos, fileInfosFailure, - fileInfosSuccess + fileInfosSuccess, + send, + sendSuccess, + sendFailure, + addEvent, + addEventSuccess } from './actions'; -import { InfoRequest, ReadResponse, FileType } from '@ucap/protocol-event'; +import { + InfoRequest, + ReadResponse, + FileType, + EventType +} from '@ucap/protocol-event'; import { ModuleConfig } from '../../config/module-config'; import { _MODULE_CONFIG } from '../../config/token'; +import { Chatting } from './state'; @Injectable() export class Effects { @@ -158,6 +172,89 @@ export class Effects { { dispatch: false } ); + addEvent$ = createEffect( + () => { + return this.actions$.pipe( + ofType(addEvent), + withLatestFrom( + this.store.pipe( + select( + (state: any) => + state.chat.chatting.chattings.entities as Dictionary + ) + ), + this.store.pipe( + select((state: any) => state.chat.chatting.activeRoomId) + ) + ), + tap(([action, chattings, activeRoomId]) => { + // Room in chattings state >> event add + if (!!chattings && !!chattings[action.roomId]) { + if (action.info.type === EventType.File) { + // Retrieve event of FileType in rooms + this.store.dispatch( + fileInfos({ + req: { + roomId: action.roomId, + type: FileType.All + } + }) + ); + } + } + + // room > rooms :: finalEvent-Infos refresh + this.store.dispatch( + addEventSuccess({ + roomId: action.roomId, + info: action.info + }) + ); + }) + ); + }, + { dispatch: false } + ); + + send$ = createEffect(() => + this.actions$.pipe( + ofType(send), + concatMap((action) => + this.eventProtocolService.send(action.req).pipe( + map((res) => { + return sendSuccess({ + senderSeq: action.senderSeq, + res + }); + }), + catchError((error) => of(sendFailure({ error }))) + ) + ) + ) + ); + + sendSuccess$ = createEffect( + () => { + return this.actions$.pipe( + ofType(sendSuccess), + tap((action) => { + const res = action.res; + console.log('sendSuccess', action); + + this.store.dispatch( + addEvent({ + roomId: res.roomId, + info: res.info, + SVC_TYPE: res.SVC_TYPE, + SSVC_TYPE: res.SSVC_TYPE + }) + ); + }) + ); + }, + { dispatch: false } + ); + constructor( private actions$: Actions, private store: Store, diff --git a/projects/store-chat/src/lib/store/chatting/reducers.ts b/projects/store-chat/src/lib/store/chatting/reducers.ts index b79e0f5..036c391 100644 --- a/projects/store-chat/src/lib/store/chatting/reducers.ts +++ b/projects/store-chat/src/lib/store/chatting/reducers.ts @@ -15,7 +15,8 @@ import { eventsFailure, readSuccess, fileInfosSuccess, - fileInfosFailure + fileInfosFailure, + addEvent } from './actions'; export const reducer = createReducer( @@ -163,5 +164,29 @@ export const reducer = createReducer( ...state.chattings }) }; + }), + + on(addEvent, (state, action) => { + const roomId = action.roomId; + const eventInfo = action.info; + + const chatting = state.chattings.entities[roomId]; + + if (!!chatting) { + return { + ...state, + chattings: adapterChatting.upsertOne( + { + ...chatting, + eventList: adapterEventList.upsertOne(eventInfo, { + ...chatting.eventList + }) + }, + { ...state.chattings } + ) + }; + } else { + return state; + } }) ); diff --git a/projects/store-chat/src/lib/store/room/actions.ts b/projects/store-chat/src/lib/store/room/actions.ts index 8f70ad3..4e72a6c 100644 --- a/projects/store-chat/src/lib/store/room/actions.ts +++ b/projects/store-chat/src/lib/store/room/actions.ts @@ -119,6 +119,20 @@ export const roomFailure = createAction( '[ucap::chat::room] room Failure', props<{ error: any }>() ); +/** + * Success of rooms2 request + * RoomUserData is detail, short type both. + */ +export const room2Success = createAction( + '[ucap::chat::room] room2 Success', + props<{ + roomInfo: RoomInfo; + roomUserInfo: { + userInfoShortList: UserInfoShort[]; + userInfoList: RoomUserInfo[]; + }; + }>() +); /** * create room diff --git a/projects/store-chat/src/lib/store/room/effects.ts b/projects/store-chat/src/lib/store/room/effects.ts index af07dd6..4326967 100644 --- a/projects/store-chat/src/lib/store/room/effects.ts +++ b/projects/store-chat/src/lib/store/room/effects.ts @@ -28,10 +28,10 @@ import { } from '@ucap/protocol-room'; import { RoomProtocolService } from '@ucap/ng-protocol-room'; - import { SyncProtocolService } from '@ucap/ng-protocol-sync'; import { LoginActions } from '@ucap/ng-store-authentication'; +import { addEventSuccess } from '../Chatting/actions'; import { RoomSelector } from '../state'; @@ -77,8 +77,11 @@ import { delMulti, delMultiSuccess, delMultiFailure, - selectedRoom + selectedRoom, + room2Success } from './actions'; +import { Router } from '@angular/router'; +import { LocaleCode } from '@ucap/core'; @Injectable() export class Effects { @@ -100,8 +103,6 @@ export class Effects { isDetail: false }; - console.log(req); - // retrieve room info this.store.dispatch(room({ req })); @@ -151,13 +152,25 @@ export class Effects { room$ = createEffect(() => { return this.actions$.pipe( ofType(room), - map((action) => action.req), - switchMap((req) => { - return this.roomProtocolService.info(req).pipe( + switchMap((action) => { + const req = action.req; + // // CASE :: RoomUser Data 중 Detail data 만 수집. + // return this.roomProtocolService.info(req).pipe( + // map((res) => + // roomSuccess({ + // roomInfo: res.roomInfo, + // userInfoList: res.userInfoList + // }) + // ), + // catchError((error) => of(roomFailure({ error }))) + // ); + + // CASE :: RoomUser Data 중 Detail data, Short data 수집. + return this.roomProtocolService.info2(req).pipe( map((res) => - roomSuccess({ + room2Success({ roomInfo: res.roomInfo, - userInfoList: res.userInfoList + roomUserInfo: res.roomUserInfo }) ), catchError((error) => of(roomFailure({ error }))) @@ -166,19 +179,40 @@ export class Effects { ); }); - create$ = createEffect(() => - this.actions$.pipe( - ofType(create), - map((action) => action.req), - exhaustMap((req) => { - return this.roomProtocolService.open(req).pipe( - map((res: CreateResponse) => { - return createSuccess({ res }); - }), - catchError((error) => of(createFailure({ error }))) - ); - }) - ) + create$ = createEffect( + () => { + return this.actions$.pipe( + ofType(create), + map((action) => action.req), + exhaustMap((req) => { + return this.roomProtocolService.open(req).pipe( + map((res: CreateResponse) => { + console.log('CreateResponse', res); + + this.store.dispatch(createSuccess({ res })); + + this.router.navigate( + [ + 'chat', + { + outlets: { content: 'chatroom' } + } + ], + { + queryParams: { roomId: res.roomId } + } + ); + + // if (!res.newRoom) { + // } else { + // } + }), + catchError((error) => of(createFailure({ error }))) + ); + }) + ); + }, + { dispatch: false } ); createTimer$ = createEffect(() => @@ -390,9 +424,30 @@ export class Effects { ); }); + /******************************************************************* + * [Chatting Action watching.] + *******************************************************************/ + addEventSuccess$ = createEffect( + () => { + return this.actions$.pipe( + ofType(addEventSuccess), + withLatestFrom(this.store.pipe(select(RoomSelector.rooms))), + map(([action, roomList]) => { + const roomId = action.roomId; + + if (!roomList.find((roomInfo) => roomInfo.roomId === roomId)) { + this.store.dispatch(rooms({ localeCode: LocaleCode.Korean })); + } + }) + ); + }, + { dispatch: false } + ); + constructor( private actions$: Actions, private store: Store, + private router: Router, private syncProtocolService: SyncProtocolService, private roomProtocolService: RoomProtocolService ) {} diff --git a/projects/store-chat/src/lib/store/room/reducers.ts b/projects/store-chat/src/lib/store/room/reducers.ts index 44174c1..b9d7663 100644 --- a/projects/store-chat/src/lib/store/room/reducers.ts +++ b/projects/store-chat/src/lib/store/room/reducers.ts @@ -24,9 +24,12 @@ import { delSuccess, rooms2Success, delMultiSuccess, - updateSuccess + updateSuccess, + room2Success, + createSuccess } from './actions'; -import { userInfo } from 'os'; +import { Info, EventJson } from '@ucap/protocol-event'; +import { ChatUtil } from '../../utils/chat.util'; export const reducer = createReducer( initialState, @@ -136,6 +139,49 @@ export const reducer = createReducer( }; }), + on(room2Success, (state, action) => { + const roomUserMapList: RoomUserMap[] = []; + const roomUserShortMapList: RoomUserShortMap[] = []; + + if ( + !!action.roomUserInfo.userInfoList && + 0 < action.roomUserInfo.userInfoList.length + ) { + roomUserMapList.push({ + roomId: action.roomInfo.roomId, + userInfos: action.roomUserInfo.userInfoList + }); + } + if ( + !!action.roomUserInfo.userInfoShortList && + 0 < action.roomUserInfo.userInfoShortList.length + ) { + roomUserShortMapList.push({ + roomId: action.roomInfo.roomId, + userInfos: action.roomUserInfo.userInfoShortList + }); + } + + return { + ...state, + rooms: adapterRoom.upsertOne(action.roomInfo, { + ...state.rooms + }), + roomUsers: + 0 < roomUserMapList.length + ? adapterRoomUser.upsertMany(roomUserMapList, { + ...state.roomUsers + }) + : state.roomUsers, + roomUsersShort: + 0 < roomUserShortMapList.length + ? adapterRoomUserShort.upsertMany(roomUserShortMapList, { + ...state.roomUsersShort + }) + : state.roomUsersShort + }; + }), + on(excludeUserSuccess, (state, action) => { const roomId = action.roomId; const roomUserMap = state.roomUsers.entities[roomId]; @@ -191,6 +237,41 @@ export const reducer = createReducer( }; }), + on(createSuccess, (state, action) => { + const standby = state.standbyRooms; + const curRoomId = action.res.roomId; + if (standby.findIndex((roomId) => roomId === curRoomId) > -1) { + // Exist. + return state; + } else { + // Not Exist. + return { + ...state, + standbyRooms: [...state.standbyRooms, curRoomId] + }; + } + }), + + on(delSuccess, (state, action) => { + const roomId = action.res.roomId; + const room = state.rooms.entities[roomId]; + + if (!room) { + return state; + } + + return { + ...state, + rooms: adapterRoom.removeOne(roomId, { ...state.rooms }), + roomUsers: adapterRoomUser.removeOne(roomId, { + ...state.roomUsers + }), + roomUsersShort: adapterRoomUserShort.removeOne(roomId, { + ...state.roomUsersShort + }) + }; + }), + on(updateSuccess, (state, action) => { const roomInfo = { ...state.rooms.entities[action.res.roomId], @@ -243,9 +324,9 @@ export const reducer = createReducer( }; }), - /** + /******************************************************************* * [Chatting Action watching.] - */ + *******************************************************************/ on(chattingActions.readSuccess, (state, action) => { const roomId = action.roomId; const trgtUserSeq = action.SENDER_SEQ; @@ -279,7 +360,10 @@ export const reducer = createReducer( userInfos: state.roomUsersShort.entities[roomId].userInfos.map( (roomUserInfo) => { if (roomUserInfo.seq === Number(trgtUserSeq)) { - return { ...roomUserInfo, lastReadEventSeq: action.lastReadSeq }; + return { + ...roomUserInfo, + lastReadEventSeq: action.lastReadSeq + }; } else { return roomUserInfo; } @@ -301,5 +385,44 @@ export const reducer = createReducer( }) : state.roomUsersShort }; + }), + + on(chattingActions.addEventSuccess, (state, action) => { + const roomId = action.roomId; + const info: Info = action.info; + + if (!roomId || !info) { + return state; + } + + const currentRoomInfo = state.rooms.entities[roomId]; + const fixedStandByRooms = state.standbyRooms.filter( + (standbyRoomId) => standbyRoomId !== roomId + ); + + if (!!currentRoomInfo) { + const finalEventMessage: + | string + | null = ChatUtil.convertFinalEventMessage( + action.info.type, + action.info.sentMessageJson || action.info.sentMessage + ); + + const roomInfo = { + ...currentRoomInfo, + finalEventType: info.type, + finalEventDate: info.sendDate, + finalEventMessage, + finalEventSeq: info.seq + } as RoomInfo; + + return { + ...state, + rooms: adapterRoom.upsertOne(roomInfo, { ...state.rooms }), + standbyRooms: fixedStandByRooms + }; + } else { + return state; + } }) ); diff --git a/projects/store-chat/src/lib/store/room/state.ts b/projects/store-chat/src/lib/store/room/state.ts index 8402240..f4123e0 100644 --- a/projects/store-chat/src/lib/store/room/state.ts +++ b/projects/store-chat/src/lib/store/room/state.ts @@ -47,6 +47,7 @@ export interface State { rooms: RoomState; roomUsers: RoomUserState; roomUsersShort: RoomUserShortState; + standbyRooms: string[]; } const roomInitialState: RoomState = adapterRoom.getInitialState({ @@ -60,7 +61,8 @@ const roomUserShortInitialState: RoomUserShortState = adapterRoomUserShort.getIn export const initialState: State = { rooms: roomInitialState, roomUsers: roomUserInitialState, - roomUsersShort: roomUserShortInitialState + roomUsersShort: roomUserShortInitialState, + standbyRooms: [] }; const { @@ -128,6 +130,10 @@ export function selectors(selector: Selector) { ); } ), + standbyRooms: createSelector( + selector, + (state: State) => state.standbyRooms + ), unreadTotal: createSelector( selectRooms, selectAllForRoom, diff --git a/projects/store-chat/src/lib/utils/chat.util.ts b/projects/store-chat/src/lib/utils/chat.util.ts new file mode 100644 index 0000000..11a6cc2 --- /dev/null +++ b/projects/store-chat/src/lib/utils/chat.util.ts @@ -0,0 +1,138 @@ +import { + EventJson, + EventType, + FileEventJson, + FileType, + VideoConferenceEventJson, + VideoConferenceContentsType, + MassTextEventJson, + TranslationEventJson, + MassTranslationEventJson, + PlanEventJson, + PlanContentType +} from '@ucap/protocol-event'; + +export class ChatUtil { + public static convertFinalEventMessage( + eventType: EventType, + finalEventMessage: EventJson + ): string | null { + let eventMessage: string = null; + + switch (eventType) { + case EventType.Join: + case EventType.Exit: + case EventType.ForcedExit: + case EventType.RenameRoom: + case EventType.NotificationForTimerRoom: + case EventType.GuideForRoomTimerChanged: + { + /** + * 해당 타입은 메시지를 갱신하지 않는다. + * @description Edit with ui-chat > messages.component.ts + */ + } + break; + case EventType.Sticker: + { + eventMessage = '스티커'; + } + break; + case EventType.File: + { + const m = finalEventMessage as FileEventJson; + + if (FileType.Image === m.fileType) { + eventMessage = '이미지'; + } else { + eventMessage = '첨부파일'; + } + } + break; + case EventType.VideoConference: + { + const m = finalEventMessage as VideoConferenceEventJson; + switch (m.contents) { + case VideoConferenceContentsType.Now: + eventMessage = '화상회의가 개설되었습니다.'; + break; + case VideoConferenceContentsType.New: + eventMessage = '화상회의가 등록되었습니다.'; + break; + case VideoConferenceContentsType.Update: + eventMessage = '화상회의가 수정되었습니다.'; + break; + case VideoConferenceContentsType.Delete: + eventMessage = '화상회의가 취소되었습니다.'; + break; + default: + eventMessage = '화상회의'; + break; + } + } + break; + case EventType.MassText: + { + const m = finalEventMessage as MassTextEventJson; + eventMessage = m.content; + } + break; + case EventType.Translation: + { + const m = finalEventMessage as TranslationEventJson; + eventMessage = m.original; + } + break; + case EventType.MassTranslation: + { + const m = finalEventMessage as MassTranslationEventJson; + eventMessage = m.original; + } + break; + case EventType.Plan: + { + const m = finalEventMessage as PlanEventJson; + switch (m.contents) { + case PlanContentType.New: + eventMessage = '새로운 일정이 등록되었습니다.'; + break; + case PlanContentType.Update: + eventMessage = '일정이 수정되었습니다.'; + break; + case PlanContentType.Delete: + eventMessage = '일정이 취소되었습니다.'; + break; + default: + eventMessage = '일정이 업데이트 되었습니다.'; + break; + } + } + break; + case EventType.NotificationForiOSCapture: + { + const m = finalEventMessage as string; + eventMessage = `${m}님이 대화내용을 캡쳐하였습니다.`; + } + break; + + case EventType.AllimElephant: // [daesang] 알림 + { + eventMessage = '코끼리 알림'; + } + break; + case EventType.AllimTms: // [daesang] 알림 + { + eventMessage = 'TMS 알림'; + } + break; + default: + { + const m = finalEventMessage as string; + eventMessage = m; + } + + break; + } + return eventMessage; + } +} diff --git a/projects/ui-authentication/package.json b/projects/ui-authentication/package.json index d8a2712..166ff6e 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.24", + "version": "0.0.25", "publishConfig": { "registry": "https://nexus.loafle.net/repository/npm-ucap/" }, diff --git a/projects/ui-authentication/src/lib/components/login.component.html b/projects/ui-authentication/src/lib/components/login.component.html index b40cc05..fdb2258 100644 --- a/projects/ui-authentication/src/lib/components/login.component.html +++ b/projects/ui-authentication/src/lib/components/login.component.html @@ -6,7 +6,7 @@ class="ucap-authentication-login-input-field" [style.display]="!!fixedCompanyCode ? 'none' : 'block'" > - + {{ 'login.fields.company' | ucapI18n }}