merged
This commit is contained in:
commit
bb1c74823d
|
@ -194,3 +194,7 @@ ipcMain.on(Channel.saveFile, (event: IpcMainEvent, ...args: any[]) => {
|
||||||
event.returnValue = false;
|
event.returnValue = false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
ipcMain.on(Channel.showNotify, (event: IpcMainEvent, ...args: any[]) => {
|
||||||
|
console.log('Channel.showNotify', args);
|
||||||
|
});
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
<ng-template mat-tab-label>
|
<ng-template mat-tab-label>
|
||||||
<mat-icon>group</mat-icon>
|
<mat-icon>group</mat-icon>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
<app-layout-chat-left-sidenav-group></app-layout-chat-left-sidenav-group>
|
<app-layout-chat-left-sidenav-group class="left-group-side"></app-layout-chat-left-sidenav-group>
|
||||||
</mat-tab>
|
</mat-tab>
|
||||||
<mat-tab>
|
<mat-tab>
|
||||||
<ng-template mat-tab-label>
|
<ng-template mat-tab-label>
|
||||||
|
|
|
@ -49,3 +49,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.left-group-side{
|
||||||
|
position: relative;
|
||||||
|
height:100%;
|
||||||
|
}
|
||||||
|
|
|
@ -1,83 +1,66 @@
|
||||||
<!--<div class="app-layout-chat-left-sidenav-chat-header list-search">
|
<div>
|
||||||
<form [formGroup]="fgSearch">
|
<div class="current-head">
|
||||||
<mat-form-field class="w-100-p searchbox" floatLabel="never">
|
<h3>대화</h3>
|
||||||
<input
|
<div class="btn-box">
|
||||||
matInput
|
<!-- <button mat-icon-button>
|
||||||
#inputSearch
|
<mat-icon>timer</mat-icon>
|
||||||
type="text"
|
|
||||||
maxlength="20"
|
|
||||||
placeholder="대화방 이름 검색"
|
|
||||||
value=""
|
|
||||||
formControlName="searchInput"
|
|
||||||
[matAutocomplete]="auto"
|
|
||||||
(keydown.enter)="onKeyDownEnter($event, inputSearch.value)"
|
|
||||||
/>
|
|
||||||
<mat-autocomplete #auto="matAutocomplete">
|
|
||||||
<mat-option
|
|
||||||
*ngFor="let filteredRecommendedWord of filteredRecommendedWordList"
|
|
||||||
[value]="filteredRecommendedWord"
|
|
||||||
>
|
|
||||||
{{ filteredRecommendedWord }}
|
|
||||||
</mat-option>
|
|
||||||
</mat-autocomplete>
|
|
||||||
|
|
||||||
<button
|
|
||||||
mat-button
|
|
||||||
matSuffix
|
|
||||||
mat-icon-button
|
|
||||||
aria-label="Clear"
|
|
||||||
(click)="inputSearch.value = ''; onClickSearchCancel()"
|
|
||||||
>
|
|
||||||
<mat-icon>close</mat-icon>
|
|
||||||
</button>
|
</button>
|
||||||
</mat-form-field>
|
<button mat-icon-button>
|
||||||
</form>-->
|
<mat-icon> add_comment</mat-icon>
|
||||||
|
</button> -->
|
||||||
<div class="list-search">
|
</div>
|
||||||
<div class="searchbox">
|
</div>
|
||||||
<form [formGroup]="fgSearch" class="w-100-p">
|
<div class="list-search">
|
||||||
<mat-form-field floatLabel="never">
|
<div class="searchbox">
|
||||||
<input
|
<form [formGroup]="fgSearch" class="w-100-p">
|
||||||
matInput
|
<mat-form-field floatLabel="never">
|
||||||
#inputSearch
|
<input
|
||||||
type="text"
|
matInput
|
||||||
maxlength="20"
|
#inputSearch
|
||||||
placeholder="대화방 이름 검색"
|
type="text"
|
||||||
value=""
|
maxlength="20"
|
||||||
formControlName="searchInput"
|
placeholder="대화방 이름 검색"
|
||||||
[matAutocomplete]="auto"
|
value=""
|
||||||
(keydown.enter)="onKeyDownEnter($event, inputSearch.value)"
|
formControlName="searchInput"
|
||||||
/>
|
[matAutocomplete]="auto"
|
||||||
<button
|
(keydown.enter)="onKeyDownEnter($event, inputSearch.value)"
|
||||||
mat-button
|
/>
|
||||||
matSuffix
|
<mat-autocomplete #auto="matAutocomplete">
|
||||||
mat-icon-button
|
<mat-option
|
||||||
aria-label="Clear"
|
*ngFor="
|
||||||
(click)="inputSearch.value = ''; onClickSearchCancel()"
|
let filteredRecommendedWord of filteredRecommendedWordList
|
||||||
>
|
"
|
||||||
<mat-icon>close</mat-icon>
|
[value]="filteredRecommendedWord"
|
||||||
</button>
|
>
|
||||||
</mat-form-field>
|
{{ filteredRecommendedWord }}
|
||||||
</form>
|
</mat-option>
|
||||||
|
</mat-autocomplete>
|
||||||
|
<button
|
||||||
|
mat-button
|
||||||
|
matSuffix
|
||||||
|
mat-icon-button
|
||||||
|
aria-label="Clear"
|
||||||
|
(click)="inputSearch.value = ''; onClickSearchCancel()"
|
||||||
|
>
|
||||||
|
<mat-icon>close</mat-icon>
|
||||||
|
</button>
|
||||||
|
</mat-form-field>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div
|
<div *ngIf="!isSearch" class="app-layout-chat-left-sidenav-chat-list">
|
||||||
*ngIf="!isSearch"
|
<ucap-room-list-item
|
||||||
class="app-layout-chat-left-sidenav-chat-list"
|
*ngFor="let room of roomList"
|
||||||
perfectScrollbar
|
[loginRes]="loginRes"
|
||||||
>
|
[roomInfo]="room"
|
||||||
<ucap-room-list-item
|
[roomUserInfo]="getRoomUserList(room)"
|
||||||
*ngFor="let room of roomList"
|
[sessionVerinfo]="sessionVerinfo"
|
||||||
[loginRes]="loginRes"
|
(click)="onSelectedRoom(room)"
|
||||||
[roomInfo]="room"
|
(contextmenu)="onContextMenuChat($event, room)"
|
||||||
[roomUserInfo]="getRoomUserList(room)"
|
>
|
||||||
[sessionVerinfo]="sessionVerinfo"
|
</ucap-room-list-item>
|
||||||
(click)="onSelectedRoom(room)"
|
<!-- <cdk-virtual-scroll-viewport
|
||||||
(contextmenu)="onContextMenuChat($event, room)"
|
|
||||||
>
|
|
||||||
</ucap-room-list-item>
|
|
||||||
<!-- <cdk-virtual-scroll-viewport
|
|
||||||
itemSize="20"
|
itemSize="20"
|
||||||
class="app-layout-chat-left-sidenav-chat-list-viewport"
|
class="app-layout-chat-left-sidenav-chat-list-viewport"
|
||||||
>
|
>
|
||||||
|
@ -92,23 +75,19 @@
|
||||||
>
|
>
|
||||||
</ucap-room-list-item>
|
</ucap-room-list-item>
|
||||||
</cdk-virtual-scroll-viewport> -->
|
</cdk-virtual-scroll-viewport> -->
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div *ngIf="!!isSearch" class="app-layout-chat-left-sidenav-chat-list search">
|
||||||
*ngIf="!!isSearch"
|
<ucap-room-list-item
|
||||||
class="app-layout-chat-left-sidenav-chat-list search"
|
*ngFor="let room of searchRoomList"
|
||||||
perfectScrollbar
|
[loginRes]="loginRes"
|
||||||
>
|
[roomInfo]="room"
|
||||||
<ucap-room-list-item
|
[roomUserInfo]="getRoomUserList(room)"
|
||||||
*ngFor="let room of searchRoomList"
|
[sessionVerinfo]="sessionVerinfo"
|
||||||
[loginRes]="loginRes"
|
(click)="onSelectedRoom(room)"
|
||||||
[roomInfo]="room"
|
(contextmenu)="onContextMenuChat($event, room)"
|
||||||
[roomUserInfo]="getRoomUserList(room)"
|
>
|
||||||
[sessionVerinfo]="sessionVerinfo"
|
</ucap-room-list-item>
|
||||||
(click)="onSelectedRoom(room)"
|
<!-- <cdk-virtual-scroll-viewport
|
||||||
(contextmenu)="onContextMenuChat($event, room)"
|
|
||||||
>
|
|
||||||
</ucap-room-list-item>
|
|
||||||
<!-- <cdk-virtual-scroll-viewport
|
|
||||||
itemSize="20"
|
itemSize="20"
|
||||||
class="app-layout-chat-left-sidenav-chat-list-viewport"
|
class="app-layout-chat-left-sidenav-chat-list-viewport"
|
||||||
>
|
>
|
||||||
|
@ -123,29 +102,30 @@
|
||||||
>
|
>
|
||||||
</ucap-room-list-item>
|
</ucap-room-list-item>
|
||||||
</cdk-virtual-scroll-viewport> -->
|
</cdk-virtual-scroll-viewport> -->
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
style="visibility: hidden; position: fixed"
|
style="visibility: hidden; position: fixed"
|
||||||
[style.left]="chatContextMenuPosition.x"
|
[style.left]="chatContextMenuPosition.x"
|
||||||
[style.top]="chatContextMenuPosition.y"
|
[style.top]="chatContextMenuPosition.y"
|
||||||
#chatContextMenuTrigger="matMenuTrigger"
|
#chatContextMenuTrigger="matMenuTrigger"
|
||||||
[matMenuTriggerFor]="chatContextMenu"
|
[matMenuTriggerFor]="chatContextMenu"
|
||||||
></div>
|
></div>
|
||||||
<mat-menu
|
<mat-menu
|
||||||
#chatContextMenu="matMenu"
|
#chatContextMenu="matMenu"
|
||||||
[hasBackdrop]="false"
|
[hasBackdrop]="false"
|
||||||
(ucapUiClickOutside)="chatContextMenuTrigger.closeMenu()"
|
(ucapUiClickOutside)="chatContextMenuTrigger.closeMenu()"
|
||||||
>
|
>
|
||||||
<ng-template matMenuContent let-roomInfo="roomInfo">
|
<ng-template matMenuContent let-roomInfo="roomInfo">
|
||||||
<button mat-menu-item (click)="onSelectedRoom(roomInfo)">
|
<button mat-menu-item (click)="onSelectedRoom(roomInfo)">
|
||||||
대화방 열기
|
대화방 열기
|
||||||
</button>
|
</button>
|
||||||
<button mat-menu-item (click)="onClickToggleAlarm(roomInfo)">
|
<button mat-menu-item (click)="onClickToggleAlarm(roomInfo)">
|
||||||
대화방 알람 {{ roomInfo.receiveAlarm ? '끄기' : '켜기' }}
|
대화방 알람 {{ roomInfo.receiveAlarm ? '끄기' : '켜기' }}
|
||||||
</button>
|
</button>
|
||||||
<button mat-menu-item (click)="onClickExit(roomInfo)">
|
<button mat-menu-item (click)="onClickExit(roomInfo)">
|
||||||
대화방 나가기
|
대화방 나가기
|
||||||
</button>
|
</button>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
</mat-menu>
|
</mat-menu>
|
||||||
|
</div>
|
||||||
|
|
|
@ -1,3 +1,69 @@
|
||||||
|
.current-head{
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 0 10px;
|
||||||
|
height: 60px;
|
||||||
|
h3{
|
||||||
|
display: inline-flex;
|
||||||
|
padding-left: 10px;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
.btn-box{
|
||||||
|
height: 100%;
|
||||||
|
margin-left: auto;
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.list-search {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
height: 60px;
|
||||||
|
align-items: center;
|
||||||
|
padding: 0;
|
||||||
|
font-size: 14px;
|
||||||
|
border-bottom: 1px solid #dddddd;
|
||||||
|
.searchbox{
|
||||||
|
width:100%;
|
||||||
|
height:100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
::ng-deep .searchbox{
|
||||||
|
.mat-form-field{
|
||||||
|
display:block;
|
||||||
|
.mat-form-field-wrapper{
|
||||||
|
padding: 0;
|
||||||
|
padding-bottom:0 !important;
|
||||||
|
height: 100%;
|
||||||
|
.mat-form-field-flex{
|
||||||
|
height: 59px;
|
||||||
|
padding:0 20px;
|
||||||
|
align-items: center;
|
||||||
|
.mat-form-field-infix{
|
||||||
|
width:100%;
|
||||||
|
font-size:14px;
|
||||||
|
border:none;
|
||||||
|
}
|
||||||
|
.mat-form-field-suffix{
|
||||||
|
.mat-icon{
|
||||||
|
line-height:24px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.mat-form-field-appearance-legacy{
|
||||||
|
.mat-form-field-wrapper{
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
.mat-form-field-underline{
|
||||||
|
bottom:0;
|
||||||
|
background-color: unset !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.app-layout-chat-left-sidenav-chat-header {
|
.app-layout-chat-left-sidenav-chat-header {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 50px;
|
height: 50px;
|
||||||
|
@ -10,60 +76,4 @@
|
||||||
.app-layout-chat-left-sidenav-chat-list-viewport {
|
.app-layout-chat-left-sidenav-chat-list-viewport {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.room-name {
|
|
||||||
white-space: nowrap;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
.list-search {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
height: 60px;
|
|
||||||
align-items: center;
|
|
||||||
padding: 0;
|
|
||||||
font-size: 14px;
|
|
||||||
border-bottom: 1px solid #dddddd;
|
|
||||||
.searchbox{
|
|
||||||
width:100%;
|
|
||||||
.mat-form-field{
|
|
||||||
display:block;
|
|
||||||
.mat-form-field-wrapper{
|
|
||||||
padding-bottom:0 !important;
|
|
||||||
height: 60px;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
::ng-deep .searchbox .mat-form-field-flex{
|
|
||||||
height: 60px;
|
|
||||||
padding:0 10px;
|
|
||||||
}
|
|
||||||
::ng-deep .searchbox .mat-form-field-appearance-legacy .mat-form-field-wrapper{
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
::ng-deep .searchbox .mat-form-field-appearance-legacy .mat-form-field-underline{
|
|
||||||
bottom:0;
|
|
||||||
background-color: #cccccc !important;
|
|
||||||
}
|
|
||||||
/*.searchbox {
|
|
||||||
width: 100%;
|
|
||||||
display: flex;
|
|
||||||
input {
|
|
||||||
display: inline-flex;
|
|
||||||
width: 100%;
|
|
||||||
font-size: 14px;
|
|
||||||
padding-left: 0;
|
|
||||||
}
|
|
||||||
.btn-search {
|
|
||||||
color: #777777;
|
|
||||||
font-size: 12px;
|
|
||||||
display: inline-flex;
|
|
||||||
margin-left: auto;
|
|
||||||
flex: none;
|
|
||||||
}
|
|
||||||
}*/
|
|
|
@ -1,4 +1,4 @@
|
||||||
<div>
|
|
||||||
<div>
|
<div>
|
||||||
<div class="current-head">
|
<div class="current-head">
|
||||||
<h3>그룹</h3>
|
<h3>그룹</h3>
|
||||||
|
@ -52,7 +52,7 @@
|
||||||
</button>
|
</button>
|
||||||
</mat-menu>
|
</mat-menu>
|
||||||
</div>
|
</div>
|
||||||
<div *ngIf="!isShowSearch">
|
<div *ngIf="!isShowSearch" class="search-result" style="overflow: auto;">
|
||||||
<ucap-group-expansion-panel
|
<ucap-group-expansion-panel
|
||||||
#groupExpansionPanel
|
#groupExpansionPanel
|
||||||
[groupBuddyList]="groupBuddyList$ | async"
|
[groupBuddyList]="groupBuddyList$ | async"
|
||||||
|
@ -71,11 +71,11 @@
|
||||||
</ucap-profile-user-list-item>
|
</ucap-profile-user-list-item>
|
||||||
</ucap-group-expansion-panel>
|
</ucap-group-expansion-panel>
|
||||||
</div>
|
</div>
|
||||||
<div *ngIf="isShowSearch">
|
<div *ngIf="isShowSearch" class="search-result">
|
||||||
<div *ngIf="searchProcessing">
|
<div *ngIf="searchProcessing">
|
||||||
<mat-progress-bar mode="indeterminate"></mat-progress-bar>
|
<mat-progress-bar mode="indeterminate"></mat-progress-bar>
|
||||||
</div>
|
</div>
|
||||||
<div>검색결과({{ searchUserInfos.length }}명)</div>
|
<div class="result-num">검색결과<span class="text-accent-color">({{ searchUserInfos.length }}명)</span></div>
|
||||||
<ucap-profile-user-list-item
|
<ucap-profile-user-list-item
|
||||||
*ngFor="let userInfo of searchUserInfos"
|
*ngFor="let userInfo of searchUserInfos"
|
||||||
[userInfo]="userInfo"
|
[userInfo]="userInfo"
|
||||||
|
@ -85,7 +85,7 @@
|
||||||
>
|
>
|
||||||
</ucap-profile-user-list-item>
|
</ucap-profile-user-list-item>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div
|
<div
|
||||||
style="visibility: hidden; position: fixed"
|
style="visibility: hidden; position: fixed"
|
||||||
|
|
|
@ -18,3 +18,16 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.search-result {
|
||||||
|
height: calc(100% - 120px);
|
||||||
|
overflow: auto;
|
||||||
|
.result-num {
|
||||||
|
padding: 10px;
|
||||||
|
display: flex;
|
||||||
|
height: 40px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
::ng-deep .mat-tab-body-content {
|
||||||
|
height: 100%;
|
||||||
|
overflow: unset;
|
||||||
|
}
|
||||||
|
|
|
@ -170,7 +170,6 @@ export class GroupComponent implements OnInit, OnDestroy {
|
||||||
CreateChatDialogResult
|
CreateChatDialogResult
|
||||||
>(CreateChatDialogComponent, {
|
>(CreateChatDialogComponent, {
|
||||||
width: '600px',
|
width: '600px',
|
||||||
height: '700px',
|
|
||||||
data: {
|
data: {
|
||||||
type: UserSelectDialogType.NewGroup,
|
type: UserSelectDialogType.NewGroup,
|
||||||
title: 'New Group'
|
title: 'New Group'
|
||||||
|
|
|
@ -10,8 +10,7 @@
|
||||||
></ucap-organization-tree>
|
></ucap-organization-tree>
|
||||||
</div>
|
</div>
|
||||||
<div class="select-list ">
|
<div class="select-list ">
|
||||||
<div class="select-dept text-accent-color">
|
<dl class="select-dept text-accent-color">
|
||||||
<dl>
|
|
||||||
<dt>
|
<dt>
|
||||||
{{ getSelectedDepartmentName() }}
|
{{ getSelectedDepartmentName() }}
|
||||||
</dt>
|
</dt>
|
||||||
|
@ -25,7 +24,6 @@
|
||||||
</mat-checkbox>
|
</mat-checkbox>
|
||||||
</dd>
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
</div>
|
|
||||||
<div *ngIf="selectedDepartmentProcessing">
|
<div *ngIf="selectedDepartmentProcessing">
|
||||||
<mat-progress-bar mode="indeterminate"></mat-progress-bar>
|
<mat-progress-bar mode="indeterminate"></mat-progress-bar>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -16,16 +16,17 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.oraganization-tab {
|
.oraganization-tab {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
flex-direction: inherit;
|
flex-direction: inherit;
|
||||||
display: flex;
|
display: flex;
|
||||||
.oraganization-tab-tree {
|
.oraganization-tab-tree {
|
||||||
height:40%;
|
height:40%;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//팝업에 있는 조직도
|
||||||
.mat-card-content{
|
.mat-card-content{
|
||||||
.mat-tab-body-content{
|
.mat-tab-body-content{
|
||||||
.oraganization-box{
|
.oraganization-box{
|
||||||
|
@ -37,34 +38,24 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn-box{
|
|
||||||
height:100px;
|
|
||||||
position: absolute;
|
|
||||||
bottom:0;
|
|
||||||
border-top:1px solid #ddd;
|
|
||||||
align-items: center;
|
|
||||||
width:100%;
|
|
||||||
background-color:#ffffff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.select-list{
|
.select-list{
|
||||||
height:60%;
|
height:60%;
|
||||||
border-top:1px solid #dddddd;
|
border-top:1px solid #dddddd;
|
||||||
.select-dept{
|
.select-dept{
|
||||||
padding:0 10px;
|
padding:0 20px;
|
||||||
height:40px;
|
height:40px;
|
||||||
line-height:40px;
|
line-height:40px;
|
||||||
.dept-name{
|
display:flex;
|
||||||
border-top:1px solid #dddddd;
|
background-color: #f9f9f9;
|
||||||
height:40px;
|
dt{
|
||||||
width:100%;
|
|
||||||
display:inline-flex;
|
}
|
||||||
align-items: center;
|
dd{
|
||||||
padding:0 10px;
|
margin-left:auto;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.search-list{
|
.search-list{
|
||||||
height: calc(100% - 140px);
|
height: calc(100% - 40px);
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
.list-item{
|
.list-item{
|
||||||
height:70px;
|
height:70px;
|
||||||
|
|
|
@ -8,19 +8,33 @@
|
||||||
<button
|
<button
|
||||||
mat-icon-button
|
mat-icon-button
|
||||||
aria-label="chats button"
|
aria-label="chats button"
|
||||||
fxHide.gt-md
|
|
||||||
class="responsive-chats-button"
|
class="responsive-chats-button"
|
||||||
>
|
>
|
||||||
<mat-icon>chat</mat-icon>
|
<mat-icon>chat</mat-icon>
|
||||||
</button>
|
</button>
|
||||||
<!-- / RESPONSIVE CHATS BUTTON-->
|
<!-- / RESPONSIVE CHATS BUTTON-->
|
||||||
|
<button
|
||||||
|
mat-icon-button
|
||||||
|
aria-label="chats button"
|
||||||
|
class="responsive-chats-button"
|
||||||
|
*ngIf="!!roomInfo && roomInfo.isTimeRoom">
|
||||||
|
<mat-icon>timer</mat-icon>
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="room-name">
|
<div class="room-info">
|
||||||
{{ getRoomName() }}
|
<h3 class="room-name">
|
||||||
</div>
|
{{ getRoomName() }}
|
||||||
<div *ngIf="!!roomInfo && roomInfo.isTimeRoom">
|
</h3>
|
||||||
<mat-icon>timer</mat-icon> {{ getConvertTimer(roomInfo.timeRoomInterval) }}
|
<!-- Timer Room Info -->
|
||||||
|
<div *ngIf="roomInfo && roomInfo.isTimeRoom" class="room-type text-accent-color ">
|
||||||
|
<span class="bg-accent-light">{{ getConvertTimer(roomInfo.timeRoomInterval) }} </span>비밀 대화방입니다.
|
||||||
|
</div>
|
||||||
|
<!-- Timer Room Info -->
|
||||||
</div>
|
</div>
|
||||||
|
<!--<div *ngIf="!!roomInfo && roomInfo.isTimeRoom">
|
||||||
|
<mat-icon>timer</mat-icon>
|
||||||
|
{{ getConvertTimer(roomInfo.timeRoomInterval) }}
|
||||||
|
</div>-->
|
||||||
<div class="room-option">
|
<div class="room-option">
|
||||||
<button
|
<button
|
||||||
*ngIf="!!roomInfo"
|
*ngIf="!!roomInfo"
|
||||||
|
@ -68,18 +82,22 @@
|
||||||
(fileDragOver)="onFileDragOver()"
|
(fileDragOver)="onFileDragOver()"
|
||||||
(fileDragLeave)="onFileDragLeave()"
|
(fileDragLeave)="onFileDragLeave()"
|
||||||
>
|
>
|
||||||
<!-- Timer Room Info -->
|
|
||||||
<span *ngIf="roomInfo && roomInfo.isTimeRoom">비밀 대화방입니다.</span>
|
|
||||||
<!-- Timer Room Info -->
|
|
||||||
|
|
||||||
<!-- CHAT MESSAGES -->
|
<!-- CHAT MESSAGES -->
|
||||||
<perfect-scrollbar fxFlex="1 1 auto" #psChatContent>
|
<perfect-scrollbar
|
||||||
|
fxFlex="1 1 auto"
|
||||||
|
#psChatContent
|
||||||
|
(psYReachStart)="onScrollup($event)"
|
||||||
|
>
|
||||||
<ucap-chat-messages
|
<ucap-chat-messages
|
||||||
[messages]="eventList$ | async"
|
[messages]="eventList$ | async"
|
||||||
[eventInfoStatus]="eventInfoStatus$ | async"
|
[eventInfoStatus]="eventInfoStatus$ | async"
|
||||||
|
[eventRemain]="eventRemain$ | async"
|
||||||
[userInfos]="userInfoList"
|
[userInfos]="userInfoList"
|
||||||
[loginRes]="loginRes"
|
[loginRes]="loginRes"
|
||||||
[sessionVerInfo]="sessionVerInfo"
|
[sessionVerInfo]="sessionVerInfo"
|
||||||
|
(moreEvent)="onMoreEvent($event)"
|
||||||
(massDetail)="onMassDetail($event)"
|
(massDetail)="onMassDetail($event)"
|
||||||
(save)="onSave($event)"
|
(save)="onSave($event)"
|
||||||
(imageViewer)="onImageViewer($event)"
|
(imageViewer)="onImageViewer($event)"
|
||||||
|
|
|
@ -1,5 +1,9 @@
|
||||||
@charset 'utf-8';
|
@charset 'utf-s';
|
||||||
$line-basic: 1px solid #dddddd;
|
:host {
|
||||||
|
display: flex;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
@mixin ellipsis($row) {
|
@mixin ellipsis($row) {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
|
@ -14,24 +18,29 @@ $line-basic: 1px solid #dddddd;
|
||||||
word-wrap: break-word;
|
word-wrap: break-word;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
:host {
|
.container{
|
||||||
display: flex;
|
position: relative;
|
||||||
width: 100%;
|
width:100%;
|
||||||
height: 100%;
|
}
|
||||||
flex: 1;
|
.chat-toolbar {
|
||||||
|
width:100%;
|
||||||
|
height: 70px;
|
||||||
|
min-height: 70px;
|
||||||
|
align-items: center;
|
||||||
|
background-color: #ffffff !important;
|
||||||
|
border: 1px solid #dddddd;
|
||||||
|
|
||||||
.container {
|
.chat-header {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
align-items: center;
|
||||||
|
display: flex;
|
||||||
.chat-toolbar {
|
justify-content: space-between;
|
||||||
height: 70px;
|
.profile-img {
|
||||||
min-height: 70px;
|
margin-right: 20px;
|
||||||
border-bottom: $line-basic;
|
.responsive-chats-button {
|
||||||
background-color: #ffffff;
|
display: none;
|
||||||
.chat-header {
|
&:last-child {
|
||||||
width: 100%;
|
display: block;
|
||||||
.responsive-chats-button {
|
|
||||||
padding: 0;
|
padding: 0;
|
||||||
width: 40px;
|
width: 40px;
|
||||||
height: 40px;
|
height: 40px;
|
||||||
|
@ -39,44 +48,38 @@ $line-basic: 1px solid #dddddd;
|
||||||
background-color: #252525;
|
background-color: #252525;
|
||||||
color: #efefef;
|
color: #efefef;
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
font-weight: 100;
|
|
||||||
line-height: 40px;
|
line-height: 40px;
|
||||||
}
|
}
|
||||||
.room-name {
|
|
||||||
font-size: 16px;
|
|
||||||
padding: 0 10px;
|
|
||||||
@include ellipsis(1);
|
|
||||||
}
|
|
||||||
.room-option {
|
|
||||||
width: 100px;
|
|
||||||
margin-left: auto;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.room-info {
|
||||||
.chat-content {
|
display:flex;
|
||||||
position: relative;
|
flex-flow: column;
|
||||||
background: transparent;
|
overflow: hidden;
|
||||||
overflow: auto;
|
.room-name {
|
||||||
-webkit-overflow-scrolling: touch;
|
font-size: 16px;
|
||||||
|
line-height: normal;
|
||||||
.file-drop-zone-container {
|
@include ellipsis(1);
|
||||||
position: absolute;
|
}
|
||||||
top: 0;
|
.room-type {
|
||||||
left: 0;
|
font-size: 14px;
|
||||||
width: 100%;
|
line-height: normal;
|
||||||
height: 100%;
|
margin-top: 6px;
|
||||||
background-color: rgba(255, 255, 255, 0.95);
|
height:20px;
|
||||||
|
span{
|
||||||
.file-drop-zone {
|
border-radius:10px;
|
||||||
position: absolute;
|
padding:1px 10px;
|
||||||
|
margin-right:6px;
|
||||||
top: 10%;
|
font-size:13px;
|
||||||
left: 10%;
|
|
||||||
width: 80%;
|
|
||||||
height: 80%;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.room-option {
|
||||||
|
wdith: 100%;
|
||||||
|
margin-left: auto;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.chat-content {
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
|
@ -58,7 +58,7 @@ import {
|
||||||
ImageViewerDialogData,
|
ImageViewerDialogData,
|
||||||
ImageViewerDialogResult
|
ImageViewerDialogResult
|
||||||
} from '@app/layouts/common/dialogs/image-viewer.dialog.component';
|
} from '@app/layouts/common/dialogs/image-viewer.dialog.component';
|
||||||
import { Maximum_Range } from '@ucap-webmessenger/core';
|
import { CONST } from '@ucap-webmessenger/core';
|
||||||
import { PerfectScrollbarComponent } from 'ngx-perfect-scrollbar';
|
import { PerfectScrollbarComponent } from 'ngx-perfect-scrollbar';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
|
@ -83,12 +83,15 @@ export class MessagesComponent implements OnInit, OnDestroy, AfterViewChecked {
|
||||||
loginRes: LoginResponse;
|
loginRes: LoginResponse;
|
||||||
loginResSubscription: Subscription;
|
loginResSubscription: Subscription;
|
||||||
eventList$: Observable<Info[]>;
|
eventList$: Observable<Info[]>;
|
||||||
|
baseEventSeq = 0;
|
||||||
roomInfo: RoomInfo;
|
roomInfo: RoomInfo;
|
||||||
roomInfoSubscription: Subscription;
|
roomInfoSubscription: Subscription;
|
||||||
userInfoList: UserInfo[];
|
userInfoList: UserInfo[];
|
||||||
userInfoListSubscription: Subscription;
|
userInfoListSubscription: Subscription;
|
||||||
eventListProcessing$: Observable<boolean>;
|
eventListProcessing$: Observable<boolean>;
|
||||||
eventInfoStatus$: Observable<InfoResponse>;
|
eventInfoStatus$: Observable<InfoResponse>;
|
||||||
|
eventRemain$: Observable<boolean>;
|
||||||
|
eventRemain = false;
|
||||||
sessionVerInfo: VersionInfo2Response;
|
sessionVerInfo: VersionInfo2Response;
|
||||||
|
|
||||||
isRecalledMessage = isRecalled;
|
isRecalledMessage = isRecalled;
|
||||||
|
@ -99,6 +102,9 @@ export class MessagesComponent implements OnInit, OnDestroy, AfterViewChecked {
|
||||||
files: File[];
|
files: File[];
|
||||||
fileItems: DataTransferItemList;
|
fileItems: DataTransferItemList;
|
||||||
|
|
||||||
|
/** Timer 대화방의 대화 삭제를 위한 interval */
|
||||||
|
interval: any;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private store: Store<any>,
|
private store: Store<any>,
|
||||||
private sessionStorageService: SessionStorageService,
|
private sessionStorageService: SessionStorageService,
|
||||||
|
@ -149,8 +155,20 @@ export class MessagesComponent implements OnInit, OnDestroy, AfterViewChecked {
|
||||||
select(AppStore.MessengerSelector.EventSelector.infoListProcessing)
|
select(AppStore.MessengerSelector.EventSelector.infoListProcessing)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
this.eventRemain$ = this.store.pipe(
|
||||||
|
select(AppStore.MessengerSelector.EventSelector.remainInfo),
|
||||||
|
tap(remainInfo => {
|
||||||
|
this.eventRemain = remainInfo;
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
this.eventList$ = this.store.pipe(
|
this.eventList$ = this.store.pipe(
|
||||||
select(AppStore.MessengerSelector.EventSelector.selectAllInfoList)
|
select(AppStore.MessengerSelector.EventSelector.selectAllInfoList),
|
||||||
|
tap(infoList => {
|
||||||
|
if (!!infoList && infoList.length > 0) {
|
||||||
|
this.baseEventSeq = infoList[0].seq;
|
||||||
|
}
|
||||||
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
this.eventInfoStatus$ = this.store.pipe(
|
this.eventInfoStatus$ = this.store.pipe(
|
||||||
|
@ -158,6 +176,12 @@ export class MessagesComponent implements OnInit, OnDestroy, AfterViewChecked {
|
||||||
);
|
);
|
||||||
|
|
||||||
this.psChatContent.directiveRef.scrollToBottom(0, 0);
|
this.psChatContent.directiveRef.scrollToBottom(0, 0);
|
||||||
|
|
||||||
|
this.interval = setInterval(() => {
|
||||||
|
if (!!this.roomInfo.isTimeRoom) {
|
||||||
|
this.store.dispatch(EventStore.infoIntervalClear({}));
|
||||||
|
}
|
||||||
|
}, 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnDestroy(): void {
|
ngOnDestroy(): void {
|
||||||
|
@ -170,6 +194,8 @@ export class MessagesComponent implements OnInit, OnDestroy, AfterViewChecked {
|
||||||
if (!!this.userInfoListSubscription) {
|
if (!!this.userInfoListSubscription) {
|
||||||
this.userInfoListSubscription.unsubscribe();
|
this.userInfoListSubscription.unsubscribe();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
clearInterval(this.interval);
|
||||||
}
|
}
|
||||||
|
|
||||||
ngAfterViewChecked(): void {
|
ngAfterViewChecked(): void {
|
||||||
|
@ -230,7 +256,7 @@ export class MessagesComponent implements OnInit, OnDestroy, AfterViewChecked {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (message.trim().length > Maximum_Range.MassText) {
|
if (message.trim().length > CONST.MASSTEXT_LEN) {
|
||||||
// MASS TEXT
|
// MASS TEXT
|
||||||
this.store.dispatch(
|
this.store.dispatch(
|
||||||
EventStore.sendMass({
|
EventStore.sendMass({
|
||||||
|
@ -261,6 +287,22 @@ export class MessagesComponent implements OnInit, OnDestroy, AfterViewChecked {
|
||||||
this.store.dispatch(RoomStore.updateOnlyAlarm({ roomInfo: this.roomInfo }));
|
this.store.dispatch(RoomStore.updateOnlyAlarm({ roomInfo: this.roomInfo }));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onScrollup(event: any) {
|
||||||
|
this.onMoreEvent(this.baseEventSeq);
|
||||||
|
}
|
||||||
|
/** More Event */
|
||||||
|
onMoreEvent(seq: number) {
|
||||||
|
if (this.eventRemain) {
|
||||||
|
this.store.dispatch(
|
||||||
|
EventStore.info({
|
||||||
|
roomSeq: this.roomInfo.roomSeq,
|
||||||
|
baseSeq: seq,
|
||||||
|
requestCount: CONST.EVENT_INFO_READ_COUNT
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** MassText Detail View */
|
/** MassText Detail View */
|
||||||
onMassDetail(value: number) {
|
onMassDetail(value: number) {
|
||||||
this.store.dispatch(
|
this.store.dispatch(
|
||||||
|
|
|
@ -55,6 +55,7 @@
|
||||||
[selectedUserList]="selectedUserList"
|
[selectedUserList]="selectedUserList"
|
||||||
[checkable]="true"
|
[checkable]="true"
|
||||||
(checkGroup)="onCheckGroup($event)"
|
(checkGroup)="onCheckGroup($event)"
|
||||||
|
class="group-expansion"
|
||||||
>
|
>
|
||||||
<ucap-profile-user-list-item
|
<ucap-profile-user-list-item
|
||||||
*ucapGroupExpansionPanelItem="let userInfo"
|
*ucapGroupExpansionPanelItem="let userInfo"
|
||||||
|
@ -68,11 +69,11 @@
|
||||||
</ucap-profile-user-list-item>
|
</ucap-profile-user-list-item>
|
||||||
</ucap-group-expansion-panel>
|
</ucap-group-expansion-panel>
|
||||||
</div>
|
</div>
|
||||||
<div *ngIf="isShowSearch">
|
<div *ngIf="isShowSearch" class="search-result">
|
||||||
<div *ngIf="searchProcessing">
|
<div *ngIf="searchProcessing">
|
||||||
<mat-progress-bar mode="indeterminate"></mat-progress-bar>
|
<mat-progress-bar mode="indeterminate"></mat-progress-bar>
|
||||||
</div>
|
</div>
|
||||||
<div>검색결과({{ searchUserInfos.length }}명)</div>
|
<div class="result-num">검색결과 <span class="text-accent-color">({{ searchUserInfos.length }}명)</span></div>
|
||||||
<ucap-profile-user-list-item
|
<ucap-profile-user-list-item
|
||||||
*ngFor="let userInfo of searchUserInfos"
|
*ngFor="let userInfo of searchUserInfos"
|
||||||
[userInfo]="userInfo"
|
[userInfo]="userInfo"
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//조직도 레이아웃 변경
|
||||||
::ng-deep .dialog-org {
|
::ng-deep .dialog-org {
|
||||||
.oraganization-tab {
|
.oraganization-tab {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
@ -43,7 +44,7 @@
|
||||||
.confirm-card {
|
.confirm-card {
|
||||||
min-width: 500px;
|
min-width: 500px;
|
||||||
.mat-card-header {
|
.mat-card-header {
|
||||||
margin-bottom: 20px;
|
margin-bottom: 10px;
|
||||||
.mat-card-header-text {
|
.mat-card-header-text {
|
||||||
.mat-card-title {
|
.mat-card-title {
|
||||||
margin: 0 -16px;
|
margin: 0 -16px;
|
||||||
|
@ -67,6 +68,11 @@
|
||||||
height: 380px;
|
height: 380px;
|
||||||
}
|
}
|
||||||
.list-panel{
|
.list-panel{
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
height: calc(100% - 60px);
|
height: calc(100% - 60px);
|
||||||
}
|
.group-expansion{
|
||||||
|
.list-item{
|
||||||
|
height:70px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { delGroupSuccess, buddy2 } from './../store/messenger/sync/actions';
|
import { delGroupSuccess, buddy2 } from './../store/messenger/sync/actions';
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable, Inject } from '@angular/core';
|
||||||
|
|
||||||
import { tap, withLatestFrom } from 'rxjs/operators';
|
import { tap, withLatestFrom } from 'rxjs/operators';
|
||||||
|
|
||||||
|
@ -79,6 +79,12 @@ import * as EventStore from '@app/store/messenger/event';
|
||||||
import * as SyncStore from '@app/store/messenger/sync';
|
import * as SyncStore from '@app/store/messenger/sync';
|
||||||
import * as RoomStore from '@app/store/messenger/room';
|
import * as RoomStore from '@app/store/messenger/room';
|
||||||
import * as StatusStore from '@app/store/messenger/status';
|
import * as StatusStore from '@app/store/messenger/status';
|
||||||
|
import {
|
||||||
|
NotiRequest,
|
||||||
|
NativeService,
|
||||||
|
UCAP_NATIVE_SERVICE
|
||||||
|
} from '@ucap-webmessenger/native';
|
||||||
|
import { StringUtil } from '@ucap-webmessenger/core';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class AppNotificationService {
|
export class AppNotificationService {
|
||||||
|
@ -90,6 +96,7 @@ export class AppNotificationService {
|
||||||
private groupProtocolService: GroupProtocolService,
|
private groupProtocolService: GroupProtocolService,
|
||||||
private buddyProtocolService: BuddyProtocolService,
|
private buddyProtocolService: BuddyProtocolService,
|
||||||
private statusProtocolService: StatusProtocolService,
|
private statusProtocolService: StatusProtocolService,
|
||||||
|
@Inject(UCAP_NATIVE_SERVICE) private nativeService: NativeService,
|
||||||
private store: Store<any>,
|
private store: Store<any>,
|
||||||
private logger: NGXLogger
|
private logger: NGXLogger
|
||||||
) {}
|
) {}
|
||||||
|
@ -143,6 +150,22 @@ export class AppNotificationService {
|
||||||
noti
|
noti
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// notification..
|
||||||
|
if (notiOrRes.SSVC_TYPE === SSVC_TYPE_EVENT_SEND_NOTI) {
|
||||||
|
const notiReq: NotiRequest = {
|
||||||
|
roomSeq: noti.roomSeq,
|
||||||
|
title: '메세지가 도착했습니다.',
|
||||||
|
contents: StringUtil.convertFinalEventMessage(
|
||||||
|
noti.eventType,
|
||||||
|
noti.message
|
||||||
|
),
|
||||||
|
image: '',
|
||||||
|
useSound: true,
|
||||||
|
interval: 0
|
||||||
|
};
|
||||||
|
this.nativeService.showNotify(notiReq);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SSVC_TYPE_EVENT_READ_RES:
|
case SSVC_TYPE_EVENT_READ_RES:
|
||||||
|
|
|
@ -29,6 +29,19 @@ export const infoSuccess = createAction(
|
||||||
}>()
|
}>()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
export const infoMoreSuccess = createAction(
|
||||||
|
'[Messenger::Event] Info More Success',
|
||||||
|
props<{
|
||||||
|
infoList: Info[];
|
||||||
|
res: InfoResponse;
|
||||||
|
}>()
|
||||||
|
);
|
||||||
|
|
||||||
|
export const infoIntervalClear = createAction(
|
||||||
|
'[Messenger::Event] Info Interval Clear',
|
||||||
|
props()
|
||||||
|
);
|
||||||
|
|
||||||
export const infoFailure = createAction(
|
export const infoFailure = createAction(
|
||||||
'[Messenger::Event] Info Failure',
|
'[Messenger::Event] Info Failure',
|
||||||
props<{ error: any }>()
|
props<{ error: any }>()
|
||||||
|
@ -174,6 +187,6 @@ export const delNotification = createAction(
|
||||||
export const delInfoList = createAction(
|
export const delInfoList = createAction(
|
||||||
'[Messenger::Event] Delete InfoList',
|
'[Messenger::Event] Delete InfoList',
|
||||||
props<{
|
props<{
|
||||||
eventSeq: number;
|
eventSeqs: number[];
|
||||||
}>()
|
}>()
|
||||||
);
|
);
|
||||||
|
|
|
@ -67,7 +67,9 @@ import {
|
||||||
forwardFailure,
|
forwardFailure,
|
||||||
forwardAfterRoomOpen,
|
forwardAfterRoomOpen,
|
||||||
sendMass,
|
sendMass,
|
||||||
sendMassFailure
|
sendMassFailure,
|
||||||
|
infoMoreSuccess,
|
||||||
|
infoIntervalClear
|
||||||
} from './actions';
|
} from './actions';
|
||||||
import { SessionStorageService } from '@ucap-webmessenger/web-storage';
|
import { SessionStorageService } from '@ucap-webmessenger/web-storage';
|
||||||
import {
|
import {
|
||||||
|
@ -81,6 +83,7 @@ import { openSuccess, openFailure } from '../room';
|
||||||
import { LoginResponse } from '@ucap-webmessenger/protocol-authentication';
|
import { LoginResponse } from '@ucap-webmessenger/protocol-authentication';
|
||||||
import { KEY_LOGIN_RES_INFO } from '@app/types/login-res-info.type';
|
import { KEY_LOGIN_RES_INFO } from '@app/types/login-res-info.type';
|
||||||
import { StatusCode } from '@ucap-webmessenger/api';
|
import { StatusCode } from '@ucap-webmessenger/api';
|
||||||
|
import { CONST } from '@ucap-webmessenger/core';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class Effects {
|
export class Effects {
|
||||||
|
@ -91,7 +94,7 @@ export class Effects {
|
||||||
return info({
|
return info({
|
||||||
roomSeq: action.roomSeq,
|
roomSeq: action.roomSeq,
|
||||||
baseSeq: 0,
|
baseSeq: 0,
|
||||||
requestCount: 50
|
requestCount: CONST.EVENT_INFO_READ_COUNT
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
@ -115,12 +118,21 @@ export class Effects {
|
||||||
break;
|
break;
|
||||||
case SSVC_TYPE_EVENT_INFO_RES:
|
case SSVC_TYPE_EVENT_INFO_RES:
|
||||||
{
|
{
|
||||||
this.store.dispatch(
|
if (req.baseSeq === 0) {
|
||||||
infoSuccess({
|
this.store.dispatch(
|
||||||
infoList,
|
infoSuccess({
|
||||||
res: res as InfoResponse
|
infoList,
|
||||||
})
|
res: res as InfoResponse
|
||||||
);
|
})
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
this.store.dispatch(
|
||||||
|
infoMoreSuccess({
|
||||||
|
infoList,
|
||||||
|
res: res as InfoResponse
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
if (req.baseSeq === 0) {
|
if (req.baseSeq === 0) {
|
||||||
// 최초 이벤트 목록 조회시 SSVC_TYPE_EVENT_READ_REQ 수행.
|
// 최초 이벤트 목록 조회시 SSVC_TYPE_EVENT_READ_REQ 수행.
|
||||||
|
@ -147,6 +159,45 @@ export class Effects {
|
||||||
{ dispatch: false }
|
{ dispatch: false }
|
||||||
);
|
);
|
||||||
|
|
||||||
|
infoIntervalClear$ = createEffect(
|
||||||
|
() => {
|
||||||
|
return this.actions$.pipe(
|
||||||
|
ofType(infoIntervalClear),
|
||||||
|
withLatestFrom(
|
||||||
|
this.store.pipe(
|
||||||
|
select((state: any) => state.messenger.room.roomInfo as RoomInfo)
|
||||||
|
),
|
||||||
|
this.store.pipe(
|
||||||
|
select(
|
||||||
|
(state: any) =>
|
||||||
|
state.messenger.event.infoList.entities as Dictionary<Info>
|
||||||
|
)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
map(([action, roomInfo, eventList]) => {
|
||||||
|
if (roomInfo.isTimeRoom && roomInfo.timeRoomInterval > 0) {
|
||||||
|
const delEventSeq: number[] = [];
|
||||||
|
// tslint:disable-next-line: forin
|
||||||
|
for (const key in eventList) {
|
||||||
|
const event: Info = eventList[key];
|
||||||
|
if (
|
||||||
|
new Date().getTime() - new Date(event.sendDate).getTime() >=
|
||||||
|
roomInfo.timeRoomInterval * 1000
|
||||||
|
) {
|
||||||
|
delEventSeq.push(event.seq);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (delEventSeq.length > 0) {
|
||||||
|
this.store.dispatch(delInfoList({ eventSeqs: delEventSeq }));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
|
},
|
||||||
|
{ dispatch: false }
|
||||||
|
);
|
||||||
|
|
||||||
read$ = createEffect(() =>
|
read$ = createEffect(() =>
|
||||||
this.actions$.pipe(
|
this.actions$.pipe(
|
||||||
ofType(read),
|
ofType(read),
|
||||||
|
@ -522,7 +573,7 @@ export class Effects {
|
||||||
tap(([noti, roomInfo]) => {
|
tap(([noti, roomInfo]) => {
|
||||||
// 현재 방이 오픈되어 있으면 방내용 갱신
|
// 현재 방이 오픈되어 있으면 방내용 갱신
|
||||||
if (!!roomInfo && roomInfo.roomSeq === noti.roomSeq) {
|
if (!!roomInfo && roomInfo.roomSeq === noti.roomSeq) {
|
||||||
this.store.dispatch(delInfoList({ eventSeq: noti.eventSeq }));
|
this.store.dispatch(delInfoList({ eventSeqs: [noti.eventSeq] }));
|
||||||
}
|
}
|
||||||
|
|
||||||
// 대화 > 리스트의 항목 갱신
|
// 대화 > 리스트의 항목 갱신
|
||||||
|
|
|
@ -6,10 +6,12 @@ import {
|
||||||
info,
|
info,
|
||||||
infoFailure,
|
infoFailure,
|
||||||
recallInfoList,
|
recallInfoList,
|
||||||
delInfoList
|
delInfoList,
|
||||||
|
infoMoreSuccess
|
||||||
} from './actions';
|
} from './actions';
|
||||||
import * as AuthenticationStore from '@app/store/account/authentication';
|
import * as AuthenticationStore from '@app/store/account/authentication';
|
||||||
import { Info, EventType } from '@ucap-webmessenger/protocol-event';
|
import { Info, EventType } from '@ucap-webmessenger/protocol-event';
|
||||||
|
import { CONST } from '@ucap-webmessenger/core';
|
||||||
|
|
||||||
export const reducer = createReducer(
|
export const reducer = createReducer(
|
||||||
initialState,
|
initialState,
|
||||||
|
@ -27,7 +29,27 @@ export const reducer = createReducer(
|
||||||
...state.infoList
|
...state.infoList
|
||||||
}),
|
}),
|
||||||
infoStatus: action.res,
|
infoStatus: action.res,
|
||||||
infoListProcessing: false
|
infoListProcessing: false,
|
||||||
|
remainInfo:
|
||||||
|
!!action.infoList &&
|
||||||
|
action.infoList.length === CONST.EVENT_INFO_READ_COUNT
|
||||||
|
? true
|
||||||
|
: false
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
on(infoMoreSuccess, (state, action) => {
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
infoList: adapterInfoList.upsertMany(action.infoList, {
|
||||||
|
...state.infoList
|
||||||
|
}),
|
||||||
|
infoStatus: action.res,
|
||||||
|
infoListProcessing: false,
|
||||||
|
remainInfo:
|
||||||
|
!!action.infoList &&
|
||||||
|
action.infoList.length === CONST.EVENT_INFO_READ_COUNT
|
||||||
|
? true
|
||||||
|
: false
|
||||||
};
|
};
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
@ -75,11 +97,11 @@ export const reducer = createReducer(
|
||||||
}),
|
}),
|
||||||
|
|
||||||
on(delInfoList, (state, action) => {
|
on(delInfoList, (state, action) => {
|
||||||
const eventSeq = action.eventSeq;
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
infoList: adapterInfoList.removeOne(eventSeq, { ...state.infoList })
|
infoList: adapterInfoList.removeMany(action.eventSeqs, {
|
||||||
|
...state.infoList
|
||||||
|
})
|
||||||
};
|
};
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@ export interface State {
|
||||||
infoListProcessing: boolean;
|
infoListProcessing: boolean;
|
||||||
infoList: InfoListState;
|
infoList: InfoListState;
|
||||||
infoStatus: InfoResponse | null;
|
infoStatus: InfoResponse | null;
|
||||||
|
remainInfo: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const adapterInfoList = createEntityAdapter<Info>({
|
export const adapterInfoList = createEntityAdapter<Info>({
|
||||||
|
@ -22,7 +23,8 @@ const infoListInitialState: InfoListState = adapterInfoList.getInitialState({});
|
||||||
export const initialState: State = {
|
export const initialState: State = {
|
||||||
infoListProcessing: false,
|
infoListProcessing: false,
|
||||||
infoList: infoListInitialState,
|
infoList: infoListInitialState,
|
||||||
infoStatus: null
|
infoStatus: null,
|
||||||
|
remainInfo: false
|
||||||
};
|
};
|
||||||
|
|
||||||
const {
|
const {
|
||||||
|
@ -43,6 +45,10 @@ export function selectors<S>(selector: Selector<any, State>) {
|
||||||
selector,
|
selector,
|
||||||
(state: State) => state.infoListProcessing
|
(state: State) => state.infoListProcessing
|
||||||
),
|
),
|
||||||
|
remainInfo: createSelector(
|
||||||
|
selector,
|
||||||
|
(state: State) => state.remainInfo
|
||||||
|
),
|
||||||
infoList: createSelector(
|
infoList: createSelector(
|
||||||
selector,
|
selector,
|
||||||
(state: State) => state.infoList
|
(state: State) => state.infoList
|
||||||
|
|
|
@ -101,6 +101,7 @@ import {
|
||||||
|
|
||||||
import * as ChatStore from '@app/store/messenger/chat';
|
import * as ChatStore from '@app/store/messenger/chat';
|
||||||
import * as RoomStore from '@app/store/messenger/room';
|
import * as RoomStore from '@app/store/messenger/room';
|
||||||
|
import { CONST } from '@ucap-webmessenger/core';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class Effects {
|
export class Effects {
|
||||||
|
@ -405,7 +406,7 @@ export class Effects {
|
||||||
divCd: 'DivCodeT',
|
divCd: 'DivCodeT',
|
||||||
roomName: '',
|
roomName: '',
|
||||||
isTimerRoom: true,
|
isTimerRoom: true,
|
||||||
timerRoomInterval: 24 * 60 * 60, // 24h default
|
timerRoomInterval: CONST.DEFAULT_TIMER_ROOM_INTERVAL, // 24h default
|
||||||
userSeqs: userSeqList
|
userSeqs: userSeqList
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
import { JsonObject } from 'type-fest';
|
|
||||||
import { createReducer, on } from '@ngrx/store';
|
import { createReducer, on } from '@ngrx/store';
|
||||||
import {
|
import {
|
||||||
initialState,
|
initialState,
|
||||||
|
@ -29,9 +28,7 @@ import {
|
||||||
|
|
||||||
import * as RoomStore from '@app/store/messenger/room';
|
import * as RoomStore from '@app/store/messenger/room';
|
||||||
import { RoomInfo } from '@ucap-webmessenger/protocol-room';
|
import { RoomInfo } from '@ucap-webmessenger/protocol-room';
|
||||||
import { EventType } from '@ucap-webmessenger/protocol-event';
|
import { StringUtil } from '@ucap-webmessenger/core';
|
||||||
import { FileType } from '@ucap-webmessenger/protocol-file';
|
|
||||||
import { JsonAnalization } from '@ucap-webmessenger/api';
|
|
||||||
|
|
||||||
export const reducer = createReducer(
|
export const reducer = createReducer(
|
||||||
initialState,
|
initialState,
|
||||||
|
@ -103,63 +100,36 @@ export const reducer = createReducer(
|
||||||
}),
|
}),
|
||||||
|
|
||||||
on(updateRoomForNewEventMessage, (state, action) => {
|
on(updateRoomForNewEventMessage, (state, action) => {
|
||||||
let finalEventMessage: string = action.info.sentMessage;
|
const finalEventMessage:
|
||||||
switch (action.info.type) {
|
| string
|
||||||
case EventType.Join:
|
| null = StringUtil.convertFinalEventMessage(
|
||||||
case EventType.Exit:
|
action.info.type,
|
||||||
case EventType.RenameRoom:
|
action.info.sentMessage
|
||||||
case EventType.NotificationForTimerRoom:
|
);
|
||||||
case EventType.GuideForRoomTimerChanged: {
|
|
||||||
/**
|
|
||||||
* 해당 타입은 메시지를 갱신하지 않는다.
|
|
||||||
* @description Edit with ui-chat > messages.component.ts
|
|
||||||
*/
|
|
||||||
return {
|
|
||||||
...state
|
|
||||||
};
|
|
||||||
}
|
|
||||||
case EventType.Sticker:
|
|
||||||
finalEventMessage = '스티커';
|
|
||||||
break;
|
|
||||||
case EventType.File:
|
|
||||||
{
|
|
||||||
const contentJson = JSON.parse(finalEventMessage);
|
|
||||||
if (contentJson.FileType === FileType.Image) {
|
|
||||||
finalEventMessage = '이미지';
|
|
||||||
} else {
|
|
||||||
finalEventMessage = '첨부파일';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case EventType.VideoConference:
|
|
||||||
finalEventMessage = '화상회의';
|
|
||||||
break;
|
|
||||||
case EventType.MassText:
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
const json: JsonObject | Error = JsonAnalization.receiveAnalization(
|
|
||||||
finalEventMessage
|
|
||||||
);
|
|
||||||
finalEventMessage = json.Content.toString();
|
|
||||||
} catch (e) {
|
|
||||||
finalEventMessage = '대용량 텍스트';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
const roomInfo = {
|
|
||||||
...state.room.entities[action.roomSeq],
|
|
||||||
finalEventDate: action.info.sendDate,
|
|
||||||
finalEventMessage
|
|
||||||
};
|
|
||||||
|
|
||||||
return {
|
if (!finalEventMessage) {
|
||||||
...state,
|
/**
|
||||||
room: adapterRoom.updateOne(
|
* 해당 타입은 메시지를 갱신하지 않는다.
|
||||||
{ id: action.roomSeq, changes: roomInfo },
|
* @description Edit with ui-chat > messages.component.ts
|
||||||
{ ...state.room }
|
*/
|
||||||
)
|
return {
|
||||||
};
|
...state
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
const roomInfo = {
|
||||||
|
...state.room.entities[action.roomSeq],
|
||||||
|
finalEventDate: action.info.sendDate,
|
||||||
|
finalEventMessage
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
room: adapterRoom.updateOne(
|
||||||
|
{ id: action.roomSeq, changes: roomInfo },
|
||||||
|
{ ...state.room }
|
||||||
|
)
|
||||||
|
};
|
||||||
|
}
|
||||||
}),
|
}),
|
||||||
|
|
||||||
on(RoomStore.updateSuccess, (state, action) => {
|
on(RoomStore.updateSuccess, (state, action) => {
|
||||||
|
|
|
@ -97,6 +97,10 @@ $lg-red: (
|
||||||
background: mat-color($accent, 600);
|
background: mat-color($accent, 600);
|
||||||
color: mat-color($primary, default-contrast);
|
color: mat-color($primary, default-contrast);
|
||||||
}
|
}
|
||||||
|
.bg-accent-light {
|
||||||
|
background: mat-color($accent, 300);
|
||||||
|
color: mat-color($primary, default-contrast);
|
||||||
|
}
|
||||||
.bg-accent-color {
|
.bg-accent-color {
|
||||||
background: mat-color($accent);
|
background: mat-color($accent);
|
||||||
color: mat-color($accent, default-contrast);
|
color: mat-color($accent, default-contrast);
|
||||||
|
@ -107,6 +111,9 @@ $lg-red: (
|
||||||
.text-accent-color {
|
.text-accent-color {
|
||||||
color: mat-color($accent);
|
color: mat-color($accent);
|
||||||
}
|
}
|
||||||
|
.text-warn-color{
|
||||||
|
color:mat-color($warn);
|
||||||
|
}
|
||||||
.border-primary-color {
|
.border-primary-color {
|
||||||
border: 1px solid mat-color($primary);
|
border: 1px solid mat-color($primary);
|
||||||
}
|
}
|
||||||
|
|
10
projects/ucap-webmessenger-core/src/lib/types/const.type.ts
Normal file
10
projects/ucap-webmessenger-core/src/lib/types/const.type.ts
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
export enum CONST {
|
||||||
|
/** 대용량 텍스트로 보내는 문자열의 길이 기준 */
|
||||||
|
MASSTEXT_LEN = 800,
|
||||||
|
/** 대화방의 이벤트를 조회하는 개수 */
|
||||||
|
EVENT_INFO_READ_COUNT = 50,
|
||||||
|
/** Timer Room 최초 오픈시 timer interval */
|
||||||
|
DEFAULT_TIMER_ROOM_INTERVAL = 24 * 60 * 60,
|
||||||
|
/** 한번에 채팅을 할 수 있는 인원수 제한 */
|
||||||
|
CHATROOM_USER = 300
|
||||||
|
}
|
|
@ -1,4 +0,0 @@
|
||||||
export enum Maximum_Range {
|
|
||||||
MassText = 800,
|
|
||||||
ChatRoom = 300
|
|
||||||
}
|
|
56
projects/ucap-webmessenger-core/src/lib/utils/string.util.ts
Normal file
56
projects/ucap-webmessenger-core/src/lib/utils/string.util.ts
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
import { EventType } from '@ucap-webmessenger/protocol-event';
|
||||||
|
import { FileType } from '@ucap-webmessenger/protocol-file';
|
||||||
|
import { JsonObject } from 'type-fest';
|
||||||
|
import { JsonAnalization } from '@ucap-webmessenger/api';
|
||||||
|
|
||||||
|
export class StringUtil {
|
||||||
|
public static convertFinalEventMessage(
|
||||||
|
eventType: EventType,
|
||||||
|
finalEventMessage: string
|
||||||
|
): string | null {
|
||||||
|
switch (eventType) {
|
||||||
|
case EventType.Join:
|
||||||
|
case EventType.Exit:
|
||||||
|
case EventType.RenameRoom:
|
||||||
|
case EventType.NotificationForTimerRoom:
|
||||||
|
case EventType.GuideForRoomTimerChanged: {
|
||||||
|
/**
|
||||||
|
* 해당 타입은 메시지를 갱신하지 않는다.
|
||||||
|
* @description Edit with ui-chat > messages.component.ts
|
||||||
|
*/
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
case EventType.Sticker:
|
||||||
|
finalEventMessage = '스티커';
|
||||||
|
break;
|
||||||
|
case EventType.File:
|
||||||
|
{
|
||||||
|
const contentJson = JSON.parse(finalEventMessage);
|
||||||
|
if (contentJson.FileType === FileType.Image) {
|
||||||
|
finalEventMessage = '이미지';
|
||||||
|
} else {
|
||||||
|
finalEventMessage = '첨부파일';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case EventType.VideoConference:
|
||||||
|
finalEventMessage = '화상회의';
|
||||||
|
break;
|
||||||
|
case EventType.MassText:
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
const json: JsonObject | Error = JsonAnalization.receiveAnalization(
|
||||||
|
finalEventMessage
|
||||||
|
);
|
||||||
|
finalEventMessage = json.Content.toString();
|
||||||
|
} catch (e) {
|
||||||
|
finalEventMessage = '대용량 텍스트';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return finalEventMessage;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -7,12 +7,12 @@ export * from './lib/types/call-alarm.type';
|
||||||
export * from './lib/types/call-forward.type';
|
export * from './lib/types/call-forward.type';
|
||||||
export * from './lib/types/call-mode.type';
|
export * from './lib/types/call-mode.type';
|
||||||
export * from './lib/types/caller-type.type';
|
export * from './lib/types/caller-type.type';
|
||||||
|
export * from './lib/types/const.type';
|
||||||
export * from './lib/types/default-screen.type';
|
export * from './lib/types/default-screen.type';
|
||||||
export * from './lib/types/device-devision.type';
|
export * from './lib/types/device-devision.type';
|
||||||
export * from './lib/types/device-type.type';
|
export * from './lib/types/device-type.type';
|
||||||
export * from './lib/types/file-transfer-permissions.type';
|
export * from './lib/types/file-transfer-permissions.type';
|
||||||
export * from './lib/types/locale-code.type';
|
export * from './lib/types/locale-code.type';
|
||||||
export * from './lib/types/maximum-range.type';
|
|
||||||
export * from './lib/types/notification-method.type';
|
export * from './lib/types/notification-method.type';
|
||||||
export * from './lib/types/organization-chart-permissions.type';
|
export * from './lib/types/organization-chart-permissions.type';
|
||||||
export * from './lib/types/push-type.type';
|
export * from './lib/types/push-type.type';
|
||||||
|
@ -20,4 +20,4 @@ export * from './lib/types/status-code.type';
|
||||||
export * from './lib/types/status-type.type';
|
export * from './lib/types/status-type.type';
|
||||||
export * from './lib/types/video-conference-type.type';
|
export * from './lib/types/video-conference-type.type';
|
||||||
|
|
||||||
export * from './lib/types/video-conference-type.type';
|
export * from './lib/utils/string.util';
|
||||||
|
|
|
@ -1,17 +1,15 @@
|
||||||
import { Observable } from 'rxjs';
|
import { Observable } from 'rxjs';
|
||||||
|
|
||||||
import { NativeService, WindowState } from '@ucap-webmessenger/native';
|
import {
|
||||||
|
NativeService,
|
||||||
|
WindowState,
|
||||||
|
NotiRequest
|
||||||
|
} from '@ucap-webmessenger/native';
|
||||||
import { HttpClient } from '@angular/common/http';
|
import { HttpClient } from '@angular/common/http';
|
||||||
import { map } from 'rxjs/operators';
|
import { map } from 'rxjs/operators';
|
||||||
|
|
||||||
export class BrowserNativeService implements NativeService {
|
export class BrowserNativeService implements NativeService {
|
||||||
showNotify(
|
showNotify(noti: NotiRequest): void {}
|
||||||
roomSeq: number,
|
|
||||||
title: string,
|
|
||||||
contents: string,
|
|
||||||
image: string,
|
|
||||||
useSound: boolean
|
|
||||||
): void {}
|
|
||||||
|
|
||||||
checkForUpdates(): Observable<boolean> {
|
checkForUpdates(): Observable<boolean> {
|
||||||
return new Observable<boolean>(subscriber => {
|
return new Observable<boolean>(subscriber => {
|
||||||
|
|
|
@ -2,7 +2,11 @@ import { ipcRenderer, remote, IpcRendererEvent } from 'electron';
|
||||||
|
|
||||||
import { Observable, Subject } from 'rxjs';
|
import { Observable, Subject } from 'rxjs';
|
||||||
|
|
||||||
import { NativeService, WindowState } from '@ucap-webmessenger/native';
|
import {
|
||||||
|
NativeService,
|
||||||
|
WindowState,
|
||||||
|
NotiRequest
|
||||||
|
} from '@ucap-webmessenger/native';
|
||||||
import { Channel } from '../types/channel.type';
|
import { Channel } from '../types/channel.type';
|
||||||
import { share } from 'rxjs/operators';
|
import { share } from 'rxjs/operators';
|
||||||
|
|
||||||
|
@ -10,20 +14,15 @@ export class ElectronNativeService implements NativeService {
|
||||||
private windowStateChangedSubject: Subject<WindowState> | null = null;
|
private windowStateChangedSubject: Subject<WindowState> | null = null;
|
||||||
private windowStateChanged$: Observable<WindowState> | null = null;
|
private windowStateChanged$: Observable<WindowState> | null = null;
|
||||||
|
|
||||||
showNotify(
|
showNotify(noti: NotiRequest): void {
|
||||||
roomSeq: number,
|
|
||||||
title: string,
|
|
||||||
contents: string,
|
|
||||||
image: string,
|
|
||||||
useSound: boolean
|
|
||||||
): void {
|
|
||||||
ipcRenderer.send(
|
ipcRenderer.send(
|
||||||
Channel.showNotify,
|
Channel.showNotify,
|
||||||
roomSeq,
|
noti.roomSeq,
|
||||||
title,
|
noti.title,
|
||||||
contents,
|
noti.contents,
|
||||||
image,
|
noti.image,
|
||||||
useSound
|
noti.useSound,
|
||||||
|
noti.interval
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,13 +3,7 @@ import { Observable } from 'rxjs';
|
||||||
import { WindowState } from '../types/window-state.type';
|
import { WindowState } from '../types/window-state.type';
|
||||||
|
|
||||||
export interface NativeService {
|
export interface NativeService {
|
||||||
showNotify(
|
showNotify(noti: NotiRequest): void;
|
||||||
roomSeq: number,
|
|
||||||
title: string,
|
|
||||||
contents: string,
|
|
||||||
image: string,
|
|
||||||
useSound: boolean
|
|
||||||
): void;
|
|
||||||
|
|
||||||
checkForUpdates(): Observable<boolean>;
|
checkForUpdates(): Observable<boolean>;
|
||||||
|
|
||||||
|
@ -23,3 +17,12 @@ export interface NativeService {
|
||||||
windowMinimize(): void;
|
windowMinimize(): void;
|
||||||
windowMaximize(): void;
|
windowMaximize(): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface NotiRequest {
|
||||||
|
roomSeq: string;
|
||||||
|
title: string;
|
||||||
|
contents: string;
|
||||||
|
image: string;
|
||||||
|
useSound: boolean;
|
||||||
|
interval?: number;
|
||||||
|
}
|
||||||
|
|
|
@ -35,8 +35,6 @@ export interface InfoResponse extends ProtocolResponse {
|
||||||
baseSeq: number;
|
baseSeq: number;
|
||||||
// 유효한파일기준이벤트SEQ(n)
|
// 유효한파일기준이벤트SEQ(n)
|
||||||
validFileBaseSeq: number;
|
validFileBaseSeq: number;
|
||||||
// 이벤트정보 개수(n)
|
|
||||||
count: number;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const encodeInfo: ProtocolEncoder<InfoRequest> = (req: InfoRequest) => {
|
export const encodeInfo: ProtocolEncoder<InfoRequest> = (req: InfoRequest) => {
|
||||||
|
@ -82,7 +80,6 @@ export const decodeInfo: ProtocolDecoder<InfoResponse> = (
|
||||||
return decodeProtocolMessage(message, {
|
return decodeProtocolMessage(message, {
|
||||||
roomSeq: message.bodyList[0],
|
roomSeq: message.bodyList[0],
|
||||||
baseSeq: message.bodyList[1],
|
baseSeq: message.bodyList[1],
|
||||||
validFileBaseSeq: message.bodyList[2],
|
validFileBaseSeq: message.bodyList[2]
|
||||||
count: message.bodyList[3]
|
|
||||||
} as InfoResponse);
|
} as InfoResponse);
|
||||||
};
|
};
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div class="btn-box">
|
<div class="btn-box">
|
||||||
<ul *ngIf="expired">
|
<ul *ngIf="expired" class="expired">
|
||||||
<li>기간이 만료된 파일입니다.</li>
|
<li>기간이 만료된 파일입니다.</li>
|
||||||
</ul>
|
</ul>
|
||||||
<ul *ngIf="!expired && fileInfo && fileInfo.AttSEQ">
|
<ul *ngIf="!expired && fileInfo && fileInfo.AttSEQ">
|
||||||
|
|
|
@ -102,5 +102,14 @@
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
&.expired{
|
||||||
|
li{
|
||||||
|
width:100%;
|
||||||
|
white-space: nowrap;
|
||||||
|
color:#999999;
|
||||||
|
align-items: center;
|
||||||
|
line-height:40px;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,7 @@
|
||||||
<div class="chat-messages">
|
<div class="chat-messages">
|
||||||
|
<!-- <div class="message-row" *ngIf="eventRemain">
|
||||||
|
<button mat-button (click)="onClickMore($event)">이전 대화 보기</button>
|
||||||
|
</div> -->
|
||||||
<!-- MESSAGE -->
|
<!-- MESSAGE -->
|
||||||
<div
|
<div
|
||||||
*ngFor="let message of messages; let i = index"
|
*ngFor="let message of messages; let i = index"
|
||||||
|
@ -34,6 +37,7 @@
|
||||||
<ucap-chat-message-box-information
|
<ucap-chat-message-box-information
|
||||||
*ngSwitchCase="EventType.Exit"
|
*ngSwitchCase="EventType.Exit"
|
||||||
[message]="message"
|
[message]="message"
|
||||||
|
class="information-msg"
|
||||||
>
|
>
|
||||||
</ucap-chat-message-box-information>
|
</ucap-chat-message-box-information>
|
||||||
<ucap-chat-message-box-information
|
<ucap-chat-message-box-information
|
||||||
|
|
|
@ -144,13 +144,13 @@ $meBox-bg: #ffffff;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
background-color: #cccccc;
|
background-color: #dddddd;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
margin: 10px 0;
|
margin: 10px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.message-row {
|
.message-row {
|
||||||
margin-bottom: 30px;
|
margin-bottom: 20px;
|
||||||
.date-splitter {
|
.date-splitter {
|
||||||
display: block;
|
display: block;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
@ -162,6 +162,9 @@ $meBox-bg: #ffffff;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
.profile-img {
|
.profile-img {
|
||||||
flex: 0 0 auto;
|
flex: 0 0 auto;
|
||||||
|
img{
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
&.me {
|
&.me {
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import { CONST } from '@ucap-webmessenger/core';
|
||||||
import {
|
import {
|
||||||
Component,
|
Component,
|
||||||
OnInit,
|
OnInit,
|
||||||
|
@ -32,17 +33,20 @@ export class MessagesComponent implements OnInit {
|
||||||
@Input()
|
@Input()
|
||||||
eventInfoStatus?: InfoResponse;
|
eventInfoStatus?: InfoResponse;
|
||||||
@Input()
|
@Input()
|
||||||
|
eventRemain: boolean;
|
||||||
|
@Input()
|
||||||
userInfos?: UserInfo[];
|
userInfos?: UserInfo[];
|
||||||
@Input()
|
@Input()
|
||||||
sessionVerInfo: VersionInfo2Response;
|
sessionVerInfo: VersionInfo2Response;
|
||||||
|
|
||||||
|
@Output()
|
||||||
|
moreEvent = new EventEmitter<number>();
|
||||||
@Output()
|
@Output()
|
||||||
massDetail = new EventEmitter<number>();
|
massDetail = new EventEmitter<number>();
|
||||||
@Output()
|
@Output()
|
||||||
imageViewer = new EventEmitter<FileInfo>();
|
imageViewer = new EventEmitter<FileInfo>();
|
||||||
@Output()
|
@Output()
|
||||||
save = new EventEmitter<{ fileInfo: FileInfo; type: string }>();
|
save = new EventEmitter<{ fileInfo: FileInfo; type: string }>();
|
||||||
|
|
||||||
@Output()
|
@Output()
|
||||||
contextMenu = new EventEmitter<{
|
contextMenu = new EventEmitter<{
|
||||||
event: MouseEvent;
|
event: MouseEvent;
|
||||||
|
@ -50,6 +54,7 @@ export class MessagesComponent implements OnInit {
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
EventType = EventType;
|
EventType = EventType;
|
||||||
|
CONST = CONST;
|
||||||
profileImageRoot: string;
|
profileImageRoot: string;
|
||||||
|
|
||||||
constructor(private logger: NGXLogger, private datePipe: DatePipe) {}
|
constructor(private logger: NGXLogger, private datePipe: DatePipe) {}
|
||||||
|
@ -138,6 +143,13 @@ export class MessagesComponent implements OnInit {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onClickMore(event: any) {
|
||||||
|
event.preventDefault();
|
||||||
|
event.stopPropagation();
|
||||||
|
|
||||||
|
this.moreEvent.emit(this.messages[0].seq);
|
||||||
|
}
|
||||||
|
|
||||||
/** [Event] MassTalk Detail View */
|
/** [Event] MassTalk Detail View */
|
||||||
onMassDetail(value: number) {
|
onMassDetail(value: number) {
|
||||||
this.massDetail.emit(value);
|
this.massDetail.emit(value);
|
||||||
|
|
|
@ -46,10 +46,10 @@
|
||||||
class="groupExpansionPanel"
|
class="groupExpansionPanel"
|
||||||
>
|
>
|
||||||
<mat-expansion-panel-header>
|
<mat-expansion-panel-header>
|
||||||
<mat-panel-title
|
<mat-panel-title class="panel-title">
|
||||||
>{{ groupBuddy.group.name }}
|
<div class="title-name ellipsis">{{ groupBuddy.group.name }}</div>
|
||||||
<span>({{ groupBuddy.buddyList.length }}명)</span></mat-panel-title
|
<span class="text-accent-color number">({{ groupBuddy.buddyList.length }}명)</span>
|
||||||
>
|
</mat-panel-title>
|
||||||
<mat-panel-description>
|
<mat-panel-description>
|
||||||
<span class="more-spacer"></span>
|
<span class="more-spacer"></span>
|
||||||
<button
|
<button
|
||||||
|
|
|
@ -38,6 +38,18 @@
|
||||||
.mat-content {
|
.mat-content {
|
||||||
color: #666666;
|
color: #666666;
|
||||||
overflow: unset;
|
overflow: unset;
|
||||||
|
.panel-title{
|
||||||
|
display:inline-flex;
|
||||||
|
.title-name{
|
||||||
|
display:inline-flex;
|
||||||
|
flex:1 1 auto;
|
||||||
|
}
|
||||||
|
.number{
|
||||||
|
margin-left:6px;
|
||||||
|
display: inline-flex;
|
||||||
|
flex: 0 0 auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -47,4 +59,10 @@
|
||||||
|
|
||||||
::ng-deep .mat-content{
|
::ng-deep .mat-content{
|
||||||
overflow: unset;
|
overflow: unset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.number{
|
||||||
|
margin-left:6px;
|
||||||
|
display: inline-flex;
|
||||||
|
flex: 0 0 auto;
|
||||||
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
<div class="list-search">
|
<div class="list-search">
|
||||||
<div class="selectbox">
|
<div class="selectbox">
|
||||||
|
<!--<mat-label>회사선택</mat-label>-->
|
||||||
<mat-select [(value)]="companyCode">
|
<mat-select [(value)]="companyCode">
|
||||||
<mat-option
|
<mat-option
|
||||||
*ngFor="let company of companyList"
|
*ngFor="let company of companyList"
|
||||||
|
@ -10,26 +11,25 @@
|
||||||
</mat-select>
|
</mat-select>
|
||||||
</div>
|
</div>
|
||||||
<div class="searchbox">
|
<div class="searchbox">
|
||||||
<input
|
<mat-form-field floatLabel="never" style="width:100%;">
|
||||||
matInput
|
<input
|
||||||
#searchWordInput
|
matInput
|
||||||
placeholder="name"
|
#searchWordInput
|
||||||
(keydown.enter)="onKeyDownEnter(searchWordInput.value)"
|
placeholder="name"
|
||||||
/>
|
(keydown.enter)="onKeyDownEnter(searchWordInput.value)"
|
||||||
<div class="btn-search">
|
/>
|
||||||
<button
|
<button
|
||||||
mat-button
|
mat-button
|
||||||
matSuffix
|
matSuffix
|
||||||
mat-icon-button
|
mat-icon-button
|
||||||
aria-label="cancel"
|
aria-label="Clear"
|
||||||
(click)="searchWordInput.value = ''; onClickCancel()"
|
(click)="searchWordInput.value = ''; onClickCancel()"
|
||||||
>
|
>
|
||||||
<mat-icon>close</mat-icon>
|
<mat-icon>close</mat-icon>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</mat-form-field>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!--검색창만 있는 경우--------------------------------------------------------------------------
|
<!--검색창만 있는 경우--------------------------------------------------------------------------
|
||||||
<div class="list-search">
|
<div class="list-search">
|
||||||
<div class="searchbox">
|
<div class="searchbox">
|
||||||
|
|
|
@ -15,13 +15,19 @@
|
||||||
.list-search {
|
.list-search {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
|
position: relative;
|
||||||
height: 60px;
|
height: 60px;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding: 0 10px 0 20px;
|
padding: 0 10px 0 20px;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
border-bottom: 1px solid #dddddd;
|
border-bottom: 1px solid #dddddd;
|
||||||
|
.selectbox {
|
||||||
|
display: inline-flex;
|
||||||
|
width: 38%;
|
||||||
|
margin-right: 2%;
|
||||||
|
}
|
||||||
.searchbox {
|
.searchbox {
|
||||||
width: 100%;
|
width: 60%;
|
||||||
display: flex;
|
display: flex;
|
||||||
input {
|
input {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
|
|
|
@ -47,14 +47,15 @@
|
||||||
line-height: 20px;
|
line-height: 20px;
|
||||||
margin-right:10px;
|
margin-right:10px;
|
||||||
.mat-icon-rtl-mirror{
|
.mat-icon-rtl-mirror{
|
||||||
border: 1px solid #dddddd;
|
border: 1px solid #dddddd;
|
||||||
padding: 2px;
|
padding: 2px;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
min-width: 14px;
|
min-width: 14px;
|
||||||
min-height: 14px;
|
min-height: 14px;
|
||||||
line-height: 14px;
|
line-height: 14px;
|
||||||
width:20px;
|
width:20px;
|
||||||
height:20px;
|
height:20px;
|
||||||
box-shadow: 0 1px 4px rgba(32, 33, 36, 0.1);
|
box-shadow: 0 2px 1px rgba(48, 48, 48, 0.2);
|
||||||
|
border-radius: 50%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,9 @@
|
||||||
[path]="imagePath"
|
[path]="imagePath"
|
||||||
[default]="defaultPath"
|
[default]="defaultPath"
|
||||||
/>
|
/>
|
||||||
|
<span *ngIf="roomInfo.isTimeRoom" class="text-warn-color badge-timer">
|
||||||
|
<mat-icon>timer</mat-icon>
|
||||||
|
</span>
|
||||||
<!-- <ucap-ui-imaage
|
<!-- <ucap-ui-imaage
|
||||||
[imageClass]="'thumbnail'"
|
[imageClass]="'thumbnail'"
|
||||||
[base]="sessionVerinfo.profileRoot"
|
[base]="sessionVerinfo.profileRoot"
|
||||||
|
@ -20,14 +23,16 @@
|
||||||
<div class="detail">
|
<div class="detail">
|
||||||
<div class="room-name">
|
<div class="room-name">
|
||||||
<div class="name">{{ getRoomName(roomInfo) }}</div>
|
<div class="name">{{ getRoomName(roomInfo) }}</div>
|
||||||
<div class="num" *ngIf="roomInfo.roomType === RoomType.Multi">
|
<div class="num text-accent-color" *ngIf="roomInfo.roomType === RoomType.Multi">
|
||||||
{{ roomInfo.joinUserCount }}명
|
{{ roomInfo.joinUserCount }}명
|
||||||
</div>
|
</div>
|
||||||
<div *ngIf="!checkable && !roomInfo.receiveAlarm">
|
<div *ngIf="!checkable && !roomInfo.receiveAlarm">
|
||||||
<mat-icon>notifications_off</mat-icon>
|
<mat-icon>notifications_off</mat-icon>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="room-msg">{{ finalEventMessage }}</div>
|
<div class="room-msg">
|
||||||
|
{{ finalEventMessage }}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="date">
|
<div class="date">
|
||||||
|
@ -44,9 +49,7 @@
|
||||||
</mat-checkbox>
|
</mat-checkbox>
|
||||||
</dd>
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
<span *ngIf="roomInfo.isTimeRoom">
|
|
||||||
<mat-icon>timer</mat-icon>
|
|
||||||
</span>
|
|
||||||
<span
|
<span
|
||||||
class="notiBadge"
|
class="notiBadge"
|
||||||
*ngIf="roomInfo.noReadCnt > 0"
|
*ngIf="roomInfo.noReadCnt > 0"
|
||||||
|
|
|
@ -3,9 +3,8 @@ $font-dark: #212121;
|
||||||
$font-mid: #666666;
|
$font-mid: #666666;
|
||||||
$font-light: #848d95;
|
$font-light: #848d95;
|
||||||
$font-white: #ffffff;
|
$font-white: #ffffff;
|
||||||
$line-basic:1px solid #dddddd;
|
$line-basic: 1px solid #dddddd;
|
||||||
$bg-list-hover: #efefef;
|
$bg-list-hover: #efefef;
|
||||||
$color-main:#e53096;
|
|
||||||
$listH-row2: 80px;
|
$listH-row2: 80px;
|
||||||
$presence-size: 8px;
|
$presence-size: 8px;
|
||||||
$thumbnail-msize: 40px;
|
$thumbnail-msize: 40px;
|
||||||
|
@ -25,6 +24,23 @@ $thumbnail-msize: 40px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.badge-timer {
|
||||||
|
position:absolute;
|
||||||
|
background-color: #ffffff;
|
||||||
|
width: 18px;
|
||||||
|
height: 18px;
|
||||||
|
border-radius: 50%;
|
||||||
|
bottom: 14px;
|
||||||
|
left: 46px;
|
||||||
|
text-align:center;
|
||||||
|
.mat-icon{
|
||||||
|
font-size:14px;
|
||||||
|
width: 18px;
|
||||||
|
height: 18px;
|
||||||
|
line-height:18px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.profile {
|
.profile {
|
||||||
white-space: normal;
|
white-space: normal;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
|
@ -84,7 +100,7 @@ $thumbnail-msize: 40px;
|
||||||
width: $thumbnail-msize;
|
width: $thumbnail-msize;
|
||||||
height: $thumbnail-msize;
|
height: $thumbnail-msize;
|
||||||
margin-right: 16px;
|
margin-right: 16px;
|
||||||
border-radius:50%;
|
border-radius: 50%;
|
||||||
}
|
}
|
||||||
.info {
|
.info {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
@ -117,9 +133,8 @@ $thumbnail-msize: 40px;
|
||||||
}
|
}
|
||||||
.num {
|
.num {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
color: $color-main;
|
|
||||||
flex: none;
|
flex: none;
|
||||||
margin-left: 10px;
|
margin-left: 6px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.room-msg {
|
.room-msg {
|
||||||
|
@ -155,9 +170,8 @@ $thumbnail-msize: 40px;
|
||||||
padding: 0 6px;
|
padding: 0 6px;
|
||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
color: #ffffff;
|
color: #ffffff;
|
||||||
background-color: $color-main;
|
|
||||||
@include ellipsis(1);
|
@include ellipsis(1);
|
||||||
border-radius:50%;
|
border-radius: 50%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.notiBadge {
|
.notiBadge {
|
||||||
|
|
|
@ -17,4 +17,11 @@
|
||||||
.mat-card-header .mat-card-title{
|
.mat-card-header .mat-card-title{
|
||||||
margin:0 -16px;
|
margin:0 -16px;
|
||||||
padding-bottom:10px;
|
padding-bottom:10px;
|
||||||
|
}
|
||||||
|
.search-result{
|
||||||
|
.result-num{
|
||||||
|
padding:10px;
|
||||||
|
display:flex;
|
||||||
|
height:40px;
|
||||||
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user