Merge branch 'master' of https://git.loafle.net/ucap-web/next-ucap-messenger
This commit is contained in:
commit
7094ebddfd
|
@ -69,7 +69,7 @@
|
|||
perfectScrollbar
|
||||
fxFlexFill
|
||||
>
|
||||
<ucap-profile-user-list-item
|
||||
<ucap-daesang-profile-user-list-item
|
||||
*ngFor="let userInfo of vsDeptUser.viewPortItems"
|
||||
[userInfo]="userInfo"
|
||||
[sessionVerinfo]="sessionVerinfo"
|
||||
|
@ -81,11 +81,8 @@
|
|||
(openProfile)="onClickOpenProfile($event)"
|
||||
(click)="onToggleUser(userInfo)"
|
||||
(contextmenu)="onContextMenuOrgUser($event, userInfo)"
|
||||
[matTooltip]="getTooltip(userInfo)"
|
||||
matTooltipShowDelay="500"
|
||||
matTooltipPosition="after"
|
||||
>
|
||||
</ucap-profile-user-list-item>
|
||||
</ucap-daesang-profile-user-list-item>
|
||||
</virtual-scroller>
|
||||
</div>
|
||||
<div *ngIf="isShowSearch" class="search-result">
|
||||
|
@ -95,7 +92,7 @@
|
|||
perfectScrollbar
|
||||
fxFlexFill
|
||||
>
|
||||
<ucap-profile-user-list-item
|
||||
<ucap-daesang-profile-user-list-item
|
||||
*ngFor="let userInfo of vsDeptSearchUser.viewPortItems"
|
||||
[userInfo]="userInfo"
|
||||
[checkable]="userInfo.seq !== loginRes.userSeq"
|
||||
|
@ -106,11 +103,8 @@
|
|||
(openProfile)="onClickOpenProfile($event)"
|
||||
(click)="onToggleUser(userInfo)"
|
||||
(contextmenu)="onContextMenuOrgUser($event, userInfo)"
|
||||
[matTooltip]="getTooltip(userInfo)"
|
||||
matTooltipShowDelay="500"
|
||||
matTooltipPosition="after"
|
||||
>
|
||||
</ucap-profile-user-list-item>
|
||||
</ucap-daesang-profile-user-list-item>
|
||||
</virtual-scroller>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -101,8 +101,8 @@ $tablet-s-width: 768px;
|
|||
border: 1px dotted #cccccc;
|
||||
box-sizing: border-box;
|
||||
img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
}
|
||||
}
|
||||
dd {
|
||||
|
|
|
@ -57,6 +57,7 @@ import { AppCommonLayoutModule } from '@app/layouts/common/common.layout.module'
|
|||
|
||||
import { COMPONENTS } from './components';
|
||||
import { DIALOGS } from './dialogs';
|
||||
import { UCapDaesangModule } from '@ucap-webmessenger/daesang';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
|
@ -108,6 +109,8 @@ import { DIALOGS } from './dialogs';
|
|||
UCapUiOrganizationModule,
|
||||
UCapUiSettingsModule,
|
||||
|
||||
UCapDaesangModule,
|
||||
|
||||
AppCommonLayoutModule
|
||||
],
|
||||
exports: [...COMPONENTS, ...DIALOGS],
|
||||
|
|
|
@ -0,0 +1,70 @@
|
|||
<!--체크박스 보여줄때는 <div class="list-item checkbox" matRipple> 클래스에 checkbox만 추가-->
|
||||
<div class="list-item checkbox" *ngIf="userInfo" matRipple>
|
||||
<!--pcOn , pcOut pcOff , pcOther-->
|
||||
<span
|
||||
class="presence"
|
||||
*ngIf="showPresence"
|
||||
[ngClass]="getPresence(PresenceType.PC)"
|
||||
[matTooltip]="getPresenceMsg()"
|
||||
matTooltipPosition="after"
|
||||
>
|
||||
</span>
|
||||
<dl class="item-default">
|
||||
<dt>
|
||||
<div class="thumbnail-mask">
|
||||
<img
|
||||
class="thumbnail"
|
||||
ucapImage
|
||||
[base]="profileImageRoot"
|
||||
[path]="userInfo.profileImageFile"
|
||||
[default]="'assets/images/img_nophoto_50.png'"
|
||||
(click)="onClickOpenProfile($event, userInfo.seq)"
|
||||
/>
|
||||
</div>
|
||||
<span
|
||||
*ngIf="getPresence(PresenceType.MOBILE) === 'mobileOn'"
|
||||
class="text-accent-color marker-mobile-state"
|
||||
>
|
||||
<mat-icon>phone_android</mat-icon>
|
||||
</span>
|
||||
</dt>
|
||||
<dd class="info">
|
||||
<div class="user-info">
|
||||
<div class="user">
|
||||
<span
|
||||
*ngIf="getWorkstatusInfo('text').length > 0"
|
||||
class="work-status"
|
||||
[ngClass]="getWorkstatusInfo('style')"
|
||||
>{{ getWorkstatusInfo('text') }}</span
|
||||
>
|
||||
<span class="detail">
|
||||
<b class="name">{{ userInfo | ucapTranslate: 'name' }}</b>
|
||||
<span class="grade">{{ userInfo | ucapTranslate: 'grade' }}</span>
|
||||
</span>
|
||||
</div>
|
||||
<span class="dept">
|
||||
<span *ngIf="!!userInfo.companyName">
|
||||
{{ userInfo.companyName }} /
|
||||
</span>
|
||||
{{ userInfo | ucapTranslate: 'deptName' }}
|
||||
</span>
|
||||
</div>
|
||||
<!-- 상태메시지 제외
|
||||
<div
|
||||
class="msg-status"
|
||||
*ngIf="!checkable && userInfo.intro.trim() && !compactable"
|
||||
>
|
||||
{{ userInfo.intro }}
|
||||
</div>
|
||||
--></dd>
|
||||
</dl>
|
||||
<mat-checkbox
|
||||
*ngIf="checkable"
|
||||
#checkbox
|
||||
[checked]="isChecked"
|
||||
[disabled]="checkDisabled"
|
||||
(change)="onChangeCheck(checkbox.checked, userInfo)"
|
||||
(click)="$event.stopPropagation()"
|
||||
>
|
||||
</mat-checkbox>
|
||||
</div>
|
|
@ -0,0 +1,145 @@
|
|||
@charset 'utf-8';
|
||||
|
||||
$font-dark: #212121;
|
||||
$font-mid: #666666;
|
||||
$font-light: #848d95;
|
||||
$font-white: #ffffff;
|
||||
$line-basic: 1px solid #dddddd;
|
||||
$bg-list-item-msg: #f0f4f6;
|
||||
$bg-list-hover: #efefef;
|
||||
$listH-row2: 60px;
|
||||
$presence-size: 8px;
|
||||
$thumbnail-msize: 40px;
|
||||
|
||||
@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;
|
||||
}
|
||||
}
|
||||
|
||||
%list-item {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
height: $listH-row2;
|
||||
border-bottom: $line-basic;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
%msg-status {
|
||||
display: inline-block;
|
||||
height: 40px;
|
||||
background-color: $bg-list-item-msg;
|
||||
font-size: 11px;
|
||||
padding: 2px 6px;
|
||||
vertical-align: middle;
|
||||
align-items: center;
|
||||
@include ellipsis(2);
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.item-default {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
dt {
|
||||
flex: none;
|
||||
position: relative;
|
||||
.thumbnail {
|
||||
width: $thumbnail-msize;
|
||||
height: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.info {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
width: calc(100% - 50px);
|
||||
transform: translateY(2px);
|
||||
.user-info {
|
||||
.user {
|
||||
display: flex;
|
||||
flex-flow: row;
|
||||
margin-bottom: 2px;
|
||||
.work-status {
|
||||
display: inline-flex;
|
||||
justify-content: center;
|
||||
justify-items: center;
|
||||
color: #ffffff;
|
||||
height: 100%;
|
||||
min-width: 32px;
|
||||
margin-right: 4px;
|
||||
border-radius: 24px;
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
.detail {
|
||||
color: $font-dark;
|
||||
width: calc(100% - 40px);
|
||||
@include ellipsis(1);
|
||||
}
|
||||
}
|
||||
.dept {
|
||||
color: $font-mid;
|
||||
@include ellipsis(1);
|
||||
}
|
||||
.msg-status {
|
||||
display: inline-block;
|
||||
float: right;
|
||||
@extend %msg-status;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//가변에 따른 list-item width값 변경
|
||||
.list-item {
|
||||
.presence[class*='pc'] {
|
||||
+ .item-default {
|
||||
width: calc(100% - 20px);
|
||||
}
|
||||
}
|
||||
&.checkbox {
|
||||
.presence[class*='pc'] {
|
||||
+ .item-default {
|
||||
width: calc(100% - 50px);
|
||||
}
|
||||
}
|
||||
.item-default {
|
||||
width: calc(100% - 30px);
|
||||
.info {
|
||||
.detail {
|
||||
width: 100%;
|
||||
}
|
||||
.msg-status {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.oraganization-tab {
|
||||
.list-item {
|
||||
.presence {
|
||||
display: none;
|
||||
}
|
||||
.item-default {
|
||||
width: calc(100% - 30px);
|
||||
}
|
||||
}
|
||||
}
|
||||
.org {
|
||||
.list-item {
|
||||
height: 70px;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
/* 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 { UserListItemComponent } from './user-list-item.component';
|
||||
|
||||
describe('UserListItemComponent', () => {
|
||||
let component: UserListItemComponent;
|
||||
let fixture: ComponentFixture<UserListItemComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ UserListItemComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(UserListItemComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
|
@ -0,0 +1,165 @@
|
|||
import {
|
||||
Component,
|
||||
OnInit,
|
||||
Input,
|
||||
Output,
|
||||
EventEmitter,
|
||||
ViewEncapsulation
|
||||
} from '@angular/core';
|
||||
import { UserInfo } from '@ucap-webmessenger/protocol-sync';
|
||||
import {
|
||||
UserInfoSS,
|
||||
UserInfoF,
|
||||
UserInfoDN
|
||||
} from '@ucap-webmessenger/protocol-query';
|
||||
import {
|
||||
StatusBulkInfo,
|
||||
StatusInfo,
|
||||
WorkStatusType
|
||||
} from '@ucap-webmessenger/protocol-status';
|
||||
import { NGXLogger } from 'ngx-logger';
|
||||
import { StatusCode, PresenceType } from '@ucap-webmessenger/core';
|
||||
import { VersionInfo2Response } from '@ucap-webmessenger/api-public';
|
||||
|
||||
@Component({
|
||||
selector: 'ucap-daesang-profile-user-list-item',
|
||||
templateUrl: './user-list-item.component.html',
|
||||
styleUrls: ['./user-list-item.component.scss'],
|
||||
encapsulation: ViewEncapsulation.None
|
||||
})
|
||||
export class UserListItemComponent implements OnInit {
|
||||
@Input()
|
||||
userInfo: UserInfoSS;
|
||||
@Input()
|
||||
profileImageRoot?: string;
|
||||
@Input()
|
||||
presence: StatusBulkInfo | StatusInfo;
|
||||
@Input()
|
||||
showPresence = true;
|
||||
@Input()
|
||||
checkable = false;
|
||||
@Input()
|
||||
checkDisabled = false;
|
||||
@Input()
|
||||
isChecked = false;
|
||||
@Input()
|
||||
compactable = false;
|
||||
@Input()
|
||||
sessionVerinfo: VersionInfo2Response;
|
||||
@Input()
|
||||
/** 선택된 사용자의 리스트 */
|
||||
selectedUserList?: UserInfoSS[] = [];
|
||||
|
||||
@Output()
|
||||
checkUser = new EventEmitter<{
|
||||
isChecked: boolean;
|
||||
userInfo: UserInfoSS;
|
||||
}>();
|
||||
@Output()
|
||||
openProfile = new EventEmitter<number>();
|
||||
|
||||
PresenceType = PresenceType;
|
||||
|
||||
constructor(private logger: NGXLogger) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.profileImageRoot =
|
||||
this.profileImageRoot || this.sessionVerinfo.profileRoot;
|
||||
}
|
||||
|
||||
getPresence(type: PresenceType): string {
|
||||
let status: string;
|
||||
let rtnClass = '';
|
||||
switch (type) {
|
||||
case PresenceType.PC:
|
||||
status = !!this.presence ? this.presence.pcStatus : undefined;
|
||||
break;
|
||||
case PresenceType.MOBILE:
|
||||
status = !!this.presence ? this.presence.mobileStatus : undefined;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (status) {
|
||||
case StatusCode.OnLine:
|
||||
rtnClass = type + 'On';
|
||||
break;
|
||||
case StatusCode.Away:
|
||||
rtnClass = type + 'Out';
|
||||
break;
|
||||
case StatusCode.Busy:
|
||||
rtnClass = type + 'Other';
|
||||
break;
|
||||
default:
|
||||
rtnClass = type + 'Off';
|
||||
break;
|
||||
}
|
||||
|
||||
return rtnClass;
|
||||
}
|
||||
getPresenceMsg(): string {
|
||||
if (
|
||||
!!this.presence &&
|
||||
!!this.presence.statusMessage &&
|
||||
this.presence.statusMessage !== '.'
|
||||
) {
|
||||
return this.presence.statusMessage;
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
/** 리스트가 checkable 할 경우 checkbox 의 change 이벤트를 상위 컴포넌트로 전달한다. */
|
||||
onChangeCheck(value: boolean, userInfo: UserInfoSS) {
|
||||
this.checkUser.emit({
|
||||
isChecked: value,
|
||||
userInfo
|
||||
});
|
||||
}
|
||||
|
||||
onClickOpenProfile(event: MouseEvent, userSeq: number) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
|
||||
this.openProfile.emit(userSeq);
|
||||
}
|
||||
|
||||
getWorkstatusInfo(type: string): string {
|
||||
let workstatus = this.userInfo.workstatus;
|
||||
|
||||
if (
|
||||
!!this.presence &&
|
||||
!!this.presence.workstatus &&
|
||||
this.presence.workstatus.trim().length > 0
|
||||
) {
|
||||
workstatus = this.presence.workstatus;
|
||||
}
|
||||
|
||||
let text = '';
|
||||
// morning-off: 오전 afternoon-off: 오후 day-off: 휴가 long-time: 장기 leave-of-absence: 휴직
|
||||
let style = '';
|
||||
switch (workstatus) {
|
||||
case WorkStatusType.VacationAM:
|
||||
style = 'morning-off';
|
||||
text = '오전';
|
||||
break;
|
||||
case WorkStatusType.VacationPM:
|
||||
style = 'afternoon-off';
|
||||
text = '오후';
|
||||
break;
|
||||
case WorkStatusType.VacationAll:
|
||||
style = 'day-off';
|
||||
text = '휴가';
|
||||
break;
|
||||
case WorkStatusType.LeaveOfAbsence:
|
||||
style = 'leave-of-absence';
|
||||
text = '휴직';
|
||||
break;
|
||||
case WorkStatusType.LongtermRefresh:
|
||||
style = 'long-time';
|
||||
text = '장기';
|
||||
break;
|
||||
}
|
||||
|
||||
return type === 'text' ? text : style;
|
||||
}
|
||||
}
|
|
@ -1,8 +1,27 @@
|
|||
import { NgModule, ModuleWithProviders } from '@angular/core';
|
||||
import { MatTooltipModule } from '@angular/material/tooltip';
|
||||
import { MatCardModule } from '@angular/material/card';
|
||||
import { CommonModule } from '@angular/common';
|
||||
|
||||
import { ReactiveFormsModule } from '@angular/forms';
|
||||
import { FlexLayoutModule } from '@angular/flex-layout';
|
||||
|
||||
import { MatRippleModule, MatCheckboxModule } from '@angular/material';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatIconModule } from '@angular/material/icon';
|
||||
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
|
||||
import { MatInputModule } from '@angular/material/input';
|
||||
import { MatFormFieldModule } from '@angular/material/form-field';
|
||||
|
||||
import { UCapUiModule } from '@ucap-webmessenger/ui';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
|
||||
import { DaesangCipherService } from './services/daesang-cipher.service';
|
||||
import { DaesangProtocolService } from './services/daesang-protocol.service';
|
||||
import { DaesangApiService } from './services/daesang-api.service';
|
||||
import { UserListItemComponent } from './components/user-list-item.component';
|
||||
|
||||
const COMPONENTS = [UserListItemComponent];
|
||||
|
||||
const SERVICES = [
|
||||
DaesangCipherService,
|
||||
|
@ -11,9 +30,26 @@ const SERVICES = [
|
|||
];
|
||||
|
||||
@NgModule({
|
||||
declarations: [],
|
||||
imports: [],
|
||||
exports: []
|
||||
imports: [
|
||||
CommonModule,
|
||||
ReactiveFormsModule,
|
||||
FlexLayoutModule,
|
||||
MatButtonModule,
|
||||
MatFormFieldModule,
|
||||
MatIconModule,
|
||||
MatInputModule,
|
||||
MatRippleModule,
|
||||
MatCheckboxModule,
|
||||
MatCardModule,
|
||||
MatTooltipModule,
|
||||
MatProgressSpinnerModule,
|
||||
|
||||
TranslateModule,
|
||||
|
||||
UCapUiModule
|
||||
],
|
||||
exports: [...COMPONENTS],
|
||||
declarations: [...COMPONENTS]
|
||||
})
|
||||
export class UCapDaesangModule {
|
||||
public static forRoot(): ModuleWithProviders<UCapDaesangModule> {
|
||||
|
|
|
@ -3,7 +3,8 @@
|
|||
position: relative;
|
||||
|
||||
img {
|
||||
height: 140px;
|
||||
max-height: 140px;
|
||||
min-height: 20px;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
|
|
|
@ -175,6 +175,10 @@ export class MessagesComponent implements OnInit, OnDestroy {
|
|||
this.loginRes = loginRes;
|
||||
});
|
||||
this.roomInfoSubscription = this.roomInfo$.subscribe(roomInfo => {
|
||||
if (!this.roomInfo || this.roomInfo.roomSeq !== roomInfo.roomSeq) {
|
||||
this.baseEventSeq = 0;
|
||||
}
|
||||
|
||||
this.roomInfo = roomInfo;
|
||||
this.showMore = false;
|
||||
|
||||
|
@ -186,6 +190,7 @@ export class MessagesComponent implements OnInit, OnDestroy {
|
|||
// clear :: readToHearEvent object
|
||||
this.readToHereEvent = undefined;
|
||||
this.existReadToHereEvent = true;
|
||||
this.firstCheckReadHere = true;
|
||||
/** [E] initializing by changed room */
|
||||
|
||||
if (!this.roomInfo || this.roomInfo.roomSeq !== roomInfo.roomSeq) {
|
||||
|
|
Loading…
Reference in New Issue
Block a user