743 lines
22 KiB
TypeScript

import {
Component,
OnInit,
Inject,
OnDestroy,
ChangeDetectorRef,
NgZone,
ViewChild
} from '@angular/core';
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
import { KEY_VER_INFO, MainMenu, KEY_AUTH_INFO } from '@app/types';
import { SessionStorageService } from '@ucap-webmessenger/web-storage';
import { Store, select } from '@ngrx/store';
import * as AppStore from '@app/store';
import * as QueryStore from '@app/store/messenger/query';
import * as ChatStore from '@app/store/messenger/chat';
import * as SettingsStore from '@app/store/messenger/settings';
import * as SyncStore from '@app/store/messenger/sync';
import { UserInfoSS, AuthResponse } from '@ucap-webmessenger/protocol-query';
import { LoginResponse } from '@ucap-webmessenger/protocol-authentication';
import { map, take, tap, catchError } from 'rxjs/operators';
import { Subscription, Observable, BehaviorSubject, 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 { StatusBulkInfo } from '@ucap-webmessenger/protocol-status';
import { VersionInfo2Response } from '@ucap-webmessenger/api-public';
import { DaesangProtocolService } from '@ucap-webmessenger/daesang';
import {
DialogService,
AlertDialogComponent,
AlertDialogData,
AlertDialogResult,
ConfirmDialogComponent,
ConfirmDialogData,
ConfirmDialogResult,
TranslateService as UCapTranslateService
} from '@ucap-webmessenger/ui';
import {
ProfileDialogComponent,
ProfileDialogData,
ProfileDialogResult
} from '../profile/profile.dialog.component';
import {
SelectGroupDialogComponent,
SelectGroupDialogData,
SelectGroupDialogResult
} from '../group/select-group.dialog.component';
import { TranslateService, LangChangeEvent } from '@ngx-translate/core';
import { GroupDetailData } from '@ucap-webmessenger/protocol-sync';
import {
ConferenceService,
PromptMessageStatusCode,
CallService
} from '@ucap-webmessenger/api-prompt';
import {
MessageWriteDialogComponent,
MessageWriteDialogResult,
MessageWriteDialogData
} from '../message/message-write.dialog.component';
import { MatSelect } from '@angular/material/select';
import { FormControl } from '@angular/forms';
import { StatusCode } from '@ucap-webmessenger/core';
import { MatOption } from '@angular/material/core';
export interface IntegratedSearchDialogData {
keyword: string;
}
export interface IntegratedSearchDialogResult {
clear: boolean;
}
@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;
loginResSubscription: Subscription;
sessionVerinfo: VersionInfo2Response;
environmentsInfo: EnvironmentsInfo;
authInfo: AuthResponse;
ucapLangChangeSubscription: Subscription;
ucapCurrentLocale: string;
searchDepartmentUserInfoListSubscription: Subscription;
searchingProcessing$: Observable<boolean>;
departmentUserInfoList: UserInfoSS[] = [];
originDepartmentUserInfoList: UserInfoSS[] = [];
selectedUserList: UserInfoSS[] = []; // selected user in departmentUserList detail
profileImageRoot: string;
presenceSubscription: Subscription;
presenceSubject = new BehaviorSubject<StatusBulkInfo[]>(undefined);
currentSearchWord: string;
StatusCode = StatusCode;
@ViewChild('filterCompany', { static: false })
filterCompany: MatSelect;
filterCompanyOption: string[] = [];
fcCompany = new FormControl();
@ViewChild('filterGrade', { static: false })
filterGrade: MatSelect;
filterGradeOption: string[] = [];
filterGradeOptionSet: {
value: string[];
valueEn: string[];
valueCn: string[];
} = {
value: [],
valueEn: [],
valueCn: []
};
fcGrade = new FormControl();
@ViewChild('filterWorkPlace', { static: false })
filterWorkPlace: MatSelect;
filterWorkPlaceOption: string[] = [];
fcWorkPlace = new FormControl();
@ViewChild('filterPresence', { static: false })
filterPresence: MatSelect;
fcPresence = new FormControl();
constructor(
public dialogRef: MatDialogRef<
IntegratedSearchDialogData,
IntegratedSearchDialogResult
>,
@Inject(UCAP_NATIVE_SERVICE) private nativeService: NativeService,
@Inject(MAT_DIALOG_DATA) public data: IntegratedSearchDialogData,
private sessionStorageService: SessionStorageService,
private daesangProtocolService: DaesangProtocolService,
private dialogService: DialogService,
private translateService: TranslateService,
private ucapTranslateService: UCapTranslateService,
private conferenceService: ConferenceService,
private callService: CallService,
private store: Store<any>,
private changeDetectorRef: ChangeDetectorRef,
private logger: NGXLogger,
private ngZone: NgZone
) {
this.environmentsInfo = this.sessionStorageService.get<EnvironmentsInfo>(
KEY_ENVIRONMENTS_INFO
);
this.authInfo = this.sessionStorageService.get<AuthResponse>(KEY_AUTH_INFO);
this.sessionVerinfo = this.sessionStorageService.get<VersionInfo2Response>(
KEY_VER_INFO
);
this.ucapCurrentLocale = this.ucapTranslateService.currentLang;
}
ngOnInit() {
this.profileImageRoot = this.sessionVerinfo.profileRoot;
this.loginResSubscription = this.store
.pipe(
select(AppStore.AccountSelector.AuthenticationSelector.loginRes),
tap(loginRes => {
this.loginRes = loginRes;
})
)
.subscribe();
this.ucapLangChangeSubscription = this.ucapTranslateService.changedLang.subscribe(
(event: LangChangeEvent) => {
this.ucapCurrentLocale = event.lang;
this.setFilterOptionsLang();
}
);
this.searchDepartmentUserInfoListSubscription = this.store
.pipe(
select(
AppStore.MessengerSelector.QuerySelector
.integrateSearchDepartmentUserInfoList
)
)
.subscribe(list => {
this.departmentUserInfoList = list;
this.originDepartmentUserInfoList = list;
// filter option add
if (!!list && list.length > 0) {
this.setFilterOptions(list);
}
});
this.searchingProcessing$ = this.store.pipe(
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 {
if (!!this.loginResSubscription) {
this.loginResSubscription.unsubscribe();
}
if (!!this.ucapLangChangeSubscription) {
this.ucapLangChangeSubscription.unsubscribe();
}
if (!!this.searchDepartmentUserInfoListSubscription) {
this.searchDepartmentUserInfoListSubscription.unsubscribe();
}
if (!!this.presenceSubscription) {
this.presenceSubscription.unsubscribe();
}
}
onSearch(searchWord: string) {
if (this.currentSearchWord !== searchWord) {
this.currentSearchWord = searchWord;
}
if (searchWord.trim().length > 0) {
this.store.dispatch(
QueryStore.integrateSearchDeptUser({
companyCode: this.loginRes.companyCode,
search: searchWord.trim()
})
);
} else {
// clear list.
this.store.dispatch(QueryStore.integrateClearSearchDeptUser({}));
}
}
/** Selected User Handling */
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;
}
if (
this.selectedUserList.filter(user => user.seq === userInfo.seq).length ===
0
) {
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
})
);
this.onClickHide();
}
}
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
});
}
}
onClickMessage() {
this.ngZone.run(() => {
const receiverList: UserInfoSS[] = this.selectedUserList.slice();
if (receiverList.length > 0) {
this.dialogService.open<
MessageWriteDialogComponent,
MessageWriteDialogData,
MessageWriteDialogResult
>(MessageWriteDialogComponent, {
width: '600px',
height: '600px',
disableClose: true,
hasBackdrop: false,
data: {
loginRes: this.loginRes,
environmentsInfo: this.environmentsInfo,
receiverList
}
});
}
});
}
onClickOpenProfile(userSeq: number) {
if (!userSeq || userSeq < 0) {
return;
}
this.daesangProtocolService
.dataUserDaesang({
divCd: 'OPENPROF',
seq: userSeq,
senderCompanyCode: this.loginRes.userInfo.companyCode,
senderEmployeeType: this.loginRes.userInfo.employeeType
})
.pipe(
take(1),
map(async res => {
if (!!res && !!res.userInfo) {
const result = await this.dialogService.open<
ProfileDialogComponent,
ProfileDialogData,
ProfileDialogResult
>(ProfileDialogComponent, {
maxWidth: '90vw',
height: '500px',
data: {
userInfo: res.userInfo
}
});
if (!!result) {
if (!!result.closeEvent && result.closeEvent === 'CHAT') {
this.onCancel();
}
}
}
})
)
.subscribe();
}
async onClickCall(calleeNumber: string) {
const madn = this.loginRes.madn;
if (!madn || madn.trim().length === 0) {
this.dialogService.open<
AlertDialogComponent,
AlertDialogData,
AlertDialogResult
>(AlertDialogComponent, {
panelClass: 'miniSize-dialog',
data: {
title: this.translateService.instant('call.errors.label'),
html: this.translateService.instant('call.errors.cannotCallToUser')
}
});
return false;
}
calleeNumber = calleeNumber.replace(/\D/g, '');
if (!!calleeNumber && calleeNumber.length > 0) {
// const result = await this.dialogService.open<
// ConfirmDialogComponent,
// ConfirmDialogData,
// ConfirmDialogResult
// >(ConfirmDialogComponent, {
// width: '360px',
// data: {
// title: this.translateService.instant('call.callTo'),
// html: this.translateService.instant('call.callWithNumber', {
// phoneNumber: calleeNumber
// })
// }
// });
// if (!!result && !!result.choice && result.choice) {
this.callService
.sendCall({
userSeq: this.loginRes.userSeq,
deviceType: this.environmentsInfo.deviceType,
tokenKey: this.loginRes.tokenString,
calleeNumber
})
.pipe(
take(1),
map(res => {
if (res.responseCode === PromptMessageStatusCode.Success) {
this.logger.debug('SUCCESS');
this.logger.debug(res);
} else {
this.logger.error(res);
}
}),
catchError(error => of(this.logger.debug(error)))
)
.subscribe();
// }
} else {
this.dialogService.open<
AlertDialogComponent,
AlertDialogData,
AlertDialogResult
>(AlertDialogComponent, {
panelClass: 'miniSize-dialog',
data: {
title: this.translateService.instant('call.errors.label'),
html: this.translateService.instant(
'call.errors.cannotCallToUserWithoutPhomeNumber'
)
}
});
}
}
onClickHide(): void {
this.dialogRef.addPanelClass('hideDialog');
}
onCancel(): void {
this.dialogRef.close({ clear: true });
}
/** Handling Filters */
setFilterOptions(list: UserInfoSS[]) {
// option set
this.filterCompanyOption = [];
this.filterGradeOption = [];
this.filterGradeOptionSet = {
value: [],
valueEn: [],
valueCn: []
};
this.filterWorkPlaceOption = [];
list.forEach(info => {
if (!!info.companyName) {
this.filterCompanyOption.push(info.companyName);
}
if (!!info.grade) {
this.filterGradeOptionSet.value.push(info.grade);
}
if (!!info.gradeEn) {
this.filterGradeOptionSet.valueEn.push(info.gradeEn);
}
if (!!info.gradeCn) {
this.filterGradeOptionSet.valueCn.push(info.gradeCn);
}
if (!!info.workplace) {
this.filterWorkPlaceOption.push(info.workplace);
}
});
// remove duplication.
if (!!this.filterCompanyOption && this.filterCompanyOption.length > 0) {
this.filterCompanyOption = this.filterCompanyOption.reduce(
(unique, item) => (unique.includes(item) ? unique : [...unique, item]),
[]
);
}
if (
!!this.filterGradeOptionSet &&
this.filterGradeOptionSet.value &&
this.filterGradeOptionSet.value.length > 0
) {
this.filterGradeOptionSet.value = this.filterGradeOptionSet.value.reduce(
(unique, item) => (unique.includes(item) ? unique : [...unique, item]),
[]
);
}
if (
!!this.filterGradeOptionSet &&
this.filterGradeOptionSet.valueEn &&
this.filterGradeOptionSet.valueEn.length > 0
) {
this.filterGradeOptionSet.valueEn = this.filterGradeOptionSet.valueEn.reduce(
(unique, item) => (unique.includes(item) ? unique : [...unique, item]),
[]
);
}
if (
!!this.filterGradeOptionSet &&
this.filterGradeOptionSet.valueCn &&
this.filterGradeOptionSet.valueCn.length > 0
) {
this.filterGradeOptionSet.valueCn = this.filterGradeOptionSet.valueCn.reduce(
(unique, item) => (unique.includes(item) ? unique : [...unique, item]),
[]
);
}
if (!!this.filterWorkPlaceOption && this.filterWorkPlaceOption.length > 0) {
this.filterWorkPlaceOption = this.filterWorkPlaceOption.reduce(
(unique, item) => (unique.includes(item) ? unique : [...unique, item]),
[]
);
}
this.setFilterOptionsLang();
}
setFilterOptionsLang() {
const ucapLang = this.ucapCurrentLocale;
switch (ucapLang) {
case 'en':
this.filterGradeOption =
!!this.filterGradeOptionSet.valueEn &&
this.filterGradeOptionSet.valueEn.length > 0
? this.filterGradeOptionSet.valueEn.slice()
: [];
break;
case 'cn':
this.filterGradeOption =
!!this.filterGradeOptionSet.valueCn &&
this.filterGradeOptionSet.valueCn.length > 0
? this.filterGradeOptionSet.valueCn.slice()
: [];
break;
default:
// ko
this.filterGradeOption =
!!this.filterGradeOptionSet.value &&
this.filterGradeOptionSet.value.length > 0
? this.filterGradeOptionSet.value.slice()
: [];
this.filterGradeOption = this.filterGradeOptionSet.value.slice();
}
}
setFilterOptionSelectedTextPresence() {
let firstPresence = '';
if (!this.filterPresence) {
return firstPresence;
}
const presences = this.filterPresence.selected as MatOption[];
if (!!presences && presences.length > 0) {
firstPresence = presences[0].value;
}
switch (firstPresence) {
case StatusCode.OnLine:
firstPresence = this.translateService.instant('presence.online');
break;
case StatusCode.Away:
firstPresence = this.translateService.instant('presence.away');
break;
case StatusCode.Busy:
firstPresence = this.translateService.instant(
'presence.statusMessage1'
);
break;
case StatusCode.Offline:
firstPresence = this.translateService.instant('presence.offline');
break;
}
return firstPresence;
}
onOpenedChange(isOpened: boolean) {
// only close action.
if (!isOpened) {
this.filteredDeptUserList();
}
}
filteredDeptUserList() {
const companies = this.filterCompany.selected as MatOption[];
const grades = this.filterGrade.selected as MatOption[];
const workplaces = this.filterWorkPlace.selected as MatOption[];
const presences = this.filterPresence.selected as MatOption[];
let isMulti = false;
if (!!companies && companies.length > 0) {
const data = !isMulti
? this.originDepartmentUserInfoList
: this.departmentUserInfoList;
isMulti = true;
this.departmentUserInfoList = data.filter(userInfo => {
if (
companies
.map(option => option.value)
.some(opt => opt === userInfo.companyName)
) {
return true;
}
return false;
});
}
if (!!grades && grades.length > 0) {
const data = !isMulti
? this.originDepartmentUserInfoList
: this.departmentUserInfoList;
isMulti = true;
this.departmentUserInfoList = data.filter(userInfo => {
if (
grades
.map(option => option.value)
.some(opt => {
let trgtGrade = userInfo.grade;
if (this.ucapCurrentLocale === 'en') {
trgtGrade = userInfo.gradeEn;
} else if (this.ucapCurrentLocale === 'cn') {
trgtGrade = userInfo.gradeCn;
}
return opt === trgtGrade;
})
) {
return true;
}
return false;
});
}
if (!!workplaces && workplaces.length > 0) {
const data = !isMulti
? this.originDepartmentUserInfoList
: this.departmentUserInfoList;
isMulti = true;
this.departmentUserInfoList = data.filter(userInfo => {
if (
workplaces
.map(option => option.value)
.some(opt => opt === userInfo.workplace)
) {
return true;
}
return false;
});
}
if (!!presences && presences.length > 0) {
const data = !isMulti
? this.originDepartmentUserInfoList
: this.departmentUserInfoList;
isMulti = true;
this.departmentUserInfoList = data.filter(userInfo => {
const userPresences = this.presenceSubject.value.filter(
presence => presence.userSeq === userInfo.seq
);
let userPresence = StatusCode.Offline;
if (!!userPresences && userPresences.length > 0) {
userPresence = userPresences[0].pcStatus;
}
if (
presences
.map(option => option.value)
.some(opt => {
return opt === userPresence;
})
) {
return true;
}
return false;
});
}
if (!isMulti) {
this.departmentUserInfoList = this.originDepartmentUserInfoList.slice();
}
// // reset filterOption by data filtered.
// this.setFilterOptions(this.departmentUserInfoList);
}
}