This commit is contained in:
병준 박 2019-11-25 09:34:20 +09:00
commit 55bfee5980
47 changed files with 399 additions and 146 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.5 KiB

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 104 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 551 B

After

Width:  |  Height:  |  Size: 503 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.9 KiB

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 886 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 551 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 999 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 107 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

@ -103,29 +103,51 @@ body.theme-pink-dark {
// ----------------------------------------------------------------------------------------------------- // -----------------------------------------------------------------------------------------------------
// Define the primary, accent and warn palettes // Define the primary, accent and warn palettes
/*$pink-light-theme-primary-palette: mat-palette($mat-grey,800); $lgRed-light-theme-primary-palette: mat-palette($mat-grey,800);
$pink-light-theme-accent-palette: mat-palette($lg-red, 400); $lgRed-light-theme-accent-palette: mat-palette($lg-red, 400);
$pink-light-theme-warn-palette: mat-palette($mat-red);*/ $lgRed-light-theme-warn-palette: mat-palette($mat-cyan);
$pink-light-theme-primary-palette: mat-palette($daesang-grey, 900);
$pink-light-theme-accent-palette: mat-palette($daesang);
$pink-light-theme-warn-palette: mat-palette($mat-deep-orange);
// Create the Material theme object // Create the Material theme object
$pink-light-theme: mat-light-theme( $lgRed-light-theme: mat-light-theme(
$pink-light-theme-primary-palette, $lgRed-light-theme-primary-palette,
$pink-light-theme-accent-palette, $lgRed-light-theme-accent-palette,
$pink-light-theme-warn-palette $lgRed-light-theme-warn-palette
);
// Add ".theme-pink-dark" class to the body to activate this theme.
// Class name must start with "theme-" !!!
body.theme-lgRed{
// Generate the Angular Material theme
@include angular-material-theme($lgRed-light-theme);
// Apply the theme to the user components
@include components-theme($lgRed-light-theme);
@include ucap-material-theme($lgRed-light-theme);
}
// -----------------------------------------------------------------------------------------------------
//aqua-blue-daesang
// -----------------------------------------------------------------------------------------------------
$aquaBlue-light-theme-primary-palette: mat-palette($daesang-grey, 900);
$aquaBlue-theme-accent-palette: mat-palette($aquaBlue-daesang);
$aquaBlue-theme-warn-palette: mat-palette($mat-orange);
// Create the Material theme object
$aquaBlue-light-theme: mat-light-theme(
$aquaBlue-light-theme-primary-palette,
$aquaBlue-theme-accent-palette,
$aquaBlue-theme-warn-palette
); );
// Add ".theme-pink-dark" class to the body to activate this theme. // Add ".theme-pink-dark" class to the body to activate this theme.
// Class name must start with "theme-" !!! // Class name must start with "theme-" !!!
body.theme-default { body.theme-default {
// Generate the Angular Material theme // Generate the Angular Material theme
@include angular-material-theme($pink-light-theme); @include angular-material-theme($aquaBlue-light-theme);
// Apply the theme to the user components // Apply the theme to the user components
@include components-theme($pink-light-theme); @include components-theme($aquaBlue-light-theme);
@include ucap-material-theme($pink-light-theme); @include ucap-material-theme($aquaBlue-light-theme);
} }

View File

@ -85,6 +85,30 @@
</div> </div>
</ng-template> </ng-template>
</mat-tab> </mat-tab>
<mat-tab [aria-label]="MainMenu.Message">
<ng-template mat-tab-label>
<!--<mat-icon>device_hub</mat-icon>-->
<div class="icon-item" matTooltip="Message" matTooltipPosition="after">
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="#000000"
stroke-width="1.5"
stroke-linecap="butt"
stroke-linejoin="bevel"
>
<polygon
points="21.368 12.001 3 21.609 3 14 11 12 3 9.794 3 2.394"
/>
</svg>
</div>
</ng-template>
</mat-tab>
<mat-tab [aria-label]="MainMenu.Call"> <mat-tab [aria-label]="MainMenu.Call">
<ng-template mat-tab-label> <ng-template mat-tab-label>
<!--<mat-icon>phone</mat-icon>--> <!--<mat-icon>phone</mat-icon>-->
@ -116,6 +140,11 @@
</mat-tab> </mat-tab>
</mat-tab-group> </mat-tab-group>
<div class="myprofile">
<span class="myprofile-img"></span>
<span>내프로필</span>
</div>
<div class="left-side-tabs-body"> <div class="left-side-tabs-body">
<div <div
#tabs #tabs
@ -145,6 +174,7 @@
> >
<app-layout-chat-left-sidenav-organization <app-layout-chat-left-sidenav-organization
[selectedUserList]="selectedUserList" [selectedUserList]="selectedUserList"
[isVisible]="currentTabLable === MainMenu.Organization"
(checkAllUser)="onCheckAllUser($event)" (checkAllUser)="onCheckAllUser($event)"
(checkUser)="onCheckUser($event)" (checkUser)="onCheckUser($event)"
(openProfile)="onClickOpenProfile($event)" (openProfile)="onClickOpenProfile($event)"
@ -157,6 +187,16 @@
id="tabs-3" id="tabs-3"
class="left-side-tabs-contents" class="left-side-tabs-contents"
style="display: none;" style="display: none;"
>
<app-layout-chat-left-sidenav-message
[isVisible]="currentTabLable === MainMenu.Message"
></app-layout-chat-left-sidenav-message>
</div>
<div
#tabs
id="tabs-4"
class="left-side-tabs-contents"
style="display: none;"
> >
<app-layout-chat-left-sidenav-call></app-layout-chat-left-sidenav-call> <app-layout-chat-left-sidenav-call></app-layout-chat-left-sidenav-call>
</div> </div>

View File

@ -34,6 +34,29 @@
flex-direction: row; flex-direction: row;
} }
.myprofile {
position: absolute;
display: flex;
flex-flow: column;
justify-content: center;
height: 80px;
width: 68px;
bottom: 10px;
color: #ffffff;
font-size: 11px;
text-align: center;
.myprofile-img {
display: block;
border-radius: 10px;
height: 42px;
width: 42px;
background-color: #efefef;
align-self: center;
margin-bottom: 6px;
}
}
::ng-deep .organization-side { ::ng-deep .organization-side {
flex-direction: column; flex-direction: column;
height: 100%; height: 100%;
@ -43,7 +66,7 @@
.mat-tab-list { .mat-tab-list {
.mat-tab-labels { .mat-tab-labels {
flex-flow: column; flex-flow: column;
height: 280px; height: 360px;
padding-top: 10px; padding-top: 10px;
border-bottom: none; border-bottom: none;
.mat-tab-label { .mat-tab-label {

View File

@ -35,6 +35,7 @@ export enum MainMenu {
Group = 'GROUP', Group = 'GROUP',
Chat = 'CAHT', Chat = 'CAHT',
Organization = 'ORGANIZATION', Organization = 'ORGANIZATION',
Message = 'MESSAGE',
Call = 'CALL', Call = 'CALL',
Conversation = 'CONVERSATION' Conversation = 'CONVERSATION'
} }
@ -52,6 +53,7 @@ export class LeftSideComponent implements OnInit, OnDestroy {
>(); >();
@ViewChildren('tabs') tabs: QueryList<ElementRef<HTMLDivElement>>; @ViewChildren('tabs') tabs: QueryList<ElementRef<HTMLDivElement>>;
currentTabLable: string;
badgeChatUnReadCount: number; badgeChatUnReadCount: number;
badgeChatUnReadCountSubscription: Subscription; badgeChatUnReadCountSubscription: Subscription;
@ -81,6 +83,7 @@ export class LeftSideComponent implements OnInit, OnDestroy {
}); });
this.setFabInitial(MainMenu.Group); this.setFabInitial(MainMenu.Group);
this.currentTabLable = MainMenu.Group;
} }
ngOnDestroy(): void { ngOnDestroy(): void {
@ -158,6 +161,7 @@ export class LeftSideComponent implements OnInit, OnDestroy {
onSelectedTabChange(event: MatTabChangeEvent) { onSelectedTabChange(event: MatTabChangeEvent) {
this.setFabInitial(event.tab.ariaLabel); this.setFabInitial(event.tab.ariaLabel);
this.currentTabLable = event.tab.ariaLabel;
this.tabs.forEach(tab => { this.tabs.forEach(tab => {
if (`tabs-${event.index}` === tab.nativeElement.id) { if (`tabs-${event.index}` === tab.nativeElement.id) {
@ -177,11 +181,6 @@ export class LeftSideComponent implements OnInit, OnDestroy {
icon: 'add', icon: 'add',
tooltip: 'New Group Add', tooltip: 'New Group Add',
divisionType: 'GROUP_NEW_ADD' divisionType: 'GROUP_NEW_ADD'
},
{
icon: 'sms',
tooltip: 'Message',
divisionType: 'MESSAGE'
} }
]; ];
} }
@ -297,16 +296,6 @@ export class LeftSideComponent implements OnInit, OnDestroy {
this.onClickNewChat('TIMER'); this.onClickNewChat('TIMER');
} }
break; break;
case 'MESSAGE':
{
this.store.dispatch(
ChatStore.selectedRightDrawer({
req: RightDrawer.Message
})
);
}
break;
} }
} }
} }

View File

@ -92,11 +92,17 @@
<span>새 그룹 추가</span> <span>새 그룹 추가</span>
</button> </button>
<button mat-menu-item (click)="onClickGroupMenu('GROUP_EXPAND_MORE')"> <button mat-menu-item (click)="onClickGroupMenu('GROUP_EXPAND_MORE')">
<mat-icon>expand_more</mat-icon> <!--<mat-icon>expand_more</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="M6 9l6 6 6-6" /></svg>
<span>그룹 전체 열기</span> <span>그룹 전체 열기</span>
</button> </button>
<button mat-menu-item (click)="onClickGroupMenu('GROUP_EXPAND_LESS')"> <button mat-menu-item (click)="onClickGroupMenu('GROUP_EXPAND_LESS')">
<mat-icon>expand_less</mat-icon> <!--<mat-icon>expand_less</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="M18 15l-6-6-6 6" /></svg>
<span>그룹 전체 닫기</span> <span>그룹 전체 닫기</span>
</button> </button>
<!-- <button mat-menu-item (click)="onClickGroupMenu('GROUP_SAVE')"> <!-- <button mat-menu-item (click)="onClickGroupMenu('GROUP_SAVE')">

View File

@ -2,10 +2,12 @@ import { CallComponent } from './call.component';
import { ChatComponent } from './chat.component'; import { ChatComponent } from './chat.component';
import { GroupComponent } from './group.component'; import { GroupComponent } from './group.component';
import { OrganizationComponent } from './organization.component'; import { OrganizationComponent } from './organization.component';
import { MessageBoxComponent } from './message.component';
export const LEFT_SIDENAV_COMPONENTS = [ export const LEFT_SIDENAV_COMPONENTS = [
CallComponent, CallComponent,
ChatComponent, ChatComponent,
GroupComponent, GroupComponent,
OrganizationComponent OrganizationComponent,
MessageBoxComponent
]; ];

View File

@ -1,4 +1,15 @@
<div class="message-box container"> <div class="message-box container">
<div class="current-head">
<h3>쪽지</h3>
<div class="btn-box">
<!-- <button mat-icon-button>
<mat-icon>timer</mat-icon>
</button>
<button mat-icon-button>
<mat-icon> add_comment</mat-icon>
</button> -->
</div>
</div>
<div class="list-search"> <div class="list-search">
<div class="searchbox"> <div class="searchbox">
<form [formGroup]="fgSearch" class="w-100-p"> <form [formGroup]="fgSearch" class="w-100-p">
@ -26,13 +37,15 @@
</form> </form>
</div> </div>
</div> </div>
<div class="container"> <div>
<mat-tab-group <mat-tab-group
#tabs
mat-stretch-tabs mat-stretch-tabs
animationDuration="0ms" animationDuration="0ms"
[selectedIndex]="0"
(selectedIndexChange)="onSelectedIndexChange($event)" (selectedIndexChange)="onSelectedIndexChange($event)"
> >
<mat-tab> <mat-tab [label]="MessageType.Receive">
<ng-template mat-tab-label> <ng-template mat-tab-label>
수신 수신
</ng-template> </ng-template>
@ -64,7 +77,7 @@
</dl> </dl>
</div> </div>
</mat-tab> </mat-tab>
<mat-tab> <mat-tab [label]="MessageType.Send">
<ng-template mat-tab-label> <ng-template mat-tab-label>
발신 발신
</ng-template> </ng-template>
@ -96,7 +109,7 @@
</dl> </dl>
</div> </div>
</mat-tab> </mat-tab>
<mat-tab> <mat-tab [label]="MessageType.Reservation">
<ng-template mat-tab-label> <ng-template mat-tab-label>
예약 예약
</ng-template> </ng-template>

View File

@ -1,3 +1,18 @@
.current-head {
h3 {
display: inline-flex;
padding-left: 10px;
align-items: center;
color: #ffffff;
}
.btn-box {
height: 100%;
margin-left: auto;
display: inline-flex;
align-items: center;
}
}
.list-search { .list-search {
display: flex; display: flex;
flex-direction: row; flex-direction: row;
@ -46,3 +61,7 @@
} }
} }
} }
.mat-tab-label-active {
opacity: 1;
}

View File

@ -1,6 +1,6 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { MessageBoxComponent } from './message-box.component'; import { MessageBoxComponent } from './message.component';
describe('MessageBoxComponent', () => { describe('MessageBoxComponent', () => {
let component: MessageBoxComponent; let component: MessageBoxComponent;
@ -9,8 +9,7 @@ describe('MessageBoxComponent', () => {
beforeEach(async(() => { beforeEach(async(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
declarations: [MessageBoxComponent] declarations: [MessageBoxComponent]
}) }).compileComponents();
.compileComponents();
})); }));
beforeEach(() => { beforeEach(() => {

View File

@ -3,7 +3,10 @@ import {
OnInit, OnInit,
OnDestroy, OnDestroy,
Output, Output,
EventEmitter EventEmitter,
ViewChild,
Input,
AfterViewChecked
} from '@angular/core'; } from '@angular/core';
import { Subscription, of } from 'rxjs'; import { Subscription, of } from 'rxjs';
import { Store, select } from '@ngrx/store'; import { Store, select } from '@ngrx/store';
@ -28,13 +31,21 @@ import { DeviceType } from '@ucap-webmessenger/core';
import { MessageStatusCode } from '@ucap-webmessenger/api'; import { MessageStatusCode } from '@ucap-webmessenger/api';
import { ContentType } from '@ucap-webmessenger/api-message'; import { ContentType } from '@ucap-webmessenger/api-message';
import { FormGroup, FormBuilder } from '@angular/forms'; import { FormGroup, FormBuilder } from '@angular/forms';
import { MatTabGroup } from '@angular/material';
@Component({ @Component({
selector: 'app-layout-chat-right-drawer-message-box', selector: 'app-layout-chat-left-sidenav-message',
templateUrl: './message-box.component.html', templateUrl: './message.component.html',
styleUrls: ['./message-box.component.scss'] styleUrls: ['./message.component.scss']
}) })
export class MessageBoxComponent implements OnInit, OnDestroy { export class MessageBoxComponent
implements OnInit, OnDestroy, AfterViewChecked {
@Input()
isVisible = false;
@ViewChild('tabs', { static: false }) tabs: MatTabGroup;
isInitTabs = false;
fgSearch: FormGroup; fgSearch: FormGroup;
userInfoList: UserInfo[]; userInfoList: UserInfo[];
@ -60,6 +71,7 @@ export class MessageBoxComponent implements OnInit, OnDestroy {
currentPage = 0; currentPage = 0;
ContentType = ContentType; ContentType = ContentType;
MessageType = MessageType;
constructor( constructor(
private store: Store<any>, private store: Store<any>,
@ -92,6 +104,17 @@ export class MessageBoxComponent implements OnInit, OnDestroy {
// 초기 검색은 수신함. // 초기 검색은 수신함.
this.getRetrieveMessage(MessageType.Receive, this.recieveCurrentPage); this.getRetrieveMessage(MessageType.Receive, this.recieveCurrentPage);
if (!!this.tabs) {
this.tabs.realignInkBar();
}
}
ngAfterViewChecked(): void {
if (!!this.tabs && !this.isInitTabs && this.isVisible) {
this.isInitTabs = true;
this.tabs.realignInkBar();
}
} }
ngOnDestroy(): void { ngOnDestroy(): void {

View File

@ -44,8 +44,13 @@
<div *ngIf="selectedDepartmentProcessing"> <div *ngIf="selectedDepartmentProcessing">
<mat-progress-bar mode="indeterminate"></mat-progress-bar> <mat-progress-bar mode="indeterminate"></mat-progress-bar>
</div> </div>
<div *ngIf="!isShowSearch" class="search-list"> <div class="search-list">
<cdk-virtual-scroll-viewport itemSize="20" perfectScrollbar fxFlexFill> <cdk-virtual-scroll-viewport
itemSize="80"
#cvsvDeptUser
perfectScrollbar
fxFlexFill
>
<ucap-profile-user-list-item <ucap-profile-user-list-item
*cdkVirtualFor="let userInfo of selectedDepartmentUserInfoList" *cdkVirtualFor="let userInfo of selectedDepartmentUserInfoList"
[userInfo]="userInfo" [userInfo]="userInfo"
@ -57,15 +62,15 @@
(openProfile)="onClickOpenProfile($event)" (openProfile)="onClickOpenProfile($event)"
(click)="onToggleUser(userInfo)" (click)="onToggleUser(userInfo)"
> >
Loading...
</ucap-profile-user-list-item> </ucap-profile-user-list-item>
</cdk-virtual-scroll-viewport> </cdk-virtual-scroll-viewport>
</div> </div>
<div *ngIf="isShowSearch" class="search-result"> <div *ngIf="isShowSearch" class="search-result">
<cdk-virtual-scroll-viewport <cdk-virtual-scroll-viewport
#cvsvDeptSearchUser
itemSize="20" itemSize="20"
perfectScrollbar perfectScrollbar
style="height: 100%;" fxFlexFill
> >
<ucap-profile-user-list-item <ucap-profile-user-list-item
*cdkVirtualFor="let userInfo of searchUserInfos" *cdkVirtualFor="let userInfo of searchUserInfos"

View File

@ -155,13 +155,3 @@
} }
} }
} }
::ng-deep .oraganization-tab{
.oraganization-tab-tree,
.select-list{
.ps{
.ps-content{
height:100%;
}
}
}
}

View File

@ -4,7 +4,11 @@ import {
OnDestroy, OnDestroy,
Output, Output,
EventEmitter, EventEmitter,
Input Input,
ViewChild,
AfterViewInit,
AfterContentChecked,
AfterViewChecked
} from '@angular/core'; } from '@angular/core';
import { ucapAnimations, DialogService } from '@ucap-webmessenger/ui'; import { ucapAnimations, DialogService } from '@ucap-webmessenger/ui';
import { Observable, Subscription, of } from 'rxjs'; import { Observable, Subscription, of } from 'rxjs';
@ -41,6 +45,8 @@ import {
} from '../../dialogs/group/select-group.dialog.component'; } from '../../dialogs/group/select-group.dialog.component';
import { LoginResponse } from '@ucap-webmessenger/protocol-authentication'; import { LoginResponse } from '@ucap-webmessenger/protocol-authentication';
import { Company } from '@ucap-webmessenger/api-external'; import { Company } from '@ucap-webmessenger/api-external';
import { PerfectScrollbarDirective } from 'ngx-perfect-scrollbar';
import { CdkVirtualScrollViewport } from '@angular/cdk/scrolling';
@Component({ @Component({
selector: 'app-layout-chat-left-sidenav-organization', selector: 'app-layout-chat-left-sidenav-organization',
@ -48,7 +54,8 @@ import { Company } from '@ucap-webmessenger/api-external';
styleUrls: ['./organization.component.scss'], styleUrls: ['./organization.component.scss'],
animations: ucapAnimations animations: ucapAnimations
}) })
export class OrganizationComponent implements OnInit, OnDestroy { export class OrganizationComponent
implements OnInit, OnDestroy, AfterViewChecked {
@Input() @Input()
showTitle = true; showTitle = true;
@Input() @Input()
@ -57,6 +64,8 @@ export class OrganizationComponent implements OnInit, OnDestroy {
@Input() @Input()
/** 선택된 사용자의 리스트 */ /** 선택된 사용자의 리스트 */
selectedUserList?: (UserInfo | UserInfoSS | UserInfoF | UserInfoDN)[] = []; selectedUserList?: (UserInfo | UserInfoSS | UserInfoF | UserInfoDN)[] = [];
@Input()
isVisible = true;
@Output() @Output()
checkUser = new EventEmitter<{ checkUser = new EventEmitter<{
@ -77,11 +86,13 @@ export class OrganizationComponent implements OnInit, OnDestroy {
UserInfo | UserInfoSS | UserInfoF | UserInfoDN UserInfo | UserInfoSS | UserInfoF | UserInfoDN
>(); >();
@ViewChild('cvsvDeptUser', { static: false })
cvsvDeptUser: CdkVirtualScrollViewport;
companyList$: Observable<Company[]>; companyList$: Observable<Company[]>;
companyCode: string; companyCode: string;
departmentInfoList$: Observable<DeptInfo[]>; departmentInfoList$: Observable<DeptInfo[]>;
selectedDepartmentUserInfoList$: Observable<UserInfoSS[]>;
selectedDepartmentUserInfoList: UserInfoSS[] = []; selectedDepartmentUserInfoList: UserInfoSS[] = [];
selectedDepartmentUserInfoListSubscription: Subscription; selectedDepartmentUserInfoListSubscription: Subscription;
selectedDepartmentStatus$: Observable<DeptUserResponse>; selectedDepartmentStatus$: Observable<DeptUserResponse>;
@ -96,6 +107,9 @@ export class OrganizationComponent implements OnInit, OnDestroy {
isShowSearch = false; isShowSearch = false;
searchUserInfos: UserInfoSS[] = []; searchUserInfos: UserInfoSS[] = [];
/** 부서원 리스트에 virture scroll의 size 가 체킹되지 않아 강제 수행. 1번만. */
isInitList = false;
constructor( constructor(
private store: Store<any>, private store: Store<any>,
private sessionStorageService: SessionStorageService, private sessionStorageService: SessionStorageService,
@ -173,6 +187,19 @@ export class OrganizationComponent implements OnInit, OnDestroy {
.subscribe(); .subscribe();
} }
ngAfterViewChecked(): void {
if (
!!this.cvsvDeptUser &&
!!this.selectedDepartmentUserInfoList &&
this.selectedDepartmentUserInfoList.length > 0 &&
!this.isInitList &&
this.isVisible
) {
this.isInitList = true;
this.cvsvDeptUser.checkViewportSize();
}
}
ngOnDestroy(): void { ngOnDestroy(): void {
if (!!this.selectedDepartmentUserInfoListSubscription) { if (!!this.selectedDepartmentUserInfoListSubscription) {
this.selectedDepartmentUserInfoListSubscription.unsubscribe(); this.selectedDepartmentUserInfoListSubscription.unsubscribe();

View File

@ -534,11 +534,11 @@ export class MessagesComponent implements OnInit, OnDestroy, AfterViewInit {
FileViewerDialogResult FileViewerDialogResult
>(FileViewerDialogComponent, { >(FileViewerDialogComponent, {
position: { position: {
top: '30px' top: '50px'
}, },
maxWidth: '100vw', maxWidth: '100vw',
maxHeight: '100vh', maxHeight: '100vh',
height: 'calc(100% - 30px)', height: 'calc(100% - 50px)',
width: '100%', width: '100%',
hasBackdrop: false, hasBackdrop: false,
panelClass: 'app-dialog-full', panelClass: 'app-dialog-full',

View File

@ -28,7 +28,5 @@
<!-- [E] About Chat room --> <!-- [E] About Chat room -->
<!-- [S] About Common --> <!-- [S] About Common -->
<app-layout-chat-right-drawer-message-box *ngSwitchCase="RightDrawer.Message">
</app-layout-chat-right-drawer-message-box>
<!-- [E] About Common --> <!-- [E] About Common -->
</ng-container> </ng-container>

View File

@ -40,9 +40,9 @@
</div> </div>
<ul> <ul>
<li class="name">{{ selectedFile.info.name }}</li> <li class="name">{{ selectedFile.info.name }}</li>
<li>size : {{ selectedFile.info.size | ucapBytes }}</li> <li><span class="text-accent-color">size :</span> {{ selectedFile.info.size | ucapBytes }}</li>
<li> <li>
date : <span class="text-accent-color">date :</span>
{{ selectedFile.info.sendDate | dateToStringFormat: 'YYYY.MM.DD' }} {{ selectedFile.info.sendDate | dateToStringFormat: 'YYYY.MM.DD' }}
</li> </li>
</ul> </ul>

View File

@ -1,11 +1,9 @@
import { FileBoxComponent } from './file-box.component'; import { FileBoxComponent } from './file-box.component';
import { AlbumBoxComponent } from './album-box.component'; import { AlbumBoxComponent } from './album-box.component';
import { RoomUserListComponent } from './room-user-list.component'; import { RoomUserListComponent } from './room-user-list.component';
import { MessageBoxComponent } from './message-box.component';
export const RIGHT_DRAWER_COMPONENTS = [ export const RIGHT_DRAWER_COMPONENTS = [
FileBoxComponent, FileBoxComponent,
AlbumBoxComponent, AlbumBoxComponent,
RoomUserListComponent, RoomUserListComponent
MessageBoxComponent
]; ];

View File

@ -125,6 +125,7 @@
[showTitle]="false" [showTitle]="false"
[selectedUserList]="selectedUserList" [selectedUserList]="selectedUserList"
[isUserSelect]="true" [isUserSelect]="true"
[isVisible]="currentTabIndex === 1"
(checkAllUser)="onCheckAllUser($event)" (checkAllUser)="onCheckAllUser($event)"
(checkUser)="onCheckUser($event)" (checkUser)="onCheckUser($event)"
(toggleUser)="onToggleUser($event)" (toggleUser)="onToggleUser($event)"

View File

@ -110,6 +110,8 @@ export class CreateChatDialogComponent implements OnInit, OnDestroy {
); );
} }
currentTabIndex: number;
UserSelectDialogType = UserSelectDialogType; UserSelectDialogType = UserSelectDialogType;
loginRes: LoginResponse; loginRes: LoginResponse;
@ -237,6 +239,8 @@ export class CreateChatDialogComponent implements OnInit, OnDestroy {
if (this.data.type === UserSelectDialogType.EditChatMember) { if (this.data.type === UserSelectDialogType.EditChatMember) {
this.selectedUserList = this.data.curRoomUser; this.selectedUserList = this.data.curRoomUser;
} }
this.currentTabIndex = 0;
} }
ngOnDestroy(): void { ngOnDestroy(): void {
@ -284,6 +288,8 @@ export class CreateChatDialogComponent implements OnInit, OnDestroy {
} }
onSelectedTabChange(tabChangeEvent: MatTabChangeEvent): void { onSelectedTabChange(tabChangeEvent: MatTabChangeEvent): void {
this.currentTabIndex = tabChangeEvent.index;
if (tabChangeEvent.index === 2) { if (tabChangeEvent.index === 2) {
this.selectedUserList = []; this.selectedUserList = [];
this.isShowSelectedUserList = false; this.isShowSelectedUserList = false;
@ -451,12 +457,13 @@ export class CreateChatDialogComponent implements OnInit, OnDestroy {
} }
getCheckableRoom(roomInfo: RoomInfo) { getCheckableRoom(roomInfo: RoomInfo) {
if (!!this.data.ignoreRoom && this.data.ignoreRoom.length > 0) { // // 현재 방도 체크 전달 할수 있도록 수정. (끌어올리기 개념.)
return !( // if (!!this.data.ignoreRoom && this.data.ignoreRoom.length > 0) {
this.data.ignoreRoom.filter(room => room.roomSeq === roomInfo.roomSeq) // return !(
.length > 0 // this.data.ignoreRoom.filter(room => room.roomSeq === roomInfo.roomSeq)
); // .length > 0
} // );
// }
return true; return true;
} }
getCheckedRoom(roomInfo: RoomInfo) { getCheckedRoom(roomInfo: RoomInfo) {

View File

@ -4,7 +4,29 @@
</div> </div>
<div class="app-layout-native-title-bar-title">UCAP M Messenger</div> <div class="app-layout-native-title-bar-title">UCAP M Messenger</div>
<div class="app-layout-native-title-bar-spacer"></div> <div class="app-layout-native-title-bar-spacer"></div>
<div class="app-layout-native-title-bar-link">
<button mat-icon-button class="button app-layout-native-title-bar-setting">
<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" alt="환경설정">
<circle cx="12" cy="12" r="3"></circle>
<path
d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z">
</path>
</svg>
</button>
<button mat-icon-button class="button app-layout-native-title-bar-logout">
<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" alt="로그아웃" class="stroke-warn-color" >
<path d="M10 3H6a2 2 0 0 0-2 2v14c0 1.1.9 2 2 2h4M16 17l5-5-5-5M19.8 12H9" /></svg>
</button>
<span class="stroke-bar"></span>
</div>
<div class="app-layout-native-title-bar-actions"> <div class="app-layout-native-title-bar-actions">
<button <button
mat-icon-button mat-icon-button
class="button app-layout-native-title-bar-minimize" class="button app-layout-native-title-bar-minimize"
@ -12,7 +34,7 @@
> >
<!--<mat-icon>minimize</mat-icon>--> <!--<mat-icon>minimize</mat-icon>-->
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor"
stroke-width="2" stroke-linecap="butt" stroke-linejoin="round"> stroke-width="2" stroke-linecap="butt" stroke-linejoin="round" alt="창 최소화">
<line x1="5" y1="18" x2="19" y2="18"></line> <line x1="5" y1="18" x2="19" y2="18"></line>
</svg> </svg>
</button> </button>
@ -24,7 +46,7 @@
<ng-container [ngSwitch]="windowStateChanged$ | async"> <ng-container [ngSwitch]="windowStateChanged$ | async">
<!--<mat-icon *ngSwitchCase="WindowState.Maximized">filter_none</mat-icon>--> <!--<mat-icon *ngSwitchCase="WindowState.Maximized">filter_none</mat-icon>-->
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor"
stroke-width="2" stroke-linecap="butt" stroke-linejoin="round" *ngSwitchCase="WindowState.Maximized"> stroke-width="2" stroke-linecap="butt" stroke-linejoin="round" *ngSwitchCase="WindowState.Maximized" alt="창 이전크기">
<path class="st0" <path class="st0"
d="M15,9.5v7c0,0.8-0.7,1.5-1.5,1.5h-7C5.7,18,5,17.3,5,16.5v-7C5,8.7,5.7,8,6.5,8h7C14.3,8,15,8.7,15,9.5z" /> d="M15,9.5v7c0,0.8-0.7,1.5-1.5,1.5h-7C5.7,18,5,17.3,5,16.5v-7C5,8.7,5.7,8,6.5,8h7C14.3,8,15,8.7,15,9.5z" />
<path class="st0" d="M8.8,6.8V6c0-0.8,0.7-1.5,1.5-1.5H17c0.8,0,1.5,0.7,1.5,1.5v6.8c0,0.8-0.7,1.5-1.5,1.5h-0.8" /> <path class="st0" d="M8.8,6.8V6c0-0.8,0.7-1.5,1.5-1.5H17c0.8,0,1.5,0.7,1.5,1.5v6.8c0,0.8-0.7,1.5-1.5,1.5h-0.8" />
@ -32,7 +54,7 @@
<!--<mat-icon *ngSwitchDefault>crop_din</mat-icon>--> <!--<mat-icon *ngSwitchDefault>crop_din</mat-icon>-->
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor"
stroke-width="2" stroke-linecap="butt" stroke-linejoin="round" *ngSwitchDefault> stroke-width="2" stroke-linecap="butt" stroke-linejoin="round" *ngSwitchDefault alt="창크기 최대">
<rect x="5" y="5" width="12" height="12" rx="2" ry="2"></rect> <rect x="5" y="5" width="12" height="12" rx="2" ry="2"></rect>
</svg> </svg>
@ -45,7 +67,7 @@
> >
<!--<mat-icon>close</mat-icon>--> <!--<mat-icon>close</mat-icon>-->
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor"
stroke-width="2" stroke-linecap="butt" stroke-linejoin="round"> stroke-width="2" stroke-linecap="butt" stroke-linejoin="round" alt="창닫기">
<line x1="18" y1="6" x2="6" y2="18"></line> <line x1="18" y1="6" x2="6" y2="18"></line>
<line x1="6" y1="6" x2="18" y2="18"></line> <line x1="6" y1="6" x2="18" y2="18"></line>
</svg> </svg>

View File

@ -9,7 +9,7 @@
display: flex; display: flex;
padding: 0 10px; padding: 0 10px;
cursor: pointer; cursor: pointer;
height: 30px; height: 50px;
color: #ffffff; color: #ffffff;
//background: rgba(37, 27, 30, 0.9); //background: rgba(37, 27, 30, 0.9);
//border-bottom: 1px solid #d5dadb; //border-bottom: 1px solid #d5dadb;
@ -28,7 +28,49 @@
flex: 1 1 auto; flex: 1 1 auto;
} }
.app-layout-native-title-bar-link {
align-items: center;
position: relative;
.stroke-bar {
width: 1px;
height: 20px;
background-color: rgba(256, 256, 256, 0.3);
margin: 0 10px 0 20px;
display: inline-flex;
}
.button {
-webkit-app-region: no-drag;
outline: 0;
cursor: pointer;
border: none;
height: 28px;
min-width: 28px;
max-width: 28px;
padding: 5px;
line-height: 10px;
border-radius: 0;
background: transparent;
transition: background 0.2s linear, color 0.2s linear;
text-align: center;
font-size: 10px;
vertical-align: middle;
margin-left: 10px;
transform: translateY(-2px);
&.app-layout-native-title-bar-logout,
&.app-layout-native-title-bar-setting {
background-color: #efefef;
border-radius: 50%;
}
&:hover {
opacity: 0.7;
}
}
}
.app-layout-native-title-bar-actions { .app-layout-native-title-bar-actions {
align-items: center;
position: relative; position: relative;
.button { .button {
@ -70,6 +112,7 @@
// } // }
&:hover { &:hover {
border-radius: 4px;
&.app-layout-native-title-bar-close { &.app-layout-native-title-bar-close {
background: darken(#000000, 10%); background: darken(#000000, 10%);
color: darken(white, 0); color: darken(white, 0);

View File

@ -2,7 +2,7 @@
height: 100%; height: 100%;
display: flex; display: flex;
flex-flow: row; flex-flow: row;
padding-top: 27px; padding-top: 47px;
border-top: none; border-top: none;
.split-area { .split-area {
overflow: hidden; overflow: hidden;

View File

@ -101,6 +101,7 @@ import {
InfoResponse as FileInfoResponse, InfoResponse as FileInfoResponse,
FileType FileType
} from '@ucap-webmessenger/protocol-file'; } from '@ucap-webmessenger/protocol-file';
import { RoomUserData } from '@ucap-webmessenger/protocol-sync';
@Injectable() @Injectable()
export class Effects { export class Effects {
@ -393,21 +394,41 @@ export class Effects {
() => { () => {
return this.actions$.pipe( return this.actions$.pipe(
ofType(forward), ofType(forward),
map(action => { withLatestFrom(
this.store.pipe(
select(
(state: any) =>
state.messenger.sync.roomUserShort.entities as Dictionary<
RoomUserData
>
)
)
),
tap(([action, roomUserList]) => {
if (!!action.trgtRoomSeq) { if (!!action.trgtRoomSeq) {
this.store.dispatch( this.store.dispatch(
ChatStore.selectedRoom({ roomSeq: action.trgtRoomSeq }) forwardAfterRoomOpen({
);
this.store.dispatch(
send({
senderSeq: action.senderSeq, senderSeq: action.senderSeq,
req: { req: action.req,
roomSeq: action.trgtRoomSeq, trgtUserSeqs: roomUserList[action.trgtRoomSeq].userInfos.map(
eventType: action.req.eventType, user => user.seq
sentMessage: action.req.sentMessage )
}
}) })
); );
// this.store.dispatch(
// ChatStore.selectedRoom({ roomSeq: action.trgtRoomSeq })
// );
// this.store.dispatch(
// send({
// senderSeq: action.senderSeq,
// req: {
// roomSeq: action.trgtRoomSeq,
// eventType: action.req.eventType,
// sentMessage: action.req.sentMessage
// }
// })
// );
} else if (!!action.trgtUserSeqs && action.trgtUserSeqs.length > 0) { } else if (!!action.trgtUserSeqs && action.trgtUserSeqs.length > 0) {
// 방오픈 후 대화전달. // 방오픈 후 대화전달.
this.store.dispatch(forwardAfterRoomOpen(action)); this.store.dispatch(forwardAfterRoomOpen(action));

View File

@ -4,8 +4,5 @@ export enum RightDrawer {
/** 대화방 > 파일함 */ /** 대화방 > 파일함 */
FileBox = 'FILE_BOX', FileBox = 'FILE_BOX',
/** 대화방 > 대화참여자목록 */ /** 대화방 > 대화참여자목록 */
RoomUser = 'ROOM_USER', RoomUser = 'ROOM_USER'
/** 쪽지함 */
Message = 'MESSAGE_BOX'
} }

View File

@ -46,12 +46,12 @@ ol {
list-style: none; list-style: none;
} }
$lg-red: ( $lg-red: (
50: #faf3f6, 50: #fff9fc,
100: #f8bbd0, 100: #f8bbd0,
200: #f48fb1, 200: #f48fb1,
300: #f06292, /*300: #f06292,*/ 300: #ef4c73,
400: #ef4c73, 400: #ec407a,
/* 400: #ec407a,*/ 500: #ed097e, 500: #ed097e,
600: #d81b60, 600: #d81b60,
700: #c2185b, 700: #c2185b,
800: #ad1457, 800: #ad1457,
@ -84,7 +84,7 @@ $lg-red: (
) )
); );
$daesang: ( $aquaBlue-daesang: (
50: #f9feff, 50: #f9feff,
//#e0f7fa, //#e0f7fa,
100: #b2ebf2, 100: #b2ebf2,
@ -94,7 +94,7 @@ $daesang: (
400: #26c6da, 400: #26c6da,
500: #00bcd4, 500: #00bcd4,
/*600: #00acc1,*/ 600: #00b6d5, /*600: #00acc1,*/ 600: #00b6d5,
700: #0097a7, 700: #1ea7b9,
800: #0367a6, 800: #0367a6,
900: #024873, 900: #024873,
A100: #84ffff, A100: #84ffff,
@ -139,7 +139,7 @@ $daesang-grey: (
A100: #ffffff, A100: #ffffff,
A200: #eeeeee, A200: #eeeeee,
A400: #bdbdbd, A400: #bdbdbd,
A700: #616161, A700: #1e2b3a,
contrast: ( contrast: (
50: $dark-primary-text, 50: $dark-primary-text,
100: $dark-primary-text, 100: $dark-primary-text,
@ -173,6 +173,10 @@ $daesang-grey: (
$gradient-light: mat-color($accent, G100); $gradient-light: mat-color($accent, G100);
//basic //basic
.bg-primary-darkest {
background: mat-color($primary, 900);
color: mat-color($primary, default-contrast);
}
.bg-primary-dark { .bg-primary-dark {
background: mat-color($primary, 900); background: mat-color($primary, 900);
color: mat-color($primary, default-contrast); color: mat-color($primary, default-contrast);
@ -186,7 +190,7 @@ $daesang-grey: (
color: mat-color($primary, default-contrast); color: mat-color($primary, default-contrast);
} }
.bg-accent-darkest { .bg-accent-darkest {
background: mat-color($accent, 900); background: mat-color($accent, 800);
color: mat-color($primary, default-contrast); color: mat-color($primary, default-contrast);
} }
.bg-accent-dark { .bg-accent-dark {
@ -209,13 +213,13 @@ $daesang-grey: (
color: mat-color($primary); color: mat-color($primary);
} }
.text-accent-darkest { .text-accent-darkest {
color: mat-color($accent, 900); color: mat-color($accent, 800);
} }
.text-accent-color { .text-accent-color {
color: mat-color($accent); color: mat-color($accent);
} }
.text-warn-color { .text-warn-color {
color: mat-color($warn); color: mat-color($warn, 800);
} }
.border-primary-color { .border-primary-color {
border: 1px solid mat-color($primary); border: 1px solid mat-color($primary);
@ -223,7 +227,12 @@ $daesang-grey: (
.border-accent-color { .border-accent-color {
border: 1px solid mat-color($accent); border: 1px solid mat-color($accent);
} }
.border-warn-color {
border: mat-color($warn);
}
.stroke-warn-color {
stroke: mat-color($warn, 900);
}
// sass 정의 // sass 정의
.mat-toolbar { .mat-toolbar {
background-color: mat-color($accent, B100); background-color: mat-color($accent, B100);
@ -251,7 +260,11 @@ $daesang-grey: (
background-color: mat-color($accent, 400); background-color: mat-color($accent, 400);
} }
.mat-chip.mat-standard-chip.mat-chip-selected.mat-primary { .mat-chip.mat-standard-chip.mat-chip-selected.mat-primary {
background-color: mat-color($accent, 200); background-color: mat-color($accent, 700);
cursor: pointer;
.mat-chip-remove {
opacity: 0.6;
}
} }
.global-menu { .global-menu {
@ -341,7 +354,7 @@ $daesang-grey: (
} }
.profile-img { .profile-img {
.responsive-chats-button:last-child { .responsive-chats-button:last-child {
background-color: $gradient-light; background-color: mat-color($accent, B100);
} }
} }
} }

View File

@ -56,14 +56,14 @@
</mat-form-field> </mat-form-field>
<button <button
class="send-message-button bg-accent-darkest" class="send-message-button bg-primary-darkest"
mat-icon-button mat-icon-button
type="submit" type="submit"
aria-label="Send message" aria-label="Send message"
> >
<i class="material-icons"> <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor"
send stroke-width="2" stroke-linecap="butt" stroke-linejoin="round">
</i> <path d="M12 19V6M5 12l7-7 7 7" /></svg>
</button> </button>
</form> </form>
</div> </div>

View File

@ -42,7 +42,7 @@ export class FileComponent implements OnInit {
getExpiredFile() { getExpiredFile() {
if ( if (
!!this.eventInfoStatus && !!this.eventInfoStatus &&
this.eventInfoStatus.validFileBaseSeq < this.message.seq this.eventInfoStatus.validFileBaseSeq <= this.message.seq
) { ) {
return false; return false;
} else { } else {

View File

@ -28,8 +28,8 @@
.mat-card-header{ .mat-card-header{
justify-content: center; justify-content: center;
padding-bottom: 40px; padding-bottom: 40px;
background: #ce395d; background: #76d9c5;
background: linear-gradient(to right, #345385, #ef4c73); /*background: linear-gradient(to right, #345385, #ef4c73);*/
color: #ffffff; color: #ffffff;
padding-top: 20px; padding-top: 20px;
width:100%; width:100%;

View File

@ -1,12 +1,7 @@
<!--체크박스 보여줄때는 <div class="list-item checkbox" matRipple> 클래스에 checkbox만 추가--> <!--체크박스 보여줄때는 <div class="list-item checkbox" matRipple> 클래스에 checkbox만 추가-->
<div class="list-item" *ngIf="userInfo" matRipple> <div class="list-item" *ngIf="userInfo" matRipple>
<!--pcOn , pcOut pcOff , pcOther--> <!--pcOn , pcOut pcOff , pcOther-->
<span <span class="presence" [ngClass]="getPresence(PresenceType.PC)"> </span>
class="presence"
[ngClass]="getPresence(PresenceType.PC)"
*ngIf="presence && presence.pcStatus"
>{{ presence.pcStatus }}
</span>
<dl class="item-default"> <dl class="item-default">
<dt> <dt>
<img <img

View File

@ -1,7 +1,7 @@
.fab-container { .fab-container {
position: absolute; position: absolute;
bottom: 15px; bottom: 15px;
right: 15px; right: 40px;
z-index: 100; z-index: 100;
display: flex; display: flex;
flex-direction: column-reverse; flex-direction: column-reverse;