통합검색에 UX 적용.
This commit is contained in:
parent
3cfa9a39ac
commit
05a148d30a
|
@ -152,7 +152,7 @@ export class OrganizationTreeComponent implements OnInit, OnDestroy {
|
||||||
}
|
}
|
||||||
/** 검색 취소 */
|
/** 검색 취소 */
|
||||||
onClickCancel() {
|
onClickCancel() {
|
||||||
this.store.dispatch(QueryStore.cancelSearchDeptUser({}));
|
this.store.dispatch(QueryStore.clearSearchDeptUser({}));
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 조직도 부서 선택 */
|
/** 조직도 부서 선택 */
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
></div>
|
></div>
|
||||||
<div class="organization-info">
|
<div class="organization-info">
|
||||||
<h3 class="organization-name">
|
<h3 class="organization-name">
|
||||||
<ng-container *ngIf="!(isSearch | async)">
|
<ng-container *ngIf="!isSearch">
|
||||||
<ng-container
|
<ng-container
|
||||||
*ngIf="
|
*ngIf="
|
||||||
!!(selectedDepartmentProcessing$ | async);
|
!!(selectedDepartmentProcessing$ | async);
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
{{ selectedDepartment$ | async | ucapTranslate: 'name' }}
|
{{ selectedDepartment$ | async | ucapTranslate: 'name' }}
|
||||||
</ng-template>
|
</ng-template>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
<ng-container *ngIf="!!(isSearch | async)">
|
<ng-container *ngIf="!!isSearch">
|
||||||
{{ 'common.searchResult' | translate
|
{{ 'common.searchResult' | translate
|
||||||
}}<span class="text-accent-color"
|
}}<span class="text-accent-color"
|
||||||
>({{ departmentUserInfoList.length }}
|
>({{ departmentUserInfoList.length }}
|
||||||
|
|
|
@ -259,7 +259,6 @@ export class OrganizationComponent implements OnInit, OnDestroy {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Handling chipset for selectedUserList */
|
/** Handling chipset for selectedUserList */
|
||||||
/** 선택된 사용자 취소 */
|
|
||||||
onClickDeleteUser(userInfo: UserInfoSS) {
|
onClickDeleteUser(userInfo: UserInfoSS) {
|
||||||
this.selectedUserList = this.selectedUserList.filter(
|
this.selectedUserList = this.selectedUserList.filter(
|
||||||
item => item.seq !== userInfo.seq
|
item => item.seq !== userInfo.seq
|
||||||
|
|
|
@ -12,20 +12,127 @@
|
||||||
</button>
|
</button>
|
||||||
</mat-card-header>
|
</mat-card-header>
|
||||||
<mat-card-content>
|
<mat-card-content>
|
||||||
<ucap-integrated-search
|
<div fxLayout="column" fxFlex="1 1 auto" class="rightDrawer-notice">
|
||||||
#integratedSearch
|
<div class="search-area">
|
||||||
[sessionVerinfo]="sessionVerinfo"
|
<ucap-integrated-search-form
|
||||||
[presence]="presence$ | async"
|
[searchWord]="!!currentSearchWord ? currentSearchWord : ''"
|
||||||
[searchWord]="!!data.keyword ? data.keyword : ''"
|
(search)="onSearch($event)"
|
||||||
[searchingProcessing]="searchingProcessing"
|
|
||||||
[searchUserInfos]="searchUserInfos"
|
|
||||||
[totalCount]="totalCount"
|
|
||||||
[pageCurrent]="pageCurrent"
|
|
||||||
[pageListCount]="pageListCount"
|
|
||||||
(search)="onReSearch($event)"
|
|
||||||
(changePage)="onChangePage($event)"
|
|
||||||
(openProfile)="onClickOpenProfile($event)"
|
|
||||||
>
|
>
|
||||||
</ucap-integrated-search>
|
</ucap-integrated-search-form>
|
||||||
|
</div>
|
||||||
|
<div style="position: relative;">
|
||||||
|
<div
|
||||||
|
*ngIf="searchingProcessing$ | async"
|
||||||
|
style="position: absolute; width: 100%; z-index: 101;"
|
||||||
|
>
|
||||||
|
<mat-progress-bar mode="indeterminate"></mat-progress-bar>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="contents-table">
|
||||||
|
<div fxFlex="0 0 auto" class="table-box">
|
||||||
|
<ucap-organization-detail-table
|
||||||
|
[loginRes]="loginRes"
|
||||||
|
[presence$]="presenceSubject.asObservable()"
|
||||||
|
[departmentUserInfoList]="departmentUserInfoList"
|
||||||
|
[profileImageRoot]="profileImageRoot"
|
||||||
|
[selectedUserList]="selectedUserList"
|
||||||
|
(openProfile)="onClickOpenProfile($event)"
|
||||||
|
(toggleAllUser)="onToggleAllUser($event)"
|
||||||
|
(toggleUser)="onToggleUser($event)"
|
||||||
|
class="detail-table"
|
||||||
|
></ucap-organization-detail-table>
|
||||||
|
</div>
|
||||||
|
<div class="footer-fix search-result-footer">
|
||||||
|
<mat-accordion>
|
||||||
|
<mat-expansion-panel>
|
||||||
|
<mat-expansion-panel-header>
|
||||||
|
<mat-panel-title>
|
||||||
|
{{ 'organization.selectedUser' | translate }}
|
||||||
|
<span *ngIf="selectedUserList.length > 0">
|
||||||
|
({{ selectedUserList.length }})
|
||||||
|
{{ 'common.units.persons' | translate }}
|
||||||
|
</span>
|
||||||
|
</mat-panel-title>
|
||||||
|
<mat-panel-description> </mat-panel-description>
|
||||||
|
</mat-expansion-panel-header>
|
||||||
|
|
||||||
|
<div class="list-chip">
|
||||||
|
<mat-chip-list aria-label="User selection">
|
||||||
|
<mat-chip
|
||||||
|
*ngFor="let userInfo of selectedUserList"
|
||||||
|
(removed)="onClickDeleteUser(userInfo)"
|
||||||
|
>
|
||||||
|
{{ userInfo.name }}
|
||||||
|
<mat-icon matChipRemove>clear</mat-icon>
|
||||||
|
</mat-chip>
|
||||||
|
</mat-chip-list>
|
||||||
|
</div>
|
||||||
|
<div class="btn-box">
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<button
|
||||||
|
mat-flat-button
|
||||||
|
[disabled]="
|
||||||
|
selectedUserList.length > 0 ? 'false' : 'true'
|
||||||
|
"
|
||||||
|
(click)="onClickAddGroup()"
|
||||||
|
class="mat-primary"
|
||||||
|
>
|
||||||
|
{{ 'organization.addToGroup' | translate }}
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<button
|
||||||
|
mat-flat-button
|
||||||
|
[disabled]="
|
||||||
|
selectedUserList.length > 0 ? 'false' : 'true'
|
||||||
|
"
|
||||||
|
(click)="onClickChatOpen()"
|
||||||
|
class="mat-primary"
|
||||||
|
>
|
||||||
|
{{ 'organization.startChat' | translate }}
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
<li *ngIf="!!authInfo && authInfo.canVideoConference">
|
||||||
|
<button
|
||||||
|
mat-flat-button
|
||||||
|
[disabled]="
|
||||||
|
selectedUserList.length > 0 ? 'false' : 'true'
|
||||||
|
"
|
||||||
|
(click)="onClickConference()"
|
||||||
|
class="mat-primary"
|
||||||
|
>
|
||||||
|
{{ 'organization.startVideoConference' | translate }}
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</mat-expansion-panel>
|
||||||
|
</mat-accordion>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="footer-fix search-result-footer">
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<button
|
||||||
|
mat-flat-button
|
||||||
|
(click)="onClickAddGroup()"
|
||||||
|
class="mat-primary"
|
||||||
|
>
|
||||||
|
검색 초기화 & 닫기
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<button
|
||||||
|
mat-flat-button
|
||||||
|
(click)="onClickChatOpen()"
|
||||||
|
class="mat-primary"
|
||||||
|
>
|
||||||
|
접어두기
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</mat-card-content>
|
</mat-card-content>
|
||||||
</mat-card>
|
</mat-card>
|
||||||
|
|
|
@ -1,23 +1,25 @@
|
||||||
import { Component, OnInit, Inject, OnDestroy, ViewChild } from '@angular/core';
|
import {
|
||||||
|
Component,
|
||||||
|
OnInit,
|
||||||
|
Inject,
|
||||||
|
OnDestroy,
|
||||||
|
ChangeDetectorRef
|
||||||
|
} from '@angular/core';
|
||||||
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
|
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
|
||||||
import { KEY_VER_INFO } from '@app/types';
|
import { KEY_VER_INFO, MainMenu, KEY_AUTH_INFO } from '@app/types';
|
||||||
import { SessionStorageService } from '@ucap-webmessenger/web-storage';
|
import { SessionStorageService } from '@ucap-webmessenger/web-storage';
|
||||||
|
|
||||||
import { Store, select } from '@ngrx/store';
|
import { Store, select } from '@ngrx/store';
|
||||||
import * as AppStore from '@app/store';
|
import * as AppStore from '@app/store';
|
||||||
import * as StatusStore from '@app/store/messenger/status';
|
import * as QueryStore from '@app/store/messenger/query';
|
||||||
import {
|
import * as ChatStore from '@app/store/messenger/chat';
|
||||||
UserInfoSS,
|
import * as SettingsStore from '@app/store/messenger/settings';
|
||||||
QueryProtocolService,
|
import * as SyncStore from '@app/store/messenger/sync';
|
||||||
DeptSearchType,
|
|
||||||
SSVC_TYPE_QUERY_DEPT_USER_DATA,
|
import { UserInfoSS, AuthResponse } from '@ucap-webmessenger/protocol-query';
|
||||||
DeptUserData,
|
|
||||||
SSVC_TYPE_QUERY_DEPT_USER_RES,
|
|
||||||
DeptUserResponse
|
|
||||||
} from '@ucap-webmessenger/protocol-query';
|
|
||||||
import { LoginResponse } from '@ucap-webmessenger/protocol-authentication';
|
import { LoginResponse } from '@ucap-webmessenger/protocol-authentication';
|
||||||
import { map, catchError, take, tap } from 'rxjs/operators';
|
import { map, take, tap } from 'rxjs/operators';
|
||||||
import { Subscription, of, Observable } from 'rxjs';
|
import { Subscription, Observable, BehaviorSubject } from 'rxjs';
|
||||||
import { EnvironmentsInfo, KEY_ENVIRONMENTS_INFO } from '@app/types';
|
import { EnvironmentsInfo, KEY_ENVIRONMENTS_INFO } from '@app/types';
|
||||||
import { NGXLogger } from 'ngx-logger';
|
import { NGXLogger } from 'ngx-logger';
|
||||||
import { NativeService, UCAP_NATIVE_SERVICE } from '@ucap-webmessenger/native';
|
import { NativeService, UCAP_NATIVE_SERVICE } from '@ucap-webmessenger/native';
|
||||||
|
@ -25,16 +27,20 @@ import { environment } from '../../../../../environments/environment';
|
||||||
import { StatusBulkInfo } from '@ucap-webmessenger/protocol-status';
|
import { StatusBulkInfo } from '@ucap-webmessenger/protocol-status';
|
||||||
import { VersionInfo2Response } from '@ucap-webmessenger/api-public';
|
import { VersionInfo2Response } from '@ucap-webmessenger/api-public';
|
||||||
import { DaesangProtocolService } from '@ucap-webmessenger/daesang';
|
import { DaesangProtocolService } from '@ucap-webmessenger/daesang';
|
||||||
import {
|
import { DialogService } from '@ucap-webmessenger/ui';
|
||||||
DialogService,
|
|
||||||
IntegratedSearchComponent
|
|
||||||
} from '@ucap-webmessenger/ui';
|
|
||||||
import {
|
import {
|
||||||
ProfileDialogComponent,
|
ProfileDialogComponent,
|
||||||
ProfileDialogData,
|
ProfileDialogData,
|
||||||
ProfileDialogResult
|
ProfileDialogResult
|
||||||
} from '../profile/profile.dialog.component';
|
} from '../profile/profile.dialog.component';
|
||||||
import { PageEvent } from '@angular/material/paginator';
|
import {
|
||||||
|
SelectGroupDialogComponent,
|
||||||
|
SelectGroupDialogData,
|
||||||
|
SelectGroupDialogResult
|
||||||
|
} from '../group/select-group.dialog.component';
|
||||||
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
|
import { GroupDetailData } from '@ucap-webmessenger/protocol-sync';
|
||||||
|
import { ConferenceService } from '@ucap-webmessenger/api-prompt';
|
||||||
|
|
||||||
export interface IntegratedSearchDialogData {
|
export interface IntegratedSearchDialogData {
|
||||||
keyword: string;
|
keyword: string;
|
||||||
|
@ -52,19 +58,21 @@ export class IntegratedSearchDialogComponent implements OnInit, OnDestroy {
|
||||||
loginResSubscription: Subscription;
|
loginResSubscription: Subscription;
|
||||||
sessionVerinfo: VersionInfo2Response;
|
sessionVerinfo: VersionInfo2Response;
|
||||||
environmentsInfo: EnvironmentsInfo;
|
environmentsInfo: EnvironmentsInfo;
|
||||||
|
authInfo: AuthResponse;
|
||||||
|
|
||||||
presence$: Observable<StatusBulkInfo[]>;
|
searchDepartmentUserInfoListSubscription: Subscription;
|
||||||
searchSubscription: Subscription;
|
searchingProcessing$: Observable<boolean>;
|
||||||
searchUserInfos: UserInfoSS[] = [];
|
|
||||||
searchingProcessing = false;
|
departmentUserInfoList: UserInfoSS[] = [];
|
||||||
|
originDepartmentUserInfoList: UserInfoSS[] = [];
|
||||||
|
|
||||||
|
selectedUserList: UserInfoSS[] = []; // selected user in departmentUserList detail
|
||||||
|
|
||||||
|
profileImageRoot: string;
|
||||||
|
presenceSubscription: Subscription;
|
||||||
|
presenceSubject = new BehaviorSubject<StatusBulkInfo[]>(undefined);
|
||||||
|
|
||||||
currentSearchWord: string;
|
currentSearchWord: string;
|
||||||
totalCount = 0;
|
|
||||||
pageCurrent = 1;
|
|
||||||
pageListCount = 20;
|
|
||||||
|
|
||||||
@ViewChild('integratedSearch', { static: false })
|
|
||||||
integratedSearchComponent: IntegratedSearchComponent;
|
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
public dialogRef: MatDialogRef<
|
public dialogRef: MatDialogRef<
|
||||||
|
@ -73,22 +81,30 @@ export class IntegratedSearchDialogComponent implements OnInit, OnDestroy {
|
||||||
>,
|
>,
|
||||||
@Inject(UCAP_NATIVE_SERVICE) private nativeService: NativeService,
|
@Inject(UCAP_NATIVE_SERVICE) private nativeService: NativeService,
|
||||||
@Inject(MAT_DIALOG_DATA) public data: IntegratedSearchDialogData,
|
@Inject(MAT_DIALOG_DATA) public data: IntegratedSearchDialogData,
|
||||||
private queryProtocolService: QueryProtocolService,
|
|
||||||
private sessionStorageService: SessionStorageService,
|
private sessionStorageService: SessionStorageService,
|
||||||
private daesangProtocolService: DaesangProtocolService,
|
private daesangProtocolService: DaesangProtocolService,
|
||||||
private dialogService: DialogService,
|
private dialogService: DialogService,
|
||||||
|
private translateService: TranslateService,
|
||||||
|
private conferenceService: ConferenceService,
|
||||||
|
|
||||||
private store: Store<any>,
|
private store: Store<any>,
|
||||||
|
private changeDetectorRef: ChangeDetectorRef,
|
||||||
private logger: NGXLogger
|
private logger: NGXLogger
|
||||||
) {
|
) {
|
||||||
this.environmentsInfo = this.sessionStorageService.get<EnvironmentsInfo>(
|
this.environmentsInfo = this.sessionStorageService.get<EnvironmentsInfo>(
|
||||||
KEY_ENVIRONMENTS_INFO
|
KEY_ENVIRONMENTS_INFO
|
||||||
);
|
);
|
||||||
|
|
||||||
|
this.authInfo = this.sessionStorageService.get<AuthResponse>(KEY_AUTH_INFO);
|
||||||
|
|
||||||
this.sessionVerinfo = this.sessionStorageService.get<VersionInfo2Response>(
|
this.sessionVerinfo = this.sessionStorageService.get<VersionInfo2Response>(
|
||||||
KEY_VER_INFO
|
KEY_VER_INFO
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
|
this.profileImageRoot = this.sessionVerinfo.profileRoot;
|
||||||
|
|
||||||
this.loginResSubscription = this.store
|
this.loginResSubscription = this.store
|
||||||
.pipe(
|
.pipe(
|
||||||
select(AppStore.AccountSelector.AuthenticationSelector.loginRes),
|
select(AppStore.AccountSelector.AuthenticationSelector.loginRes),
|
||||||
|
@ -98,26 +114,48 @@ export class IntegratedSearchDialogComponent implements OnInit, OnDestroy {
|
||||||
)
|
)
|
||||||
.subscribe();
|
.subscribe();
|
||||||
|
|
||||||
this.onSearch(this.data.keyword);
|
this.searchDepartmentUserInfoListSubscription = this.store
|
||||||
|
.pipe(
|
||||||
|
select(
|
||||||
|
AppStore.MessengerSelector.QuerySelector
|
||||||
|
.integrateSearchDepartmentUserInfoList
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.subscribe(list => {
|
||||||
|
this.departmentUserInfoList = list;
|
||||||
|
this.originDepartmentUserInfoList = list;
|
||||||
|
});
|
||||||
|
|
||||||
this.presence$ = this.store.pipe(
|
this.searchingProcessing$ = this.store.pipe(
|
||||||
select(AppStore.MessengerSelector.StatusSelector.selectAllStatusBulkInfo)
|
select(
|
||||||
|
AppStore.MessengerSelector.QuerySelector
|
||||||
|
.integrateSearchDepartmentProcessing
|
||||||
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
this.presenceSubscription = this.store
|
||||||
|
.pipe(
|
||||||
|
select(
|
||||||
|
AppStore.MessengerSelector.StatusSelector.selectAllStatusBulkInfo
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.subscribe(presence => {
|
||||||
|
this.presenceSubject.next(presence);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.onSearch(this.data.keyword);
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnDestroy(): void {
|
ngOnDestroy(): void {
|
||||||
if (!!this.searchSubscription) {
|
|
||||||
this.searchSubscription.unsubscribe();
|
|
||||||
}
|
|
||||||
if (!!this.loginResSubscription) {
|
if (!!this.loginResSubscription) {
|
||||||
this.loginResSubscription.unsubscribe();
|
this.loginResSubscription.unsubscribe();
|
||||||
}
|
}
|
||||||
|
if (!!this.searchDepartmentUserInfoListSubscription) {
|
||||||
|
this.searchDepartmentUserInfoListSubscription.unsubscribe();
|
||||||
|
}
|
||||||
|
if (!!this.presenceSubscription) {
|
||||||
|
this.presenceSubscription.unsubscribe();
|
||||||
}
|
}
|
||||||
|
|
||||||
onReSearch(searchWord: string) {
|
|
||||||
this.pageCurrent = 1;
|
|
||||||
this.integratedSearchComponent.paginator.pageIndex = 0;
|
|
||||||
this.onSearch(searchWord);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onSearch(searchWord: string) {
|
onSearch(searchWord: string) {
|
||||||
|
@ -126,78 +164,122 @@ export class IntegratedSearchDialogComponent implements OnInit, OnDestroy {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (searchWord.trim().length > 0) {
|
if (searchWord.trim().length > 0) {
|
||||||
this.searchingProcessing = true;
|
|
||||||
const searchUserInfos: UserInfoSS[] = [];
|
|
||||||
|
|
||||||
this.searchSubscription = this.queryProtocolService
|
|
||||||
.deptUser({
|
|
||||||
divCd: 'INT_SRCH',
|
|
||||||
companyCode: this.loginRes.companyCode,
|
|
||||||
searchRange: DeptSearchType.All,
|
|
||||||
search: searchWord.trim(),
|
|
||||||
senderCompanyCode: this.loginRes.companyCode,
|
|
||||||
senderEmployeeType: this.loginRes.userInfo.employeeType,
|
|
||||||
pageCurrent: this.pageCurrent,
|
|
||||||
pageListCount: this.pageListCount
|
|
||||||
})
|
|
||||||
.pipe(
|
|
||||||
map(res => {
|
|
||||||
switch (res.SSVC_TYPE) {
|
|
||||||
case SSVC_TYPE_QUERY_DEPT_USER_DATA:
|
|
||||||
const userInfos = (res as DeptUserData).userInfos;
|
|
||||||
searchUserInfos.push(...userInfos);
|
|
||||||
break;
|
|
||||||
case SSVC_TYPE_QUERY_DEPT_USER_RES:
|
|
||||||
{
|
|
||||||
const response = res as DeptUserResponse;
|
|
||||||
|
|
||||||
// 검색 결과 처리.
|
|
||||||
this.searchUserInfos = searchUserInfos.sort((a, b) =>
|
|
||||||
a.name < b.name ? -1 : a.name > b.name ? 1 : 0
|
|
||||||
);
|
|
||||||
|
|
||||||
this.totalCount = response.pageTotalCount;
|
|
||||||
this.pageCurrent = response.pageCurrent;
|
|
||||||
this.pageListCount = response.pageListCount;
|
|
||||||
this.searchingProcessing = false;
|
|
||||||
|
|
||||||
// 검색 결과에 따른 프레즌스 조회.
|
|
||||||
if (searchUserInfos.length > 0) {
|
|
||||||
this.store.dispatch(
|
this.store.dispatch(
|
||||||
StatusStore.bulkInfo({
|
QueryStore.integrateSearchDeptUser({
|
||||||
divCd: 'INT_SRCH',
|
companyCode: this.loginRes.companyCode,
|
||||||
userSeqs: this.searchUserInfos.map(user => user.seq)
|
search: searchWord.trim()
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
catchError(error => {
|
|
||||||
this.searchingProcessing = false;
|
|
||||||
return of(this.logger.error(error));
|
|
||||||
})
|
|
||||||
)
|
|
||||||
.subscribe();
|
|
||||||
} else {
|
} else {
|
||||||
// clear list.
|
// clear list.
|
||||||
this.searchingProcessing = false;
|
this.store.dispatch(QueryStore.integrateClearSearchDeptUser({}));
|
||||||
this.searchUserInfos = [];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onCancel(): void {
|
/** Selected User Handling */
|
||||||
this.dialogRef.close({});
|
onToggleAllUser(params: { isChecked: boolean; userInfos: UserInfoSS[] }) {
|
||||||
|
params.userInfos.forEach(userInfo => {
|
||||||
|
if (params.isChecked) {
|
||||||
|
if (
|
||||||
|
this.selectedUserList.filter(user => user.seq === userInfo.seq)
|
||||||
|
.length === 0
|
||||||
|
) {
|
||||||
|
this.selectedUserList = [...this.selectedUserList, userInfo];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.selectedUserList = this.selectedUserList.filter(
|
||||||
|
user => user.seq !== userInfo.seq
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
onToggleUser(userInfo: UserInfoSS) {
|
||||||
|
if (userInfo.seq === this.loginRes.userSeq) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
onChangePage(event: PageEvent) {
|
if (
|
||||||
this.pageCurrent = event.pageIndex + 1;
|
this.selectedUserList.filter(user => user.seq === userInfo.seq).length ===
|
||||||
this.pageListCount = event.pageSize;
|
0
|
||||||
|
) {
|
||||||
this.onSearch(this.currentSearchWord);
|
this.selectedUserList = [...this.selectedUserList, userInfo];
|
||||||
|
} else {
|
||||||
|
this.selectedUserList = this.selectedUserList.filter(
|
||||||
|
item => item.seq !== userInfo.seq
|
||||||
|
);
|
||||||
|
}
|
||||||
|
this.changeDetectorRef.detectChanges();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Handling chipset for selectedUserList */
|
||||||
|
onClickDeleteUser(userInfo: UserInfoSS) {
|
||||||
|
this.selectedUserList = this.selectedUserList.filter(
|
||||||
|
item => item.seq !== userInfo.seq
|
||||||
|
);
|
||||||
|
this.changeDetectorRef.detectChanges();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Handling Button */
|
||||||
|
async onClickAddGroup() {
|
||||||
|
this.logger.debug('onClickAddGroup', this.selectedUserList);
|
||||||
|
|
||||||
|
const result = await this.dialogService.open<
|
||||||
|
SelectGroupDialogComponent,
|
||||||
|
SelectGroupDialogData,
|
||||||
|
SelectGroupDialogResult
|
||||||
|
>(SelectGroupDialogComponent, {
|
||||||
|
width: '600px',
|
||||||
|
data: {
|
||||||
|
title: this.translateService.instant('group.selectTargetGroup')
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!!result && !!result.choice && result.choice) {
|
||||||
|
if (!!result.group) {
|
||||||
|
const oldGroup: GroupDetailData = result.group;
|
||||||
|
const trgtUserSeq: number[] = [];
|
||||||
|
result.group.userSeqs.map(seq => trgtUserSeq.push(seq));
|
||||||
|
this.selectedUserList
|
||||||
|
.filter(v => result.group.userSeqs.indexOf(v.seq) < 0)
|
||||||
|
.forEach(user => {
|
||||||
|
trgtUserSeq.push(user.seq);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.store.dispatch(
|
||||||
|
SyncStore.updateGroupMember({
|
||||||
|
oldGroup,
|
||||||
|
trgtUserSeq
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
onClickChatOpen() {
|
||||||
|
if (!!this.selectedUserList && this.selectedUserList.length > 0) {
|
||||||
|
// Open Room.
|
||||||
|
const seq: number[] = [];
|
||||||
|
this.selectedUserList.map(user => seq.push(user.seq));
|
||||||
|
this.store.dispatch(ChatStore.openRoom({ userSeqList: seq }));
|
||||||
|
|
||||||
|
// GNB Change to Chat
|
||||||
|
this.store.dispatch(
|
||||||
|
SettingsStore.selectedGnbMenuIndex({
|
||||||
|
menuIndex: MainMenu.Chat
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
onClickConference() {
|
||||||
|
const targetUserSeqs = this.selectedUserList.map(userInfo => userInfo.seq);
|
||||||
|
if (!!targetUserSeqs && targetUserSeqs.length > 0) {
|
||||||
|
this.conferenceService.conferenceCreate({
|
||||||
|
userSeq: this.loginRes.userSeq,
|
||||||
|
deviceType: this.environmentsInfo.deviceType,
|
||||||
|
tokenKey: this.loginRes.tokenString,
|
||||||
|
targetUserSeqs
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
onClickOpenProfile(userSeq: number) {
|
onClickOpenProfile(userSeq: number) {
|
||||||
if (!userSeq || userSeq < 0) {
|
if (!userSeq || userSeq < 0) {
|
||||||
return;
|
return;
|
||||||
|
@ -234,4 +316,7 @@ export class IntegratedSearchDialogComponent implements OnInit, OnDestroy {
|
||||||
)
|
)
|
||||||
.subscribe();
|
.subscribe();
|
||||||
}
|
}
|
||||||
|
onCancel(): void {
|
||||||
|
this.dialogRef.close({});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -100,10 +100,34 @@ export const searchDeptUserSuccess = createAction(
|
||||||
|
|
||||||
export const searchDeptUserFailure = createAction(
|
export const searchDeptUserFailure = createAction(
|
||||||
'[Messenger::Query] Search Dept User Failure',
|
'[Messenger::Query] Search Dept User Failure',
|
||||||
|
props<{ error: any }>()
|
||||||
|
);
|
||||||
|
|
||||||
|
export const clearSearchDeptUser = createAction(
|
||||||
|
'[Messenger::Query] Clear Search Dept User Success',
|
||||||
props()
|
props()
|
||||||
);
|
);
|
||||||
|
|
||||||
export const cancelSearchDeptUser = createAction(
|
/** 통합검색 > 조회 */
|
||||||
'[Messenger::Query] Cancel Search Dept User Success',
|
export const integrateSearchDeptUser = createAction(
|
||||||
|
'[Messenger::Query] Integration Search Dept User',
|
||||||
|
props<{
|
||||||
|
companyCode: string;
|
||||||
|
search: string;
|
||||||
|
}>()
|
||||||
|
);
|
||||||
|
|
||||||
|
export const integrateSearchDeptUserSuccess = createAction(
|
||||||
|
'[Messenger::Query] Integration Search Dept User Success.',
|
||||||
|
props<{ userInfos: UserInfoSS[] }>()
|
||||||
|
);
|
||||||
|
|
||||||
|
export const integrateSearchDeptUserFailure = createAction(
|
||||||
|
'[Messenger::Query] Integration Search Dept User Failure.',
|
||||||
|
props<{ error: any }>()
|
||||||
|
);
|
||||||
|
|
||||||
|
export const integrateClearSearchDeptUser = createAction(
|
||||||
|
'[Messenger::Query] Integration Clear Search Dept User Success',
|
||||||
props()
|
props()
|
||||||
);
|
);
|
||||||
|
|
|
@ -28,7 +28,11 @@ import {
|
||||||
selectedDeptSuccess,
|
selectedDeptSuccess,
|
||||||
searchDeptUser,
|
searchDeptUser,
|
||||||
searchDeptUserSuccess,
|
searchDeptUserSuccess,
|
||||||
cancelSearchDeptUser
|
clearSearchDeptUser,
|
||||||
|
integrateSearchDeptUser,
|
||||||
|
integrateSearchDeptUserSuccess,
|
||||||
|
integrateSearchDeptUserFailure,
|
||||||
|
searchDeptUserFailure
|
||||||
} from './actions';
|
} from './actions';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
@ -146,7 +150,58 @@ export class Effects {
|
||||||
|
|
||||||
this.store.dispatch(selectedDeptSuccess({}));
|
this.store.dispatch(selectedDeptSuccess({}));
|
||||||
}),
|
}),
|
||||||
catchError(error => of(deptUserFailure({ error })))
|
catchError(error => of(searchDeptUserFailure({ error })))
|
||||||
|
);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
},
|
||||||
|
{ dispatch: false }
|
||||||
|
);
|
||||||
|
|
||||||
|
integrateSearchDeptUser$ = createEffect(
|
||||||
|
() => {
|
||||||
|
return this.actions$.pipe(
|
||||||
|
ofType(integrateSearchDeptUser),
|
||||||
|
withLatestFrom(
|
||||||
|
this.store.pipe(
|
||||||
|
select(
|
||||||
|
(state: any) =>
|
||||||
|
state.account.authentication.loginRes as LoginResponse
|
||||||
|
)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
switchMap(([req, loginResInfo]) => {
|
||||||
|
return this.organizationService
|
||||||
|
.getDeptUser({
|
||||||
|
divCd: 'INT_SRCH',
|
||||||
|
companyCode: req.companyCode,
|
||||||
|
search: req.search,
|
||||||
|
searchRange: DeptSearchType.All,
|
||||||
|
senderCompanyCode: loginResInfo.companyCode,
|
||||||
|
senderEmployeeType: loginResInfo.userInfo.employeeType
|
||||||
|
})
|
||||||
|
.pipe(
|
||||||
|
map(datas => {
|
||||||
|
const userInfos: UserInfoSS[] = datas.userInfos;
|
||||||
|
this.store.dispatch(
|
||||||
|
integrateSearchDeptUserSuccess({
|
||||||
|
userInfos
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
// 검색 결과에 따른 프레즌스 조회.
|
||||||
|
const userSeqList: number[] = [];
|
||||||
|
userInfos.map(user => userSeqList.push(user.seq));
|
||||||
|
if (userSeqList.length > 0) {
|
||||||
|
this.store.dispatch(
|
||||||
|
StatusStore.bulkInfo({
|
||||||
|
divCd: 'inttrSrch',
|
||||||
|
userSeqs: userSeqList
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
catchError(error => of(integrateSearchDeptUserFailure({ error })))
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
@ -179,7 +234,6 @@ export class Effects {
|
||||||
.pipe(
|
.pipe(
|
||||||
map(datas => {
|
map(datas => {
|
||||||
const userInfos: UserInfoSS[] = datas.userInfos;
|
const userInfos: UserInfoSS[] = datas.userInfos;
|
||||||
|
|
||||||
this.store.dispatch(
|
this.store.dispatch(
|
||||||
searchDeptUserSuccess({
|
searchDeptUserSuccess({
|
||||||
userInfos
|
userInfos
|
||||||
|
|
|
@ -11,8 +11,12 @@ import {
|
||||||
searchDeptUserSuccess,
|
searchDeptUserSuccess,
|
||||||
searchDeptUserFailure,
|
searchDeptUserFailure,
|
||||||
deptUserFailure,
|
deptUserFailure,
|
||||||
cancelSearchDeptUser,
|
clearSearchDeptUser,
|
||||||
myDeptUserFailure
|
myDeptUserFailure,
|
||||||
|
integrateSearchDeptUser,
|
||||||
|
integrateSearchDeptUserSuccess,
|
||||||
|
integrateSearchDeptUserFailure,
|
||||||
|
integrateClearSearchDeptUser
|
||||||
} from './actions';
|
} from './actions';
|
||||||
|
|
||||||
import * as AuthenticationStore from '@app/store/account/authentication';
|
import * as AuthenticationStore from '@app/store/account/authentication';
|
||||||
|
@ -96,7 +100,7 @@ export const reducer = createReducer(
|
||||||
};
|
};
|
||||||
}),
|
}),
|
||||||
|
|
||||||
on(cancelSearchDeptUser, (state, action) => {
|
on(clearSearchDeptUser, (state, action) => {
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
isSearch: false,
|
isSearch: false,
|
||||||
|
@ -104,6 +108,35 @@ export const reducer = createReducer(
|
||||||
};
|
};
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
on(integrateSearchDeptUser, (state, action) => {
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
integrateSearchDepartmentProcessing: true
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
|
||||||
|
on(integrateSearchDeptUserSuccess, (state, action) => {
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
integrateSearchDepartmentUserInfoList: action.userInfos,
|
||||||
|
integrateSearchDepartmentProcessing: false
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
|
||||||
|
on(integrateSearchDeptUserFailure, (state, action) => {
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
integrateSearchDepartmentProcessing: false
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
|
||||||
|
on(integrateClearSearchDeptUser, (state, action) => {
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
integrateSearchDepartmentUserInfoList: null
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
|
||||||
on(AuthenticationStore.logoutInitialize, (state, action) => {
|
on(AuthenticationStore.logoutInitialize, (state, action) => {
|
||||||
return {
|
return {
|
||||||
...initialState
|
...initialState
|
||||||
|
|
|
@ -18,6 +18,9 @@ export interface State {
|
||||||
searchDepartmentUserInfoList: UserInfoSS[] | null;
|
searchDepartmentUserInfoList: UserInfoSS[] | null;
|
||||||
departmentUserInfoList: UserInfoSS[] | null;
|
departmentUserInfoList: UserInfoSS[] | null;
|
||||||
myDepartmentUserInfoList: UserInfoSS[] | null;
|
myDepartmentUserInfoList: UserInfoSS[] | null;
|
||||||
|
|
||||||
|
integrateSearchDepartmentProcessing: boolean;
|
||||||
|
integrateSearchDepartmentUserInfoList: UserInfoSS[] | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const initialState: State = {
|
export const initialState: State = {
|
||||||
|
@ -30,7 +33,10 @@ export const initialState: State = {
|
||||||
|
|
||||||
searchDepartmentUserInfoList: null,
|
searchDepartmentUserInfoList: null,
|
||||||
departmentUserInfoList: null,
|
departmentUserInfoList: null,
|
||||||
myDepartmentUserInfoList: null
|
myDepartmentUserInfoList: null,
|
||||||
|
|
||||||
|
integrateSearchDepartmentProcessing: false,
|
||||||
|
integrateSearchDepartmentUserInfoList: null
|
||||||
};
|
};
|
||||||
|
|
||||||
export function selectors<S>(selector: Selector<any, State>) {
|
export function selectors<S>(selector: Selector<any, State>) {
|
||||||
|
@ -62,6 +68,15 @@ export function selectors<S>(selector: Selector<any, State>) {
|
||||||
myDepartmentUserInfoList: createSelector(
|
myDepartmentUserInfoList: createSelector(
|
||||||
selector,
|
selector,
|
||||||
(state: State) => state.myDepartmentUserInfoList
|
(state: State) => state.myDepartmentUserInfoList
|
||||||
|
),
|
||||||
|
|
||||||
|
integrateSearchDepartmentProcessing: createSelector(
|
||||||
|
selector,
|
||||||
|
(state: State) => state.integrateSearchDepartmentProcessing
|
||||||
|
),
|
||||||
|
integrateSearchDepartmentUserInfoList: createSelector(
|
||||||
|
selector,
|
||||||
|
(state: State) => state.integrateSearchDepartmentUserInfoList
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user