diff --git a/documents/업무/6월/0601.txt b/documents/업무/6월/1째주/0601.txt similarity index 100% rename from documents/업무/6월/0601.txt rename to documents/업무/6월/1째주/0601.txt diff --git a/documents/업무/6월/0602.txt b/documents/업무/6월/1째주/0602.txt similarity index 88% rename from documents/업무/6월/0602.txt rename to documents/업무/6월/1째주/0602.txt index 8f021a6..9de71f4 100644 --- a/documents/업무/6월/0602.txt +++ b/documents/업무/6월/1째주/0602.txt @@ -28,4 +28,15 @@ if (!!buddies && buddies.length > 0) { }); console.log(userSeqsForAdd); -} \ No newline at end of file +} + +update-user-dialog +manage-dialog + +index.page +sidenav.page + updateMember + copy + move + add + create diff --git a/documents/업무/6월/1째주/0603.txt b/documents/업무/6월/1째주/0603.txt new file mode 100644 index 0000000..c80dc76 --- /dev/null +++ b/documents/업무/6월/1째주/0603.txt @@ -0,0 +1,107 @@ +프로필 + 나와의 채팅 진행 (O) + 이벤트 + 파라미터(loginres, userseq ) +채팅 + 대화 이벤트 + 답장 + 대화전달 + 대화복사 + + 대화 나에게 전달 + 액션 + 대화 전달 + 타겟 대화방 번호 + 타겟 대화상대 번호 + roomSeq = -999 + eventType = c + sentMassage + 대화방 오픈 + 대화방 오픈 프로토콜 호출 + divCd: 'forwardOpen' + 오픈성공 + 파일 타입 + 텍스트 타입 + 이벤트 전송 + 대화방 선택 처리 + + 대화방 오픈 결과 + 대화 전송 + + +액션 정의 + forward => file type, bundle type, text type + openAfterSend => file type, text type + openAfter => event send + roomSelected => + +이펙트 + chat foward + openAfterSend + + selectedRoom + selectedRoomValidate + room2 success + events + events success + read + fileInfos + read success + fileInfos success +리듀서 구현 + +팝업 조직도 + + + + + // forwardAfterRoomOpen$ = createEffect(() => { + // return this.actions$.pipe( + // ofType(forwardAfterRoomOpen), + // map((action) => + // RoomActions.create({ + // req: { divCd: 'forwardOpen', userSeqs: action.trgtUserSeqs } + // }) + // ), + // exhaustMap((action) => { + // return []; + // }) + // ); + // }); + + + /** forward */ +export const forward = createAction( + '[ucap::chat::chatting] Forward', + props<{ + senderSeq: string; + req: SendRequest; + trgtUserSeqs?: string[]; + trgtRoomSeq?: string; + }>() +); +/** chat forward failure */ +export const forwardFailure = createAction( + '[ucap::chat::chatting] Forward failure', + props<{ error: any }>() +); + +export const forwardAfterRoomOpen = createAction( + '[ucap::chat::chatting] Forward after room open', + props<{ + senderSeq: string; + req: SendRequest; + trgtUserSeqs?: string[]; + trgtRoomSeq?: string; + }>() +); + +export const roomOpenAfterForward = createAction( + '[ucap::chat::chatting] Room open after forward', + props<{ + senderSeq: string; + req: SendRequest; + trgtUserSeqs?: string[]; + trgtRoomSeq?: string; + }>() +); diff --git a/documents/업무/6월/1째주/0604.txt b/documents/업무/6월/1째주/0604.txt new file mode 100644 index 0000000..42c84c6 --- /dev/null +++ b/documents/업무/6월/1째주/0604.txt @@ -0,0 +1,26 @@ +tap component + teanant search + bySearch, searchword + search result + bySearch + expansion + + room list + ucap-chat-room-list-item-01 + selection user + +기존 절차 + 메세지 전송 + 대화방 대화 추가 + 대화방 갱신 + 대화방 마지막 대화 갱신 + +roomOpenAfterForward + newInfo + appedInfoList + newEventMessage + updateRoomForNewEventMessage + selectedRoom + clearEvent + info + diff --git a/documents/업무/6월/1째주/0605.txt b/documents/업무/6월/1째주/0605.txt new file mode 100644 index 0000000..b1f5239 --- /dev/null +++ b/documents/업무/6월/1째주/0605.txt @@ -0,0 +1,70 @@ +대화 복사 + 일반 텍스트 + 대용량 텍스트 + 일반 번역 텍스트 + 대용량 번역 텍스트 + +ucap prj + protocol-event isRecall fnc 데이터형 number로 변경 + +daesang recall effect + cancel (roomseq, eventseq, deviceType) + cnacelNotification() + recallInfoList - reducer + infoList 해당 메세지 갱신 + 대화방 갱신 + +대화방 eventList 갱신 + +대화방 새로고침 + 액션 생성 + 대화 삭제 + 대화 수정 -> 대화 회수 + 이펙트 + 대화방 새로고침 + info2 호출 파라미터 + roomId, isDetail: false, localeCode: loginRes.localeCode + 리듀서 + room2Success + + +infoRequest + roomId: string + isDetail: boolean + localeCode + +InfoResponse + roomId: string; + + + +// /** +// * Refresh of Room request +// */ +// export const roomRefresh = createAction( +// '[ucap::chat::room] room refresh ', +// props() +// ); +// export const roomRefreshFailure = createAction( +// '[ucap::chat::room] room refresh Failure', +// props<{ error: any }>() +// ); + + roomRefresh$ = createEffect(() => { + return this.actions$.pipe( + ofType(roomRefresh), + switchMap((action) => { + const req = action.req; + + return this.roomProtocolService.info2(req).pipe( + map((res) => + room2Success({ + roomInfo: res.roomInfo, + roomUserInfo: res.roomUserInfo + }) + ), + catchError((error) => of(roomFailure({ error }))) + ); + }) + ); + }); \ No newline at end of file diff --git a/documents/업무/6월/1째주/backup/chat/actions.ts b/documents/업무/6월/1째주/backup/chat/actions.ts new file mode 100644 index 0000000..6dc8976 --- /dev/null +++ b/documents/업무/6월/1째주/backup/chat/actions.ts @@ -0,0 +1,234 @@ +import { createAction, props } from '@ngrx/store'; + +import { + Info, + InfoRequest as EventInfoRequest, + InfoResponse as EventInfoResponse, + SendRequest as SendEventRequest, + SendResponse as SendEventResponse, + ReadRequest, + DelRequest, + DelResponse, + CancelRequest, + CancelResponse, + SendNotification, + ReadNotification, + CancelNotification, + DelNotification, + EventJson, + ReadResponse, + SendRequest +} from '@ucap/protocol-event'; + +import { + InfoRequest as FileInfoRequest, + InfoResponse as FileInfoResponse, + FileDownloadInfo, + FileInfo +} from '@ucap/protocol-file'; + +/** + * retrieve list of event + */ +export const events = createAction( + '[ucap::chat::chatting] events', + props<{ req: EventInfoRequest }>() +); +/** + * Success of events request + */ +export const eventsSuccess = createAction( + '[ucap::chat::chatting] events Success', + props<{ + eventInfoList: Info[]; + res: EventInfoResponse; + remainEvent: boolean; + }>() +); +/** + * Failure of events request + */ +export const eventsFailure = createAction( + '[ucap::chat::chatting] events Failure', + props<{ roomId: string; error: any }>() +); +/** + * retrieve list of event + */ +export const moreEvents = createAction( + '[ucap::chat::chatting] events more', + props<{ roomId: string }>() +); + +/** + * retrieve list of file information + */ +export const fileInfos = createAction( + '[ucap::chat::chatting] fileInfos', + props<{ req: FileInfoRequest }>() +); +/** + * Success of fileInfos request + */ +export const fileInfosSuccess = createAction( + '[ucap::chat::chatting] fileInfos Success', + props<{ + fileInfoList: FileInfo[]; + fileInfoCheckList: FileDownloadInfo[]; + res: FileInfoResponse; + }>() +); +/** + * Failure of fileInfos request + */ +export const fileInfosFailure = createAction( + '[ucap::chat::chatting] fileInfos Failure', + props<{ roomId: string; error: any }>() +); + +/** + * add new event + */ +export const addEvent = createAction( + '[ucap::chat::chatting] addEvent', + 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( + '[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 }>() +); + +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 }>() +); + +/** 대화 삭제 */ +export const del = createAction( + '[ucap::chat::chatting] Delete', + props() +); +export const delFailure = createAction( + '[ucap::chat::chatting] Delete Failure', + props<{ error: any }>() +); +export const delNotification = createAction( + '[ucap::chat::chatting] Delete Notification || Response', + props<{ noti: DelNotification | DelResponse }>() +); +/** 대화 삭제시 열린 대화방의 대화 내용 갱신 */ +export const delEventList = createAction( + '[ucap::chat::chatting] Delete InfoList', + props<{ + roomId: string; + eventSeqs: number[]; + }>() +); + +/** forward */ +export const forward = createAction( + '[ucap::chat::chatting] Forward', + props<{ + senderSeq: string; + req: SendRequest; + trgtUserSeqs?: string[]; + trgtRoomSeq?: string; + }>() +); +/** chat forward failure */ +export const forwardFailure = createAction( + '[ucap::chat::chatting] Forward failure', + props<{ error: any }>() +); + +export const forwardAfterRoomOpen = createAction( + '[ucap::chat::chatting] Forward after room open', + props<{ + senderSeq: string; + req: SendRequest; + trgtUserSeqs?: string[]; + trgtRoomSeq?: string; + }>() +); + +export const roomOpenAfterForward = createAction( + '[ucap::chat::chatting] Room open after forward', + props<{ + senderSeq: string; + req: SendRequest; + trgtUserSeqs?: string[]; + trgtRoomSeq?: string; + }>() +); + +/** 대화 회수 */ +export const cancel = createAction( + '[ucap::chat::chatting] Cancel', + props() +); +export const cancelFailure = createAction( + '[ucap::chat::chatting] Cancel Failure', + props<{ error: any }>() +); +export const cancelNotification = createAction( + '[ucap::chat::chatting] Cancel Notification || Response', + props<{ noti: CancelNotification | CancelResponse }>() +); +/** 대화 회수시 열린 대화방의 대화 내용 갱신 */ +export const updateEventList = createAction( + '[ucap::chat::chatting] Update InfoList', + props<{ + roomId: string; + eventSeq: number; + sentMessage: string; + }>() +); diff --git a/documents/업무/6월/1째주/backup/chat/effects.ts b/documents/업무/6월/1째주/backup/chat/effects.ts new file mode 100644 index 0000000..37cfe8e --- /dev/null +++ b/documents/업무/6월/1째주/backup/chat/effects.ts @@ -0,0 +1,533 @@ +import { of } from 'rxjs'; +import { + tap, + switchMap, + map, + catchError, + exhaustMap, + concatMap, + withLatestFrom, + debounceTime, + mergeMap +} from 'rxjs/operators'; + +import { Injectable, Inject } from '@angular/core'; + +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 { + RoomType, + OpenResponse as CreateResponse, + Open3Response as CreateTimerResponse, + ExitResponse as DeleteResponse, + ExitAllResponse as DeleteMultiResponse +} from '@ucap/protocol-room'; +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, + send, + sendSuccess, + sendFailure, + addEvent, + addEventSuccess, + del, + delNotification, + delFailure, + delEventList, + moreEvents, + forward, + forwardFailure, + forwardAfterRoomOpen, + roomOpenAfterForward, + cancel, + cancelFailure, + cancelNotification, + updateEventList +} from './actions'; + +import { + InfoRequest, + ReadResponse, + FileType, + EventType, + DelResponse, + SendResponse, + CancelResponse +} from '@ucap/protocol-event'; + +import { ModuleConfig } from '../../config/module-config'; +import { _MODULE_CONFIG } from '../../config/token'; +import { Chatting } from './state'; +import { ChattingSelector, RoomSelector } from '../state'; +import { Router } from '@angular/router'; +import { LocaleCode } from '@ucap/core'; +import { LoginSelector } from '@ucap/ng-store-authentication'; +import { I18nService } from '@ucap/ng-i18n'; + +@Injectable() +export class Effects { + 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 } + ); + + moreEvents$ = createEffect( + () => { + return this.actions$.pipe( + ofType(moreEvents), + mergeMap( + (action) => + of(action).pipe( + withLatestFrom( + this.store.pipe( + select(ChattingSelector.eventList, action.roomId) + ) + ) + ), + (action, latestStoreData) => latestStoreData + ), + tap(([req, eventList]) => { + if (!!eventList && eventList.length > 0) { + this.store.dispatch( + events({ + req: { + roomId: req.roomId, + baseSeq: eventList.sort((a, b) => a.seq - b.seq)[0].seq, + requestCount: + this.moduleConfig?.eventRequestDefaultCount || 50 + } as InfoRequest + }) + ); + } + }) + ); + }, + { dispatch: false } + ); + + read$ = createEffect( + () => { + return this.actions$.pipe( + ofType(read), + exhaustMap((req) => + this.eventProtocolService.read(req).pipe( + map((res: ReadResponse) => { + // room user lastReadEventSeq reset. + this.store.dispatch(readSuccess(res)); + // room noReadCount reset. + this.store.dispatch( + RoomActions.updateUnreadCount({ + roomId: res.roomId + }) + ); + }), + 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 } + ); + + 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; + + this.store.dispatch( + addEvent({ + roomId: res.roomId, + info: res.info, + SVC_TYPE: res.SVC_TYPE, + SSVC_TYPE: res.SSVC_TYPE + }) + ); + }) + ); + }, + { dispatch: false } + ); + + /******************************************************************* + * [Room Action watching.] + *******************************************************************/ + selectedRoomSuccess$ = createEffect( + () => { + return this.actions$.pipe( + ofType(RoomActions.selectedRoomSuccess), + 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 } + ); + + del$ = createEffect(() => + this.actions$.pipe( + ofType(del), + exhaustMap((req) => + this.eventProtocolService.del(req).pipe( + map((res: DelResponse) => { + return delNotification({ noti: res }); + }), + catchError((error) => of(delFailure({ error }))) + ) + ) + ) + ); + + delNotification$ = createEffect( + () => { + return this.actions$.pipe( + ofType(delNotification), + map((action) => action.noti), + withLatestFrom(this.store.pipe(select(ChattingSelector.activeRoomId))), + tap(([noti, activeRoomId]) => { + // 현재 방이 오픈되어 있으면 방내용 갱신 + const roomId = noti.roomId; + + if (!!activeRoomId && activeRoomId === roomId) { + this.store.dispatch( + delEventList({ roomId, eventSeqs: [noti.eventSeq] }) + ); + } + + // 대화 > 리스트의 항목 갱신 + this.store.dispatch( + RoomActions.room({ + req: { + roomId: noti.roomId, + isDetail: false, + localeCode: this.i18nService.currentLng.toUpperCase() as LocaleCode + } + }) + ); + }) + ); + }, + { dispatch: false } + ); + + forward$ = createEffect( + () => { + return this.actions$.pipe( + ofType(forward), + tap((action) => { + if (!!action.trgtRoomSeq) { + // 대화전달 후 방오픈. Exist roomSeq. + if (action.req.eventType === EventType.File) { + // file share request action + } else { + this.store.dispatch(roomOpenAfterForward(action)); + } + } else if (!!action.trgtUserSeqs && action.trgtUserSeqs.length > 0) { + // 방오픈 후 대화전달. + this.store.dispatch(forwardAfterRoomOpen(action)); + } + }) + ); + }, + { dispatch: false } + ); + + forwardAfterRoomOpen$ = createEffect( + () => { + let createRes: CreateResponse; + return this.actions$.pipe( + ofType(forwardAfterRoomOpen), + exhaustMap((actionReq) => { + return this.roomProtocolService + .open({ divCd: 'forwardOpen', userSeqs: actionReq.trgtUserSeqs }) + .pipe( + map((res: CreateResponse) => { + createRes = res; + this.store.dispatch(RoomActions.createSuccess({ res })); + }), + map(() => { + if (actionReq.req.eventType === EventType.File) { + // file share request action + } else { + this.store.dispatch( + send({ + senderSeq: actionReq.senderSeq, + req: { + roomId: createRes.roomId, + eventType: actionReq.req.eventType, + sentMessage: actionReq.req.sentMessage + } + }) + ); + } + }), + catchError((error) => of(RoomActions.createFailure({ error }))) + ); + }) + ); + }, + { dispatch: false } + ); + + roomOpenAfterForward$ = createEffect( + () => { + return this.actions$.pipe( + ofType(roomOpenAfterForward), + exhaustMap((action) => { + return this.eventProtocolService + .send({ + roomId: action.trgtRoomSeq, + eventType: action.req.eventType, + sentMessage: action.req.sentMessage + }) + .pipe( + map((res: SendResponse) => { + this.store.dispatch( + addEvent({ + roomId: res.roomId, + info: res.info, + SVC_TYPE: res.SVC_TYPE, + SSVC_TYPE: res.SSVC_TYPE + }) + ); + this.store.dispatch( + RoomActions.selectedRoom({ + roomId: res.roomId, + localeCode: this.i18nService.currentLng.toUpperCase() as LocaleCode + }) + ); + }), + catchError((error) => of(RoomActions.createFailure({ error }))) + ); + }) + ); + }, + { dispatch: false } + ); + + cancel$ = createEffect(() => + this.actions$.pipe( + ofType(cancel), + exhaustMap((req) => + this.eventProtocolService.cancel(req).pipe( + map((res: CancelResponse) => { + return delNotification({ noti: res }); + }), + catchError((error) => of(delFailure({ error }))) + ) + ) + ) + ); + + cancelNotification$ = createEffect( + () => { + return this.actions$.pipe( + ofType(cancelNotification), + withLatestFrom(this.store.pipe(select(ChattingSelector.activeRoomId))), + tap(([action, activeRoomId]) => { + // 현재 방이 오픈되어 있으면 방내용 갱신 + if ( + !!activeRoomId && + activeRoomId.localeCompare(action.noti.roomId) === 0 + ) { + this.store.dispatch( + updateEventList({ + roomId: action.noti.roomId, + eventSeq: action.noti.eventSeq, + sentMessage: this.i18nService.t('event.recalled') + }) + ); + } + + // 대화 > 리스트의 항목 갱신 + this.store.dispatch( + RoomActions.room({ + req: { + roomId: action.noti.roomId, + isDetail: false, + localeCode: this.i18nService.currentLng.toUpperCase() as LocaleCode + } + }) + ); + }) + ); + }, + { dispatch: false } + ); + + constructor( + private actions$: Actions, + private store: Store, + private router: Router, + @Inject(_MODULE_CONFIG) private moduleConfig: ModuleConfig, + private roomProtocolService: RoomProtocolService, + private eventProtocolService: EventProtocolService, + private fileProtocolService: FileProtocolService, + private i18nService: I18nService + ) { + this.i18nService.setDefaultNamespace('chat'); + } +} diff --git a/documents/업무/6월/1째주/backup/chat/reducers.ts b/documents/업무/6월/1째주/backup/chat/reducers.ts new file mode 100644 index 0000000..cb9b317 --- /dev/null +++ b/documents/업무/6월/1째주/backup/chat/reducers.ts @@ -0,0 +1,253 @@ +import { createReducer, on } from '@ngrx/store'; + +import { + initialState, + adapterChatting, + adapterEventList, + Chatting, + adapterFileInfoList, + adapterFileInfoCheckList +} from './state'; + +import * as RoomActions from '../room/actions'; +import { + eventsSuccess, + eventsFailure, + fileInfosSuccess, + fileInfosFailure, + addEvent, + delEventList, + updateEventList +} from './actions'; +import { Info, EventJson, EventType } from '@ucap/protocol-event'; + +export const reducer = createReducer( + initialState, + + 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 + }) + }; + }), + + 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; + } + }), + + /******************************************************************* + * [Room Action watching.] + *******************************************************************/ + on(RoomActions.selectedRoomSuccess, (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(RoomActions.close, (state, action) => { + const roomIds = action.roomIds; + + return { + ...state, + chattings: adapterChatting.removeMany(roomIds, { ...state.chattings }) + }; + }), + + on(delEventList, (state, action) => { + const roomId = action.roomId; + const chatting = state.chattings.entities[roomId]; + + return { + ...state, + chattings: adapterChatting.upsertOne( + { + ...chatting, + eventList: adapterEventList.removeMany(action.eventSeqs, { + ...chatting.eventList + }) + }, + { ...state.chattings } + ) + }; + }), + + on(updateEventList, (state, action) => { + const roomId = action.roomId; + const eventSeq = action.eventSeq; + const sentMessage = action.sentMessage; + const chatting = state.chattings.entities[roomId]; + + const statusEventInfo: Info = { + ...chatting.eventList[eventSeq], + type: EventType.RecalledMessage, + sentMessage + }; + + return { + ...state, + chattings: adapterChatting.upsertOne( + { + ...chatting, + eventList: adapterEventList.updateOne( + { id: eventSeq, changes: statusEventInfo }, + { + ...chatting.eventList + } + ) + }, + { ...state.chattings } + ) + }; + }) +); diff --git a/documents/업무/6월/1째주/backup/etc/forward.dialog.component.html b/documents/업무/6월/1째주/backup/etc/forward.dialog.component.html new file mode 100644 index 0000000..f6736bd --- /dev/null +++ b/documents/업무/6월/1째주/backup/etc/forward.dialog.component.html @@ -0,0 +1,93 @@ +
+ +
+ {{ 'dialog.title.newChatRoom' | ucapI18n }} +
+
+ +
+ + +
+ +
+ + + + + +

그룹

+
+
+ +
+
+ + +

대화방 리스트

+
+
+
+ +
+
+ + +
+
+
+ +
+
+ + + +
+
+
diff --git a/documents/업무/6월/1째주/backup/etc/forward.dialog.component.scss b/documents/업무/6월/1째주/backup/etc/forward.dialog.component.scss new file mode 100644 index 0000000..cccbc78 --- /dev/null +++ b/documents/업무/6월/1째주/backup/etc/forward.dialog.component.scss @@ -0,0 +1,9 @@ +.dialog-container { + width: 100%; + height: 100%; + + .dialog-body { + width: 100%; + height: 100%; + } +} diff --git a/documents/업무/6월/1째주/backup/etc/forward.dialog.component.spec.ts b/documents/업무/6월/1째주/backup/etc/forward.dialog.component.spec.ts new file mode 100644 index 0000000..831cf64 --- /dev/null +++ b/documents/업무/6월/1째주/backup/etc/forward.dialog.component.spec.ts @@ -0,0 +1,26 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { By } from '@angular/platform-browser'; +import { DebugElement } from '@angular/core'; + +import { ForwardDialogComponent } from './forward.dialog.component'; + +describe('app::ui-chat::ForwardDialogComponent', () => { + let component: ForwardDialogComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ForwardDialogComponent] + }).compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(ForwardDialogComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/documents/업무/6월/1째주/backup/etc/forward.dialog.component.ts b/documents/업무/6월/1째주/backup/etc/forward.dialog.component.ts new file mode 100644 index 0000000..a0a6809 --- /dev/null +++ b/documents/업무/6월/1째주/backup/etc/forward.dialog.component.ts @@ -0,0 +1,123 @@ +import { Subject } from 'rxjs'; + +import { + Component, + OnInit, + OnDestroy, + ChangeDetectionStrategy, + ChangeDetectorRef, + Inject, + Input +} from '@angular/core'; + +import { + MatDialogRef, + MAT_DIALOG_DATA, + MatDialog +} from '@angular/material/dialog'; + +import { UserInfo, GroupDetailData } from '@ucap/protocol-sync'; +import { UserInfoSS, UserInfoF, UserInfoDN } from '@ucap/protocol-query'; +import { UserInfo as RoomUserInfo } from '@ucap/protocol-room'; +import { MatStepper } from '@angular/material/stepper'; +import { I18nService } from '@ucap/ng-i18n'; +import { GroupActions } from '@ucap/ng-store-group'; +import { + AlertDialogComponent, + AlertDialogData, + AlertDialogResult +} from '@ucap/ng-ui'; +import { environment } from '@environments'; + +export type UserInfoTypes = + | UserInfo + | UserInfoSS + | UserInfoF + | UserInfoDN + | RoomUserInfo; + +export interface ForwardDialogData {} +export interface ForwardDialogResult { + userSeqs: string[]; + isTimer: boolean | undefined; +} + +@Component({ + selector: 'app-dialog-chat-forward', + templateUrl: './forward.dialog.component.html', + styleUrls: ['./forward.dialog.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ForwardDialogComponent implements OnInit, OnDestroy { + currentStep = 0; + maxChatRoomUser: number; + + isTimer: boolean | undefined; + selectedUserList: UserInfoTypes[] = []; + + constructor( + public dialogRef: MatDialogRef, + @Inject(MAT_DIALOG_DATA) public data: ForwardDialogData, + private i18nService: I18nService, + public dialog: MatDialog, + private changeDetectorRef: ChangeDetectorRef + ) { + this.maxChatRoomUser = environment.productConfig.chat.maxChatRoomUser; + } + + ngOnInit(): void {} + + ngOnDestroy(): void {} + + onClosed(event: MouseEvent): void { + this.dialogRef.close(); + } + + onCancel() { + + } + onConfirm() { + + } + + onChangeUserList(data: { checked: boolean; userInfo: UserInfoSS }) { + const i = this.selectedUserList.findIndex( + (u) => u.seq === data.userInfo.seq + ); + + if (data.checked) { + if (-1 === i) { + this.selectedUserList = [...this.selectedUserList, data.userInfo]; + } + } else { + if (-1 < i) { + this.selectedUserList = this.selectedUserList.filter( + (u) => u.seq !== data.userInfo.seq + ); + } + } + } + + onChangeGroupList(params: { + isChecked: boolean; + groupBuddyList: { group: GroupDetailData; buddyList: UserInfo[] }; + }) { + if (params.isChecked) { + params.groupBuddyList.buddyList.forEach((item) => { + if ( + this.selectedUserList.filter((user) => user.seq === item.seq) + .length === 0 + ) { + this.selectedUserList = [...this.selectedUserList, item]; + } + }); + } else { + this.selectedUserList = this.selectedUserList.filter( + (item) => + params.groupBuddyList.buddyList.filter((del) => del.seq === item.seq) + .length === 0 + ); + } + } + +} diff --git a/documents/업무/6월/1째주/backup/etc/room-list-item-02.component.html b/documents/업무/6월/1째주/backup/etc/room-list-item-02.component.html new file mode 100644 index 0000000..6e4546e --- /dev/null +++ b/documents/업무/6월/1째주/backup/etc/room-list-item-02.component.html @@ -0,0 +1,31 @@ +
+
+
+ +
+
+
+
+
{{ roomName }}
+
+ ({{ roomInfo.joinUserCount }}) +
+
+
{{ roomInfo.finalEventMessage }}
+
+ + + +
diff --git a/documents/업무/6월/1째주/backup/etc/room-list-item-02.component.scss b/documents/업무/6월/1째주/backup/etc/room-list-item-02.component.scss new file mode 100644 index 0000000..03c20f4 --- /dev/null +++ b/documents/업무/6월/1째주/backup/etc/room-list-item-02.component.scss @@ -0,0 +1,34 @@ +.ucap-chat-room-list-item2 { + width: 100%; + height: 100%; + + display: flex; + flex-direction: row; + align-content: center; + justify-content: space-between; + + .ucap-chat-room-list-item2-profile-image { + display: inline-flex; + position: relative; + align-self: center; + } + .ucap-chat-room-list-item2-info { + display: flex; + flex-direction: column; + justify-content: center; + .roomName { + display: flex; + flex-direction: row; + .ico-chat-list { + .ico-off { + &-false { + display: inline-block; + } + &-true { + display: none; + } + } + } + } + } +} diff --git a/documents/업무/6월/1째주/backup/etc/room-list-item-02.component.spec.ts b/documents/업무/6월/1째주/backup/etc/room-list-item-02.component.spec.ts new file mode 100644 index 0000000..4e535a6 --- /dev/null +++ b/documents/업무/6월/1째주/backup/etc/room-list-item-02.component.spec.ts @@ -0,0 +1,24 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { RoomListItem02Component } from './room-list-item-02.component'; + +describe('ucap::chat::RoomListItem01Component', () => { + let component: RoomListItem02Component; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [RoomListItem02Component] + }).compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(RoomListItem02Component); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/documents/업무/6월/1째주/backup/etc/room-list-item-02.component.stories.ts b/documents/업무/6월/1째주/backup/etc/room-list-item-02.component.stories.ts new file mode 100644 index 0000000..ddd1cfb --- /dev/null +++ b/documents/업무/6월/1째주/backup/etc/room-list-item-02.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 { RoomListItem02Component } from './room-list-item-02.component'; + +export default { + title: 'ui-chat::RoomListItem02Component', + component: RoomListItem02Component, + decorators: [ + moduleMetadata({ + imports: [BrowserModule, BrowserAnimationsModule, ChatUiModule], + providers: [] + }) + ] +}; + +export const Default = () => ({ + component: RoomListItem02Component, + props: {} +}); diff --git a/documents/업무/6월/1째주/backup/etc/room-list-item-02.component.theme.scss b/documents/업무/6월/1째주/backup/etc/room-list-item-02.component.theme.scss new file mode 100644 index 0000000..5303614 --- /dev/null +++ b/documents/업무/6월/1째주/backup/etc/room-list-item-02.component.theme.scss @@ -0,0 +1,20 @@ +@import '~@ucap/ng-ui-material/material'; + +@mixin ucap-chat-room-list-item-02-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-02-container { + border-color: mat-color($foreground, secondary-text); + } +} + +@mixin ucap-chat-room-list-item-02-typography($config) { + .ucap-chat-room-list-item-01-container { + font-family: mat-font-family($config); + } +} diff --git a/documents/업무/6월/1째주/backup/etc/room-list-item-02.component.ts b/documents/업무/6월/1째주/backup/etc/room-list-item-02.component.ts new file mode 100644 index 0000000..7901c45 --- /dev/null +++ b/documents/업무/6월/1째주/backup/etc/room-list-item-02.component.ts @@ -0,0 +1,63 @@ +import { + Component, + OnInit, + ChangeDetectionStrategy, + Input, + OnDestroy, + EventEmitter, + Output, + ChangeDetectorRef +} from '@angular/core'; +import { RoomInfo, RoomType } from '@ucap/protocol-room'; + +@Component({ + selector: 'ucap-chat-room-list-item-02', + templateUrl: './room-list-item-02.component.html', + styleUrls: ['./room-list-item-02.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class RoomListItem02Component implements OnInit, OnDestroy { + @Input() + roomInfo: RoomInfo; + + @Input() + profileImageRoot: string; + + @Input() + defaultProfileImage: string; + + @Input() + profileImage: string; + + @Input() + roomName: string; + + @Input() + checkable = false; + + @Input() + checked = false; + + @Output() + toggleItem = new EventEmitter<{ + checked: boolean; + roomInfo: RoomInfo; + }>(); + + RoomType = RoomType; + + constructor(private changeDetectorRef: ChangeDetectorRef) {} + + ngOnInit(): void {} + + ngOnDestroy(): void {} + + onToggleItem(value: boolean): void { + this.toggleItem.emit({ + checked: value, + roomInfo: this.roomInfo + }); + + this.changeDetectorRef.detectChanges(); + } +} diff --git a/documents/업무/6월/backup/ucap-lg-web-0602.zip b/documents/업무/6월/1째주/backup/etc/ucap-lg-web-0602.zip similarity index 100% rename from documents/업무/6월/backup/ucap-lg-web-0602.zip rename to documents/업무/6월/1째주/backup/etc/ucap-lg-web-0602.zip diff --git a/documents/업무/6월/1째주/backup/room/effects.ts b/documents/업무/6월/1째주/backup/room/effects.ts new file mode 100644 index 0000000..1b6dccf --- /dev/null +++ b/documents/업무/6월/1째주/backup/room/effects.ts @@ -0,0 +1,530 @@ +import { of } from 'rxjs'; +import { + catchError, + map, + switchMap, + exhaustMap, + withLatestFrom, + tap, + debounceTime +} from 'rxjs/operators'; + +import { Injectable } from '@angular/core'; + +import { Store, select } from '@ngrx/store'; +import { Actions, ofType, createEffect } from '@ngrx/effects'; + +import { + OpenResponse as CreateResponse, + Open3Response as CreateTimerResponse, + ExitResponse as DeleteResponse, + ExitAllResponse as DeleteMultiResponse, + UpdateResponse, + InviteResponse, + ExitForcingResponse, + UpdateTimerSetResponse, + InfoRequest +} from '@ucap/protocol-room'; + +import { RoomProtocolService } from '@ucap/ng-protocol-room'; +import { SyncProtocolService } from '@ucap/ng-protocol-sync'; + +import { LoginActions, LoginSelector } from '@ucap/ng-store-authentication'; +import * as ChattingAction from '../Chatting/actions'; +import { RoomSelector, ChattingSelector } from '../state'; + +import { + rooms, + room, + roomFailure, + inviteNotification, + exitNotification, + excludeUser, + excludeUserSuccess, + close, + delSuccess, + create, + createSuccess, + createFailure, + createTimer, + createTimerSuccess, + createTimerFailure, + del, + delFailure, + update, + updateSuccess, + updateFailure, + open, + openSuccess, + closeSuccess, + invite, + inviteSuccess, + inviteFailure, + expel, + expelSuccess, + expelFailure, + updateTimeRoomInterval, + updateTimeRoomIntervalSuccess, + updateTimeRoomIntervalFailure, + rooms2Success, + rooms2Failure, + delMulti, + delMultiSuccess, + delMultiFailure, + selectedRoom, + room2Success, + selectedRoomSuccess, + clearSelectedRoom +} from './actions'; +import { LocaleCode } from '@ucap/core'; +import { PresenceActions } from '@ucap/ng-store-organization'; +import { I18nService } from '@ucap/ng-i18n'; + +@Injectable() +export class Effects { + sessionCreatedForRooms$ = createEffect(() => { + return this.actions$.pipe( + ofType(LoginActions.sessionCreated), + map((action) => rooms({ localeCode: action.loginSession.localeCode })) + ); + }); + + selectedRoom$ = createEffect( + () => { + return this.actions$.pipe( + ofType(selectedRoom), + debounceTime(300), + tap((action) => { + const req: InfoRequest = { + ...action, + isDetail: false + }; + + // retrieve room info + this.roomProtocolService + .info2(req) + .pipe( + map((res) => { + let isJoinRoom = true; + if (!res.roomInfo || !res.roomInfo.isJoinRoom) { + isJoinRoom = false; + } + + if (!!isJoinRoom) { + this.store.dispatch( + selectedRoomSuccess({ + roomId: req.roomId, + roomInfo2Res: res + }) + ); + + // Buddy Presence + const targetUserInfos = req.isDetail + ? res.roomUserInfo.userInfoList.map( + (userInfo) => userInfo.seq + '' + ) + : res.roomUserInfo.userInfoShortList.map( + (userInfo) => userInfo.seq + '' + ); + if (!!targetUserInfos && targetUserInfos.length > 0) { + this.store.dispatch( + PresenceActions.bulkInfo({ + divCd: 'roomBulk', + userSeqs: targetUserInfos + }) + ); + } + } else { + // is not join room. so, redirect chat main. + this.store.dispatch( + clearSelectedRoom({ roomId: req.roomId }) + ); + } + }), + catchError((error) => of(roomFailure({ error }))) + ) + .subscribe(); + + // retrieve event info >> chatting.effect.selectedRoom$ + }) + ); + }, + { dispatch: false } + ); + + selectedRoomSuccess$ = createEffect( + () => { + return this.actions$.pipe( + ofType(selectedRoomSuccess), + tap((action) => { + // room info success reduce. + this.store.dispatch( + room2Success({ + roomInfo: action.roomInfo2Res.roomInfo, + roomUserInfo: action.roomInfo2Res.roomUserInfo + }) + ); + }) + ); + }, + { dispatch: false } + ); + + rooms$ = createEffect(() => { + return this.actions$.pipe( + ofType(rooms), + withLatestFrom(this.store.pipe(select(RoomSelector.roomsSyncDate))), + switchMap(([action, syncDate]) => { + // // CASE :: RoomUser Data 중 Detail data 만 수집. + // return this.syncProtocolService + // .room({ syncDate, localeCode: action.localeCode }) + // .pipe( + // map((res) => { + // return roomsSuccess({ + // roomList: res.roomList, + // roomUserInfoMap: res.roomUserInfoMap, + // syncDate: res.res.syncDate + // }); + // }), + // catchError((error) => of(roomsFailure({ error }))) + // ); + + // CASE :: RoomUser Data 중 Detail data, Short data 수집. + return this.syncProtocolService + .room2({ syncDate, localeCode: action.localeCode }) + .pipe( + map((res) => { + return rooms2Success({ + roomList: res.roomList, + roomUserInfoMap: res.roomUserInfoMap, + syncDate: res.res.syncDate + }); + }), + catchError((error) => of(rooms2Failure({ error }))) + ); + }) + ); + }); + + room$ = createEffect(() => { + return this.actions$.pipe( + ofType(room), + 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) => + room2Success({ + roomInfo: res.roomInfo, + roomUserInfo: res.roomUserInfo + }) + ), + catchError((error) => of(roomFailure({ error }))) + ); + }) + ); + }); + + create$ = createEffect( + () => { + return this.actions$.pipe( + ofType(create), + map((action) => action.req), + exhaustMap((req) => { + return this.roomProtocolService.open(req).pipe( + map((res: CreateResponse) => { + 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(() => + this.actions$.pipe( + ofType(createTimer), + map((action) => action.req), + exhaustMap((req) => { + return this.roomProtocolService.open3(req).pipe( + map((res: CreateTimerResponse) => { + return createTimerSuccess({ res }); + }), + catchError((error) => of(createTimerFailure({ error }))) + ); + }) + ) + ); + + del$ = createEffect(() => + this.actions$.pipe( + ofType(del), + map((action) => action.req), + exhaustMap((req) => { + return this.roomProtocolService.exit(req).pipe( + switchMap((res: DeleteResponse) => [ + // clear activeRoomId + clearSelectedRoom({ roomId: res.roomId }), + // close room, clear chatting + close({ roomIds: [res.roomId] }), + // clear room in rooms. + delSuccess({ res }) + ]), + catchError((error) => of(delFailure({ error }))) + ); + }) + ) + ); + + delMulti$ = createEffect(() => + this.actions$.pipe( + ofType(delMulti), + map((action) => action.req), + withLatestFrom(this.store.pipe(select(ChattingSelector.activeRoomId))), + exhaustMap(([req, activeRoomId]) => { + const existActiveRoomId = req.roomIds.find( + (roomId) => roomId === activeRoomId + ); + + return this.roomProtocolService.exitAll(req).pipe( + switchMap((res: DeleteMultiResponse) => { + if (!!existActiveRoomId) { + return [ + // clear selected room + clearSelectedRoom({ roomId: existActiveRoomId }), + // close room, clear chatting + close({ roomIds: res.roomIds }), + // clear room in rooms. + delMultiSuccess({ res }) + ]; + } else { + return [ + // close room, clear chatting + close({ roomIds: res.roomIds }), + // clear room in rooms. + delMultiSuccess({ res }) + ]; + } + }), + catchError((error) => of(delMultiFailure({ error }))) + ); + }) + ) + ); + + update$ = createEffect(() => + this.actions$.pipe( + ofType(update), + map((action) => action.req), + exhaustMap((req) => { + return this.roomProtocolService.update(req).pipe( + map((res: UpdateResponse) => { + return updateSuccess({ res }); + }), + catchError((error) => of(updateFailure({ error }))) + ); + }) + ) + ); + + excludeUser$ = createEffect(() => { + return this.actions$.pipe( + ofType(excludeUser), + map((action) => + excludeUserSuccess({ + roomId: action.roomId, + userSeqs: action.userSeqs + }) + ) + ); + }); + + open$ = createEffect(() => { + return this.actions$.pipe( + ofType(open), + map((action) => openSuccess({ roomIds: [...action.roomIds] })) + ); + }); + + close$ = createEffect(() => { + return this.actions$.pipe( + ofType(close), + map((action) => closeSuccess({ roomIds: [...action.roomIds] })) + ); + }); + + invite$ = createEffect(() => + this.actions$.pipe( + ofType(invite), + exhaustMap((action) => { + const req = action.req; + const localeCode = action.localeCode; + + return this.roomProtocolService.invite(req).pipe( + switchMap((res: InviteResponse) => { + return [ + inviteSuccess({ res }), + room({ + req: { + roomId: req.roomId, + isDetail: true, + localeCode + } + }) + ]; + }), + catchError((error) => of(inviteFailure({ error }))) + ); + }) + ) + ); + + expel$ = createEffect(() => + this.actions$.pipe( + ofType(expel), + map((action) => action.req), + exhaustMap((req) => { + return this.roomProtocolService.exitForcing(req).pipe( + map((res: ExitForcingResponse) => { + return expelSuccess({ res }); + }), + catchError((error) => of(expelFailure({ error }))) + ); + }) + ) + ); + + updateTimeRoomInterval$ = createEffect(() => + this.actions$.pipe( + ofType(updateTimeRoomInterval), + map((action) => action.req), + exhaustMap((req) => { + return this.roomProtocolService.updateTimerSet(req).pipe( + map((res: UpdateTimerSetResponse) => { + return updateTimeRoomIntervalSuccess({ res }); + }), + catchError((error) => of(updateTimeRoomIntervalFailure({ error }))) + ); + }) + ) + ); + + /** + * @discription Call by notifications case in SSVC_TYPE_ROOM_INVITE_RES, SSVC_TYPE_ROOM_INVITE_NOTI + * 1. roomlist 를 체크하여 없을경우 내가 초대된 경우라 간주하고 방 조회하여 갱신하지 않도록 한다.(첫 대화가 들어오면 그때 조회.) + * 2. roomlist 를 체크하여 있을 경우 기존방에 다른 인원이 추가되었을 경우이므로 방 조회하여 갱신한다. + */ + inviteNotification$ = createEffect( + () => { + return this.actions$.pipe( + ofType(inviteNotification), + withLatestFrom(this.store.pipe(select(RoomSelector.rooms))), + map(([action, roomList]) => { + const roomId = action.noti.roomId; + if (!!roomList && roomList.length > 0) { + if (roomList.some((roomInfo) => roomId === roomInfo.roomId)) { + this.store.dispatch( + room({ + req: { + roomId, + isDetail: true, + localeCode: action.localeCode + } + }) + ); + } + } + }) + ); + }, + { + dispatch: false + } + ); + + exitNotification$ = createEffect(() => { + return this.actions$.pipe( + ofType(exitNotification), + withLatestFrom(this.store.pipe(select(LoginSelector.loginRes))), + switchMap(([action, loginRes]) => { + if (loginRes.userSeq + '' === action.senderSeq + '') { + return [ + close({ roomIds: [action.roomId] }), + clearSelectedRoom({ roomId: action.roomId }), + delSuccess({ + res: { roomId: action.roomId } + }) + ]; + } else { + return [ + excludeUser({ + roomId: action.roomId, + userSeqs: [action.senderSeq] + }) + ]; + } + }) + ); + }); + + /******************************************************************* + * [Chatting Action watching.] + *******************************************************************/ + addEventSuccess$ = createEffect( + () => { + return this.actions$.pipe( + ofType(ChattingAction.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: this.i18nService.currentLng.toUpperCase() as LocaleCode + }) + ); + } + }) + ); + }, + { dispatch: false } + ); + + constructor( + private actions$: Actions, + private store: Store, + private syncProtocolService: SyncProtocolService, + private roomProtocolService: RoomProtocolService, + private i18nService: I18nService + ) {} +} diff --git a/documents/업무/6월/1째주/backup/ucap-0605.zip b/documents/업무/6월/1째주/backup/ucap-0605.zip new file mode 100644 index 0000000..042961c Binary files /dev/null and b/documents/업무/6월/1째주/backup/ucap-0605.zip differ diff --git a/documents/업무/6월/1째주/backup/ucap-angular-0605.zip b/documents/업무/6월/1째주/backup/ucap-angular-0605.zip new file mode 100644 index 0000000..d531120 Binary files /dev/null and b/documents/업무/6월/1째주/backup/ucap-angular-0605.zip differ diff --git a/documents/업무/6월/1째주/backup/ucap-lg-web-0605.zip b/documents/업무/6월/1째주/backup/ucap-lg-web-0605.zip new file mode 100644 index 0000000..2a076d2 Binary files /dev/null and b/documents/업무/6월/1째주/backup/ucap-lg-web-0605.zip differ diff --git a/documents/업무/6월/1째주/todo b/documents/업무/6월/1째주/todo new file mode 100644 index 0000000..3495cc5 --- /dev/null +++ b/documents/업무/6월/1째주/todo @@ -0,0 +1,15 @@ +버그 + 동료 삭제, 그룹 삭제 시 프로토콜 절차 정상적으로 진행되나 새로고침 시 기존 데이터가 다시 로드됨 + 팝업 테넌트 검색 시 결과에 대한 체크박스 체크 후 다시 검색 시 체크가 됨 + +추가 기능 + 그룹 + 팝업 조직도 사용자 선택 + 팝업 사용자 선택 창 사이즈 조절 시 위치 변경 + 그룹 추가 팝업 "그룹지정 완료" 시 + 사용자 선택 x + 그룹 선택 x + 완료 버튼 비활성화 + 채팅 + 노티피케이션 연동 + diff --git a/documents/업무/6월/2째주/0608.txt b/documents/업무/6월/2째주/0608.txt new file mode 100644 index 0000000..e69de29 diff --git a/weekly-report/6월/주간보고_박병은_2020.0605.pptx b/weekly-report/6월/주간보고_박병은_2020.0605.pptx new file mode 100644 index 0000000..b6b3301 Binary files /dev/null and b/weekly-report/6월/주간보고_박병은_2020.0605.pptx differ