diff --git a/electron-projects/ucap-webmessenger-electron/src/index.ts b/electron-projects/ucap-webmessenger-electron/src/index.ts index 7c4d4c37..a825c3e7 100644 --- a/electron-projects/ucap-webmessenger-electron/src/index.ts +++ b/electron-projects/ucap-webmessenger-electron/src/index.ts @@ -645,6 +645,16 @@ ipcMain.on( } ); +ipcMain.on( + IdleStateChannel.ChangeLimitTime, + (event: IpcMainEvent, ...args: any[]) => { + const limitTime: number = args[0]; + if (!!idle) { + idle.resetIdleTime(limitTime); + } + } +); + ipcMain.on( NotificationChannel.Notify, (event: IpcMainEvent, ...args: any[]) => { diff --git a/projects/ucap-webmessenger-app/src/app/layouts/native/components/top-bar.component.html b/projects/ucap-webmessenger-app/src/app/layouts/native/components/top-bar.component.html index b13d2226..908e27a6 100644 --- a/projects/ucap-webmessenger-app/src/app/layouts/native/components/top-bar.component.html +++ b/projects/ucap-webmessenger-app/src/app/layouts/native/components/top-bar.component.html @@ -150,6 +150,7 @@
- +
- + +
- + +
- + +
- + + +
+ + + +
+ {{ 'presence.settingOfAwayTime' | translate }} +
+
+ 10{{ 'common.units.minute' | translate }} +
+
+ 20{{ 'common.units.minute' | translate }} +
+
+ 30{{ 'common.units.minute' | translate }}
diff --git a/projects/ucap-webmessenger-app/src/app/layouts/native/components/top-bar.component.ts b/projects/ucap-webmessenger-app/src/app/layouts/native/components/top-bar.component.ts index 97ec4a33..d2bb2e86 100644 --- a/projects/ucap-webmessenger-app/src/app/layouts/native/components/top-bar.component.ts +++ b/projects/ucap-webmessenger-app/src/app/layouts/native/components/top-bar.component.ts @@ -20,6 +20,7 @@ import * as ChatStore from '@app/store/messenger/chat'; import * as AuthenticationStore from '@app/store/account/authentication'; import * as SettingsStore from '@app/store/messenger/settings'; import * as UpdateStore from '@app/store/setting/update'; +import * as StatusStore from '@app/store/messenger/status'; import { LoginResponse } from '@ucap-webmessenger/protocol-authentication'; import { tap, take, map, catchError } from 'rxjs/operators'; @@ -55,7 +56,9 @@ import { } from '@app/layouts/messenger/dialogs/profile/profile.dialog.component'; import { DialogService } from '@ucap-webmessenger/ui'; import { DOCUMENT } from '@angular/common'; -import { MatMenu } from '@angular/material'; +import { MatMenu, MatRadioChange } from '@angular/material'; +import { StatusCode, StatusType } from '@ucap-webmessenger/core'; +import { StatusInfo } from '@ucap-webmessenger/protocol-status'; @Component({ selector: 'app-layout-native-top-bar', @@ -72,12 +75,19 @@ export class TopBarComponent implements OnInit, OnDestroy { updateInfo$: Observable; + myStatus: StatusInfo; + myStatusSubscription: Subscription; + + myIdleCheckTime: number; + myIdleCheckTimeSubscription: Subscription; + loginInfo: LoginInfo; weblink: WebLink[] = []; webLinkBadgeMail = 0; webLinkBadgePayment = 0; WebLinkType = WebLinkType; + StatusCode = StatusCode; @ViewChild('profileMenu', { static: true }) profileMenu: MatMenu; @@ -118,11 +128,39 @@ export class TopBarComponent implements OnInit, OnDestroy { ) .subscribe(); + this.myStatusSubscription = this.store + .pipe(select(AppStore.MessengerSelector.StatusSelector.selectedMyStatus)) + .subscribe(myStatus => { + this.myStatus = myStatus; + }); + + this.myIdleCheckTimeSubscription = this.store + .pipe( + select( + AppStore.MessengerSelector.StatusSelector.selectedMyIdleCheckTime + ) + ) + .subscribe(myIdleCheckTime => { + this.myIdleCheckTime = myIdleCheckTime; + }); + this.updateInfo$ = this.store.pipe( select(AppStore.SettingSelector.UpdateSelector.updateInfo) ); } + ngOnDestroy(): void { + if (!!this.loginResSubscription) { + this.loginResSubscription.unsubscribe(); + } + if (!!this.myStatusSubscription) { + this.myStatusSubscription.unsubscribe(); + } + if (!!this.myIdleCheckTimeSubscription) { + this.myIdleCheckTimeSubscription.unsubscribe(); + } + } + initWebLink(): void { const loginRes = this.sessionStorageService.get( KEY_LOGIN_RES_INFO @@ -207,12 +245,6 @@ export class TopBarComponent implements OnInit, OnDestroy { } } - ngOnDestroy(): void { - if (!!this.loginResSubscription) { - this.loginResSubscription.unsubscribe(); - } - } - onClickClose() { this.nativeService.windowClose(); } @@ -343,4 +375,61 @@ export class TopBarComponent implements OnInit, OnDestroy { onClickRemoteSupport(event: Event) { this.nativeService.executeProcess('AeroAdmin'); } + + onClickStatusOnline(event: Event) { + this.store.dispatch( + StatusStore.status({ + req: { + statusDivisionType: StatusType.Messenger, + statusType: StatusCode.OnLine + } + }) + ); + } + + onClickStatusAway(event: Event) { + this.store.dispatch( + StatusStore.status({ + req: { + statusDivisionType: StatusType.Messenger, + statusType: StatusCode.Away + } + }) + ); + } + + onClickStatusBusy(event: Event, index: number) { + let statusMessage = ''; + switch (index) { + case 1: + statusMessage = this.loginRes.statusMessage1; + break; + case 2: + statusMessage = this.loginRes.statusMessage2; + break; + case 3: + statusMessage = this.loginRes.statusMessage3; + break; + } + + this.store.dispatch( + StatusStore.status({ + req: { + statusDivisionType: StatusType.Messenger, + statusType: StatusCode.Busy, + statusMessage + } + }) + ); + } + + onClickChangeStatusBusy(event: Event, index: number) { + event.stopPropagation(); + } + + onChangeAwayTime(event: MatRadioChange) { + this.store.dispatch( + StatusStore.changeMyIdleCheckTime({ checkTime: Number(event.value) }) + ); + } } diff --git a/projects/ucap-webmessenger-app/src/app/layouts/native/native.layout.module.ts b/projects/ucap-webmessenger-app/src/app/layouts/native/native.layout.module.ts index 4134e647..178d6eac 100644 --- a/projects/ucap-webmessenger-app/src/app/layouts/native/native.layout.module.ts +++ b/projects/ucap-webmessenger-app/src/app/layouts/native/native.layout.module.ts @@ -6,6 +6,7 @@ import { FlexLayoutModule } from '@angular/flex-layout'; import { MatDividerModule } from '@angular/material/divider'; import { MatIconModule } from '@angular/material/icon'; import { MatMenuModule } from '@angular/material/menu'; +import { MatRadioModule } from '@angular/material/radio'; import { MatToolbarModule } from '@angular/material/toolbar'; import { TranslateModule } from '@ngx-translate/core'; @@ -25,6 +26,7 @@ import { MatTooltipModule, MatBadgeModule } from '@angular/material'; MatToolbarModule, MatTooltipModule, MatMenuModule, + MatRadioModule, MatBadgeModule, TranslateModule, diff --git a/projects/ucap-webmessenger-app/src/app/pages/messenger/components/main.page.component.ts b/projects/ucap-webmessenger-app/src/app/pages/messenger/components/main.page.component.ts index dc19cc9a..4d500e43 100644 --- a/projects/ucap-webmessenger-app/src/app/pages/messenger/components/main.page.component.ts +++ b/projects/ucap-webmessenger-app/src/app/pages/messenger/components/main.page.component.ts @@ -13,6 +13,7 @@ import { Store, select } from '@ngrx/store'; import * as AppStore from '@app/store'; import * as ChatStore from '@app/store/messenger/chat'; import * as MessageStore from '@app/store/messenger/message'; +import * as StatusStore from '@app/store/messenger/status'; import { Observable, Subscription, of } from 'rxjs'; import { UCAP_NATIVE_SERVICE, NativeService } from '@ucap-webmessenger/native'; @@ -59,6 +60,7 @@ export class MainPageComponent implements OnInit, OnDestroy { idleStateChangedSubscription: Subscription; chatOpenRoomSubscription: Subscription; msgOpenMessageSubscription: Subscription; + myIdleCheckTimeSubscription: Subscription; defaultLeftSideComponentWidth = 380; leftSideComponentWidth = this.defaultLeftSideComponentWidth; @@ -122,11 +124,39 @@ export class MainPageComponent implements OnInit, OnDestroy { statusType = StatusCode.OnLine; } - this.statusProtocolService.status({ - statusDivisionType: StatusType.Messenger, - statusType, - statusMessage: '' - }); + this.store.dispatch( + StatusStore.status({ + req: { + statusDivisionType: StatusType.Messenger, + statusType, + statusMessage: '' + } + }) + ); + }); + + this.myIdleCheckTimeSubscription = this.store + .pipe( + select( + AppStore.MessengerSelector.StatusSelector.selectedMyIdleCheckTime + ) + ) + .subscribe(checkTime => { + this.nativeService.changeLimitOfIdleState(checkTime); + + const appUserInfo = this.localStorageService.encGet( + KEY_APP_USER_INFO, + environment.customConfig.appKey + ); + + this.localStorageService.encSet( + KEY_APP_USER_INFO, + { + ...appUserInfo, + idleCheckTime: checkTime + }, + environment.customConfig.appKey + ); }); this.chatOpenRoomSubscription = this.nativeService @@ -186,6 +216,10 @@ export class MainPageComponent implements OnInit, OnDestroy { this.loginResSubscription.unsubscribe(); } + if (!!this.myIdleCheckTimeSubscription) { + this.myIdleCheckTimeSubscription.unsubscribe(); + } + this.logger.debug('-----------------------MainPageComponent ngOnDestroy'); } diff --git a/projects/ucap-webmessenger-app/src/app/resolvers/messenger.resolver.ts b/projects/ucap-webmessenger-app/src/app/resolvers/messenger.resolver.ts index f4d1a4fa..d49e397d 100644 --- a/projects/ucap-webmessenger-app/src/app/resolvers/messenger.resolver.ts +++ b/projects/ucap-webmessenger-app/src/app/resolvers/messenger.resolver.ts @@ -17,7 +17,10 @@ import { import { Store, select } from '@ngrx/store'; import { ProtocolService, ServerErrorCode } from '@ucap-webmessenger/protocol'; -import { SessionStorageService } from '@ucap-webmessenger/web-storage'; +import { + SessionStorageService, + LocalStorageService +} from '@ucap-webmessenger/web-storage'; import { PublicApiService, VersionInfo2Response @@ -54,6 +57,7 @@ import * as VersionInfoStore from '@app/store/setting/version-info'; import * as OptionStore from '@app/store/messenger/option'; import * as QueryStore from '@app/store/messenger/query'; import * as SyncStore from '@app/store/messenger/sync'; +import * as StatusStore from '@app/store/messenger/status'; import { KEY_LOGIN_RES_INFO, KEY_VER_INFO } from '@app/types'; import { environment } from '../../environments/environment'; @@ -66,6 +70,7 @@ import { } from '@ucap-webmessenger/api-external'; import { StatusCode } from '@ucap-webmessenger/api'; import { UCAP_NATIVE_SERVICE, NativeService } from '@ucap-webmessenger/native'; +import { AppUserInfo, KEY_APP_USER_INFO } from '@app/types/app-user-info.type'; @Injectable() export class AppMessengerResolver implements Resolve { @@ -73,6 +78,7 @@ export class AppMessengerResolver implements Resolve { @Inject(UCAP_NATIVE_SERVICE) private nativeService: NativeService, private store: Store, private sessionStorageService: SessionStorageService, + private localStorageService: LocalStorageService, private publicApiService: PublicApiService, private externalApiService: ExternalApiService, private protocolService: ProtocolService, @@ -264,6 +270,17 @@ export class AppMessengerResolver implements Resolve { ); this.store.dispatch(AuthenticationStore.postLogin({ loginRes })); this.appNativeService.subscribeAfterLogin(); + + const appUserInfo = this.localStorageService.encGet( + KEY_APP_USER_INFO, + environment.customConfig.appKey + ); + this.store.dispatch( + StatusStore.changeMyIdleCheckTime({ + checkTime: appUserInfo.idleCheckTime + }) + ); + resolve(); }, err => { diff --git a/projects/ucap-webmessenger-app/src/app/services/authentication.service.ts b/projects/ucap-webmessenger-app/src/app/services/authentication.service.ts index ebd1d012..d3a8d813 100644 --- a/projects/ucap-webmessenger-app/src/app/services/authentication.service.ts +++ b/projects/ucap-webmessenger-app/src/app/services/authentication.service.ts @@ -64,6 +64,7 @@ export class AppAuthenticationService { if (!appUserInfo) { appUserInfo = { + idleCheckTime: 10, settings: { ...environment.productConfig.defaultSettings, chat: { diff --git a/projects/ucap-webmessenger-app/src/app/store/messenger/status/actions.ts b/projects/ucap-webmessenger-app/src/app/store/messenger/status/actions.ts index fb0a082f..31b6ac56 100644 --- a/projects/ucap-webmessenger-app/src/app/store/messenger/status/actions.ts +++ b/projects/ucap-webmessenger-app/src/app/store/messenger/status/actions.ts @@ -2,7 +2,9 @@ import { createAction, props } from '@ngrx/store'; import { BulkInfoRequest, StatusBulkInfo, - StatusNotification + StatusNotification, + StatusRequest, + StatusResponse } from '@ucap-webmessenger/protocol-status'; export const bulkInfo = createAction( @@ -24,3 +26,23 @@ export const statusNotification = createAction( '[Messenger::Status] Status Notification', props<{ noti: StatusNotification }>() ); + +export const status = createAction( + '[Messenger::Status] Status', + props<{ req: StatusRequest }>() +); +export const statusSuccess = createAction( + '[Messenger::Status] Status Success', + props<{ + res: StatusResponse; + }>() +); +export const statusFailure = createAction( + '[Messenger::Status] Status Failure', + props<{ error: any }>() +); + +export const changeMyIdleCheckTime = createAction( + '[Messenger::Status] Change MyIdleCheckTime', + props<{ checkTime: number }>() +); diff --git a/projects/ucap-webmessenger-app/src/app/store/messenger/status/effects.ts b/projects/ucap-webmessenger-app/src/app/store/messenger/status/effects.ts index f8044353..6b6fdb80 100644 --- a/projects/ucap-webmessenger-app/src/app/store/messenger/status/effects.ts +++ b/projects/ucap-webmessenger-app/src/app/store/messenger/status/effects.ts @@ -10,15 +10,18 @@ import { bulkInfo, bulkInfoSuccess, bulkInfoFailure, - statusNotification + status, + statusFailure, + statusSuccess } from './actions'; -import { tap, switchMap, map, catchError } from 'rxjs/operators'; +import { tap, switchMap, map, catchError, exhaustMap } from 'rxjs/operators'; import { StatusProtocolService, SSVC_TYPE_STATUS_BULK_INFO_DATA, SSVC_TYPE_STATUS_BULK_INFO_RES, BulkInfoData, - StatusBulkInfo + StatusBulkInfo, + StatusResponse } from '@ucap-webmessenger/protocol-status'; import { of } from 'rxjs'; @@ -84,6 +87,21 @@ export class Effects { // { dispatch: false } // ); + status$ = createEffect(() => + this.actions$.pipe( + ofType(status), + map(action => action.req), + exhaustMap(req => { + return this.statusProtocolService.status(req).pipe( + map((res: StatusResponse) => { + return statusSuccess({ res }); + }), + catchError(error => of(statusFailure({ error }))) + ); + }) + ) + ); + constructor( private actions$: Actions, private store: Store, diff --git a/projects/ucap-webmessenger-app/src/app/store/messenger/status/reducers.ts b/projects/ucap-webmessenger-app/src/app/store/messenger/status/reducers.ts index c65060d2..62b4abbf 100644 --- a/projects/ucap-webmessenger-app/src/app/store/messenger/status/reducers.ts +++ b/projects/ucap-webmessenger-app/src/app/store/messenger/status/reducers.ts @@ -1,6 +1,11 @@ import { createReducer, on } from '@ngrx/store'; import { initialState, State, adapterStatusBulkInfo } from './state'; -import { bulkInfoSuccess, statusNotification } from './actions'; +import { + bulkInfoSuccess, + statusNotification, + statusSuccess, + changeMyIdleCheckTime +} from './actions'; import * as AuthenticationStore from '@app/store/account/authentication'; import { StatusBulkInfo } from '@ucap-webmessenger/protocol-status'; @@ -42,6 +47,24 @@ export const reducer = createReducer( }; }), + on(statusSuccess, (state, action) => { + return { + ...state, + myStatus: { + ...state.myStatus, + pcStatus: action.res.statusType, + statusMessage: action.res.statusMessage + } + } as State; + }), + + on(changeMyIdleCheckTime, (state, action) => { + return { + ...state, + myIdleCheckTime: action.checkTime + } as State; + }), + on(AuthenticationStore.logoutInitialize, (state, action) => { return { ...initialState diff --git a/projects/ucap-webmessenger-app/src/app/store/messenger/status/state.ts b/projects/ucap-webmessenger-app/src/app/store/messenger/status/state.ts index fd7fb618..7e25c0ed 100644 --- a/projects/ucap-webmessenger-app/src/app/store/messenger/status/state.ts +++ b/projects/ucap-webmessenger-app/src/app/store/messenger/status/state.ts @@ -1,11 +1,14 @@ import { Selector, createSelector } from '@ngrx/store'; -import { StatusBulkInfo } from '@ucap-webmessenger/protocol-status'; +import { StatusBulkInfo, StatusInfo } from '@ucap-webmessenger/protocol-status'; import { EntityState, createEntityAdapter } from '@ngrx/entity'; +import { StatusCode } from '@ucap-webmessenger/core'; export interface StatusBulkInfoState extends EntityState {} export interface State { statusBulkInfo: StatusBulkInfoState; + myStatus: StatusInfo; + myIdleCheckTime: number; } export const adapterStatusBulkInfo = createEntityAdapter({ @@ -17,7 +20,18 @@ const statusBulkInfoInitialState: StatusBulkInfoState = adapterStatusBulkInfo.ge ); export const initialState: State = { - statusBulkInfo: statusBulkInfoInitialState + statusBulkInfo: statusBulkInfoInitialState, + myStatus: { + userSeq: -1, + pcStatus: StatusCode.OnLine, + phoneStatus: StatusCode.Offline, + mobileStatus: StatusCode.Offline, + conferenceStatus: StatusCode.Offline, + statusMessage: '', + mobileConferenceStatus: StatusCode.Offline, + imessengerStatus: StatusCode.Offline + }, + myIdleCheckTime: 10 }; const { @@ -47,6 +61,14 @@ export function selectors(selector: Selector) { selectStatusBulkInfo, ngeSelectEntitiesStatusBulkInfo, (_, entities) => (!!entities ? entities[userSeq] : undefined) - ) + ), + selectedMyStatus: createSelector( + selector, + (state: State) => state.myStatus + ), + selectedMyIdleCheckTime: createSelector( + selector, + (state: State) => state.myIdleCheckTime + ) }; } diff --git a/projects/ucap-webmessenger-app/src/app/types/app-user-info.type.ts b/projects/ucap-webmessenger-app/src/app/types/app-user-info.type.ts index 16be3b5c..2dde9efd 100644 --- a/projects/ucap-webmessenger-app/src/app/types/app-user-info.type.ts +++ b/projects/ucap-webmessenger-app/src/app/types/app-user-info.type.ts @@ -10,6 +10,7 @@ export interface AppUserInfo { companyCode?: string; companyGroupType?: string; localeCode?: LocaleCode; + idleCheckTime?: number; settings?: Settings; } diff --git a/projects/ucap-webmessenger-app/src/assets/i18n/en.json b/projects/ucap-webmessenger-app/src/assets/i18n/en.json index bb224c4f..791c716e 100644 --- a/projects/ucap-webmessenger-app/src/assets/i18n/en.json +++ b/projects/ucap-webmessenger-app/src/assets/i18n/en.json @@ -111,8 +111,12 @@ } }, "presence": { + "settingOfAwayTime": "Setting of away time", "online": "Online", - "offline": "Offline" + "away": "Away", + "statusMessage1": "Busy", + "statusMessage2": "In conference", + "statusMessage3": "In intensive work" }, "group": { "label": "Group", diff --git a/projects/ucap-webmessenger-app/src/assets/i18n/ko.json b/projects/ucap-webmessenger-app/src/assets/i18n/ko.json index 614a292c..7eb3ca62 100644 --- a/projects/ucap-webmessenger-app/src/assets/i18n/ko.json +++ b/projects/ucap-webmessenger-app/src/assets/i18n/ko.json @@ -111,8 +111,12 @@ } }, "presence": { + "settingOfAwayTime": "부재 중 시간 설정", "online": "온라인", - "offline": "부재중" + "away": "부재중", + "statusMessage1": "다른용무중", + "statusMessage2": "회의중", + "statusMessage3": "집중근무중" }, "group": { "label": "그룹", diff --git a/projects/ucap-webmessenger-native-browser/src/lib/services/browser-native.service.ts b/projects/ucap-webmessenger-native-browser/src/lib/services/browser-native.service.ts index cc7b7dcc..7929d7ec 100644 --- a/projects/ucap-webmessenger-native-browser/src/lib/services/browser-native.service.ts +++ b/projects/ucap-webmessenger-native-browser/src/lib/services/browser-native.service.ts @@ -226,6 +226,8 @@ export class BrowserNativeService extends NativeService { }); } + changeLimitOfIdleState(limitTime: number): void {} + chatOpenRoom(): Observable { if (!this.chatOpenRoomSubject) { this.chatOpenRoomSubject = new Subject(); diff --git a/projects/ucap-webmessenger-native-electron/src/lib/services/electron-native.service.ts b/projects/ucap-webmessenger-native-electron/src/lib/services/electron-native.service.ts index 6997ddf3..63726d4f 100644 --- a/projects/ucap-webmessenger-native-electron/src/lib/services/electron-native.service.ts +++ b/projects/ucap-webmessenger-native-electron/src/lib/services/electron-native.service.ts @@ -396,6 +396,10 @@ export class ElectronNativeService implements NativeService { return this.idleStateChanged$; } + changeLimitOfIdleState(limitTime: number): void { + this.ipcRenderer.send(IdleStateChannel.ChangeLimitTime, limitTime); + } + chatOpenRoom(): Observable { if (!this.chatOpenRoomSubject) { this.chatOpenRoomSubject = new Subject(); diff --git a/projects/ucap-webmessenger-native-electron/src/lib/types/channel.type.ts b/projects/ucap-webmessenger-native-electron/src/lib/types/channel.type.ts index c5fce0c5..f766d95a 100644 --- a/projects/ucap-webmessenger-native-electron/src/lib/types/channel.type.ts +++ b/projects/ucap-webmessenger-native-electron/src/lib/types/channel.type.ts @@ -49,5 +49,6 @@ export enum WindowStateChannel { export enum IdleStateChannel { Changed = 'UCAP::idleState::changed', - StartCheck = 'UCAP::idleState::startCheck' + StartCheck = 'UCAP::idleState::startCheck', + ChangeLimitTime = 'UCAP::idleState::changeLimitTime' } diff --git a/projects/ucap-webmessenger-native/src/lib/services/native.service.ts b/projects/ucap-webmessenger-native/src/lib/services/native.service.ts index 08b709a6..94158b7f 100644 --- a/projects/ucap-webmessenger-native/src/lib/services/native.service.ts +++ b/projects/ucap-webmessenger-native/src/lib/services/native.service.ts @@ -68,6 +68,7 @@ export abstract class NativeService { abstract windowMaximize(): void; abstract idleStateChanged(): Observable; + abstract changeLimitOfIdleState(limitTime: number): void; abstract chatOpenRoom(): Observable; abstract msgOpenMessage(): Observable; diff --git a/projects/ucap-webmessenger-ui-profile/src/lib/components/my-profile-widget.component.html b/projects/ucap-webmessenger-ui-profile/src/lib/components/my-profile-widget.component.html index 6d570800..658f8d55 100644 --- a/projects/ucap-webmessenger-ui-profile/src/lib/components/my-profile-widget.component.html +++ b/projects/ucap-webmessenger-ui-profile/src/lib/components/my-profile-widget.component.html @@ -9,7 +9,7 @@ />
- +