Merge branch 'master' of https://git.loafle.net/ucap-web/next-ucap-messenger
This commit is contained in:
commit
415de783c0
|
@ -5,6 +5,7 @@ import { DIALOGS as MESSAGE_DIALOGS } from './message';
|
||||||
import { DIALOGS as NOTICE_DIALOGS } from './notice';
|
import { DIALOGS as NOTICE_DIALOGS } from './notice';
|
||||||
import { DIALOGS as ORGANIZATION_DIALOGS } from './organization';
|
import { DIALOGS as ORGANIZATION_DIALOGS } from './organization';
|
||||||
import { DIALOGS as PROFILE_DIALOGS } from './profile';
|
import { DIALOGS as PROFILE_DIALOGS } from './profile';
|
||||||
|
import { DIALOGS as SEARCH_DIALOGS } from './search';
|
||||||
import { DIALOGS as SETTINGS_DIALOGS } from './settings';
|
import { DIALOGS as SETTINGS_DIALOGS } from './settings';
|
||||||
|
|
||||||
export const DIALOGS = [
|
export const DIALOGS = [
|
||||||
|
@ -15,5 +16,6 @@ export const DIALOGS = [
|
||||||
...NOTICE_DIALOGS,
|
...NOTICE_DIALOGS,
|
||||||
...ORGANIZATION_DIALOGS,
|
...ORGANIZATION_DIALOGS,
|
||||||
...PROFILE_DIALOGS,
|
...PROFILE_DIALOGS,
|
||||||
|
...SEARCH_DIALOGS,
|
||||||
...SETTINGS_DIALOGS
|
...SETTINGS_DIALOGS
|
||||||
];
|
];
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
import { IntegratedSearchDialogComponent } from './integrated-search.dialog.component';
|
||||||
|
|
||||||
|
export const DIALOGS = [IntegratedSearchDialogComponent];
|
|
@ -0,0 +1,11 @@
|
||||||
|
<ucap-integrated-search
|
||||||
|
[searchWord]="!!data.keyword ? data.keyword : ''"
|
||||||
|
[searchingProcessing]="searchingProcessing"
|
||||||
|
[searchUserInfos]="searchUserInfos"
|
||||||
|
[totalCount]="totalCount"
|
||||||
|
[pageCurrent]="pageCurrent"
|
||||||
|
[pageListCount]="pageListCount"
|
||||||
|
(search)="onSearch($event)"
|
||||||
|
(changePage)="onChangePage($event)"
|
||||||
|
>
|
||||||
|
</ucap-integrated-search>
|
|
@ -0,0 +1,25 @@
|
||||||
|
/* tslint:disable:no-unused-variable */
|
||||||
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { IntegratedSearchDialogComponent } from './integrated-search.dialog.component';
|
||||||
|
|
||||||
|
describe('IntegratedSearchDialogComponent', () => {
|
||||||
|
let component: IntegratedSearchDialogComponent;
|
||||||
|
let fixture: ComponentFixture<IntegratedSearchDialogComponent>;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [IntegratedSearchDialogComponent]
|
||||||
|
}).compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(IntegratedSearchDialogComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,152 @@
|
||||||
|
import { Component, OnInit, Inject, OnDestroy } from '@angular/core';
|
||||||
|
import { MatDialogRef, MAT_DIALOG_DATA, PageEvent } from '@angular/material';
|
||||||
|
import { KEY_LOGIN_RES_INFO } from '@app/types';
|
||||||
|
import { SessionStorageService } from '@ucap-webmessenger/web-storage';
|
||||||
|
|
||||||
|
import { Store } from '@ngrx/store';
|
||||||
|
import * as StatusStore from '@app/store/messenger/status';
|
||||||
|
import {
|
||||||
|
UserInfoSS,
|
||||||
|
QueryProtocolService,
|
||||||
|
DeptSearchType,
|
||||||
|
SSVC_TYPE_QUERY_DEPT_USER_DATA,
|
||||||
|
DeptUserData,
|
||||||
|
SSVC_TYPE_QUERY_DEPT_USER_RES,
|
||||||
|
DeptUserResponse
|
||||||
|
} from '@ucap-webmessenger/protocol-query';
|
||||||
|
import { LoginResponse } from '@ucap-webmessenger/protocol-authentication';
|
||||||
|
import { map, catchError } from 'rxjs/operators';
|
||||||
|
import { Subscription, of } from 'rxjs';
|
||||||
|
import { EnvironmentsInfo, KEY_ENVIRONMENTS_INFO } from '@app/types';
|
||||||
|
import { NGXLogger } from 'ngx-logger';
|
||||||
|
import { NativeService, UCAP_NATIVE_SERVICE } from '@ucap-webmessenger/native';
|
||||||
|
import { environment } from '../../../../../environments/environment';
|
||||||
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
|
|
||||||
|
export interface IntegratedSearchDialogData {
|
||||||
|
keyword: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IntegratedSearchDialogResult {}
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-integrated-search.dialog',
|
||||||
|
templateUrl: './integrated-search.dialog.component.html',
|
||||||
|
styleUrls: ['./integrated-search.dialog.component.scss']
|
||||||
|
})
|
||||||
|
export class IntegratedSearchDialogComponent implements OnInit, OnDestroy {
|
||||||
|
loginRes: LoginResponse;
|
||||||
|
environmentsInfo: EnvironmentsInfo;
|
||||||
|
|
||||||
|
searchSubscription: Subscription;
|
||||||
|
searchUserInfos: UserInfoSS[] = [];
|
||||||
|
searchingProcessing = false;
|
||||||
|
|
||||||
|
currentSearchWord: string;
|
||||||
|
totalCount = 0;
|
||||||
|
pageCurrent = 1;
|
||||||
|
pageListCount = 20;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
public dialogRef: MatDialogRef<
|
||||||
|
IntegratedSearchDialogData,
|
||||||
|
IntegratedSearchDialogResult
|
||||||
|
>,
|
||||||
|
@Inject(UCAP_NATIVE_SERVICE) private nativeService: NativeService,
|
||||||
|
@Inject(MAT_DIALOG_DATA) public data: IntegratedSearchDialogData,
|
||||||
|
private queryProtocolService: QueryProtocolService,
|
||||||
|
private sessionStorageService: SessionStorageService,
|
||||||
|
private store: Store<any>,
|
||||||
|
private logger: NGXLogger
|
||||||
|
) {
|
||||||
|
this.loginRes = this.sessionStorageService.get<LoginResponse>(
|
||||||
|
KEY_LOGIN_RES_INFO
|
||||||
|
);
|
||||||
|
this.environmentsInfo = this.sessionStorageService.get<EnvironmentsInfo>(
|
||||||
|
KEY_ENVIRONMENTS_INFO
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
this.onSearch(this.data.keyword);
|
||||||
|
}
|
||||||
|
|
||||||
|
onSearch(searchWord: string) {
|
||||||
|
this.currentSearchWord = this.data.keyword;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
this.totalCount = response.pageTotalCount;
|
||||||
|
this.pageCurrent = response.pageCurrent;
|
||||||
|
this.pageListCount = response.pageListCount;
|
||||||
|
this.searchingProcessing = false;
|
||||||
|
|
||||||
|
// 검색 결과에 따른 프레즌스 조회.
|
||||||
|
const userSeqList: number[] = [];
|
||||||
|
if (userSeqList.length > 0) {
|
||||||
|
this.store.dispatch(
|
||||||
|
StatusStore.bulkInfo({
|
||||||
|
divCd: 'INT_SRCH',
|
||||||
|
userSeqs: this.searchUserInfos.map(user => user.seq)
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(this.searchUserInfos);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
catchError(error => {
|
||||||
|
this.searchingProcessing = false;
|
||||||
|
return of(this.logger.error(error));
|
||||||
|
})
|
||||||
|
)
|
||||||
|
.subscribe();
|
||||||
|
} else {
|
||||||
|
// clear list.
|
||||||
|
this.searchingProcessing = false;
|
||||||
|
this.searchUserInfos = [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnDestroy(): void {
|
||||||
|
if (!!this.searchSubscription) {
|
||||||
|
this.searchSubscription.unsubscribe();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onChangePage(event: PageEvent) {
|
||||||
|
this.pageCurrent = event.pageIndex + 1;
|
||||||
|
this.pageListCount = event.pageSize;
|
||||||
|
|
||||||
|
this.onSearch(this.currentSearchWord);
|
||||||
|
}
|
||||||
|
}
|
|
@ -8,6 +8,9 @@
|
||||||
*ngIf="!!loginRes && !!weblink"
|
*ngIf="!!loginRes && !!weblink"
|
||||||
class="app-layout-native-title-bar-link"
|
class="app-layout-native-title-bar-link"
|
||||||
>
|
>
|
||||||
|
<ucap-integrated-search-form (search)="onIntegratedSearch($event)">
|
||||||
|
</ucap-integrated-search-form>
|
||||||
|
|
||||||
<ng-container *ngFor="let link of weblink" [ngSwitch]="link.key">
|
<ng-container *ngFor="let link of weblink" [ngSwitch]="link.key">
|
||||||
<button
|
<button
|
||||||
mat-icon-button
|
mat-icon-button
|
||||||
|
@ -230,7 +233,6 @@
|
||||||
class="button app-layout-native-title-bar-close"
|
class="button app-layout-native-title-bar-close"
|
||||||
(click)="onClickClose()"
|
(click)="onClickClose()"
|
||||||
>
|
>
|
||||||
<!--<mat-icon>close</mat-icon>-->
|
|
||||||
<svg
|
<svg
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
width="20"
|
width="20"
|
||||||
|
|
|
@ -70,6 +70,11 @@ import {
|
||||||
MessageIndexType,
|
MessageIndexType,
|
||||||
MessageUpdateRequest
|
MessageUpdateRequest
|
||||||
} from '@ucap-webmessenger/protocol-status';
|
} from '@ucap-webmessenger/protocol-status';
|
||||||
|
import {
|
||||||
|
IntegratedSearchDialogComponent,
|
||||||
|
IntegratedSearchDialogResult,
|
||||||
|
IntegratedSearchDialogData
|
||||||
|
} from '@app/layouts/messenger/dialogs/search/integrated-search.dialog.component';
|
||||||
|
|
||||||
const zoomFactors = [60, 70, 85, 100, 120, 145, 170, 200];
|
const zoomFactors = [60, 70, 85, 100, 120, 145, 170, 200];
|
||||||
|
|
||||||
|
@ -555,4 +560,16 @@ export class TopBarComponent implements OnInit, OnDestroy {
|
||||||
onClickApplyUpdate(event: Event) {
|
onClickApplyUpdate(event: Event) {
|
||||||
this.nativeService.checkForUpdates(this.checkingUpdateAppVersion);
|
this.nativeService.checkForUpdates(this.checkingUpdateAppVersion);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onIntegratedSearch(keyword: string) {
|
||||||
|
this.dialogService.open<
|
||||||
|
IntegratedSearchDialogComponent,
|
||||||
|
IntegratedSearchDialogData,
|
||||||
|
IntegratedSearchDialogResult
|
||||||
|
>(IntegratedSearchDialogComponent, {
|
||||||
|
data: {
|
||||||
|
keyword
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,6 +73,20 @@
|
||||||
"failToChangeProfileImage": "Failed to change profile image."
|
"failToChangeProfileImage": "Failed to change profile image."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"search": {
|
||||||
|
"label": "User search",
|
||||||
|
"searchFormPlaceholder": "Name, department, position, phone number, email",
|
||||||
|
"fieldProfile": "Profile",
|
||||||
|
"fieldName": "Name",
|
||||||
|
"fieldDeptartment": "Department",
|
||||||
|
"fieldCompany": "Company",
|
||||||
|
"fieldGrade": "Grade",
|
||||||
|
"fieldOfficePhoneNumber": "Office",
|
||||||
|
"fieldHandphone": "Mobile",
|
||||||
|
"fieldEmail": "Email",
|
||||||
|
"fieldResponsibilities": "Responsibilities",
|
||||||
|
"fieldWorkPlace": "WorkPlace"
|
||||||
|
},
|
||||||
"information": {
|
"information": {
|
||||||
"label": "Information",
|
"label": "Information",
|
||||||
"version": "Version",
|
"version": "Version",
|
||||||
|
|
|
@ -73,6 +73,20 @@
|
||||||
"failToChangeProfileImage": "프로필 이미지 변경에 실패 하였습니다."
|
"failToChangeProfileImage": "프로필 이미지 변경에 실패 하였습니다."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"search": {
|
||||||
|
"label": "사용자 검색",
|
||||||
|
"searchFormPlaceholder": "이름, 부서, 직위, 전화번호, 이메일",
|
||||||
|
"fieldProfile": "프로필",
|
||||||
|
"fieldName": "이름",
|
||||||
|
"fieldDeptartment": "부서",
|
||||||
|
"fieldCompany": "회사",
|
||||||
|
"fieldGrade": "직위",
|
||||||
|
"fieldOfficePhoneNumber": "사무실",
|
||||||
|
"fieldHandphone": "핸드폰",
|
||||||
|
"fieldEmail": "이메일",
|
||||||
|
"fieldResponsibilities": "담당업무",
|
||||||
|
"fieldWorkPlace": "근무지"
|
||||||
|
},
|
||||||
"information": {
|
"information": {
|
||||||
"label": "정보",
|
"label": "정보",
|
||||||
"version": "버전",
|
"version": "버전",
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
<div class="search-container">
|
||||||
|
<mat-form-field appearance="outline">
|
||||||
|
<input
|
||||||
|
matInput
|
||||||
|
#searchWordInput
|
||||||
|
placeholder="{{ 'search.searchFormPlaceholder' | translate }}"
|
||||||
|
(keydown.enter)="onKeyDownEnter(searchWordInput.value)"
|
||||||
|
[value]="!!searchWord ? searchWord : ''"
|
||||||
|
/>
|
||||||
|
<mat-icon matPrefix>search</mat-icon>
|
||||||
|
</mat-form-field>
|
||||||
|
</div>
|
|
@ -0,0 +1,3 @@
|
||||||
|
.search-container {
|
||||||
|
-webkit-app-region: no-drag;
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
/* tslint:disable:no-unused-variable */
|
||||||
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
import { By } from '@angular/platform-browser';
|
||||||
|
import { DebugElement } from '@angular/core';
|
||||||
|
|
||||||
|
import { IntegratedSearchFormComponent } from './integrated-search-form.component';
|
||||||
|
|
||||||
|
describe('IntegratedSearchFormComponent', () => {
|
||||||
|
let component: IntegratedSearchFormComponent;
|
||||||
|
let fixture: ComponentFixture<IntegratedSearchFormComponent>;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [IntegratedSearchFormComponent]
|
||||||
|
}).compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(IntegratedSearchFormComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,31 @@
|
||||||
|
import {
|
||||||
|
Component,
|
||||||
|
OnInit,
|
||||||
|
Input,
|
||||||
|
Output,
|
||||||
|
EventEmitter,
|
||||||
|
ChangeDetectorRef
|
||||||
|
} from '@angular/core';
|
||||||
|
import { ucapAnimations } from '../animations';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'ucap-integrated-search-form',
|
||||||
|
templateUrl: './integrated-search-form.component.html',
|
||||||
|
styleUrls: ['./integrated-search-form.component.scss'],
|
||||||
|
animations: ucapAnimations
|
||||||
|
})
|
||||||
|
export class IntegratedSearchFormComponent implements OnInit {
|
||||||
|
@Input()
|
||||||
|
searchWord?: string;
|
||||||
|
|
||||||
|
@Output()
|
||||||
|
search = new EventEmitter<string>();
|
||||||
|
|
||||||
|
constructor(private changeDetectorRef: ChangeDetectorRef) {}
|
||||||
|
|
||||||
|
ngOnInit() {}
|
||||||
|
|
||||||
|
onKeyDownEnter(keyword: string) {
|
||||||
|
this.search.emit(keyword);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,221 @@
|
||||||
|
<mat-card class="confirm-card mat-elevation-z">
|
||||||
|
<mat-card-header
|
||||||
|
cdkDrag
|
||||||
|
cdkDragRootElement=".cdk-overlay-pane"
|
||||||
|
cdkDragHandle
|
||||||
|
class="card-header"
|
||||||
|
>
|
||||||
|
<mat-card-title>{{ 'search.label' | translate }}</mat-card-title>
|
||||||
|
</mat-card-header>
|
||||||
|
<mat-card-content>
|
||||||
|
<div fxLayout="column" class="rightDrawer-notice">
|
||||||
|
<div fxFlex="1 1 80px" class="search-area">
|
||||||
|
<ucap-integrated-search-form
|
||||||
|
[searchWord]="!!searchWord ? searchWord : ''"
|
||||||
|
(search)="onSearch($event)"
|
||||||
|
>
|
||||||
|
</ucap-integrated-search-form>
|
||||||
|
</div>
|
||||||
|
<div style="position: relative;">
|
||||||
|
<div
|
||||||
|
*ngIf="searchingProcessing"
|
||||||
|
style="position: absolute; width: 100%; z-index: 101;"
|
||||||
|
>
|
||||||
|
<mat-progress-bar mode="indeterminate"></mat-progress-bar>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div fxFlex="0 0 auto" class="table-box">
|
||||||
|
<perfect-scrollbar class="search-scrollbar">
|
||||||
|
<table mat-table [dataSource]="searchUserInfos">
|
||||||
|
<ng-container matColumnDef="profile">
|
||||||
|
<th
|
||||||
|
mat-header-cell
|
||||||
|
*matHeaderCellDef
|
||||||
|
#header
|
||||||
|
class="profile"
|
||||||
|
(mousedown)="resizeTable($event, header)"
|
||||||
|
>
|
||||||
|
{{ 'search.fieldProfile' | translate }}
|
||||||
|
</th>
|
||||||
|
<td mat-cell *matCellDef="let element">
|
||||||
|
<div class="profile">
|
||||||
|
{{ element.name }}
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</ng-container>
|
||||||
|
<ng-container matColumnDef="name">
|
||||||
|
<th
|
||||||
|
mat-header-cell
|
||||||
|
*matHeaderCellDef
|
||||||
|
#header
|
||||||
|
class="name"
|
||||||
|
(mousedown)="resizeTable($event, header)"
|
||||||
|
>
|
||||||
|
{{ 'search.fieldName' | translate }}
|
||||||
|
</th>
|
||||||
|
<td mat-cell *matCellDef="let element">
|
||||||
|
<div class="name">
|
||||||
|
{{ element.name }}
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</ng-container>
|
||||||
|
<ng-container matColumnDef="deptName">
|
||||||
|
<th
|
||||||
|
mat-header-cell
|
||||||
|
*matHeaderCellDef
|
||||||
|
#header
|
||||||
|
class="deptName"
|
||||||
|
(mousedown)="resizeTable($event, header)"
|
||||||
|
>
|
||||||
|
{{ 'search.fieldDeptartment' | translate }}
|
||||||
|
</th>
|
||||||
|
<td mat-cell *matCellDef="let element">
|
||||||
|
<div class="deptName">
|
||||||
|
{{ element.deptName }}
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</ng-container>
|
||||||
|
<ng-container matColumnDef="companyName">
|
||||||
|
<th
|
||||||
|
mat-header-cell
|
||||||
|
*matHeaderCellDef
|
||||||
|
#header
|
||||||
|
class="companyName"
|
||||||
|
(mousedown)="resizeTable($event, header)"
|
||||||
|
>
|
||||||
|
{{ 'search.fieldCompany' | translate }}
|
||||||
|
</th>
|
||||||
|
<td mat-cell *matCellDef="let element">
|
||||||
|
<div class="companyName">
|
||||||
|
{{ element.companyName }}
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</ng-container>
|
||||||
|
<ng-container matColumnDef="grade">
|
||||||
|
<th
|
||||||
|
mat-header-cell
|
||||||
|
*matHeaderCellDef
|
||||||
|
#header
|
||||||
|
class="grade"
|
||||||
|
(mousedown)="resizeTable($event, header)"
|
||||||
|
>
|
||||||
|
{{ 'search.fieldGrade' | translate }}
|
||||||
|
</th>
|
||||||
|
<td mat-cell *matCellDef="let element" class="grade">
|
||||||
|
<div class="grade">
|
||||||
|
{{ element.grade }}
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</ng-container>
|
||||||
|
<ng-container matColumnDef="lineNumber">
|
||||||
|
<th
|
||||||
|
mat-header-cell
|
||||||
|
*matHeaderCellDef
|
||||||
|
#header
|
||||||
|
class="lineNumber"
|
||||||
|
(mousedown)="resizeTable($event, header)"
|
||||||
|
>
|
||||||
|
{{ 'search.fieldOfficePhoneNumber' | translate }}
|
||||||
|
</th>
|
||||||
|
<td mat-cell *matCellDef="let element" class="lineNumber">
|
||||||
|
<div class="lineNumber">
|
||||||
|
{{ element.lineNumber }}
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</ng-container>
|
||||||
|
<ng-container matColumnDef="hpNumber">
|
||||||
|
<th
|
||||||
|
mat-header-cell
|
||||||
|
*matHeaderCellDef
|
||||||
|
#header
|
||||||
|
class="hpNumber"
|
||||||
|
(mousedown)="resizeTable($event, header)"
|
||||||
|
>
|
||||||
|
{{ 'search.fieldHandphone' | translate }}
|
||||||
|
</th>
|
||||||
|
<td mat-cell *matCellDef="let element" class="hpNumber">
|
||||||
|
<div class="hpNumber">
|
||||||
|
{{ element.hpNumber }}
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</ng-container>
|
||||||
|
<ng-container matColumnDef="email">
|
||||||
|
<th
|
||||||
|
mat-header-cell
|
||||||
|
*matHeaderCellDef
|
||||||
|
#header
|
||||||
|
class="email"
|
||||||
|
(mousedown)="resizeTable($event, header)"
|
||||||
|
>
|
||||||
|
{{ 'search.fieldEmail' | translate }}
|
||||||
|
</th>
|
||||||
|
<td mat-cell *matCellDef="let element" class="email">
|
||||||
|
<div class="email">
|
||||||
|
{{ element.email }}
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</ng-container>
|
||||||
|
<ng-container matColumnDef="responsibilities">
|
||||||
|
<th
|
||||||
|
mat-header-cell
|
||||||
|
*matHeaderCellDef
|
||||||
|
#header
|
||||||
|
class="responsibilities"
|
||||||
|
(mousedown)="resizeTable($event, header)"
|
||||||
|
>
|
||||||
|
{{ 'search.fieldResponsibilities' | translate }}
|
||||||
|
</th>
|
||||||
|
<td mat-cell *matCellDef="let element" class="responsibilities">
|
||||||
|
<div class="responsibilities">
|
||||||
|
{{ element.responsibilities }}
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</ng-container>
|
||||||
|
<ng-container matColumnDef="workplace">
|
||||||
|
<th
|
||||||
|
mat-header-cell
|
||||||
|
*matHeaderCellDef
|
||||||
|
#header
|
||||||
|
class="workplace"
|
||||||
|
(mousedown)="resizeTable($event, header)"
|
||||||
|
>
|
||||||
|
{{ 'search.fieldWorkPlace' | translate }}
|
||||||
|
</th>
|
||||||
|
<td mat-cell *matCellDef="let element" class="workplace">
|
||||||
|
<div class="workplace">
|
||||||
|
{{ element.workplace }}
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</ng-container>
|
||||||
|
<tr
|
||||||
|
mat-header-row
|
||||||
|
*matHeaderRowDef="displayedColumns; sticky: true"
|
||||||
|
></tr>
|
||||||
|
<tr mat-row *matRowDef="let row; columns: displayedColumns"></tr>
|
||||||
|
</table>
|
||||||
|
</perfect-scrollbar>
|
||||||
|
</div>
|
||||||
|
<div class="footer-fix">
|
||||||
|
<mat-paginator
|
||||||
|
[length]="totalCount"
|
||||||
|
[pageSize]="pageListCount"
|
||||||
|
[pageSizeOptions]="[10, 20, 30]"
|
||||||
|
(page)="onChangePage($event)"
|
||||||
|
showFirstLastButtons
|
||||||
|
></mat-paginator>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</mat-card-content>
|
||||||
|
<!-- <mat-card-actions *ngIf="!hideAction" class="button-farm flex-row">
|
||||||
|
<button
|
||||||
|
mat-stroked-button
|
||||||
|
(click)="onClickChoice(false)"
|
||||||
|
class="mat-primary"
|
||||||
|
>
|
||||||
|
{{ 'common.messages.no' | translate }}
|
||||||
|
</button>
|
||||||
|
<button mat-flat-button (click)="onClickChoice(true)" class="mat-primary">
|
||||||
|
{{ 'common.messages.yes' | translate }}
|
||||||
|
</button>
|
||||||
|
</mat-card-actions> -->
|
||||||
|
</mat-card>
|
|
@ -0,0 +1,106 @@
|
||||||
|
.search-scrollbar {
|
||||||
|
height: 550px;
|
||||||
|
}
|
||||||
|
// .search-container {
|
||||||
|
// -webkit-app-region: no-drag;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// @mixin ellipsis($row) {
|
||||||
|
// overflow: hidden;
|
||||||
|
// text-overflow: ellipsis;
|
||||||
|
// @if $row == 1 {
|
||||||
|
// display: block;
|
||||||
|
// white-space: nowrap;
|
||||||
|
// word-wrap: normal;
|
||||||
|
// } @else if $row >= 2 {
|
||||||
|
// display: -webkit-box;
|
||||||
|
// -webkit-line-clamp: $row;
|
||||||
|
// -webkit-box-orient: vertical;
|
||||||
|
// word-wrap: break-word;
|
||||||
|
// line-height: 1.2em;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// .rightDrawer-notice {
|
||||||
|
// width: 100%;
|
||||||
|
// height: calc(100% - 60px);
|
||||||
|
|
||||||
|
// .table-box {
|
||||||
|
// height: calc(100% - 111.5px);
|
||||||
|
// overflow: auto;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// .mat-table {
|
||||||
|
// width: 100%;
|
||||||
|
// position: relative;
|
||||||
|
// th.infos {
|
||||||
|
// padding: 10px;
|
||||||
|
// text-align: center;
|
||||||
|
// }
|
||||||
|
// tr.mat-row {
|
||||||
|
// height: 70px;
|
||||||
|
// .notice-info {
|
||||||
|
// padding: 16px;
|
||||||
|
// display: grid;
|
||||||
|
// height: 70px;
|
||||||
|
// .title {
|
||||||
|
// font-weight: 600;
|
||||||
|
// margin-bottom: 2px;
|
||||||
|
// width: 100%;
|
||||||
|
// @include ellipsis(2);
|
||||||
|
// display: flex;
|
||||||
|
// align-items: center;
|
||||||
|
// .important {
|
||||||
|
// color: red;
|
||||||
|
// margin-right: 6px;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// .date {
|
||||||
|
// .date {
|
||||||
|
// font-size: 0.8em;
|
||||||
|
// text-align: right;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// .mat-paginator-container {
|
||||||
|
// display: flex;
|
||||||
|
// flex-flow: column;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// .mat-row:hover {
|
||||||
|
// background: rgba(0, 0, 0, 0.04);
|
||||||
|
// cursor: pointer;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// .footer-fix {
|
||||||
|
// position: absolute;
|
||||||
|
// bottom: 0;
|
||||||
|
// flex-direction: column;
|
||||||
|
// box-sizing: border-box;
|
||||||
|
// display: flex;
|
||||||
|
// border-top: 1px solid #dddddd;
|
||||||
|
// .mat-paginator {
|
||||||
|
// .mat-paginator-container {
|
||||||
|
// justify-content: center;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// .btn-box {
|
||||||
|
// height: 50px;
|
||||||
|
// padding-bottom: 10px;
|
||||||
|
// width: 100%;
|
||||||
|
// background-color: #ffffff;
|
||||||
|
// button {
|
||||||
|
// margin: 5px;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// .mat-form-field-appearance-legacy {
|
||||||
|
// .mat-form-field-infix {
|
||||||
|
// padding: 6px;
|
||||||
|
// }
|
||||||
|
// }
|
|
@ -0,0 +1,27 @@
|
||||||
|
/* tslint:disable:no-unused-variable */
|
||||||
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
import { By } from '@angular/platform-browser';
|
||||||
|
import { DebugElement } from '@angular/core';
|
||||||
|
|
||||||
|
import { IntegratedSearchComponent } from './integrated-search.component';
|
||||||
|
|
||||||
|
describe('IntegratedSearchComponent', () => {
|
||||||
|
let component: IntegratedSearchComponent;
|
||||||
|
let fixture: ComponentFixture<IntegratedSearchComponent>;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [IntegratedSearchComponent]
|
||||||
|
}).compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(IntegratedSearchComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,108 @@
|
||||||
|
import {
|
||||||
|
Component,
|
||||||
|
OnInit,
|
||||||
|
Input,
|
||||||
|
Output,
|
||||||
|
EventEmitter,
|
||||||
|
ViewChild,
|
||||||
|
ChangeDetectorRef,
|
||||||
|
Renderer2
|
||||||
|
} from '@angular/core';
|
||||||
|
import { ucapAnimations } from '../animations';
|
||||||
|
import { UserInfoSS } from '@ucap-webmessenger/protocol-query';
|
||||||
|
import { MatPaginator, PageEvent, MatTabLabel } from '@angular/material';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'ucap-integrated-search',
|
||||||
|
templateUrl: './integrated-search.component.html',
|
||||||
|
styleUrls: ['./integrated-search.component.scss'],
|
||||||
|
animations: ucapAnimations
|
||||||
|
})
|
||||||
|
export class IntegratedSearchComponent implements OnInit {
|
||||||
|
@Input()
|
||||||
|
searchWord?: string;
|
||||||
|
@Input()
|
||||||
|
searchingProcessing: boolean;
|
||||||
|
@Input()
|
||||||
|
searchUserInfos: UserInfoSS[] = [];
|
||||||
|
@Input()
|
||||||
|
totalCount = 0;
|
||||||
|
@Input()
|
||||||
|
pageCurrent = 1;
|
||||||
|
@Input()
|
||||||
|
pageListCount = 20;
|
||||||
|
|
||||||
|
@Output()
|
||||||
|
search = new EventEmitter<string>();
|
||||||
|
@Output()
|
||||||
|
changePage = new EventEmitter<PageEvent>();
|
||||||
|
|
||||||
|
@ViewChild(MatPaginator, { static: true }) paginator: MatPaginator;
|
||||||
|
displayedColumns: string[] = [
|
||||||
|
'profile',
|
||||||
|
'name',
|
||||||
|
'deptName',
|
||||||
|
'companyName',
|
||||||
|
'grade',
|
||||||
|
'lineNumber',
|
||||||
|
'hpNumber',
|
||||||
|
'email',
|
||||||
|
'responsibilities',
|
||||||
|
'workplace'
|
||||||
|
];
|
||||||
|
|
||||||
|
start: any = undefined;
|
||||||
|
pressed = false;
|
||||||
|
startX: any;
|
||||||
|
startWidth: any;
|
||||||
|
resizableFnMousemove: () => void;
|
||||||
|
resizableFnMouseup: () => void;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private changeDetectorRef: ChangeDetectorRef,
|
||||||
|
private renderer: Renderer2
|
||||||
|
) {}
|
||||||
|
|
||||||
|
ngOnInit() {}
|
||||||
|
|
||||||
|
onSearch(keyword: string) {
|
||||||
|
this.search.emit(keyword);
|
||||||
|
}
|
||||||
|
|
||||||
|
onChangePage(event: PageEvent) {
|
||||||
|
this.changePage.emit(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
resizeTable(event: any, column: any) {
|
||||||
|
this.start = event.target;
|
||||||
|
this.pressed = true;
|
||||||
|
this.startX = event.pageX;
|
||||||
|
this.startWidth = this.start.clientWidth;
|
||||||
|
this.mouseMove(column);
|
||||||
|
}
|
||||||
|
|
||||||
|
mouseMove(column: any) {
|
||||||
|
this.resizableFnMousemove = this.renderer.listen(
|
||||||
|
'document',
|
||||||
|
'mousemove',
|
||||||
|
event => {
|
||||||
|
if (this.pressed) {
|
||||||
|
let width = this.startWidth + (event.pageX - this.startX);
|
||||||
|
let index = this.start.cellIndex;
|
||||||
|
column.width = width;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
this.resizableFnMouseup = this.renderer.listen(
|
||||||
|
'document',
|
||||||
|
'mouseup',
|
||||||
|
event => {
|
||||||
|
if (this.pressed) {
|
||||||
|
this.pressed = false;
|
||||||
|
this.resizableFnMousemove();
|
||||||
|
this.resizableFnMouseup();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -22,7 +22,9 @@ import { MatDatepickerModule } from '@angular/material/datepicker';
|
||||||
import {
|
import {
|
||||||
MatTabsModule,
|
MatTabsModule,
|
||||||
MatSelectModule,
|
MatSelectModule,
|
||||||
MatSlideToggleModule
|
MatSlideToggleModule,
|
||||||
|
MatTableModule,
|
||||||
|
MatPaginatorModule
|
||||||
} from '@angular/material';
|
} from '@angular/material';
|
||||||
|
|
||||||
import { DragDropModule } from '@angular/cdk/drag-drop';
|
import { DragDropModule } from '@angular/cdk/drag-drop';
|
||||||
|
@ -77,6 +79,9 @@ import {
|
||||||
import { ClickDebounceDirective } from './directives/click-debounce.directive';
|
import { ClickDebounceDirective } from './directives/click-debounce.directive';
|
||||||
import { TranslationSectionComponent } from './components/translation-section.component';
|
import { TranslationSectionComponent } from './components/translation-section.component';
|
||||||
import { AlertSnackbarComponent } from './snackbars/alert.snackbar.component';
|
import { AlertSnackbarComponent } from './snackbars/alert.snackbar.component';
|
||||||
|
import { IntegratedSearchFormComponent } from './components/integrated-search-form.component';
|
||||||
|
import { IntegratedSearchComponent } from './components/integrated-search.component';
|
||||||
|
import { PerfectScrollbarModule } from 'ngx-perfect-scrollbar';
|
||||||
|
|
||||||
const COMPONENTS = [
|
const COMPONENTS = [
|
||||||
FileUploadQueueComponent,
|
FileUploadQueueComponent,
|
||||||
|
@ -90,6 +95,8 @@ const COMPONENTS = [
|
||||||
StepInputComponent,
|
StepInputComponent,
|
||||||
TranslationSectionComponent,
|
TranslationSectionComponent,
|
||||||
InlineEditInputComponent,
|
InlineEditInputComponent,
|
||||||
|
IntegratedSearchComponent,
|
||||||
|
IntegratedSearchFormComponent,
|
||||||
|
|
||||||
BinaryViewerComponent,
|
BinaryViewerComponent,
|
||||||
DocumentViewerComponent,
|
DocumentViewerComponent,
|
||||||
|
@ -153,6 +160,10 @@ const SERVICES = [
|
||||||
MatDatepickerModule,
|
MatDatepickerModule,
|
||||||
MatSelectModule,
|
MatSelectModule,
|
||||||
MatSlideToggleModule,
|
MatSlideToggleModule,
|
||||||
|
MatTableModule,
|
||||||
|
MatPaginatorModule,
|
||||||
|
|
||||||
|
PerfectScrollbarModule,
|
||||||
DragDropModule,
|
DragDropModule,
|
||||||
TranslateModule
|
TranslateModule
|
||||||
],
|
],
|
||||||
|
|
Loading…
Reference in New Issue
Block a user