Merge branch 'master' of http://10.81.13.221:6990/Web/next-ucap-messenger
This commit is contained in:
commit
fe1ebca2b5
|
@ -2,14 +2,18 @@ import { IntroComponent } from './intro.component';
|
||||||
import { LeftSideComponent } from './left-side.component';
|
import { LeftSideComponent } from './left-side.component';
|
||||||
import { MessagesComponent } from './messages.component';
|
import { MessagesComponent } from './messages.component';
|
||||||
import { RightSideComponent } from './right-side.component';
|
import { RightSideComponent } from './right-side.component';
|
||||||
|
import { RightDrawerComponent } from './right-drawer.component';
|
||||||
|
|
||||||
import { LEFT_SIDENAV_COMPONENTS } from './left-sidenav';
|
import { LEFT_SIDENAV_COMPONENTS } from './left-sidenav';
|
||||||
|
import { RIGHT_DRAWER_COMPONENTS } from './right-drawer';
|
||||||
|
|
||||||
export const COMPONENTS = [
|
export const COMPONENTS = [
|
||||||
IntroComponent,
|
IntroComponent,
|
||||||
LeftSideComponent,
|
LeftSideComponent,
|
||||||
MessagesComponent,
|
MessagesComponent,
|
||||||
RightSideComponent,
|
RightSideComponent,
|
||||||
|
RightDrawerComponent,
|
||||||
|
|
||||||
...LEFT_SIDENAV_COMPONENTS
|
...LEFT_SIDENAV_COMPONENTS,
|
||||||
|
...RIGHT_DRAWER_COMPONENTS
|
||||||
];
|
];
|
||||||
|
|
|
@ -27,7 +27,14 @@
|
||||||
[hasBackdrop]="false"
|
[hasBackdrop]="false"
|
||||||
>
|
>
|
||||||
<button mat-menu-item (click)="onClickGroupMenu('GROUP_NEW')">
|
<button mat-menu-item (click)="onClickGroupMenu('GROUP_NEW')">
|
||||||
<mat-icon>group_add</mat-icon>
|
<!--<mat-icon>group_add</mat-icon>-->
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor"
|
||||||
|
stroke-width="1.5" stroke-linecap="butt" stroke-linejoin="round">
|
||||||
|
<path d="M16 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"></path>
|
||||||
|
<circle cx="8.5" cy="7" r="4"></circle>
|
||||||
|
<line x1="20" y1="8" x2="20" y2="14"></line>
|
||||||
|
<line x1="23" y1="11" x2="17" y2="11"></line>
|
||||||
|
</svg>
|
||||||
<span>새 그룹 추가</span>
|
<span>새 그룹 추가</span>
|
||||||
</button>
|
</button>
|
||||||
<button mat-menu-item (click)="onClickGroupMenu('GROUP_EXPAND_MORE')">
|
<button mat-menu-item (click)="onClickGroupMenu('GROUP_EXPAND_MORE')">
|
||||||
|
|
|
@ -37,3 +37,10 @@
|
||||||
height: 100%;
|
height: 100%;
|
||||||
overflow: unset;
|
overflow: unset;
|
||||||
}
|
}
|
||||||
|
.mat-menu-item{
|
||||||
|
display:flex;
|
||||||
|
align-items: center;
|
||||||
|
svg{
|
||||||
|
margin-right:10px;
|
||||||
|
}
|
||||||
|
}
|
|
@ -11,15 +11,24 @@
|
||||||
class="responsive-chats-button"
|
class="responsive-chats-button"
|
||||||
>
|
>
|
||||||
<!--<mat-icon>chat</mat-icon>-->
|
<!--<mat-icon>chat</mat-icon>-->
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="30" height="30" viewBox="0 0 24 24" fill="currentColor"
|
<svg
|
||||||
stroke-width="1.5" stroke-linecap="butt" stroke-linejoin="round">
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="30"
|
||||||
|
height="30"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="currentColor"
|
||||||
|
stroke-width="1.5"
|
||||||
|
stroke-linecap="butt"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
>
|
||||||
<g>
|
<g>
|
||||||
<path d="M3,21.8c-0.2,0-0.4-0.1-0.5-0.2c-0.2-0.2-0.3-0.5-0.2-0.8l1.8-5.4c-0.6-1.2-0.8-2.5-0.8-3.9c0-3.5,2-6.7,5.1-8.3
|
<path
|
||||||
|
d="M3,21.8c-0.2,0-0.4-0.1-0.5-0.2c-0.2-0.2-0.3-0.5-0.2-0.8l1.8-5.4c-0.6-1.2-0.8-2.5-0.8-3.9c0-3.5,2-6.7,5.1-8.3
|
||||||
c1.3-0.6,2.7-0.9,4.1-1H13c4.7,0.3,8.5,4,8.7,8.7l0,0.5c0,1.4-0.3,2.9-1,4.1c-1.6,3.2-4.7,5.1-8.3,5.1c0,0,0,0,0,0
|
c1.3-0.6,2.7-0.9,4.1-1H13c4.7,0.3,8.5,4,8.7,8.7l0,0.5c0,1.4-0.3,2.9-1,4.1c-1.6,3.2-4.7,5.1-8.3,5.1c0,0,0,0,0,0
|
||||||
c-1.3,0-2.6-0.3-3.8-0.8l-5.4,1.8C3.2,21.7,3.1,21.8,3,21.8z M12.5,3.8C11.3,3.8,10.1,4,9,4.6c-2.6,1.3-4.3,4-4.3,6.9
|
c-1.3,0-2.6-0.3-3.8-0.8l-5.4,1.8C3.2,21.7,3.1,21.8,3,21.8z M12.5,3.8C11.3,3.8,10.1,4,9,4.6c-2.6,1.3-4.3,4-4.3,6.9
|
||||||
c0,1.2,0.3,2.4,0.8,3.5c0.1,0.2,0.1,0.4,0,0.6l-1.4,4.3l4.3-1.4c0.2-0.1,0.4,0,0.6,0c1.1,0.5,2.3,0.8,3.5,0.8c3,0,5.6-1.6,6.9-4.3
|
c0,1.2,0.3,2.4,0.8,3.5c0.1,0.2,0.1,0.4,0,0.6l-1.4,4.3l4.3-1.4c0.2-0.1,0.4,0,0.6,0c1.1,0.5,2.3,0.8,3.5,0.8c3,0,5.6-1.6,6.9-4.3
|
||||||
c0.5-1.1,0.8-2.3,0.8-3.5c0,0,0,0,0,0V11C20,7.1,16.9,4,13,3.7L12.5,3.8C12.5,3.8,12.5,3.8,12.5,3.8z" />
|
c0.5-1.1,0.8-2.3,0.8-3.5c0,0,0,0,0,0V11C20,7.1,16.9,4,13,3.7L12.5,3.8C12.5,3.8,12.5,3.8,12.5,3.8z"
|
||||||
|
/>
|
||||||
</g>
|
</g>
|
||||||
<g>
|
<g>
|
||||||
<circle cx="9" cy="12" r="1" />
|
<circle cx="9" cy="12" r="1" />
|
||||||
|
@ -27,7 +36,6 @@
|
||||||
<circle cx="16" cy="12" r="1" />
|
<circle cx="16" cy="12" r="1" />
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
|
|
||||||
</button>
|
</button>
|
||||||
<!-- / RESPONSIVE CHATS BUTTON-->
|
<!-- / RESPONSIVE CHATS BUTTON-->
|
||||||
<button
|
<button
|
||||||
|
@ -48,7 +56,7 @@
|
||||||
*ngIf="roomInfo && roomInfo.isTimeRoom"
|
*ngIf="roomInfo && roomInfo.isTimeRoom"
|
||||||
class="room-type text-accent-color "
|
class="room-type text-accent-color "
|
||||||
>
|
>
|
||||||
<span class="bg-accent-light"
|
<span class="bg-accent-dark"
|
||||||
>{{ getConvertTimer(roomInfo.timeRoomInterval) }} </span
|
>{{ getConvertTimer(roomInfo.timeRoomInterval) }} </span
|
||||||
>비밀 대화방입니다.
|
>비밀 대화방입니다.
|
||||||
</div>
|
</div>
|
||||||
|
@ -78,9 +86,18 @@
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<mat-menu #contactMenu="matMenu" [hasBackdrop]="false">
|
<mat-menu #contactMenu="matMenu" [hasBackdrop]="false">
|
||||||
|
<button mat-menu-item (click)="onClickContextMenu('OPEN_ALBUM_LIST')">
|
||||||
|
앨범함
|
||||||
|
</button>
|
||||||
|
<button mat-menu-item (click)="onClickContextMenu('OPEN_FILE_LIST')">
|
||||||
|
파일함
|
||||||
|
</button>
|
||||||
<button mat-menu-item (click)="onClickContextMenu('ADD_MEMBER')">
|
<button mat-menu-item (click)="onClickContextMenu('ADD_MEMBER')">
|
||||||
대화상대추가
|
대화상대추가
|
||||||
</button>
|
</button>
|
||||||
|
<button mat-menu-item (click)="onClickContextMenu('ADD_GROUP')">
|
||||||
|
그룹멤버로추가
|
||||||
|
</button>
|
||||||
<button mat-menu-item (click)="onClickContextMenu('EDIT_ROOM')">
|
<button mat-menu-item (click)="onClickContextMenu('EDIT_ROOM')">
|
||||||
대화방설정
|
대화방설정
|
||||||
</button>
|
</button>
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
.chat-toolbar {
|
.chat-toolbar {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 80px;
|
height: 80px;
|
||||||
min-height: 70px;
|
min-height: 80px;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
background-color: #ffffff !important;
|
background-color: #ffffff !important;
|
||||||
border-bottom: 1px solid #dddddd;
|
border-bottom: 1px solid #dddddd;
|
||||||
|
@ -68,7 +68,7 @@
|
||||||
height: 20px;
|
height: 20px;
|
||||||
span {
|
span {
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
padding: 1px 10px;
|
padding: 2px 10px;
|
||||||
margin-right: 6px;
|
margin-right: 6px;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,12 +40,14 @@ import * as AppStore from '@app/store';
|
||||||
import * as EventStore from '@app/store/messenger/event';
|
import * as EventStore from '@app/store/messenger/event';
|
||||||
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 * as SyncStore from '@app/store/messenger/sync';
|
||||||
import { LoginResponse } from '@ucap-webmessenger/protocol-authentication';
|
import { LoginResponse } from '@ucap-webmessenger/protocol-authentication';
|
||||||
import { SessionStorageService } from '@ucap-webmessenger/web-storage';
|
import { SessionStorageService } from '@ucap-webmessenger/web-storage';
|
||||||
import {
|
import {
|
||||||
EnvironmentsInfo,
|
EnvironmentsInfo,
|
||||||
KEY_ENVIRONMENTS_INFO,
|
KEY_ENVIRONMENTS_INFO,
|
||||||
UserSelectDialogType
|
UserSelectDialogType,
|
||||||
|
RightDrawer
|
||||||
} from '@app/types';
|
} from '@app/types';
|
||||||
import { RoomInfo, UserInfo, RoomType } from '@ucap-webmessenger/protocol-room';
|
import { RoomInfo, UserInfo, RoomType } from '@ucap-webmessenger/protocol-room';
|
||||||
import { tap, take, map, catchError } from 'rxjs/operators';
|
import { tap, take, map, catchError } from 'rxjs/operators';
|
||||||
|
@ -84,6 +86,12 @@ import {
|
||||||
EditChatRoomDialogResult,
|
EditChatRoomDialogResult,
|
||||||
EditChatRoomDialogData
|
EditChatRoomDialogData
|
||||||
} from '../dialogs/chat/edit-chat-room.dialog.component';
|
} from '../dialogs/chat/edit-chat-room.dialog.component';
|
||||||
|
import {
|
||||||
|
SelectGroupDialogComponent,
|
||||||
|
SelectGroupDialogResult,
|
||||||
|
SelectGroupDialogData
|
||||||
|
} from '../dialogs/group/select-group.dialog.component';
|
||||||
|
import { GroupDetailData } from '@ucap-webmessenger/protocol-sync';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-layout-messenger-messages',
|
selector: 'app-layout-messenger-messages',
|
||||||
|
@ -794,6 +802,24 @@ export class MessagesComponent implements OnInit, OnDestroy, AfterViewInit {
|
||||||
|
|
||||||
async onClickContextMenu(menuType: string) {
|
async onClickContextMenu(menuType: string) {
|
||||||
switch (menuType) {
|
switch (menuType) {
|
||||||
|
case 'OPEN_ALBUM_LIST':
|
||||||
|
{
|
||||||
|
this.store.dispatch(
|
||||||
|
ChatStore.selectedRightDrawer({
|
||||||
|
req: RightDrawer.AlbumBox
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'OPEN_FILE_LIST':
|
||||||
|
{
|
||||||
|
this.store.dispatch(
|
||||||
|
ChatStore.selectedRightDrawer({
|
||||||
|
req: RightDrawer.FileBox
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
break;
|
||||||
case 'ADD_MEMBER':
|
case 'ADD_MEMBER':
|
||||||
{
|
{
|
||||||
const result = await this.dialogService.open<
|
const result = await this.dialogService.open<
|
||||||
|
@ -838,6 +864,40 @@ export class MessagesComponent implements OnInit, OnDestroy, AfterViewInit {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case 'ADD_GROUP':
|
||||||
|
{
|
||||||
|
const result = await this.dialogService.open<
|
||||||
|
SelectGroupDialogComponent,
|
||||||
|
SelectGroupDialogData,
|
||||||
|
SelectGroupDialogResult
|
||||||
|
>(SelectGroupDialogComponent, {
|
||||||
|
width: '600px',
|
||||||
|
data: {
|
||||||
|
title: 'Group Select'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
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.userInfoList
|
||||||
|
.filter(v => result.group.userSeqs.indexOf(v.seq) < 0)
|
||||||
|
.forEach(user => {
|
||||||
|
trgtUserSeq.push(user.seq);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.store.dispatch(
|
||||||
|
SyncStore.updateGroupMember({
|
||||||
|
oldGroup,
|
||||||
|
trgtUserSeq
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
case 'EDIT_ROOM':
|
case 'EDIT_ROOM':
|
||||||
{
|
{
|
||||||
const result = await this.dialogService.open<
|
const result = await this.dialogService.open<
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
<ng-container *ngIf="selectedRightDrawer" [ngSwitch]="selectedRightDrawer">
|
||||||
|
<app-layout-chat-right-drawer-file-box *ngSwitchCase="RightDrawer.FileBox">
|
||||||
|
</app-layout-chat-right-drawer-file-box>
|
||||||
|
|
||||||
|
<app-layout-chat-right-drawer-album-box *ngSwitchCase="RightDrawer.AlbumBox">
|
||||||
|
</app-layout-chat-right-drawer-album-box>
|
||||||
|
</ng-container>
|
|
@ -0,0 +1,25 @@
|
||||||
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { RightDrawerComponent } from './right-drawer.component';
|
||||||
|
|
||||||
|
describe('RightDrawerComponent', () => {
|
||||||
|
let component: RightDrawerComponent;
|
||||||
|
let fixture: ComponentFixture<RightDrawerComponent>;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [ RightDrawerComponent ]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(RightDrawerComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,18 @@
|
||||||
|
import { Component, OnInit, Input } from '@angular/core';
|
||||||
|
import { RightDrawer } from '@app/types';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-layout-messenger-right-drawer',
|
||||||
|
templateUrl: './right-drawer.component.html',
|
||||||
|
styleUrls: ['./right-drawer.component.scss']
|
||||||
|
})
|
||||||
|
export class RightDrawerComponent implements OnInit {
|
||||||
|
@Input()
|
||||||
|
selectedRightDrawer: RightDrawer;
|
||||||
|
|
||||||
|
RightDrawer = RightDrawer;
|
||||||
|
|
||||||
|
constructor() {}
|
||||||
|
|
||||||
|
ngOnInit() {}
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
<p>album-box works!</p>
|
|
@ -0,0 +1,25 @@
|
||||||
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { AlbumBoxComponent } from './album-box.component';
|
||||||
|
|
||||||
|
describe('AlbumBoxComponent', () => {
|
||||||
|
let component: AlbumBoxComponent;
|
||||||
|
let fixture: ComponentFixture<AlbumBoxComponent>;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [ AlbumBoxComponent ]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(AlbumBoxComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,12 @@
|
||||||
|
import { Component, OnInit } from '@angular/core';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-layout-chat-right-drawer-album-box',
|
||||||
|
templateUrl: './album-box.component.html',
|
||||||
|
styleUrls: ['./album-box.component.scss']
|
||||||
|
})
|
||||||
|
export class AlbumBoxComponent implements OnInit {
|
||||||
|
constructor() {}
|
||||||
|
|
||||||
|
ngOnInit() {}
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
<p>file-box works!</p>
|
|
@ -0,0 +1,25 @@
|
||||||
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { FileBoxComponent } from './file-box.component';
|
||||||
|
|
||||||
|
describe('FileBoxComponent', () => {
|
||||||
|
let component: FileBoxComponent;
|
||||||
|
let fixture: ComponentFixture<FileBoxComponent>;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [ FileBoxComponent ]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(FileBoxComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,12 @@
|
||||||
|
import { Component, OnInit } from '@angular/core';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-layout-chat-right-drawer-file-box',
|
||||||
|
templateUrl: './file-box.component.html',
|
||||||
|
styleUrls: ['./file-box.component.scss']
|
||||||
|
})
|
||||||
|
export class FileBoxComponent implements OnInit {
|
||||||
|
constructor() {}
|
||||||
|
|
||||||
|
ngOnInit() {}
|
||||||
|
}
|
|
@ -0,0 +1,4 @@
|
||||||
|
import { FileBoxComponent } from './file-box.component';
|
||||||
|
import { AlbumBoxComponent } from './album-box.component';
|
||||||
|
|
||||||
|
export const RIGHT_DRAWER_COMPONENTS = [FileBoxComponent, AlbumBoxComponent];
|
|
@ -76,3 +76,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.mat-tab-group>.mat-tab-header .mat-tab-label{
|
||||||
|
border-bottom:2px solid #dddddd;
|
||||||
|
}
|
|
@ -5,12 +5,11 @@
|
||||||
></app-layout-messenger-left-side>
|
></app-layout-messenger-left-side>
|
||||||
</div>
|
</div>
|
||||||
<mat-drawer-container class="contents" autosize>
|
<mat-drawer-container class="contents" autosize>
|
||||||
<mat-drawer #drawer mode="over">
|
<!-- <mat-drawer #drawer mode="over">
|
||||||
<p>Auto-resizing sidenav</p>
|
<p>Auto-resizing sidenav</p>
|
||||||
</mat-drawer>
|
</mat-drawer> -->
|
||||||
<div class="messages">
|
<div class="messages">
|
||||||
<app-layout-messenger-intro
|
<app-layout-messenger-intro
|
||||||
(click)="drawer.toggle()"
|
|
||||||
*ngIf="!(this.selectedChat$ | async)"
|
*ngIf="!(this.selectedChat$ | async)"
|
||||||
></app-layout-messenger-intro>
|
></app-layout-messenger-intro>
|
||||||
<!-- <app-layout-messenger-intro
|
<!-- <app-layout-messenger-intro
|
||||||
|
@ -21,9 +20,17 @@
|
||||||
(openProfile)="onClickOpenProfile($event)"
|
(openProfile)="onClickOpenProfile($event)"
|
||||||
></app-layout-messenger-messages>
|
></app-layout-messenger-messages>
|
||||||
</div>
|
</div>
|
||||||
<!-- <mat-drawer #drawer mode="side" position="end">
|
<mat-drawer
|
||||||
<p>Auto-resizing sidenav</p>
|
#rightDrawer
|
||||||
</mat-drawer> -->
|
mode="side"
|
||||||
|
position="end"
|
||||||
|
(openedChange)="onOpenedChange($event)"
|
||||||
|
>
|
||||||
|
<app-layout-messenger-right-drawer
|
||||||
|
[selectedRightDrawer]="selectedRightDrawer$ | async"
|
||||||
|
>
|
||||||
|
</app-layout-messenger-right-drawer>
|
||||||
|
</mat-drawer>
|
||||||
</mat-drawer-container>
|
</mat-drawer-container>
|
||||||
|
|
||||||
<!-- <div class="right-side">
|
<!-- <div class="right-side">
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
import { map, tap } from 'rxjs/operators';
|
import { map, tap } from 'rxjs/operators';
|
||||||
import { Component, OnInit, Inject, OnDestroy } from '@angular/core';
|
import { Component, OnInit, Inject, OnDestroy, ViewChild } from '@angular/core';
|
||||||
|
|
||||||
import { Store, select } from '@ngrx/store';
|
import { Store, select } from '@ngrx/store';
|
||||||
|
|
||||||
import * as AppSotre from '@app/store';
|
import * as AppSotre from '@app/store';
|
||||||
|
import * as ChatStore from '@app/store/messenger/chat';
|
||||||
import { Observable, Subscription } from 'rxjs';
|
import { Observable, Subscription } from 'rxjs';
|
||||||
import {
|
import {
|
||||||
WindowIdle,
|
WindowIdle,
|
||||||
|
@ -25,6 +26,7 @@ import {
|
||||||
ProfileDialogData,
|
ProfileDialogData,
|
||||||
ProfileDialogResult
|
ProfileDialogResult
|
||||||
} from '@app/layouts/messenger/dialogs/profile/profile.dialog.component';
|
} from '@app/layouts/messenger/dialogs/profile/profile.dialog.component';
|
||||||
|
import { MatSidenav, MatDrawer } from '@angular/material';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-page-messenger-main',
|
selector: 'app-page-messenger-main',
|
||||||
|
@ -33,8 +35,11 @@ import {
|
||||||
})
|
})
|
||||||
export class MainPageComponent implements OnInit {
|
export class MainPageComponent implements OnInit {
|
||||||
selectedChat$: Observable<string | null>;
|
selectedChat$: Observable<string | null>;
|
||||||
|
selectedRightDrawer$: Observable<string | null>;
|
||||||
idleStateChangedSubscription: Subscription;
|
idleStateChangedSubscription: Subscription;
|
||||||
|
|
||||||
|
@ViewChild('rightDrawer', { static: true }) rightDrawer: MatDrawer;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@Inject(UCAP_NATIVE_SERVICE) private nativeService: NativeService,
|
@Inject(UCAP_NATIVE_SERVICE) private nativeService: NativeService,
|
||||||
private store: Store<any>,
|
private store: Store<any>,
|
||||||
|
@ -44,7 +49,23 @@ export class MainPageComponent implements OnInit {
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.selectedChat$ = this.store.pipe(
|
this.selectedChat$ = this.store.pipe(
|
||||||
select(AppSotre.MessengerSelector.ChatSelector.selectedRoom)
|
select(AppSotre.MessengerSelector.ChatSelector.selectedRoom),
|
||||||
|
tap(selectedRoom => {
|
||||||
|
if (!selectedRoom) {
|
||||||
|
this.rightDrawer.close();
|
||||||
|
}
|
||||||
|
return selectedRoom;
|
||||||
|
})
|
||||||
|
);
|
||||||
|
this.selectedRightDrawer$ = this.store.pipe(
|
||||||
|
select(AppSotre.MessengerSelector.ChatSelector.selectedRightDrawer),
|
||||||
|
tap(selectedRightDrawer => {
|
||||||
|
if (!!selectedRightDrawer) {
|
||||||
|
this.rightDrawer.open();
|
||||||
|
} else {
|
||||||
|
this.rightDrawer.close();
|
||||||
|
}
|
||||||
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
this.idleStateChangedSubscription = this.nativeService
|
this.idleStateChangedSubscription = this.nativeService
|
||||||
|
@ -75,6 +96,16 @@ export class MainPageComponent implements OnInit {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onOpenedChange(event: boolean) {
|
||||||
|
if (!event) {
|
||||||
|
this.store.dispatch(
|
||||||
|
ChatStore.selectedRightDrawer({
|
||||||
|
req: null
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
onClickOpenProfile(userInfo: UserInfo | UserInfoSS | UserInfoF | UserInfoDN) {
|
onClickOpenProfile(userInfo: UserInfo | UserInfoSS | UserInfoF | UserInfoDN) {
|
||||||
this.dialogService.open<
|
this.dialogService.open<
|
||||||
ProfileDialogComponent,
|
ProfileDialogComponent,
|
||||||
|
|
|
@ -4,6 +4,7 @@ import {
|
||||||
MassTalkDownloadRequest,
|
MassTalkDownloadRequest,
|
||||||
MassTalkDownloadResponse
|
MassTalkDownloadResponse
|
||||||
} from '@ucap-webmessenger/api-common';
|
} from '@ucap-webmessenger/api-common';
|
||||||
|
import { RightDrawer } from '@app/types';
|
||||||
|
|
||||||
export const selectedRoom = createAction(
|
export const selectedRoom = createAction(
|
||||||
'[Messenger::Chat] selectedRoom',
|
'[Messenger::Chat] selectedRoom',
|
||||||
|
@ -43,3 +44,12 @@ export const openRoom = createAction(
|
||||||
'[Messenger::Chat] Open Room',
|
'[Messenger::Chat] Open Room',
|
||||||
props<{ userSeqList: number[]; isTimeRoom?: boolean }>()
|
props<{ userSeqList: number[]; isTimeRoom?: boolean }>()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
export const selectedRightDrawer = createAction(
|
||||||
|
'[Messenger::Chat] Selected Right Drawer',
|
||||||
|
props<{ req: RightDrawer }>()
|
||||||
|
);
|
||||||
|
export const clearRightDrawer = createAction(
|
||||||
|
'[Messenger::Chat] Clear Right Drawer',
|
||||||
|
props()
|
||||||
|
);
|
||||||
|
|
|
@ -10,7 +10,8 @@ import {
|
||||||
selectedMassDetail,
|
selectedMassDetail,
|
||||||
massTalkDownload,
|
massTalkDownload,
|
||||||
massTalkDownloadFailure,
|
massTalkDownloadFailure,
|
||||||
massTalkDownloadSuccess
|
massTalkDownloadSuccess,
|
||||||
|
clearSelectedRoom
|
||||||
} from './actions';
|
} from './actions';
|
||||||
import { of } from 'rxjs';
|
import { of } from 'rxjs';
|
||||||
import { SessionStorageService } from '@ucap-webmessenger/web-storage';
|
import { SessionStorageService } from '@ucap-webmessenger/web-storage';
|
||||||
|
@ -24,6 +25,7 @@ import {
|
||||||
AlertDialogComponent,
|
AlertDialogComponent,
|
||||||
AlertDialogData
|
AlertDialogData
|
||||||
} from '@ucap-webmessenger/ui';
|
} from '@ucap-webmessenger/ui';
|
||||||
|
import { initialState } from '../event';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class Effects {
|
export class Effects {
|
||||||
|
|
|
@ -6,7 +6,9 @@ import {
|
||||||
massTalkDownloadFailure,
|
massTalkDownloadFailure,
|
||||||
massTalkDownload,
|
massTalkDownload,
|
||||||
massTalkDownloadSuccess,
|
massTalkDownloadSuccess,
|
||||||
clearSelectedRoom
|
clearSelectedRoom,
|
||||||
|
selectedRightDrawer,
|
||||||
|
clearRightDrawer
|
||||||
} from './actions';
|
} from './actions';
|
||||||
|
|
||||||
export const reducer = createReducer(
|
export const reducer = createReducer(
|
||||||
|
@ -49,5 +51,18 @@ export const reducer = createReducer(
|
||||||
...state,
|
...state,
|
||||||
massDetailProcessing: false
|
massDetailProcessing: false
|
||||||
};
|
};
|
||||||
|
}),
|
||||||
|
|
||||||
|
on(selectedRightDrawer, (state, action) => {
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
selectedRightDrawer: action.req
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
on(clearRightDrawer, (state, action) => {
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
selectedRightDrawer: null
|
||||||
|
};
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
|
@ -5,12 +5,15 @@ export interface State {
|
||||||
|
|
||||||
selectedMassDetail: number | null;
|
selectedMassDetail: number | null;
|
||||||
massDetailProcessing: boolean;
|
massDetailProcessing: boolean;
|
||||||
|
|
||||||
|
selectedRightDrawer: string | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const initialState: State = {
|
export const initialState: State = {
|
||||||
selectedRoom: null,
|
selectedRoom: null,
|
||||||
selectedMassDetail: null,
|
selectedMassDetail: null,
|
||||||
massDetailProcessing: false
|
massDetailProcessing: false,
|
||||||
|
selectedRightDrawer: ''
|
||||||
};
|
};
|
||||||
|
|
||||||
export function selectors<S>(selector: Selector<any, State>) {
|
export function selectors<S>(selector: Selector<any, State>) {
|
||||||
|
@ -22,6 +25,10 @@ export function selectors<S>(selector: Selector<any, State>) {
|
||||||
selectedMassDetail: createSelector(
|
selectedMassDetail: createSelector(
|
||||||
selector,
|
selector,
|
||||||
(state: State) => state.selectedMassDetail
|
(state: State) => state.selectedMassDetail
|
||||||
|
),
|
||||||
|
selectedRightDrawer: createSelector(
|
||||||
|
selector,
|
||||||
|
(state: State) => state.selectedRightDrawer
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,12 +16,17 @@ import {
|
||||||
CancelResponse,
|
CancelResponse,
|
||||||
EventJson
|
EventJson
|
||||||
} from '@ucap-webmessenger/protocol-event';
|
} from '@ucap-webmessenger/protocol-event';
|
||||||
|
import {
|
||||||
|
InfoRequest as FileInfoRequest,
|
||||||
|
InfoResponse as FileInfoResponse,
|
||||||
|
FileDownloadInfo,
|
||||||
|
FileInfo
|
||||||
|
} from '@ucap-webmessenger/protocol-file';
|
||||||
|
|
||||||
export const info = createAction(
|
export const info = createAction(
|
||||||
'[Messenger::Event] Info',
|
'[Messenger::Event] Info',
|
||||||
props<InfoRequest>()
|
props<InfoRequest>()
|
||||||
);
|
);
|
||||||
|
|
||||||
export const infoSuccess = createAction(
|
export const infoSuccess = createAction(
|
||||||
'[Messenger::Event] Info Success',
|
'[Messenger::Event] Info Success',
|
||||||
props<{
|
props<{
|
||||||
|
@ -29,6 +34,27 @@ export const infoSuccess = createAction(
|
||||||
res: InfoResponse;
|
res: InfoResponse;
|
||||||
}>()
|
}>()
|
||||||
);
|
);
|
||||||
|
export const infoFailure = createAction(
|
||||||
|
'[Messenger::Event] Info Failure',
|
||||||
|
props<{ error: any }>()
|
||||||
|
);
|
||||||
|
|
||||||
|
export const fileInfo = createAction(
|
||||||
|
'[Messenger::Event] File Info',
|
||||||
|
props<{ req: FileInfoRequest }>()
|
||||||
|
);
|
||||||
|
export const fileInfoSuccess = createAction(
|
||||||
|
'[Messenger::Event] File Info Success',
|
||||||
|
props<{
|
||||||
|
fileInfoList: FileInfo[];
|
||||||
|
fileInfoCheckList: FileDownloadInfo[];
|
||||||
|
res: FileInfoResponse;
|
||||||
|
}>()
|
||||||
|
);
|
||||||
|
export const fileInfoFailure = createAction(
|
||||||
|
'[Messenger::Event] File Info Failure',
|
||||||
|
props<{ error: any }>()
|
||||||
|
);
|
||||||
|
|
||||||
export const infoMoreSuccess = createAction(
|
export const infoMoreSuccess = createAction(
|
||||||
'[Messenger::Event] Info More Success',
|
'[Messenger::Event] Info More Success',
|
||||||
|
@ -43,11 +69,6 @@ export const infoIntervalClear = createAction(
|
||||||
props()
|
props()
|
||||||
);
|
);
|
||||||
|
|
||||||
export const infoFailure = createAction(
|
|
||||||
'[Messenger::Event] Info Failure',
|
|
||||||
props<{ error: any }>()
|
|
||||||
);
|
|
||||||
|
|
||||||
export const newInfo = createAction(
|
export const newInfo = createAction(
|
||||||
'[Messenger::Event] New Info',
|
'[Messenger::Event] New Info',
|
||||||
props<{
|
props<{
|
||||||
|
|
|
@ -70,7 +70,10 @@ import {
|
||||||
sendMass,
|
sendMass,
|
||||||
sendMassFailure,
|
sendMassFailure,
|
||||||
infoMoreSuccess,
|
infoMoreSuccess,
|
||||||
infoIntervalClear
|
infoIntervalClear,
|
||||||
|
fileInfo,
|
||||||
|
fileInfoSuccess,
|
||||||
|
fileInfoFailure
|
||||||
} from './actions';
|
} from './actions';
|
||||||
import { SessionStorageService } from '@ucap-webmessenger/web-storage';
|
import { SessionStorageService } from '@ucap-webmessenger/web-storage';
|
||||||
import {
|
import {
|
||||||
|
@ -85,6 +88,18 @@ 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';
|
import { CONST } from '@ucap-webmessenger/core';
|
||||||
|
import {
|
||||||
|
FileProtocolService,
|
||||||
|
SSVC_TYPE_FILE_INFO_DATA,
|
||||||
|
SSVC_TYPE_FILE_INFO_CHECK_DATA,
|
||||||
|
SSVC_TYPE_FILE_INFO_RES,
|
||||||
|
FileInfo,
|
||||||
|
FileDownloadInfo,
|
||||||
|
InfoData as FileInfoData,
|
||||||
|
InfoCheckData as FileInfoCheckData,
|
||||||
|
InfoResponse as FileInfoResponse,
|
||||||
|
FileType
|
||||||
|
} from '@ucap-webmessenger/protocol-file';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class Effects {
|
export class Effects {
|
||||||
|
@ -136,7 +151,8 @@ export class Effects {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (req.baseSeq === 0) {
|
if (req.baseSeq === 0) {
|
||||||
// 최초 이벤트 목록 조회시 SSVC_TYPE_EVENT_READ_REQ 수행.
|
// 최초 이벤트 목록 조회
|
||||||
|
// SSVC_TYPE_EVENT_READ_REQ 수행.
|
||||||
const maxSeq = Math.max.apply(
|
const maxSeq = Math.max.apply(
|
||||||
Math,
|
Math,
|
||||||
infoList.map(v => v.seq)
|
infoList.map(v => v.seq)
|
||||||
|
@ -147,6 +163,17 @@ export class Effects {
|
||||||
lastReadSeq: Number(maxSeq)
|
lastReadSeq: Number(maxSeq)
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// File 정보 수집.
|
||||||
|
this.store.dispatch(
|
||||||
|
fileInfo({
|
||||||
|
req: {
|
||||||
|
roomSeq: req.roomSeq,
|
||||||
|
// { 파일타입 } cf) I : 이미지 V: 동영상 F: 파일 "" 빈값이면 모든 타입을 내려줌
|
||||||
|
type: FileType.All
|
||||||
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -160,6 +187,50 @@ export class Effects {
|
||||||
{ dispatch: false }
|
{ dispatch: false }
|
||||||
);
|
);
|
||||||
|
|
||||||
|
fileInfo$ = createEffect(
|
||||||
|
() => {
|
||||||
|
let fileInfoList: FileInfo[];
|
||||||
|
let fileInfoCheckList: FileDownloadInfo[];
|
||||||
|
|
||||||
|
return this.actions$.pipe(
|
||||||
|
ofType(fileInfo),
|
||||||
|
tap(() => {
|
||||||
|
fileInfoList = [];
|
||||||
|
fileInfoCheckList = [];
|
||||||
|
}),
|
||||||
|
switchMap(action => {
|
||||||
|
return this.fileProtocolService.info(action.req).pipe(
|
||||||
|
map(res => {
|
||||||
|
switch (res.SSVC_TYPE) {
|
||||||
|
case SSVC_TYPE_FILE_INFO_DATA:
|
||||||
|
fileInfoList.push(...(res as FileInfoData).fileInfos);
|
||||||
|
break;
|
||||||
|
case SSVC_TYPE_FILE_INFO_CHECK_DATA:
|
||||||
|
fileInfoCheckList.push(
|
||||||
|
...(res as FileInfoCheckData).fileDownloadInfos
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case SSVC_TYPE_FILE_INFO_RES:
|
||||||
|
{
|
||||||
|
this.store.dispatch(
|
||||||
|
fileInfoSuccess({
|
||||||
|
fileInfoList,
|
||||||
|
fileInfoCheckList,
|
||||||
|
res: res as FileInfoResponse
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
catchError(error => of(fileInfoFailure({ error })))
|
||||||
|
);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
},
|
||||||
|
{ dispatch: false }
|
||||||
|
);
|
||||||
|
|
||||||
infoIntervalClear$ = createEffect(
|
infoIntervalClear$ = createEffect(
|
||||||
() => {
|
() => {
|
||||||
return this.actions$.pipe(
|
return this.actions$.pipe(
|
||||||
|
@ -584,6 +655,7 @@ export class Effects {
|
||||||
private store: Store<any>,
|
private store: Store<any>,
|
||||||
private commonApiService: CommonApiService,
|
private commonApiService: CommonApiService,
|
||||||
private eventProtocolService: EventProtocolService,
|
private eventProtocolService: EventProtocolService,
|
||||||
|
private fileProtocolService: FileProtocolService,
|
||||||
private roomProtocolService: RoomProtocolService,
|
private roomProtocolService: RoomProtocolService,
|
||||||
private sessionStorageService: SessionStorageService,
|
private sessionStorageService: SessionStorageService,
|
||||||
private logger: NGXLogger
|
private logger: NGXLogger
|
||||||
|
|
|
@ -1,5 +1,10 @@
|
||||||
import { createReducer, on } from '@ngrx/store';
|
import { createReducer, on } from '@ngrx/store';
|
||||||
import { initialState, adapterInfoList } from './state';
|
import {
|
||||||
|
initialState,
|
||||||
|
adapterInfoList,
|
||||||
|
adapterFileInfoList,
|
||||||
|
adapterFileInfoCheckList
|
||||||
|
} from './state';
|
||||||
import {
|
import {
|
||||||
infoSuccess,
|
infoSuccess,
|
||||||
appendInfoList,
|
appendInfoList,
|
||||||
|
@ -7,9 +12,11 @@ import {
|
||||||
infoFailure,
|
infoFailure,
|
||||||
recallInfoList,
|
recallInfoList,
|
||||||
delInfoList,
|
delInfoList,
|
||||||
infoMoreSuccess
|
infoMoreSuccess,
|
||||||
|
fileInfoSuccess
|
||||||
} from './actions';
|
} from './actions';
|
||||||
import * as AuthenticationStore from '@app/store/account/authentication';
|
import * as AuthenticationStore from '@app/store/account/authentication';
|
||||||
|
import * as ChatStore from '@app/store/messenger/chat';
|
||||||
import { Info, EventType, EventJson } from '@ucap-webmessenger/protocol-event';
|
import { Info, EventType, EventJson } from '@ucap-webmessenger/protocol-event';
|
||||||
import { CONST } from '@ucap-webmessenger/core';
|
import { CONST } from '@ucap-webmessenger/core';
|
||||||
|
|
||||||
|
@ -52,7 +59,6 @@ export const reducer = createReducer(
|
||||||
: false
|
: false
|
||||||
};
|
};
|
||||||
}),
|
}),
|
||||||
|
|
||||||
on(infoFailure, (state, action) => {
|
on(infoFailure, (state, action) => {
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
|
@ -60,6 +66,23 @@ export const reducer = createReducer(
|
||||||
};
|
};
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
on(fileInfoSuccess, (state, action) => {
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
fileInfoList: adapterFileInfoList.addAll(action.fileInfoList, {
|
||||||
|
...state.fileInfoList
|
||||||
|
}),
|
||||||
|
fileInfoCheckList: adapterFileInfoCheckList.addAll(
|
||||||
|
action.fileInfoCheckList,
|
||||||
|
{
|
||||||
|
...state.fileInfoCheckList
|
||||||
|
}
|
||||||
|
),
|
||||||
|
fileInfoListProcessing: false,
|
||||||
|
fileInfoSyncDate: new Date().toString()
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
|
||||||
on(appendInfoList, (state, action) => {
|
on(appendInfoList, (state, action) => {
|
||||||
const eventinfo = action.info;
|
const eventinfo = action.info;
|
||||||
|
|
||||||
|
@ -109,5 +132,10 @@ export const reducer = createReducer(
|
||||||
return {
|
return {
|
||||||
...initialState
|
...initialState
|
||||||
};
|
};
|
||||||
|
}),
|
||||||
|
on(ChatStore.clearSelectedRoom, (state, action) => {
|
||||||
|
return {
|
||||||
|
...initialState
|
||||||
|
};
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
|
@ -5,14 +5,22 @@ import {
|
||||||
EventJson
|
EventJson
|
||||||
} from '@ucap-webmessenger/protocol-event';
|
} from '@ucap-webmessenger/protocol-event';
|
||||||
import { EntityState, createEntityAdapter } from '@ngrx/entity';
|
import { EntityState, createEntityAdapter } from '@ngrx/entity';
|
||||||
|
import { FileInfo, FileDownloadInfo } from '@ucap-webmessenger/protocol-file';
|
||||||
|
|
||||||
export interface InfoListState extends EntityState<Info<EventJson>> {}
|
export interface InfoListState extends EntityState<Info<EventJson>> {}
|
||||||
|
export interface FileInfoListState extends EntityState<FileInfo> {}
|
||||||
|
export interface FileInfoCheckListState extends EntityState<FileDownloadInfo> {}
|
||||||
|
|
||||||
export interface State {
|
export interface State {
|
||||||
infoListProcessing: boolean;
|
infoListProcessing: boolean;
|
||||||
infoList: InfoListState;
|
infoList: InfoListState;
|
||||||
infoStatus: InfoResponse | null;
|
infoStatus: InfoResponse | null;
|
||||||
remainInfo: boolean;
|
remainInfo: boolean;
|
||||||
|
|
||||||
|
fileInfoListProcessing: boolean;
|
||||||
|
fileInfoList: FileInfoListState;
|
||||||
|
fileInfoCheckList: FileInfoCheckListState;
|
||||||
|
fileInfoSyncDate: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const adapterInfoList = createEntityAdapter<Info<EventJson>>({
|
export const adapterInfoList = createEntityAdapter<Info<EventJson>>({
|
||||||
|
@ -21,14 +29,37 @@ export const adapterInfoList = createEntityAdapter<Info<EventJson>>({
|
||||||
return a.seq - b.seq;
|
return a.seq - b.seq;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
export const adapterFileInfoList = createEntityAdapter<FileInfo>({
|
||||||
|
selectId: info => info.seq,
|
||||||
|
sortComparer: (a, b) => {
|
||||||
|
return b.seq - a.seq;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
export const adapterFileInfoCheckList = createEntityAdapter<FileDownloadInfo>({
|
||||||
|
selectId: info => info.seq,
|
||||||
|
sortComparer: (a, b) => {
|
||||||
|
return b.seq - a.seq;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
const infoListInitialState: InfoListState = adapterInfoList.getInitialState({});
|
const infoListInitialState: InfoListState = adapterInfoList.getInitialState({});
|
||||||
|
const fileInfoListInitialState: FileInfoListState = adapterFileInfoList.getInitialState(
|
||||||
|
{}
|
||||||
|
);
|
||||||
|
const fileInfoCheckListInitialState: FileInfoCheckListState = adapterFileInfoCheckList.getInitialState(
|
||||||
|
{}
|
||||||
|
);
|
||||||
|
|
||||||
export const initialState: State = {
|
export const initialState: State = {
|
||||||
infoListProcessing: false,
|
infoListProcessing: false,
|
||||||
infoList: infoListInitialState,
|
infoList: infoListInitialState,
|
||||||
infoStatus: null,
|
infoStatus: null,
|
||||||
remainInfo: false
|
remainInfo: false,
|
||||||
|
|
||||||
|
fileInfoListProcessing: false,
|
||||||
|
fileInfoList: fileInfoListInitialState,
|
||||||
|
fileInfoCheckList: fileInfoCheckListInitialState,
|
||||||
|
fileInfoSyncDate: ''
|
||||||
};
|
};
|
||||||
|
|
||||||
const {
|
const {
|
||||||
|
@ -37,12 +68,32 @@ const {
|
||||||
selectIds: ngeSelectIdsInfoList,
|
selectIds: ngeSelectIdsInfoList,
|
||||||
selectTotal: ngeSelectTotalInfoList
|
selectTotal: ngeSelectTotalInfoList
|
||||||
} = adapterInfoList.getSelectors();
|
} = adapterInfoList.getSelectors();
|
||||||
|
const {
|
||||||
|
selectAll: ngeSelectAllFileInfoList,
|
||||||
|
selectEntities: ngeSelectEntitiesFileInfoList,
|
||||||
|
selectIds: ngeSelectIdsFileInfoList,
|
||||||
|
selectTotal: ngeSelectTotalFileInfoList
|
||||||
|
} = adapterFileInfoList.getSelectors();
|
||||||
|
const {
|
||||||
|
selectAll: ngeSelectAllFileInfoCheckList,
|
||||||
|
selectEntities: ngeSelectEntitiesFileInfoCheckList,
|
||||||
|
selectIds: ngeSelectIdsFileInfoCheckList,
|
||||||
|
selectTotal: ngeSelectTotalFileInfoCheckList
|
||||||
|
} = adapterFileInfoCheckList.getSelectors();
|
||||||
|
|
||||||
export function selectors<S>(selector: Selector<any, State>) {
|
export function selectors<S>(selector: Selector<any, State>) {
|
||||||
const selectInfoList = createSelector(
|
const selectInfoList = createSelector(
|
||||||
selector,
|
selector,
|
||||||
(state: State) => state.infoList
|
(state: State) => state.infoList
|
||||||
);
|
);
|
||||||
|
const selectFileInfoList = createSelector(
|
||||||
|
selector,
|
||||||
|
(state: State) => state.fileInfoList
|
||||||
|
);
|
||||||
|
const selectFileInfoCheckList = createSelector(
|
||||||
|
selector,
|
||||||
|
(state: State) => state.fileInfoCheckList
|
||||||
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
infoListProcessing: createSelector(
|
infoListProcessing: createSelector(
|
||||||
|
@ -75,6 +126,51 @@ export function selectors<S>(selector: Selector<any, State>) {
|
||||||
selectInfoList,
|
selectInfoList,
|
||||||
ngeSelectEntitiesInfoList,
|
ngeSelectEntitiesInfoList,
|
||||||
(_, entities) => (!!entities ? entities[seq] : undefined)
|
(_, entities) => (!!entities ? entities[seq] : undefined)
|
||||||
|
),
|
||||||
|
|
||||||
|
fileInfoListProcessing: createSelector(
|
||||||
|
selector,
|
||||||
|
(state: State) => state.fileInfoListProcessing
|
||||||
|
),
|
||||||
|
fileInfoSyncDate: createSelector(
|
||||||
|
selector,
|
||||||
|
(state: State) => state.fileInfoSyncDate
|
||||||
|
),
|
||||||
|
fileInfoList: createSelector(
|
||||||
|
selector,
|
||||||
|
(state: State) => state.fileInfoList
|
||||||
|
),
|
||||||
|
fileInfoCheckList: createSelector(
|
||||||
|
selector,
|
||||||
|
(state: State) => state.fileInfoCheckList
|
||||||
|
),
|
||||||
|
selectAllFileInfoList: createSelector(
|
||||||
|
selectFileInfoList,
|
||||||
|
ngeSelectAllFileInfoList
|
||||||
|
),
|
||||||
|
selectEntitiesFileInfoList: createSelector(
|
||||||
|
selectFileInfoList,
|
||||||
|
ngeSelectEntitiesFileInfoList
|
||||||
|
),
|
||||||
|
selectFileInfoList: (seq: number) =>
|
||||||
|
createSelector(
|
||||||
|
selectFileInfoList,
|
||||||
|
ngeSelectEntitiesFileInfoList,
|
||||||
|
(_, entities) => (!!entities ? entities[seq] : undefined)
|
||||||
|
),
|
||||||
|
selectAllFileInfoCheckList: createSelector(
|
||||||
|
selectFileInfoCheckList,
|
||||||
|
ngeSelectAllFileInfoCheckList
|
||||||
|
),
|
||||||
|
selectEntitiesFileInfoCheckList: createSelector(
|
||||||
|
selectFileInfoCheckList,
|
||||||
|
ngeSelectEntitiesFileInfoCheckList
|
||||||
|
),
|
||||||
|
selectFileInfoCheckList: (seq: number) =>
|
||||||
|
createSelector(
|
||||||
|
selectFileInfoCheckList,
|
||||||
|
ngeSelectEntitiesFileInfoCheckList,
|
||||||
|
(_, entities) => (!!entities ? entities[seq] : undefined)
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
export * from './environment.type';
|
export * from './environment.type';
|
||||||
export * from './login-info.type';
|
export * from './login-info.type';
|
||||||
export * from './userselect.dialog.type';
|
export * from './userselect.dialog.type';
|
||||||
|
export * from './right-drawer.type';
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
export enum RightDrawer {
|
||||||
|
FileBox = 'FILE_BOX',
|
||||||
|
AlbumBox = 'ALBUM_BOX'
|
||||||
|
}
|
|
@ -1,12 +1,12 @@
|
||||||
export enum FileType {
|
export enum FileType {
|
||||||
// I : 이미지
|
/** I : 이미지 */
|
||||||
Image = 'I',
|
Image = 'I',
|
||||||
// V : 동영상
|
/** V : 동영상 */
|
||||||
Video = 'V',
|
Video = 'V',
|
||||||
// F : 파일
|
/** F : 파일 */
|
||||||
File = 'F',
|
File = 'F',
|
||||||
// S : 사운드파일
|
/** S : 사운드파일 */
|
||||||
Sound = 'S',
|
Sound = 'S',
|
||||||
// "" 빈값이면 모든 타입을 내려줌
|
/** "" 빈값이면 모든 타입을 내려줌 */
|
||||||
All = ''
|
All = ' '
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,8 @@
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
line-height: 1.6em;
|
line-height: 1.6em;
|
||||||
|
width:100%;
|
||||||
|
margin-top:10px;
|
||||||
.file-name {
|
.file-name {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
|
@ -59,5 +61,14 @@
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
&.expired{
|
||||||
|
li{
|
||||||
|
width:100%;
|
||||||
|
white-space: nowrap;
|
||||||
|
color:#999999;
|
||||||
|
align-items: center;
|
||||||
|
line-height:40px;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -51,16 +51,17 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.box-more-spacer {
|
.box-more-spacer {
|
||||||
margin-right: 0;
|
margin-right: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
::ng-deep .mat-content{
|
::ng-deep .mat-content{
|
||||||
overflow: unset;
|
overflow: unset !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.number{
|
.number{
|
||||||
margin-left:6px;
|
margin-left:6px;
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
flex: 0 0 auto;
|
flex: 0 0 auto;
|
||||||
}
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
<div class="ucap-image-viewer-container">
|
<div class="ucap-image-viewer-container">
|
||||||
<mat-toolbar color="primary">
|
<mat-toolbar class="bg-primary-dark">
|
||||||
<span>Third Line</span>
|
<span>Third Line</span>
|
||||||
<span class="ucap-image-viewer-spacer"></span>
|
<span class="ucap-image-viewer-spacer"></span>
|
||||||
<mat-icon
|
<mat-icon
|
||||||
|
|
|
@ -1,6 +1,17 @@
|
||||||
<div class="ucap-video-viewer-container">
|
<div class="ucap-video-viewer-container">
|
||||||
<mat-toolbar color="accent" class="ucap-video-viewer-header">
|
<mat-toolbar color="accent" class="ucap-video-viewer-header">
|
||||||
<mat-icon class="ucap-video-viewer-icon">video_label</mat-icon>
|
<!--<mat-icon class="ucap-video-viewer-icon">video_label</mat-icon>-->
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor"
|
||||||
|
stroke-width="2" stroke-linecap="butt" stroke-linejoin="round" class="ucap-video-viewer-icon">
|
||||||
|
<rect x="2" y="2" width="20" height="20" rx="2.18" ry="2.18"></rect>
|
||||||
|
<line x1="7" y1="2" x2="7" y2="22"></line>
|
||||||
|
<line x1="17" y1="2" x2="17" y2="22"></line>
|
||||||
|
<line x1="2" y1="12" x2="22" y2="12"></line>
|
||||||
|
<line x1="2" y1="7" x2="7" y2="7"></line>
|
||||||
|
<line x1="2" y1="17" x2="7" y2="17"></line>
|
||||||
|
<line x1="17" y1="17" x2="22" y2="17"></line>
|
||||||
|
<line x1="17" y1="7" x2="22" y2="7"></line>
|
||||||
|
</svg>
|
||||||
<span class="ucap-video-viewer-title">{{ fileInfo.fileName }}</span>
|
<span class="ucap-video-viewer-title">{{ fileInfo.fileName }}</span>
|
||||||
<span class="ucap-video-viewer-spacer"></span>
|
<span class="ucap-video-viewer-spacer"></span>
|
||||||
<button
|
<button
|
||||||
|
@ -11,16 +22,25 @@
|
||||||
aria-label=""
|
aria-label=""
|
||||||
(click)="onClickDownload()"
|
(click)="onClickDownload()"
|
||||||
>
|
>
|
||||||
<mat-icon>get_app</mat-icon>
|
<!--<mat-icon>get_app</mat-icon>-->
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="21" height="21" viewBox="0 0 24 24" fill="none" stroke="currentColor"
|
||||||
|
stroke-width="2" stroke-linecap="butt" stroke-linejoin="round">
|
||||||
|
<path d="M3 15v4c0 1.1.9 2 2 2h14a2 2 0 0 0 2-2v-4M17 9l-5 5-5-5M12 12.8V2.5" />
|
||||||
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
|
<span class="stroke-bar"></span>
|
||||||
<button
|
<button
|
||||||
mat-raised-button
|
mat-icon-button
|
||||||
color="primary"
|
color="warn"
|
||||||
class="ucap-video-viewer-action"
|
class="ucap-image-viewer-action btn-close"
|
||||||
|
matTooltip="뷰어닫기"
|
||||||
(click)="onClickClose()"
|
(click)="onClickClose()"
|
||||||
>
|
>
|
||||||
Close
|
<svg xmlns="http://www.w3.org/2000/svg" width="21" height="21" viewBox="0 0 24 24" fill="none" stroke="currentColor"
|
||||||
|
stroke-width="2" stroke-linecap="butt" stroke-linejoin="round">
|
||||||
|
<line x1="18" y1="6" x2="6" y2="18"></line>
|
||||||
|
<line x1="6" y1="6" x2="18" y2="18"></line>
|
||||||
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
</mat-toolbar>
|
</mat-toolbar>
|
||||||
<div class="ucap-video-viewer-body">
|
<div class="ucap-video-viewer-body">
|
||||||
|
@ -41,6 +61,7 @@
|
||||||
(loadeddata)="onLoadedDataVideo()"
|
(loadeddata)="onLoadedDataVideo()"
|
||||||
></video>
|
></video>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="viewer-bottom">
|
||||||
<div
|
<div
|
||||||
class="ucap-video-viewer-video-time"
|
class="ucap-video-viewer-video-time"
|
||||||
fxLayout="row"
|
fxLayout="row"
|
||||||
|
@ -60,7 +81,6 @@
|
||||||
class="ucap-video-viewer-video-controls"
|
class="ucap-video-viewer-video-controls"
|
||||||
fxLayout="row"
|
fxLayout="row"
|
||||||
fxLayout.xs="column"
|
fxLayout.xs="column"
|
||||||
fxLayoutAlign="center center"
|
|
||||||
>
|
>
|
||||||
<div class="ucap-video-viewer-video-time-current">
|
<div class="ucap-video-viewer-video-time-current">
|
||||||
{{ currentTime | ucapSecondsToMinutes }}
|
{{ currentTime | ucapSecondsToMinutes }}
|
||||||
|
@ -74,6 +94,14 @@
|
||||||
(click)="onClickPlayOrPause()"
|
(click)="onClickPlayOrPause()"
|
||||||
>
|
>
|
||||||
<mat-icon>{{ playing ? 'pause' : 'play_arrow' }}</mat-icon>
|
<mat-icon>{{ playing ? 'pause' : 'play_arrow' }}</mat-icon>
|
||||||
|
<!--{{ playing ? '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor"
|
||||||
|
stroke-width="2" stroke-linecap="butt" stroke-linejoin="round">
|
||||||
|
<rect x="6" y="4" width="4" height="16"></rect>
|
||||||
|
<rect x="14" y="4" width="4" height="16"></rect>
|
||||||
|
</svg>' : '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor"
|
||||||
|
stroke-width="2" stroke-linecap="butt" stroke-linejoin="round">
|
||||||
|
<polygon points="5 3 19 12 5 21 5 3"></polygon>
|
||||||
|
</svg>'}}-->
|
||||||
</button>
|
</button>
|
||||||
<span class="ucap-video-viewer-spacer"></span>
|
<span class="ucap-video-viewer-spacer"></span>
|
||||||
<div class="ucap-video-viewer-video-time-total">
|
<div class="ucap-video-viewer-video-time-total">
|
||||||
|
@ -81,4 +109,5 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -4,33 +4,49 @@
|
||||||
|
|
||||||
.ucap-video-viewer-header {
|
.ucap-video-viewer-header {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 50px;
|
height: 60px;
|
||||||
|
box-shadow: 0 3px 6px rgba(0, 0, 0, 0.6);
|
||||||
|
background-color: #333333;
|
||||||
|
|
||||||
.ucap-video-viewer-icon {
|
.ucap-video-viewer-icon {
|
||||||
|
margin-right: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ucap-video-viewer-title {
|
.ucap-video-viewer-title {
|
||||||
|
font-size:16px;
|
||||||
|
}
|
||||||
|
.stroke-bar {
|
||||||
|
width: 1px;
|
||||||
|
height: 30px;
|
||||||
|
background-color: rgba(256, 256, 256, 0.3);
|
||||||
|
margin: 0 10px;
|
||||||
|
}
|
||||||
|
.ucap-image-viewer-action {
|
||||||
|
&:hover {
|
||||||
|
opacity: 0.7;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.ucap-video-viewer-body {
|
.ucap-video-viewer-body {
|
||||||
position: relative;
|
position: relative;
|
||||||
background-color: white;
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: calc(100% - 60px);
|
||||||
padding-bottom: 70px;
|
|
||||||
|
|
||||||
.ucap-video-viewer-video-icon {
|
.ucap-video-viewer-video-icon {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: calc(100% - 60px);
|
height: calc(100% - 80px);
|
||||||
}
|
}
|
||||||
|
.viewer-bottom{
|
||||||
|
background-color: #212121;
|
||||||
|
color:#ffffff;
|
||||||
.ucap-video-viewer-video-time {
|
.ucap-video-viewer-video-time {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 30px;
|
height: 30px;
|
||||||
}
|
}
|
||||||
.ucap-video-viewer-video-controls {
|
.ucap-video-viewer-video-controls {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 30px;
|
height: 50px;
|
||||||
|
|
||||||
.ucap-video-viewer-video-time-current {
|
.ucap-video-viewer-video-time-current {
|
||||||
padding-left: 30px;
|
padding-left: 30px;
|
||||||
|
@ -41,13 +57,27 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
.ucap-video-viewer-spacer {
|
.ucap-video-viewer-spacer {
|
||||||
flex: 1 1 auto;
|
flex: 1 1 auto;
|
||||||
}
|
}
|
||||||
.ucap-video-viewer-action {
|
.ucap-video-viewer-action {
|
||||||
|
.mat-icon{
|
||||||
|
font-size: 40px;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
line-height:40px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mat-slider {
|
mat-slider {
|
||||||
width: 95%;
|
width: 94%;
|
||||||
|
}
|
||||||
|
|
||||||
|
::ng-deep .mat-slider-horizontal .mat-slider-track-background{
|
||||||
|
background-color: #999999 !important;
|
||||||
|
}
|
||||||
|
::ng-deep .mat-slider-min-value:not(.mat-slider-thumb-label-showing) .mat-slider-thumb{
|
||||||
|
border-color: #999999 !important;
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user