통합검색에 UX 적용.

This commit is contained in:
leejinho 2020-03-06 16:42:14 +09:00
parent 3cfa9a39ac
commit 05a148d30a
9 changed files with 448 additions and 131 deletions

View File

@ -152,7 +152,7 @@ export class OrganizationTreeComponent implements OnInit, OnDestroy {
} }
/** 검색 취소 */ /** 검색 취소 */
onClickCancel() { onClickCancel() {
this.store.dispatch(QueryStore.cancelSearchDeptUser({})); this.store.dispatch(QueryStore.clearSearchDeptUser({}));
} }
/** 조직도 부서 선택 */ /** 조직도 부서 선택 */

View File

@ -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 }}

View File

@ -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

View File

@ -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>

View File

@ -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({});
}
} }

View File

@ -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()
); );

View File

@ -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

View File

@ -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

View File

@ -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
) )
}; };
} }