기능추가 :: 조직도 > 부서 선택 :: 부서원 조회 시 프로그레스 추가.

수정 :: 유저선택 팝업 > 선택된 유저 met-chips 로 변경.
수정 :: sync_group2 수행시 syncDate 에 ' ' blank 하나 주는것으로 처리 :: 서버에서 해당 부분 파싱 불가.
This commit is contained in:
leejh 2019-10-22 17:05:29 +09:00
parent 7ff8edb4a7
commit 3d219837bd
8 changed files with 135 additions and 45 deletions

View File

@ -1,16 +1,31 @@
<div class="oraganization-tab" fxLayout="column" *ngIf="departmentInfoList$ | async"> <div
class="oraganization-tab"
fxLayout="column"
*ngIf="departmentInfoList$ | async"
>
<div class="oraganization-tab-tree" fxFlex="40" style="overflow: scroll"> <div class="oraganization-tab-tree" fxFlex="40" style="overflow: scroll">
<ucap-organization-tree [oraganizationList]="departmentInfoList$ | async" <ucap-organization-tree
(selected)="onSelectedOrganization($event)"></ucap-organization-tree> [oraganizationList]="departmentInfoList$ | async"
(selected)="onSelectedOrganization($event)"
></ucap-organization-tree>
</div> </div>
<div fxFlex="60" > <div fxFlex="60">
<div class="select-dept"> <div class="select-dept">
(선택된부서명) {{ getSelectedDepartmentName() }}
</div> </div>
<div class="select-list" > <div *ngIf="selectedDepartmentProcessing">
<ucap-profile-user-list-item *ngFor="let userInfo of selectedDepartmentUserInfoList$ | async" <mat-progress-bar mode="indeterminate"></mat-progress-bar>
[userInfo]="userInfo" [checkable]="true" [sessionVerinfo]="sessionVerinfo" [selectedUserList]="selectedUserList" </div>
[isChecked]="getCheckedUser(userInfo)" (checkUser)="onCheckUser($event)"> <div class="select-list">
<ucap-profile-user-list-item
*ngFor="let userInfo of selectedDepartmentUserInfoList$ | async"
[userInfo]="userInfo"
[checkable]="true"
[sessionVerinfo]="sessionVerinfo"
[selectedUserList]="selectedUserList"
[isChecked]="getCheckedUser(userInfo)"
(checkUser)="onCheckUser($event)"
>
</ucap-profile-user-list-item> </ucap-profile-user-list-item>
</div> </div>
</div> </div>

View File

@ -5,25 +5,24 @@
overflow-y: auto; overflow-y: auto;
} }
} }
.btn-box{ .btn-box {
height:80px; height: 80px;
position: absolute; position: absolute;
bottom:0; bottom: 0;
border-top:1px solid #ddd; border-top: 1px solid #ddd;
align-items: center; align-items: center;
width:100%; width: 100%;
background-color:#ffffff; background-color: #ffffff;
} }
.select-dept{ .select-dept {
border-top:1px solid #dddddd; border-top: 1px solid #dddddd;
height:40px; height: 40px;
width:100%; width: 100%;
display:inline-flex; display: inline-flex;
align-items: center; align-items: center;
padding:0 10px; padding: 0 10px;
} }
.select-list{ .select-list {
height: calc(100% - 120px); height: calc(100% - 120px);
overflow: auto; overflow: auto;
} }

View File

@ -1,6 +1,13 @@
import { Component, OnInit, Output, EventEmitter, Input } from '@angular/core'; import {
Component,
OnInit,
OnDestroy,
Output,
EventEmitter,
Input
} from '@angular/core';
import { ucapAnimations } from '@ucap-webmessenger/ui'; import { ucapAnimations } from '@ucap-webmessenger/ui';
import { Observable } from 'rxjs'; import { Observable, Subscription } from 'rxjs';
import { import {
DeptInfo, DeptInfo,
QueryProtocolService, QueryProtocolService,
@ -18,7 +25,7 @@ import * as AppStore from '@app/store';
import * as QueryStore from '@app/store/messenger/query'; import * as QueryStore from '@app/store/messenger/query';
import { SessionStorageService } from '@ucap-webmessenger/web-storage'; import { SessionStorageService } from '@ucap-webmessenger/web-storage';
import { LoginInfo, KEY_LOGIN_INFO } from '@app/types'; import { LoginInfo, KEY_LOGIN_INFO } from '@app/types';
import { take, map, switchMap } from 'rxjs/operators'; import { take, map, tap, delay } from 'rxjs/operators';
import { VersionInfo2Response } from '@ucap-webmessenger/api-public'; import { VersionInfo2Response } from '@ucap-webmessenger/api-public';
import { KEY_VER_INFO } from '@app/types/ver-info.type'; import { KEY_VER_INFO } from '@app/types/ver-info.type';
@ -28,7 +35,7 @@ import { KEY_VER_INFO } from '@app/types/ver-info.type';
styleUrls: ['./organization.component.scss'], styleUrls: ['./organization.component.scss'],
animations: ucapAnimations animations: ucapAnimations
}) })
export class OrganizationComponent implements OnInit { export class OrganizationComponent implements OnInit, OnDestroy {
@Input() @Input()
/** 사용자 선택용으로 사용시 true 로 유입 */ /** 사용자 선택용으로 사용시 true 로 유입 */
isUserSelect = false; isUserSelect = false;
@ -45,6 +52,9 @@ export class OrganizationComponent implements OnInit {
departmentInfoList$: Observable<DeptInfo[]>; departmentInfoList$: Observable<DeptInfo[]>;
selectedDepartmentUserInfoList$: Observable<UserInfoSS[]>; selectedDepartmentUserInfoList$: Observable<UserInfoSS[]>;
selectedDepartmentStatus$: Observable<DeptUserResponse>; selectedDepartmentStatus$: Observable<DeptUserResponse>;
selectedDepartmentProcessing = false;
selectedDepartmentProcessingSubscription: Subscription;
selectedDepartmentName: string;
loginInfo = this.sessionStorageService.get<LoginInfo>(KEY_LOGIN_INFO); loginInfo = this.sessionStorageService.get<LoginInfo>(KEY_LOGIN_INFO);
sessionVerinfo = this.sessionStorageService.get<VersionInfo2Response>( sessionVerinfo = this.sessionStorageService.get<VersionInfo2Response>(
@ -62,6 +72,19 @@ export class OrganizationComponent implements OnInit {
this.departmentInfoList$ = this.store.pipe( this.departmentInfoList$ = this.store.pipe(
select(AppStore.MessengerSelector.QuerySelector.departmentInfoList) select(AppStore.MessengerSelector.QuerySelector.departmentInfoList)
); );
this.selectedDepartmentProcessingSubscription = this.store
.pipe(
delay(0),
select(
AppStore.MessengerSelector.QuerySelector.selectedDepartmentProcessing
),
tap(processing => {
this.selectedDepartmentProcessing = processing;
})
)
.subscribe();
this.selectedDepartmentUserInfoList$ = this.store.pipe( this.selectedDepartmentUserInfoList$ = this.store.pipe(
select( select(
AppStore.MessengerSelector.QuerySelector.selectedDepartmentUserInfoList AppStore.MessengerSelector.QuerySelector.selectedDepartmentUserInfoList
@ -87,11 +110,21 @@ export class OrganizationComponent implements OnInit {
senderEmployeeType: loginRes.userInfo.employeeType senderEmployeeType: loginRes.userInfo.employeeType
}) })
); );
return loginRes;
}),
map(loginRes => {
this.selectedDepartmentName = loginRes.userInfo.deptName;
}) })
) )
.subscribe(); .subscribe();
} }
ngOnDestroy(): void {
if (!!this.selectedDepartmentProcessingSubscription) {
this.selectedDepartmentProcessingSubscription.unsubscribe();
}
}
onSelectedOrganization(deptInfo: DeptInfo) { onSelectedOrganization(deptInfo: DeptInfo) {
this.store this.store
.pipe( .pipe(
@ -109,11 +142,26 @@ export class OrganizationComponent implements OnInit {
senderEmployeeType: loginRes.userInfo.employeeType senderEmployeeType: loginRes.userInfo.employeeType
}) })
); );
}),
map(() => {
this.selectedDepartmentName = deptInfo.name;
}) })
) )
.subscribe(); .subscribe();
} }
getSelectedDepartmentName() {
if (!!this.selectedDepartmentProcessing) {
return '부서조회중..';
}
if (!!this.selectedDepartmentName) {
return this.selectedDepartmentName;
} else {
return '조회중..';
}
}
/** 리스트 checkable 할 경우 checkbox 의 isChecked 를 관장하며 리스트의 전체선택 여부를 판단한다. */ /** 리스트 checkable 할 경우 checkbox 의 isChecked 를 관장하며 리스트의 전체선택 여부를 판단한다. */
getCheckedUser(userInfo: UserInfo | UserInfoSS | UserInfoF | UserInfoDN) { getCheckedUser(userInfo: UserInfo | UserInfoSS | UserInfoF | UserInfoDN) {
if (!!this.selectedUserList && this.selectedUserList.length > 0) { if (!!this.selectedUserList && this.selectedUserList.length > 0) {

View File

@ -83,19 +83,17 @@
</mat-tab-group> </mat-tab-group>
</div> </div>
<div fxFlex="150px"> <div fxFlex="150px">
<ul> <mat-chip-list aria-label="User selection">
<li *ngFor="let userInfo of selectedUserList"> <mat-chip
{{ userInfo.name }} *ngFor="let userInfo of selectedUserList"
<button color="primary"
mat-icon-button selected
aria-label="Delete user" (removed)="onClickDeleteUser(userInfo)"
(click)="onClickDeleteUser(userInfo)"
> >
<mat-icon>close</mat-icon> {{ userInfo.name }}
</button> <mat-icon matChipRemove>clear</mat-icon>
<mat-icon></mat-icon> </mat-chip>
</li> </mat-chip-list>
</ul>
</div> </div>
</div> </div>
</mat-card-content> </mat-card-content>

View File

@ -1,3 +1,4 @@
import { MatChipsModule } from '@angular/material/chips';
import { NgModule } from '@angular/core'; import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common'; import { CommonModule } from '@angular/common';
@ -49,6 +50,7 @@ import { ReactiveFormsModule } from '@angular/forms';
MatProgressBarModule, MatProgressBarModule,
MatTabsModule, MatTabsModule,
MatToolbarModule, MatToolbarModule,
MatChipsModule,
UCapUiModule, UCapUiModule,
UCapUiChatModule, UCapUiChatModule,
UCapUiRoomModule, UCapUiRoomModule,

View File

@ -1,6 +1,12 @@
import { createReducer, on } from '@ngrx/store'; import { createReducer, on } from '@ngrx/store';
import { initialState } from './state'; import { initialState } from './state';
import { authSuccess, deptSuccess, deptUserSuccess } from './actions'; import {
authSuccess,
deptSuccess,
deptUserSuccess,
deptUser,
deptUserFailure
} from './actions';
import * as AuthenticationStore from '@app/store/account/authentication'; import * as AuthenticationStore from '@app/store/account/authentication';
@ -20,13 +26,29 @@ export const reducer = createReducer(
}; };
}), }),
on(deptUser, (state, action) => {
return {
...state,
selectedDepartmentProcessing: true
};
}),
on(deptUserSuccess, (state, action) => { on(deptUserSuccess, (state, action) => {
return { return {
...state, ...state,
selectedDepartmentUserInfoList: action.userInfos, selectedDepartmentUserInfoList: action.userInfos,
selectedDepartmentStatus: action.res selectedDepartmentStatus: action.res,
selectedDepartmentProcessing: false
}; };
}), }),
on(deptUserFailure, (state, action) => {
return {
...state,
selectedDepartmentProcessing: false
};
}),
on(AuthenticationStore.logout, (state, action) => { on(AuthenticationStore.logout, (state, action) => {
return { return {
...initialState ...initialState

View File

@ -13,13 +13,15 @@ export interface State {
selectedDepartmentUserInfoList: UserInfoSS[] | null; selectedDepartmentUserInfoList: UserInfoSS[] | null;
selectedDepartmentStatus: DeptUserResponse | null; selectedDepartmentStatus: DeptUserResponse | null;
selectedDepartmentProcessing: boolean;
} }
export const initialState: State = { export const initialState: State = {
auth: null, auth: null,
departmentInfoList: null, departmentInfoList: null,
selectedDepartmentUserInfoList: null, selectedDepartmentUserInfoList: null,
selectedDepartmentStatus: null selectedDepartmentStatus: null,
selectedDepartmentProcessing: false
}; };
export function selectors<S>(selector: Selector<any, State>) { export function selectors<S>(selector: Selector<any, State>) {
@ -39,6 +41,10 @@ export function selectors<S>(selector: Selector<any, State>) {
selectedDepartmentStatus: createSelector( selectedDepartmentStatus: createSelector(
selector, selector,
(state: State) => state.selectedDepartmentStatus (state: State) => state.selectedDepartmentStatus
),
selectedDepartmentProcessing: createSelector(
selector,
(state: State) => state.selectedDepartmentProcessing
) )
}; };
} }

View File

@ -43,7 +43,7 @@ export const encodeGroup: ProtocolEncoder<GroupRequest> = (
) => { ) => {
const bodyList: PacketBody[] = []; const bodyList: PacketBody[] = [];
bodyList.push({ type: PacketBodyValue.String, value: req.syncDate || '' }); bodyList.push({ type: PacketBodyValue.String, value: req.syncDate || ' ' });
return bodyList; return bodyList;
}; };