조직도 타이틀, 검색 기능 구현.

This commit is contained in:
leejinho 2019-11-12 09:47:56 +09:00
parent d28b6cc171
commit 8fec0e15f2
3 changed files with 264 additions and 107 deletions

View File

@ -1,7 +1,16 @@
<div
class="oraganization-tab"
*ngIf="departmentInfoList$ | async"
<div>
<div class="current-head">
<h3>조직도</h3>
</div>
<ucap-organization-tenant-search
[companyList]="companyList$ | async"
[companyCode]="companyCode"
(keyDownEnter)="onKeyDownEnterOrganizationTenantSearch($event)"
(cancel)="onClickCancel($event)"
>
</ucap-organization-tenant-search>
</div>
<div class="oraganization-tab" *ngIf="departmentInfoList$ | async">
<div class="oraganization-tab-tree">
<ucap-organization-tree
[oraganizationList]="departmentInfoList$ | async"
@ -12,7 +21,14 @@
<div class="select-list">
<dl class="select-dept text-accent-color">
<dt>
<ng-container *ngIf="!isShowSearch">
{{ getSelectedDepartmentName() }}
</ng-container>
<ng-container *ngIf="isShowSearch">
검색결과<span class="text-accent-color"
>({{ searchUserInfos.length }}명)</span
>
</ng-container>
</dt>
<dd>
<mat-checkbox
@ -27,11 +43,8 @@
<div *ngIf="selectedDepartmentProcessing">
<mat-progress-bar mode="indeterminate"></mat-progress-bar>
</div>
<div class="search-list">
<cdk-virtual-scroll-viewport
itemSize="20"
style="height: 100%;"
>
<div *ngIf="!isShowSearch" class="search-list">
<cdk-virtual-scroll-viewport itemSize="20" style="height: 100%;">
<ucap-profile-user-list-item
*cdkVirtualFor="let userInfo of selectedDepartmentUserInfoList"
[userInfo]="userInfo"
@ -55,11 +68,25 @@
>
</ucap-profile-user-list-item> -->
</div>
<div *ngIf="isShowSearch" class="search-result">
<cdk-virtual-scroll-viewport itemSize="20" style="height: 100%;">
<ucap-profile-user-list-item
*cdkVirtualFor="let userInfo of searchUserInfos"
[userInfo]="userInfo"
[checkable]="true"
[sessionVerinfo]="sessionVerinfo"
[selectedUserList]="selectedUserList"
[isChecked]="getCheckedUser(userInfo)"
(checkUser)="onCheckUser($event)"
>
</ucap-profile-user-list-item>
</cdk-virtual-scroll-viewport>
</div>
</div>
<div *ngIf="!isUserSelect" class="btn-box">
<!--선택된 후에는 disabled="true" 빼주세요. -->
<button
mat-stroked-button
[disabled]="selectedUserList.length > 0 ? 'false' : 'true'"
class="mat-primary"
(click)="onClickShowSelectedUserList()"
>
@ -69,18 +96,29 @@
</button>
<ul>
<li>
<button mat-flat-button (click)="onClickAddGroup()" class="mat-primary">
<button
mat-flat-button
[disabled]="selectedUserList.length > 0 ? 'false' : 'true'"
(click)="onClickAddGroup()"
class="mat-primary"
>
그룹에 추가
</button>
</li>
<li>
<button mat-flat-button (click)="onClickChatOpen()" class="mat-primary">
<button
mat-flat-button
[disabled]="selectedUserList.length > 0 ? 'false' : 'true'"
(click)="onClickChatOpen()"
class="mat-primary"
>
대화
</button>
</li>
<li>
<button
mat-flat-button
[disabled]="selectedUserList.length > 0 ? 'false' : 'true'"
(click)="onClickConference()"
class="mat-primary"
>

View File

@ -15,9 +15,44 @@
}
}
.current-head {
display: flex;
justify-content: center;
padding: 0 10px;
height: 70px;
background-color: #eeeeee;
background: #f15f79;
background: -webkit-linear-gradient(to right, #352a37, #f15f79);
background: linear-gradient(to right, #352a37, #ef4c73);
color: #ffffff;
h3 {
display: inline-flex;
padding-left: 10px;
align-items: center;
width: 100%;
}
.btn-box {
height: 100%;
margin-left: auto;
display: inline-flex;
align-items: center;
svg {
stroke: #333333;
}
}
}
.search-result {
height: calc(100% - 40px);
overflow: auto;
.result-num {
padding: 10px;
display: flex;
height: 40px;
}
}
.oraganization-tab {
height: 100%;
height: calc(100% - 130px);
flex-direction: inherit;
display: flex;
.oraganization-tab-tree {
@ -48,7 +83,6 @@
display: flex;
background-color: #f9f9f9;
dt {
}
dd {
margin-left: auto;
@ -67,6 +101,9 @@
button {
width: 100%;
@include ellipsis(1);
span {
vertical-align: baseline;
}
}
ul {
display: flex;
@ -92,7 +129,6 @@
}
}
.dialog-org {
.oraganization-tab {
width: 100%;

View File

@ -4,10 +4,10 @@ import {
OnDestroy,
Output,
EventEmitter,
Input
Input,
} from '@angular/core';
import { ucapAnimations, DialogService } from '@ucap-webmessenger/ui';
import { Observable, Subscription } from 'rxjs';
import { Observable, Subscription, of } from 'rxjs';
import {
DeptInfo,
QueryProtocolService,
@ -15,7 +15,10 @@ import {
UserInfoSS,
DeptUserResponse,
UserInfoF,
UserInfoDN
UserInfoDN,
SSVC_TYPE_QUERY_DEPT_USER_DATA,
SSVC_TYPE_QUERY_DEPT_USER_RES,
DeptUserData,
} from '@ucap-webmessenger/protocol-query';
import { UserInfo, GroupDetailData } from '@ucap-webmessenger/protocol-sync';
import { Store, select } from '@ngrx/store';
@ -25,23 +28,25 @@ import * as AppStore from '@app/store';
import * as QueryStore from '@app/store/messenger/query';
import * as SyncStore from '@app/store/messenger/sync';
import * as ChatStore from '@app/store/messenger/chat';
import * as StatusStore from '@app/store/messenger/status';
import { SessionStorageService } from '@ucap-webmessenger/web-storage';
import { LoginInfo, KEY_LOGIN_INFO } from '@app/types';
import { take, map, tap, delay } from 'rxjs/operators';
import { take, map, tap, delay, catchError } from 'rxjs/operators';
import { VersionInfo2Response } from '@ucap-webmessenger/api-public';
import { KEY_VER_INFO } from '@app/types/ver-info.type';
import {
SelectGroupDialogComponent,
SelectGroupDialogData,
SelectGroupDialogResult
SelectGroupDialogResult,
} from '../../dialogs/group/select-group.dialog.component';
import { LoginResponse } from '@ucap-webmessenger/protocol-authentication';
import { Company } from '@ucap-webmessenger/api-external';
@Component({
selector: 'app-layout-chat-left-sidenav-organization',
templateUrl: './organization.component.html',
styleUrls: ['./organization.component.scss'],
animations: ucapAnimations
animations: ucapAnimations,
})
export class OrganizationComponent implements OnInit, OnDestroy {
@Input()
@ -62,6 +67,9 @@ export class OrganizationComponent implements OnInit, OnDestroy {
userInfos: (UserInfo | UserInfoSS | UserInfoF | UserInfoDN)[];
}>();
companyList$: Observable<Company[]>;
companyCode: string;
departmentInfoList$: Observable<DeptInfo[]>;
selectedDepartmentUserInfoList$: Observable<UserInfoSS[]>;
selectedDepartmentUserInfoList: UserInfoSS[] = [];
@ -75,9 +83,13 @@ export class OrganizationComponent implements OnInit, OnDestroy {
loginRes: LoginResponse;
sessionVerinfo: VersionInfo2Response;
isShowSearch = false;
searchUserInfos: UserInfoSS[] = [];
constructor(
private store: Store<any>,
private sessionStorageService: SessionStorageService,
private queryProtocolService: QueryProtocolService,
private dialogService: DialogService,
private logger: NGXLogger
) {
@ -88,6 +100,11 @@ export class OrganizationComponent implements OnInit, OnDestroy {
}
ngOnInit() {
this.companyCode = this.loginInfo.companyCode;
this.companyList$ = this.store.pipe(
select(AppStore.SettingSelector.CompanySelector.companyList)
);
this.departmentInfoList$ = this.store.pipe(
select(AppStore.MessengerSelector.QuerySelector.departmentInfoList)
);
@ -133,7 +150,7 @@ export class OrganizationComponent implements OnInit, OnDestroy {
search: '',
searchRange: DeptSearchType.All,
senderCompanyCode: this.loginInfo.companyCode,
senderEmployeeType: loginRes.userInfo.employeeType
senderEmployeeType: loginRes.userInfo.employeeType,
})
);
return loginRes;
@ -155,7 +172,67 @@ export class OrganizationComponent implements OnInit, OnDestroy {
}
}
/** 유저검색 */
onKeyDownEnterOrganizationTenantSearch(params: {
companyCode: string;
searchWord: string;
}) {
if (params.searchWord.trim().length > 1) {
this.isShowSearch = true;
this.selectedDepartmentProcessing = true;
const searchUserInfos: UserInfoSS[] = [];
this.queryProtocolService
.deptUser({
divCd: 'GRP',
companyCode: params.companyCode,
searchRange: DeptSearchType.All,
search: params.searchWord,
senderCompanyCode: params.companyCode,
senderEmployeeType: this.loginRes.userInfo.employeeType,
})
.pipe(
map(res => {
switch (res.SSVC_TYPE) {
case SSVC_TYPE_QUERY_DEPT_USER_DATA:
searchUserInfos.push(...(res as DeptUserData).userInfos);
break;
case SSVC_TYPE_QUERY_DEPT_USER_RES:
{
// 검색 결과 처리.
this.searchUserInfos = searchUserInfos;
this.selectedDepartmentProcessing = false;
// 검색 결과에 따른 프레즌스 조회.
const userSeqList: number[] = [];
this.searchUserInfos.map(user => userSeqList.push(user.seq));
if (userSeqList.length > 0) {
this.store.dispatch(
StatusStore.bulkInfo({
divCd: 'orgSrch',
userSeqs: userSeqList,
})
);
}
}
break;
}
}),
catchError(error => {
this.selectedDepartmentProcessing = false;
return of(this.logger.error(error));
})
)
.subscribe();
}
}
/** 검색 취소 */
onClickCancel() {
this.isShowSearch = false;
this.searchUserInfos = [];
}
onSelectedOrganization(deptInfo: DeptInfo) {
this.onClickCancel();
this.store
.pipe(
take(1),
@ -169,7 +246,7 @@ export class OrganizationComponent implements OnInit, OnDestroy {
search: '',
searchRange: DeptSearchType.All,
senderCompanyCode: this.loginInfo.companyCode,
senderEmployeeType: loginRes.userInfo.employeeType
senderEmployeeType: loginRes.userInfo.employeeType,
})
);
}),
@ -182,7 +259,7 @@ export class OrganizationComponent implements OnInit, OnDestroy {
getSelectedDepartmentName() {
if (!!this.selectedDepartmentProcessing) {
return '부서조회중..';
return '조회중..';
}
if (!!this.selectedDepartmentName) {
@ -194,10 +271,14 @@ export class OrganizationComponent implements OnInit, OnDestroy {
/** 전체 체크여부 */
getCheckedAllUser() {
const compareList: UserInfoSS[] = this.isShowSearch
? this.searchUserInfos
: this.selectedDepartmentUserInfoList;
if (
!this.selectedDepartmentUserInfoList ||
this.selectedDepartmentUserInfoList.length === 0 ||
this.selectedDepartmentUserInfoList.filter(
!compareList ||
compareList.length === 0 ||
compareList.filter(
item =>
!(
this.selectedUserList.filter(user => user.seq === item.seq).length >
@ -225,7 +306,9 @@ export class OrganizationComponent implements OnInit, OnDestroy {
onCheckAllUser(value: boolean) {
this.checkAllUser.emit({
isChecked: value,
userInfos: this.selectedDepartmentUserInfoList
userInfos: this.isShowSearch
? this.searchUserInfos
: this.selectedDepartmentUserInfoList,
});
}
@ -251,8 +334,8 @@ export class OrganizationComponent implements OnInit, OnDestroy {
>(SelectGroupDialogComponent, {
width: '600px',
data: {
title: 'Group Select'
}
title: 'Group Select',
},
});
if (!!result && !!result.choice && result.choice) {
@ -269,7 +352,7 @@ export class OrganizationComponent implements OnInit, OnDestroy {
this.store.dispatch(
SyncStore.updateGroupMember({
oldGroup,
trgtUserSeq
trgtUserSeq,
})
);