sync
This commit is contained in:
parent
98ff58c39e
commit
eded98a6cf
6
package-lock.json
generated
6
package-lock.json
generated
|
@ -2022,9 +2022,9 @@
|
||||||
"integrity": "sha512-GA9MDcwCvtxI0gOysgRm7DDHIfKfhCkDSa69QBFIEgWbob2OdGYKvxfymr6lGdl+vY7AqjlJXvSFkA1b0rTy1A=="
|
"integrity": "sha512-GA9MDcwCvtxI0gOysgRm7DDHIfKfhCkDSa69QBFIEgWbob2OdGYKvxfymr6lGdl+vY7AqjlJXvSFkA1b0rTy1A=="
|
||||||
},
|
},
|
||||||
"@ucap/ng-core": {
|
"@ucap/ng-core": {
|
||||||
"version": "0.0.7",
|
"version": "0.0.8",
|
||||||
"resolved": "https://nexus.loafle.net/repository/npm-all/@ucap/ng-core/-/ng-core-0.0.7.tgz",
|
"resolved": "https://nexus.loafle.net/repository/npm-all/@ucap/ng-core/-/ng-core-0.0.8.tgz",
|
||||||
"integrity": "sha512-ZC6LE3A0bg+REGbzDI/i1ad7mGpKsw6X0UtZ+Q8TUthHNv0DfWEieHFCgfYTRY1u022XyQ4ViOsrq9KunU1vfw=="
|
"integrity": "sha512-VMvitw2PnaGo4tsdD9EJcvzVi5Kt+xjzA6z09uLavPpAWViFXTx7P76N1nt7XMgACRAMOTMyNocWTbFs6oKsqA=="
|
||||||
},
|
},
|
||||||
"@ucap/ng-i18n": {
|
"@ucap/ng-i18n": {
|
||||||
"version": "0.0.6",
|
"version": "0.0.6",
|
||||||
|
|
91
package.json
91
package.json
|
@ -31,24 +31,39 @@
|
||||||
"@ngrx/entity": "^9.2.0",
|
"@ngrx/entity": "^9.2.0",
|
||||||
"@ngrx/router-store": "^9.2.0",
|
"@ngrx/router-store": "^9.2.0",
|
||||||
"@ngrx/store": "^9.2.0",
|
"@ngrx/store": "^9.2.0",
|
||||||
"@ucap/api": "~0.0.4",
|
"@ucap/api": "~0.0.5",
|
||||||
"@ucap/api-common": "~0.0.11",
|
"@ucap/api-common": "~0.0.12",
|
||||||
"@ucap/api-external": "~0.0.5",
|
"@ucap/api-contact": "~0.0.5",
|
||||||
"@ucap/api-message": "~0.0.3",
|
"@ucap/api-external": "~0.0.8",
|
||||||
"@ucap/api-prompt": "~0.0.3",
|
"@ucap/api-message": "~0.0.7",
|
||||||
"@ucap/api-public": "~0.0.4",
|
"@ucap/api-prompt": "~0.0.6",
|
||||||
"@ucap/core": "~0.0.14",
|
"@ucap/api-public": "~0.0.6",
|
||||||
"@ucap/logger": "~0.0.13",
|
"@ucap/api-webex": "~0.0.2",
|
||||||
"@ucap/native": "~0.0.19",
|
"@ucap/core": "~0.0.15",
|
||||||
|
"@ucap/domain-authentication": "~0.0.4",
|
||||||
|
"@ucap/domain-authorization": "~0.0.3",
|
||||||
|
"@ucap/domain-call": "~0.0.4",
|
||||||
|
"@ucap/domain-chat": "~0.0.3",
|
||||||
|
"@ucap/domain-common": "~0.0.1",
|
||||||
|
"@ucap/domain-group": "~0.0.2",
|
||||||
|
"@ucap/domain-message": "~0.0.1",
|
||||||
|
"@ucap/domain-organization": "~0.0.1",
|
||||||
|
"@ucap/domain-status": "~0.0.1",
|
||||||
|
"@ucap/electron-native": "~0.0.19",
|
||||||
|
"@ucap/i18n": "~0.0.2",
|
||||||
|
"@ucap/logger": "~0.0.14",
|
||||||
|
"@ucap/native": "~0.0.27",
|
||||||
"@ucap/ng-api-common": "~0.0.1",
|
"@ucap/ng-api-common": "~0.0.1",
|
||||||
"@ucap/ng-api-external": "~0.0.1",
|
"@ucap/ng-api-external": "~0.0.1",
|
||||||
"@ucap/ng-api-message": "~0.0.1",
|
"@ucap/ng-api-message": "~0.0.1",
|
||||||
"@ucap/ng-api-prompt": "~0.0.1",
|
"@ucap/ng-api-prompt": "~0.0.1",
|
||||||
"@ucap/ng-api-public": "~0.0.1",
|
"@ucap/ng-api-public": "~0.0.1",
|
||||||
"@ucap/ng-core": "~0.0.7",
|
"@ucap/ng-api-webex": "~0.0.1",
|
||||||
|
"@ucap/ng-api-contact": "~0.0.2",
|
||||||
|
"@ucap/ng-core": "~0.0.9",
|
||||||
"@ucap/ng-logger": "~0.0.2",
|
"@ucap/ng-logger": "~0.0.2",
|
||||||
"@ucap/ng-i18n": "~0.0.6",
|
"@ucap/ng-i18n": "~0.0.8",
|
||||||
"@ucap/ng-native": "~0.0.5",
|
"@ucap/ng-native": "~0.0.12",
|
||||||
"@ucap/ng-pi": "~0.0.1",
|
"@ucap/ng-pi": "~0.0.1",
|
||||||
"@ucap/ng-protocol": "~0.0.3",
|
"@ucap/ng-protocol": "~0.0.3",
|
||||||
"@ucap/ng-protocol-authentication": "~0.0.3",
|
"@ucap/ng-protocol-authentication": "~0.0.3",
|
||||||
|
@ -66,35 +81,37 @@
|
||||||
"@ucap/ng-protocol-status": "~0.0.3",
|
"@ucap/ng-protocol-status": "~0.0.3",
|
||||||
"@ucap/ng-protocol-sync": "~0.0.3",
|
"@ucap/ng-protocol-sync": "~0.0.3",
|
||||||
"@ucap/ng-protocol-umg": "~0.0.3",
|
"@ucap/ng-protocol-umg": "~0.0.3",
|
||||||
"@ucap/ng-store-authentication": "~0.0.14",
|
"@ucap/ng-store-authentication": "~0.0.17",
|
||||||
"@ucap/ng-store-chat": "~0.0.66",
|
"@ucap/ng-store-chat": "~0.0.74",
|
||||||
"@ucap/ng-store-group": "~0.0.22",
|
"@ucap/ng-store-group": "~0.0.25",
|
||||||
"@ucap/ng-store-organization": "~0.0.20",
|
"@ucap/ng-store-organization": "~0.0.23",
|
||||||
|
"@ucap/ng-store-call": "~0.0.7",
|
||||||
"@ucap/ng-web-socket": "~0.0.2",
|
"@ucap/ng-web-socket": "~0.0.2",
|
||||||
"@ucap/ng-web-storage": "~0.0.3",
|
"@ucap/ng-web-storage": "~0.0.3",
|
||||||
"@ucap/ng-ui": "0.0.97",
|
"@ucap/ng-ui": "~0.0.108",
|
||||||
"@ucap/ng-ui-organization": "~0.0.202",
|
"@ucap/ng-ui-organization": "~0.0.222",
|
||||||
"@ucap/ng-ui-authentication": "~0.0.29",
|
"@ucap/ng-ui-authentication": "~0.0.32",
|
||||||
"@ucap/ng-ui-group": "~0.0.78",
|
"@ucap/ng-ui-group": "~0.0.87",
|
||||||
"@ucap/ng-ui-chat": "~0.0.72",
|
"@ucap/ng-ui-chat": "~0.0.80",
|
||||||
|
"@ucap/ng-ui-call": "~0.0.15",
|
||||||
"@ucap/ng-ui-material": "~0.0.4",
|
"@ucap/ng-ui-material": "~0.0.4",
|
||||||
"@ucap/ng-ui-skin-default": "~0.0.1",
|
"@ucap/ng-ui-skin-default": "~0.0.1",
|
||||||
"@ucap/pi": "~0.0.8",
|
"@ucap/pi": "~0.0.9",
|
||||||
"@ucap/protocol": "~0.0.17",
|
"@ucap/protocol": "~0.0.20",
|
||||||
"@ucap/protocol-authentication": "~0.0.5",
|
"@ucap/protocol-authentication": "~0.0.7",
|
||||||
"@ucap/protocol-buddy": "~0.0.5",
|
"@ucap/protocol-buddy": "~0.0.6",
|
||||||
"@ucap/protocol-event": "~0.0.6",
|
"@ucap/protocol-event": "~0.0.11",
|
||||||
"@ucap/protocol-file": "~0.0.6",
|
"@ucap/protocol-file": "~0.0.7",
|
||||||
"@ucap/protocol-group": "~0.0.5",
|
"@ucap/protocol-group": "~0.0.6",
|
||||||
"@ucap/protocol-info": "~0.0.9",
|
"@ucap/protocol-info": "~0.0.10",
|
||||||
"@ucap/protocol-inner": "~0.0.4",
|
"@ucap/protocol-inner": "~0.0.5",
|
||||||
"@ucap/protocol-option": "~0.0.7",
|
"@ucap/protocol-option": "~0.0.9",
|
||||||
"@ucap/protocol-ping": "~0.0.6",
|
"@ucap/protocol-ping": "~0.0.7",
|
||||||
"@ucap/protocol-query": "~0.0.5",
|
"@ucap/protocol-query": "~0.0.8",
|
||||||
"@ucap/protocol-room": "~0.0.7",
|
"@ucap/protocol-room": "~0.0.9",
|
||||||
"@ucap/protocol-service": "~0.0.4",
|
"@ucap/protocol-service": "~0.0.5",
|
||||||
"@ucap/protocol-status": "~0.0.5",
|
"@ucap/protocol-status": "~0.0.6",
|
||||||
"@ucap/protocol-sync": "~0.0.6",
|
"@ucap/protocol-sync": "~0.0.8",
|
||||||
"@ucap/protocol-umg": "~0.0.5",
|
"@ucap/protocol-umg": "~0.0.5",
|
||||||
"@ucap/ui-scss": "~0.0.5",
|
"@ucap/ui-scss": "~0.0.5",
|
||||||
"@ucap/web-socket": "~0.0.10",
|
"@ucap/web-socket": "~0.0.10",
|
||||||
|
|
|
@ -15,10 +15,13 @@ import { AppAuthenticationService } from './services/app-authentication.service'
|
||||||
import { AppNotificationService } from './services/app-notification.service';
|
import { AppNotificationService } from './services/app-notification.service';
|
||||||
import { AppNativeService } from './services/app-native.service';
|
import { AppNativeService } from './services/app-native.service';
|
||||||
import { AppService } from './services/app.service';
|
import { AppService } from './services/app.service';
|
||||||
|
import { AppCallService } from './services/app-call.service';
|
||||||
import { AppChatService } from './services/app-chat.service';
|
import { AppChatService } from './services/app-chat.service';
|
||||||
import { AppFileService } from './services/app-file.service';
|
import { AppFileService } from './services/app-file.service';
|
||||||
import { AppGroupService } from './services/app-group.service';
|
import { AppGroupService } from './services/app-group.service';
|
||||||
import { AppAccountService } from './services/app-account.service';
|
import { AppAccountService } from './services/app-account.service';
|
||||||
|
import { AppUiService } from './services/app-ui.service';
|
||||||
|
import { AppOrganizationService } from './services/app-organization.service';
|
||||||
|
|
||||||
const GUARDS = [AppAuthenticationGuard];
|
const GUARDS = [AppAuthenticationGuard];
|
||||||
const RESOLVERS = [AppSessionResolver];
|
const RESOLVERS = [AppSessionResolver];
|
||||||
|
@ -27,10 +30,13 @@ const SERVICES = [
|
||||||
AppAuthenticationService,
|
AppAuthenticationService,
|
||||||
AppNativeService,
|
AppNativeService,
|
||||||
AppFileService,
|
AppFileService,
|
||||||
|
AppCallService,
|
||||||
AppChatService,
|
AppChatService,
|
||||||
AppNotificationService,
|
AppNotificationService,
|
||||||
|
AppOrganizationService,
|
||||||
AppGroupService,
|
AppGroupService,
|
||||||
AppAccountService
|
AppAccountService,
|
||||||
|
AppUiService
|
||||||
];
|
];
|
||||||
|
|
||||||
const axiosFactory = () => {
|
const axiosFactory = () => {
|
||||||
|
|
|
@ -6,11 +6,12 @@ import { NoNaviLayoutComponent } from '@app/layouts/components/no-navi.layout.co
|
||||||
|
|
||||||
import { AppAuthenticationGuard } from '@app/guards/app-authentication.guard';
|
import { AppAuthenticationGuard } from '@app/guards/app-authentication.guard';
|
||||||
import { AppSessionResolver } from './resolvers/app-session.resolver';
|
import { AppSessionResolver } from './resolvers/app-session.resolver';
|
||||||
|
import { NavigationType } from './types';
|
||||||
|
|
||||||
const routes: Routes = [
|
const routes: Routes = [
|
||||||
{
|
{
|
||||||
path: '',
|
path: '',
|
||||||
redirectTo: '/group/(content:index)',
|
redirectTo: `/${NavigationType.Group}/(content:index)`,
|
||||||
pathMatch: 'full'
|
pathMatch: 'full'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -38,35 +39,35 @@ const routes: Routes = [
|
||||||
},
|
},
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: 'organization',
|
path: NavigationType.Organization,
|
||||||
loadChildren: () =>
|
loadChildren: () =>
|
||||||
import('./pages/organization/organization.page.module').then(
|
import('./pages/organization/organization.page.module').then(
|
||||||
(m) => m.AppOrganizationPageModule
|
(m) => m.AppOrganizationPageModule
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'group',
|
path: NavigationType.Group,
|
||||||
loadChildren: () =>
|
loadChildren: () =>
|
||||||
import('./pages/group/group.page.module').then(
|
import('./pages/group/group.page.module').then(
|
||||||
(m) => m.AppGroupPageModule
|
(m) => m.AppGroupPageModule
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'chat',
|
path: NavigationType.Chat,
|
||||||
loadChildren: () =>
|
loadChildren: () =>
|
||||||
import('./pages/chat/chat.page.module').then(
|
import('./pages/chat/chat.page.module').then(
|
||||||
(m) => m.AppChatPageModule
|
(m) => m.AppChatPageModule
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'call',
|
path: NavigationType.Call,
|
||||||
loadChildren: () =>
|
loadChildren: () =>
|
||||||
import('./pages/call/call.page.module').then(
|
import('./pages/call/call.page.module').then(
|
||||||
(m) => m.AppCallPageModule
|
(m) => m.AppCallPageModule
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'message',
|
path: NavigationType.Message,
|
||||||
loadChildren: () =>
|
loadChildren: () =>
|
||||||
import('./pages/message/message.page.module').then(
|
import('./pages/message/message.page.module').then(
|
||||||
(m) => m.AppMessagePageModule
|
(m) => m.AppMessagePageModule
|
||||||
|
|
|
@ -1,30 +1,44 @@
|
||||||
|
import { fromEvent, interval, Subject } from 'rxjs';
|
||||||
|
import { debounce, takeUntil } from 'rxjs/operators';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Component,
|
Component,
|
||||||
OnDestroy,
|
OnDestroy,
|
||||||
OnInit,
|
OnInit,
|
||||||
AfterViewInit,
|
AfterViewInit,
|
||||||
Renderer2
|
Renderer2,
|
||||||
|
Inject
|
||||||
} from '@angular/core';
|
} from '@angular/core';
|
||||||
|
import { DOCUMENT } from '@angular/common';
|
||||||
|
import { Router } from '@angular/router';
|
||||||
|
|
||||||
import { Store } from '@ngrx/store';
|
import { Store } from '@ngrx/store';
|
||||||
|
|
||||||
|
import { NativeService } from '@ucap/native';
|
||||||
|
|
||||||
|
import { UCAP_NATIVE_SERVICE } from '@ucap/ng-native';
|
||||||
|
|
||||||
import { AppActions } from '@app/store/actions';
|
import { AppActions } from '@app/store/actions';
|
||||||
import { fromEvent, interval, Subject } from 'rxjs';
|
|
||||||
import { debounce, takeUntil } from 'rxjs/operators';
|
|
||||||
import { AppAuthenticationService } from './services/app-authentication.service';
|
import { AppAuthenticationService } from './services/app-authentication.service';
|
||||||
|
import { AnimationBuilder, style, animate } from '@angular/animations';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-root',
|
selector: 'app-root',
|
||||||
templateUrl: './app.component.html',
|
templateUrl: './app.component.html',
|
||||||
styleUrls: ['./app.component.scss']
|
styleUrls: ['./app.component.scss']
|
||||||
})
|
})
|
||||||
export class AppComponent implements OnInit, OnDestroy, AfterViewInit {
|
export class AppComponent implements OnInit, OnDestroy {
|
||||||
private ngOnDestroySubject: Subject<void> = new Subject();
|
private ngOnDestroySubject: Subject<void> = new Subject();
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
|
private router: Router,
|
||||||
private renderer2: Renderer2,
|
private renderer2: Renderer2,
|
||||||
private store: Store<any>,
|
private store: Store<any>,
|
||||||
private appAuthenticationService: AppAuthenticationService
|
private appAuthenticationService: AppAuthenticationService,
|
||||||
|
@Inject(UCAP_NATIVE_SERVICE) private nativeService: NativeService,
|
||||||
|
@Inject(DOCUMENT) private _document: any,
|
||||||
|
private _animationBuilder: AnimationBuilder
|
||||||
) {
|
) {
|
||||||
fromEvent(window, 'resize')
|
fromEvent(window, 'resize')
|
||||||
.pipe(
|
.pipe(
|
||||||
|
@ -38,6 +52,12 @@ export class AppComponent implements OnInit, OnDestroy, AfterViewInit {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
fromEvent(window, 'unload')
|
||||||
|
.pipe(takeUntil(this.ngOnDestroySubject))
|
||||||
|
.subscribe((event: any) => {
|
||||||
|
this.nativeService.app_postDestroy();
|
||||||
|
});
|
||||||
|
|
||||||
// fromEvent(window, 'beforeunload')
|
// fromEvent(window, 'beforeunload')
|
||||||
// .pipe(takeUntil(this.ngOnDestroySubject))
|
// .pipe(takeUntil(this.ngOnDestroySubject))
|
||||||
// .subscribe((event: any) => {
|
// .subscribe((event: any) => {
|
||||||
|
@ -50,6 +70,53 @@ export class AppComponent implements OnInit, OnDestroy, AfterViewInit {
|
||||||
width: window.innerWidth,
|
width: window.innerWidth,
|
||||||
height: window.innerHeight
|
height: window.innerHeight
|
||||||
});
|
});
|
||||||
|
this.nativeService.app_postInit().then((info) => {
|
||||||
|
if (!info) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!!info.initUrl) {
|
||||||
|
this.router.navigateByUrl(info.initUrl);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const splash = this._document.body.querySelector('#ucap-lg-web-splash');
|
||||||
|
const player = this._animationBuilder
|
||||||
|
.build([
|
||||||
|
style({ opacity: '1' }),
|
||||||
|
animate(
|
||||||
|
'400ms ease',
|
||||||
|
style({
|
||||||
|
opacity: '0',
|
||||||
|
zIndex: '-10'
|
||||||
|
})
|
||||||
|
)
|
||||||
|
])
|
||||||
|
.create(splash);
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
player.play();
|
||||||
|
}, 0);
|
||||||
|
|
||||||
|
// const preloader = this.renderer2.selectRootElement(
|
||||||
|
// '#ucap-lg-web-preloader'
|
||||||
|
// );
|
||||||
|
// const fadeEffect = setInterval(() => {
|
||||||
|
// if (!preloader.style.opacity) {
|
||||||
|
// this.renderer2.setStyle(preloader, 'opacity', 1);
|
||||||
|
// }
|
||||||
|
// if (preloader.style.opacity > 0) {
|
||||||
|
// this.renderer2.setStyle(
|
||||||
|
// preloader,
|
||||||
|
// 'opacity',
|
||||||
|
// preloader.style.opacity - 0.1
|
||||||
|
// );
|
||||||
|
// } else {
|
||||||
|
// this.renderer2.setStyle(preloader, 'display', 'none');
|
||||||
|
// clearInterval(fadeEffect);
|
||||||
|
// }
|
||||||
|
// }, 200);
|
||||||
|
|
||||||
|
// this.renderer2.setStyle(preloader, 'display', 'none');
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnDestroy(): void {
|
ngOnDestroy(): void {
|
||||||
|
@ -59,13 +126,6 @@ export class AppComponent implements OnInit, OnDestroy, AfterViewInit {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ngAfterViewInit(): void {
|
|
||||||
const preloader = this.renderer2.selectRootElement(
|
|
||||||
'#ucap-lg-web-preloader'
|
|
||||||
);
|
|
||||||
this.renderer2.setStyle(preloader, 'display', 'none');
|
|
||||||
}
|
|
||||||
|
|
||||||
private dispatchWindowSize(size: { width: number; height: number }) {
|
private dispatchWindowSize(size: { width: number; height: number }) {
|
||||||
this.store.dispatch(AppActions.windowResized(size));
|
this.store.dispatch(AppActions.windowResized(size));
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,8 +15,10 @@ import { LoggerModule } from '@ucap/ng-logger';
|
||||||
import { CommonApiModule } from '@ucap/ng-api-common';
|
import { CommonApiModule } from '@ucap/ng-api-common';
|
||||||
import { PublicApiModule } from '@ucap/ng-api-public';
|
import { PublicApiModule } from '@ucap/ng-api-public';
|
||||||
import { ExternalApiModule } from '@ucap/ng-api-external';
|
import { ExternalApiModule } from '@ucap/ng-api-external';
|
||||||
|
import { ContactApiModule } from '@ucap/ng-api-contact';
|
||||||
import { MessageApiModule } from '@ucap/ng-api-message';
|
import { MessageApiModule } from '@ucap/ng-api-message';
|
||||||
import { PromptApiModule } from '@ucap/ng-api-prompt';
|
import { PromptApiModule } from '@ucap/ng-api-prompt';
|
||||||
|
import { WebexApiModule } from '@ucap/ng-api-webex';
|
||||||
|
|
||||||
import { PiModule } from '@ucap/ng-pi';
|
import { PiModule } from '@ucap/ng-pi';
|
||||||
|
|
||||||
|
@ -46,6 +48,7 @@ import { OrganizationStoreModule } from '@ucap/ng-store-organization';
|
||||||
import { AuthenticationStoreModule } from '@ucap/ng-store-authentication';
|
import { AuthenticationStoreModule } from '@ucap/ng-store-authentication';
|
||||||
import { GroupStoreModule } from '@ucap/ng-store-group';
|
import { GroupStoreModule } from '@ucap/ng-store-group';
|
||||||
import { ChatStoreModule } from '@ucap/ng-store-chat';
|
import { ChatStoreModule } from '@ucap/ng-store-chat';
|
||||||
|
import { CallStoreModule } from '@ucap/ng-store-call';
|
||||||
|
|
||||||
import { OrganizationUiModule } from '@ucap/ng-ui-organization';
|
import { OrganizationUiModule } from '@ucap/ng-ui-organization';
|
||||||
|
|
||||||
|
@ -62,6 +65,7 @@ import { metaReducers } from '@app/store/state';
|
||||||
import { AppAccountDialogModule } from '@app/dialogs/account/account.dialog.module';
|
import { AppAccountDialogModule } from '@app/dialogs/account/account.dialog.module';
|
||||||
|
|
||||||
import { environment } from '@environments';
|
import { environment } from '@environments';
|
||||||
|
import { MatDialogModule } from '@angular/material/dialog';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [AppComponent],
|
declarations: [AppComponent],
|
||||||
|
@ -121,13 +125,17 @@ import { environment } from '@environments';
|
||||||
*/
|
*/
|
||||||
EffectsModule.forRoot([...effects]),
|
EffectsModule.forRoot([...effects]),
|
||||||
|
|
||||||
|
MatDialogModule,
|
||||||
|
|
||||||
LoggerModule.forRoot({}),
|
LoggerModule.forRoot({}),
|
||||||
|
|
||||||
CommonApiModule.forRoot(environment.commonApiModuleConfig),
|
CommonApiModule.forRoot(environment.commonApiModuleConfig),
|
||||||
PublicApiModule.forRoot(environment.publicApiModuleConfig),
|
PublicApiModule.forRoot(environment.publicApiModuleConfig),
|
||||||
ExternalApiModule.forRoot(environment.externalApiModuleConfig),
|
ExternalApiModule.forRoot(environment.externalApiModuleConfig),
|
||||||
|
ContactApiModule.forRoot(environment.contactApiModuleConfig),
|
||||||
MessageApiModule.forRoot(environment.messageApiModuleConfig),
|
MessageApiModule.forRoot(environment.messageApiModuleConfig),
|
||||||
PromptApiModule.forRoot(environment.promptApiModuleConfig),
|
PromptApiModule.forRoot(environment.promptApiModuleConfig),
|
||||||
|
WebexApiModule.forRoot(environment.webexApiModuleConfig),
|
||||||
|
|
||||||
PiModule.forRoot(environment.piModuleConfig),
|
PiModule.forRoot(environment.piModuleConfig),
|
||||||
|
|
||||||
|
@ -162,6 +170,10 @@ import { environment } from '@environments';
|
||||||
eventRequestDefaultCount:
|
eventRequestDefaultCount:
|
||||||
environment.productConfig.chat.eventRequestDefaultCount
|
environment.productConfig.chat.eventRequestDefaultCount
|
||||||
}),
|
}),
|
||||||
|
CallStoreModule.forRoot({
|
||||||
|
historyRequestDefaultCount:
|
||||||
|
environment.productConfig.call.historyRequestDefaultCount
|
||||||
|
}),
|
||||||
|
|
||||||
OrganizationUiModule.forRoot({}),
|
OrganizationUiModule.forRoot({}),
|
||||||
|
|
||||||
|
|
|
@ -13,11 +13,12 @@ import { MatSelectModule } from '@angular/material/select';
|
||||||
import { MatTabsModule } from '@angular/material/tabs';
|
import { MatTabsModule } from '@angular/material/tabs';
|
||||||
|
|
||||||
import { I18nModule } from '@ucap/ng-i18n';
|
import { I18nModule } from '@ucap/ng-i18n';
|
||||||
import { UiModule } from '@ucap/ng-ui';
|
|
||||||
|
import { UiscrollingModule } from '@ucap/ng-ui/scrolling';
|
||||||
|
|
||||||
import { AppLayoutsModule } from '@app/layouts/layouts.module';
|
import { AppLayoutsModule } from '@app/layouts/layouts.module';
|
||||||
import { AppAccountSectionModule } from '@app/sections/account/account.section.module';
|
import { AppAccountSectionModule } from '@app/sections/account/account.section.module';
|
||||||
|
import { AppAuthenticationModule } from '@app/ucap/authentication/authentication.module';
|
||||||
import { COMPONENTS } from './components';
|
import { COMPONENTS } from './components';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
|
@ -36,7 +37,9 @@ import { COMPONENTS } from './components';
|
||||||
|
|
||||||
I18nModule,
|
I18nModule,
|
||||||
|
|
||||||
UiModule,
|
UiscrollingModule,
|
||||||
|
|
||||||
|
AppAuthenticationModule,
|
||||||
|
|
||||||
AppLayoutsModule,
|
AppLayoutsModule,
|
||||||
AppAccountSectionModule
|
AppAccountSectionModule
|
||||||
|
|
|
@ -30,7 +30,10 @@
|
||||||
<div class="settings-contents">
|
<div class="settings-contents">
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
<mat-checkbox>
|
<mat-checkbox
|
||||||
|
[value]="settings.general.autoLaunch"
|
||||||
|
(change)="onChangeForAutoStartOnBoot($event)"
|
||||||
|
>
|
||||||
{{
|
{{
|
||||||
'authentication:login.settings.autoStartOnBoot'
|
'authentication:login.settings.autoStartOnBoot'
|
||||||
| ucapI18n
|
| ucapI18n
|
||||||
|
@ -38,12 +41,18 @@
|
||||||
</mat-checkbox>
|
</mat-checkbox>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<mat-checkbox>
|
<mat-checkbox
|
||||||
|
[value]="settings.general.autoLogin"
|
||||||
|
(change)="onChangeForAutoLogin($event)"
|
||||||
|
>
|
||||||
{{ 'authentication:login.settings.autoLogin' | ucapI18n }}
|
{{ 'authentication:login.settings.autoLogin' | ucapI18n }}
|
||||||
</mat-checkbox>
|
</mat-checkbox>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<mat-checkbox>
|
<mat-checkbox
|
||||||
|
[value]="settings.general.startupHideWindow"
|
||||||
|
(change)="onChangeForAutoHide($event)"
|
||||||
|
>
|
||||||
{{ 'authentication:login.settings.autoHide' | ucapI18n }}
|
{{ 'authentication:login.settings.autoHide' | ucapI18n }}
|
||||||
</mat-checkbox>
|
</mat-checkbox>
|
||||||
</li>
|
</li>
|
||||||
|
@ -66,7 +75,7 @@
|
||||||
class="setting-select-obj ucap-mat-input-container"
|
class="setting-select-obj ucap-mat-input-container"
|
||||||
>
|
>
|
||||||
<mat-select
|
<mat-select
|
||||||
[value]="generalSetting.locale"
|
[value]="settings.general.locale"
|
||||||
(selectionChange)="onSelectionChangeLanguage($event)"
|
(selectionChange)="onSelectionChangeLanguage($event)"
|
||||||
>
|
>
|
||||||
<mat-option
|
<mat-option
|
||||||
|
@ -95,7 +104,7 @@
|
||||||
class="setting-select-obj ucap-mat-input-container"
|
class="setting-select-obj ucap-mat-input-container"
|
||||||
>
|
>
|
||||||
<mat-select
|
<mat-select
|
||||||
[value]="generalSetting.hrInfoLocale"
|
[value]="settings.general.hrInfoLocale"
|
||||||
(selectionChange)="onSelectionChangeHrLanguage($event)"
|
(selectionChange)="onSelectionChangeHrLanguage($event)"
|
||||||
>
|
>
|
||||||
<mat-option
|
<mat-option
|
||||||
|
@ -122,10 +131,13 @@
|
||||||
class="setting-select-obj ucap-mat-input-container"
|
class="setting-select-obj ucap-mat-input-container"
|
||||||
>
|
>
|
||||||
<mat-select
|
<mat-select
|
||||||
|
[class.ucap-select-placeholder-value]="
|
||||||
|
!!timezonePlaceholder
|
||||||
|
"
|
||||||
#selectForTimezone
|
#selectForTimezone
|
||||||
[formControl]="formControlForTimezone"
|
[formControl]="formControlForTimezone"
|
||||||
[placeholder]="timezonePlaceholder"
|
[placeholder]="timezonePlaceholder"
|
||||||
[value]="generalSetting.timezone"
|
[value]="settings.general.timezone"
|
||||||
(openedChange)="onOpenedChangeTimezone($event)"
|
(openedChange)="onOpenedChangeTimezone($event)"
|
||||||
>
|
>
|
||||||
<ucap-virtual-scroll-viewport
|
<ucap-virtual-scroll-viewport
|
||||||
|
@ -162,6 +174,8 @@
|
||||||
<mat-radio-group
|
<mat-radio-group
|
||||||
aria-label="Select an type of alarm"
|
aria-label="Select an type of alarm"
|
||||||
class="settings-radio-group"
|
class="settings-radio-group"
|
||||||
|
[value]="String(settings.notification.use)"
|
||||||
|
(change)="onChangeForReceiveNotification($event)"
|
||||||
>
|
>
|
||||||
<mat-radio-button value="true">
|
<mat-radio-button value="true">
|
||||||
{{
|
{{
|
||||||
|
@ -186,20 +200,25 @@
|
||||||
appearance="standard"
|
appearance="standard"
|
||||||
class="setting-select-obj ucap-mat-input-container"
|
class="setting-select-obj ucap-mat-input-container"
|
||||||
>
|
>
|
||||||
<mat-select>
|
<mat-select
|
||||||
<mat-option value="sound">
|
[value]="settings.notification.method"
|
||||||
|
(selectionChange)="
|
||||||
|
onSelectionChangeMethodOfNotification($event)
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<mat-option [value]="NotificationMethod.Sound">
|
||||||
{{
|
{{
|
||||||
'organization:settings.notification.methodTypeSound'
|
'organization:settings.notification.methodTypeSound'
|
||||||
| ucapI18n
|
| ucapI18n
|
||||||
}}
|
}}
|
||||||
</mat-option>
|
</mat-option>
|
||||||
<mat-option value="alert">
|
<mat-option [value]="NotificationMethod.Alert">
|
||||||
{{
|
{{
|
||||||
'organization:settings.notification.methodTypeAlert'
|
'organization:settings.notification.methodTypeAlert'
|
||||||
| ucapI18n
|
| ucapI18n
|
||||||
}}
|
}}
|
||||||
</mat-option>
|
</mat-option>
|
||||||
<mat-option value="soundAndAlert">
|
<mat-option [value]="NotificationMethod.SoundAndAlert">
|
||||||
{{
|
{{
|
||||||
'organization:settings.notification.methodTypeSoundAndAlert'
|
'organization:settings.notification.methodTypeSoundAndAlert'
|
||||||
| ucapI18n
|
| ucapI18n
|
||||||
|
@ -222,7 +241,12 @@
|
||||||
appearance="standard"
|
appearance="standard"
|
||||||
class="setting-select-obj ucap-mat-input-container"
|
class="setting-select-obj ucap-mat-input-container"
|
||||||
>
|
>
|
||||||
<mat-select>
|
<mat-select
|
||||||
|
[value]="String(settings.notification.alertExposureTime)"
|
||||||
|
(selectionChange)="
|
||||||
|
onSelectionChangeAlertExposureTimeOfNotification($event)
|
||||||
|
"
|
||||||
|
>
|
||||||
<mat-option value="5">
|
<mat-option value="5">
|
||||||
5{{ 'common:units.second' | ucapI18n }}
|
5{{ 'common:units.second' | ucapI18n }}
|
||||||
</mat-option>
|
</mat-option>
|
||||||
|
@ -249,7 +273,12 @@
|
||||||
<div class="settings-contents">
|
<div class="settings-contents">
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
<mat-checkbox>
|
<mat-checkbox
|
||||||
|
[value]="settings.notification.receiveForMessage"
|
||||||
|
(change)="
|
||||||
|
onChangeForReceiveForMessageOfNotification($event)
|
||||||
|
"
|
||||||
|
>
|
||||||
{{
|
{{
|
||||||
'organization:settings.notification.receiveForMessageTypePopup'
|
'organization:settings.notification.receiveForMessageTypePopup'
|
||||||
| ucapI18n
|
| ucapI18n
|
||||||
|
@ -269,7 +298,7 @@
|
||||||
<!-- 대화 -->
|
<!-- 대화 -->
|
||||||
<div class="messenger-settings-area">
|
<div class="messenger-settings-area">
|
||||||
<div class="title-settings-subject">파일 전송</div>
|
<div class="title-settings-subject">파일 전송</div>
|
||||||
<div class="settings-contents02">
|
<div class="settings-contents02" *ngIf="'electron' === platform">
|
||||||
<div class="subtitle-settings-info">
|
<div class="subtitle-settings-info">
|
||||||
다운로드 폴더
|
다운로드 폴더
|
||||||
</div>
|
</div>
|
||||||
|
@ -278,18 +307,12 @@
|
||||||
color="accent"
|
color="accent"
|
||||||
class="setting-input-obj input-set-obj ucap-mat-input-container"
|
class="setting-input-obj input-set-obj ucap-mat-input-container"
|
||||||
>
|
>
|
||||||
<input
|
<input matInput placeholder="" value="" />
|
||||||
matInput
|
|
||||||
placeholder=""
|
|
||||||
value=""
|
|
||||||
[readonly]="'browser' === platform"
|
|
||||||
/>
|
|
||||||
<button
|
<button
|
||||||
mat-button
|
mat-button
|
||||||
matSuffix
|
matSuffix
|
||||||
mat-icon-button
|
mat-icon-button
|
||||||
aria-label="file"
|
aria-label="file"
|
||||||
[disabled]="'browser' === platform"
|
|
||||||
>
|
>
|
||||||
<mat-icon>folder</mat-icon>
|
<mat-icon>folder</mat-icon>
|
||||||
</button>
|
</button>
|
||||||
|
@ -299,7 +322,6 @@
|
||||||
mat-stroked-button
|
mat-stroked-button
|
||||||
color="primary"
|
color="primary"
|
||||||
class="btn-folder-first"
|
class="btn-folder-first"
|
||||||
[disabled]="'browser' === platform"
|
|
||||||
>
|
>
|
||||||
폴더 초기화
|
폴더 초기화
|
||||||
</button>
|
</button>
|
||||||
|
@ -338,123 +360,7 @@
|
||||||
</ng-template>
|
</ng-template>
|
||||||
<div class="secret-num-settings-area">
|
<div class="secret-num-settings-area">
|
||||||
<!-- 비밀번호 -->
|
<!-- 비밀번호 -->
|
||||||
<div class="messenger-settings-area">
|
<app-authentication-change-password></app-authentication-change-password>
|
||||||
<div class="title-settings-subject">
|
|
||||||
{{ 'authentication:password.fields.changePassword' | ucapI18n }}
|
|
||||||
</div>
|
|
||||||
<div class="settings-contents02">
|
|
||||||
<div class="subtitle-settings-info">
|
|
||||||
{{
|
|
||||||
'authentication:password.fields.currentPassword' | ucapI18n
|
|
||||||
}}
|
|
||||||
</div>
|
|
||||||
<div class="settings-sub-content">
|
|
||||||
<mat-form-field
|
|
||||||
color="accent"
|
|
||||||
class="setting-input-obj ucap-mat-input-container"
|
|
||||||
>
|
|
||||||
<input
|
|
||||||
matInput
|
|
||||||
placeholder="{{
|
|
||||||
'authentication:password.placeholder.currentPassword'
|
|
||||||
| ucapI18n
|
|
||||||
}}"
|
|
||||||
value=""
|
|
||||||
/>
|
|
||||||
<button
|
|
||||||
mat-button
|
|
||||||
matSuffix
|
|
||||||
mat-icon-button
|
|
||||||
aria-label="action"
|
|
||||||
>
|
|
||||||
<mat-icon>done</mat-icon>
|
|
||||||
</button>
|
|
||||||
<mat-hint>Hint</mat-hint>
|
|
||||||
</mat-form-field>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="settings-contents02">
|
|
||||||
<div class="subtitle-settings-info">
|
|
||||||
{{ 'authentication:password.fields.newPassword' | ucapI18n }}
|
|
||||||
</div>
|
|
||||||
<div class="settings-sub-content">
|
|
||||||
<mat-form-field
|
|
||||||
color="accent"
|
|
||||||
class="setting-input-obj ucap-mat-input-container"
|
|
||||||
>
|
|
||||||
<input
|
|
||||||
matInput
|
|
||||||
placeholder="{{
|
|
||||||
'authentication:password.placeholder.newPassword'
|
|
||||||
| ucapI18n
|
|
||||||
}}"
|
|
||||||
value=""
|
|
||||||
/>
|
|
||||||
<button
|
|
||||||
mat-button
|
|
||||||
matSuffix
|
|
||||||
mat-icon-button
|
|
||||||
aria-label="action"
|
|
||||||
>
|
|
||||||
<mat-icon>done</mat-icon>
|
|
||||||
</button>
|
|
||||||
<mat-hint
|
|
||||||
>반드시 영어 소문자, 숫자, 특수문자 중 2가지 이상 사용해야
|
|
||||||
합니다.</mat-hint
|
|
||||||
>
|
|
||||||
</mat-form-field>
|
|
||||||
|
|
||||||
<mat-form-field
|
|
||||||
color="accent"
|
|
||||||
class="setting-input-obj ucap-mat-input-container"
|
|
||||||
>
|
|
||||||
<input
|
|
||||||
matInput
|
|
||||||
placeholder="{{
|
|
||||||
'authentication:password.placeholder.newPasswordConfirm'
|
|
||||||
| ucapI18n
|
|
||||||
}}"
|
|
||||||
value=""
|
|
||||||
/>
|
|
||||||
<button
|
|
||||||
mat-button
|
|
||||||
matSuffix
|
|
||||||
mat-icon-button
|
|
||||||
aria-label="action"
|
|
||||||
>
|
|
||||||
<mat-icon>done</mat-icon>
|
|
||||||
</button>
|
|
||||||
<mat-error>Error</mat-error>
|
|
||||||
</mat-form-field>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="pass-info-box">
|
|
||||||
<dl>
|
|
||||||
<dt>
|
|
||||||
<mat-icon color="accent" class="bullet-ico-info"
|
|
||||||
>info_outline</mat-icon
|
|
||||||
>
|
|
||||||
{{ 'authentication:password.notice.condition' | ucapI18n }}
|
|
||||||
</dt>
|
|
||||||
<dd>
|
|
||||||
{{ 'authentication:password.notice.condition1' | ucapI18n }}
|
|
||||||
</dd>
|
|
||||||
<dd>
|
|
||||||
{{ 'authentication:password.notice.condition2' | ucapI18n }}
|
|
||||||
</dd>
|
|
||||||
<dd>
|
|
||||||
{{ 'authentication:password.notice.condition3' | ucapI18n }}
|
|
||||||
</dd>
|
|
||||||
<dd>
|
|
||||||
{{ 'authentication:password.notice.condition4' | ucapI18n }}
|
|
||||||
</dd>
|
|
||||||
<dd>
|
|
||||||
{{ 'authentication:password.notice.condition5' | ucapI18n }}
|
|
||||||
</dd>
|
|
||||||
</dl>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</mat-tab>
|
</mat-tab>
|
||||||
</mat-tab-group>
|
</mat-tab-group>
|
||||||
|
|
|
@ -12,10 +12,10 @@
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
padding: 10px 16px 9px;
|
padding: 10px 16px;
|
||||||
&:first-of-type {
|
&:first-of-type {
|
||||||
border-top: 0;
|
border-top: 0;
|
||||||
padding: 20px 16px 9px;
|
padding: 20px 16px 10px;
|
||||||
}
|
}
|
||||||
.title-settings-subject {
|
.title-settings-subject {
|
||||||
color: #5c444b;
|
color: #5c444b;
|
||||||
|
@ -52,11 +52,11 @@
|
||||||
.settings-contents {
|
.settings-contents {
|
||||||
ul {
|
ul {
|
||||||
li {
|
li {
|
||||||
padding: 6px 0 7px;
|
padding: 6px 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.settings-radio-group {
|
.settings-radio-group {
|
||||||
padding: 6px 0 7px;
|
padding: 6px 0;
|
||||||
height: 42px;
|
height: 42px;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
|
|
|
@ -13,17 +13,27 @@ import {
|
||||||
Inject,
|
Inject,
|
||||||
ViewChild
|
ViewChild
|
||||||
} from '@angular/core';
|
} from '@angular/core';
|
||||||
|
import { FormControl } from '@angular/forms';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
MatDialogRef,
|
MatDialogRef,
|
||||||
MAT_DIALOG_DATA,
|
MAT_DIALOG_DATA,
|
||||||
MatDialog
|
MatDialog
|
||||||
} from '@angular/material/dialog';
|
} from '@angular/material/dialog';
|
||||||
|
import { MatOptionSelectionChange } from '@angular/material/core';
|
||||||
import { MatSelectChange, MatSelect } from '@angular/material/select';
|
import { MatSelectChange, MatSelect } from '@angular/material/select';
|
||||||
|
import { MatCheckboxChange } from '@angular/material/checkbox';
|
||||||
|
import { MatRadioChange } from '@angular/material/radio';
|
||||||
|
|
||||||
|
import { ObjectUtil } from '@ucap/core';
|
||||||
|
import { NotificationMethod } from '@ucap/domain-common';
|
||||||
import { NativeService, NativeType } from '@ucap/native';
|
import { NativeService, NativeType } from '@ucap/native';
|
||||||
|
|
||||||
import { UCAP_NATIVE_SERVICE } from '@ucap/ng-native';
|
import { UCAP_NATIVE_SERVICE } from '@ucap/ng-native';
|
||||||
|
import { I18nService } from '@ucap/ng-i18n';
|
||||||
|
import { DateService } from '@ucap/ng-ui/date';
|
||||||
|
import { VirtualScrollViewportComponent } from '@ucap/ng-ui/scrolling';
|
||||||
|
import { TranslateService } from '@ucap/ng-ui-organization';
|
||||||
|
|
||||||
import { environment } from '@environments';
|
import { environment } from '@environments';
|
||||||
|
|
||||||
|
@ -34,10 +44,6 @@ import {
|
||||||
ChatSetting,
|
ChatSetting,
|
||||||
PresenceSetting
|
PresenceSetting
|
||||||
} from '@app/models/settings';
|
} from '@app/models/settings';
|
||||||
import { I18nService } from '@ucap/ng-i18n';
|
|
||||||
import { VirtualScrollViewportComponent } from '@ucap/ng-ui';
|
|
||||||
import { FormControl } from '@angular/forms';
|
|
||||||
import { MatOptionSelectionChange } from '@angular/material/core';
|
|
||||||
|
|
||||||
export interface TimezoneData {
|
export interface TimezoneData {
|
||||||
displayName: string;
|
displayName: string;
|
||||||
|
@ -47,7 +53,9 @@ export interface TimezoneData {
|
||||||
export interface SettingsDialogData {
|
export interface SettingsDialogData {
|
||||||
settings: Settings;
|
settings: Settings;
|
||||||
}
|
}
|
||||||
export interface SettingsDialogResult {}
|
export interface SettingsDialogResult {
|
||||||
|
settings: Settings;
|
||||||
|
}
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-sections-account-settings',
|
selector: 'app-sections-account-settings',
|
||||||
|
@ -66,10 +74,7 @@ export class SettingsDialogComponent implements OnInit, OnDestroy {
|
||||||
|
|
||||||
platform: 'browser' | 'electron' = 'electron';
|
platform: 'browser' | 'electron' = 'electron';
|
||||||
|
|
||||||
generalSetting: GeneralSetting;
|
settings: Settings;
|
||||||
notificationSetting: NotificationSetting;
|
|
||||||
chatSetting: ChatSetting;
|
|
||||||
presenceSetting: PresenceSetting;
|
|
||||||
|
|
||||||
timezoneList: TimezoneData[];
|
timezoneList: TimezoneData[];
|
||||||
timezonePlaceholder: string;
|
timezonePlaceholder: string;
|
||||||
|
@ -78,15 +83,24 @@ export class SettingsDialogComponent implements OnInit, OnDestroy {
|
||||||
supportedHrLanguages =
|
supportedHrLanguages =
|
||||||
environment.productConfig.organization.supportedLanguages;
|
environment.productConfig.organization.supportedLanguages;
|
||||||
|
|
||||||
|
String = String;
|
||||||
|
NotificationMethod = NotificationMethod;
|
||||||
|
|
||||||
|
private ngOnDestroySubject: Subject<void> = new Subject();
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
public dialogRef: MatDialogRef<SettingsDialogData, SettingsDialogResult>,
|
public dialogRef: MatDialogRef<SettingsDialogData, SettingsDialogResult>,
|
||||||
@Inject(MAT_DIALOG_DATA) public data: SettingsDialogData,
|
@Inject(MAT_DIALOG_DATA) public data: SettingsDialogData,
|
||||||
@Inject(UCAP_NATIVE_SERVICE) private nativeService: NativeService,
|
@Inject(UCAP_NATIVE_SERVICE) private nativeService: NativeService,
|
||||||
|
private dateService: DateService,
|
||||||
private i18nService: I18nService,
|
private i18nService: I18nService,
|
||||||
|
private translateService: TranslateService,
|
||||||
private changeDetectorRef: ChangeDetectorRef,
|
private changeDetectorRef: ChangeDetectorRef,
|
||||||
public matDialog: MatDialog
|
public matDialog: MatDialog
|
||||||
) {
|
) {
|
||||||
this.nativeService.platform_nativeType().then((type) => {
|
this.nativeService.platform_nativeType().then((type) => {
|
||||||
|
// this.platform = 'electron';
|
||||||
|
// return;
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case NativeType.Browser:
|
case NativeType.Browser:
|
||||||
this.platform = 'browser';
|
this.platform = 'browser';
|
||||||
|
@ -99,14 +113,9 @@ export class SettingsDialogComponent implements OnInit, OnDestroy {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
this.generalSetting = data.settings.general;
|
this.settings = ObjectUtil.deepClone(data.settings);
|
||||||
this.notificationSetting = data.settings.notification;
|
|
||||||
this.chatSetting = data.settings.chat;
|
|
||||||
this.presenceSetting = data.settings.presence;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private ngOnDestroySubject: Subject<void> = new Subject();
|
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.generateTimezoneData();
|
this.generateTimezoneData();
|
||||||
|
|
||||||
|
@ -124,9 +133,27 @@ export class SettingsDialogComponent implements OnInit, OnDestroy {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onSelectionChangeLanguage(event: MatSelectChange) {}
|
onChangeForAutoStartOnBoot(event: MatCheckboxChange) {
|
||||||
|
this.settings.general.autoLaunch = event.checked;
|
||||||
|
}
|
||||||
|
|
||||||
onSelectionChangeHrLanguage(event: MatSelectChange) {}
|
onChangeForAutoLogin(event: MatCheckboxChange) {
|
||||||
|
this.settings.general.autoLogin = event.checked;
|
||||||
|
}
|
||||||
|
|
||||||
|
onChangeForAutoHide(event: MatCheckboxChange) {
|
||||||
|
this.settings.general.startupHideWindow = event.checked;
|
||||||
|
}
|
||||||
|
|
||||||
|
onSelectionChangeLanguage(event: MatSelectChange) {
|
||||||
|
this.i18nService.changeLanguage(event.value);
|
||||||
|
this.settings.general.locale = event.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
onSelectionChangeHrLanguage(event: MatSelectChange) {
|
||||||
|
this.translateService.use(event.value);
|
||||||
|
this.settings.general.hrInfoLocale = event.value;
|
||||||
|
}
|
||||||
|
|
||||||
onOpenedChangeTimezone(opened: boolean) {
|
onOpenedChangeTimezone(opened: boolean) {
|
||||||
if (opened) {
|
if (opened) {
|
||||||
|
@ -139,15 +166,41 @@ export class SettingsDialogComponent implements OnInit, OnDestroy {
|
||||||
if (!event.isUserInput) {
|
if (!event.isUserInput) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
this.dateService.use(event.source.value);
|
||||||
|
this.settings.general.timezone = event.source.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
onChangeForReceiveNotification(event: MatRadioChange) {
|
||||||
|
const use = 'true' === event.value;
|
||||||
|
console.log('onChangeForReceiveNotification', use);
|
||||||
|
}
|
||||||
|
|
||||||
|
onSelectionChangeMethodOfNotification(event: MatSelectChange) {
|
||||||
|
console.log('onSelectionChangeMethodOfNotification', event.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
onSelectionChangeAlertExposureTimeOfNotification(event: MatSelectChange) {
|
||||||
|
const v = Number(event.value);
|
||||||
|
console.log('onSelectionChangeAlertExposureTimeOfNotification', v);
|
||||||
|
}
|
||||||
|
|
||||||
|
onChangeForReceiveForMessageOfNotification(event: MatCheckboxChange) {
|
||||||
|
console.log('onChangeForReceiveForMessageOfNotification', event.checked);
|
||||||
}
|
}
|
||||||
|
|
||||||
onClosed(event: MouseEvent): void {
|
onClosed(event: MouseEvent): void {
|
||||||
this.dialogRef.close();
|
this.dialogRef.close({ settings: this.data.settings });
|
||||||
}
|
}
|
||||||
|
|
||||||
onCancel() {}
|
onCancel() {
|
||||||
|
this.dialogRef.close({ settings: this.data.settings });
|
||||||
|
}
|
||||||
|
|
||||||
onConfirm() {}
|
onConfirm() {
|
||||||
|
this.dialogRef.close({
|
||||||
|
settings: this.settings
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
private generateTimezoneData() {
|
private generateTimezoneData() {
|
||||||
const timezoneData = this.i18nService.t('locale:timezone', {
|
const timezoneData = this.i18nService.t('locale:timezone', {
|
||||||
|
@ -159,11 +212,14 @@ export class SettingsDialogComponent implements OnInit, OnDestroy {
|
||||||
const displayName = `(UTC${moment.tz(name).format('Z')}) ${
|
const displayName = `(UTC${moment.tz(name).format('Z')}) ${
|
||||||
timezoneData[name]
|
timezoneData[name]
|
||||||
}`;
|
}`;
|
||||||
|
if (-1 < displayName.indexOf('undefined')) {
|
||||||
|
console.log('timezone', name);
|
||||||
|
}
|
||||||
timezoneList.push({
|
timezoneList.push({
|
||||||
displayName,
|
displayName,
|
||||||
name
|
name
|
||||||
});
|
});
|
||||||
if (name === this.generalSetting.timezone) {
|
if (name === this.settings.general.timezone) {
|
||||||
this.timezonePlaceholder = displayName;
|
this.timezonePlaceholder = displayName;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -176,12 +232,12 @@ export class SettingsDialogComponent implements OnInit, OnDestroy {
|
||||||
|
|
||||||
private setTimezoneData() {
|
private setTimezoneData() {
|
||||||
const timezoneIndex = this.timezoneList.findIndex(
|
const timezoneIndex = this.timezoneList.findIndex(
|
||||||
(t) => t.name === this.generalSetting.timezone
|
(t) => t.name === this.settings.general.timezone
|
||||||
);
|
);
|
||||||
|
|
||||||
if (-1 !== timezoneIndex) {
|
if (-1 !== timezoneIndex) {
|
||||||
if (!!this.vsTimezone && !!this.selectForTimezone) {
|
if (!!this.vsTimezone && !!this.selectForTimezone) {
|
||||||
this.vsTimezone.scrollToIndex(timezoneIndex);
|
this.vsTimezone.scrollToIndex(timezoneIndex, 'start');
|
||||||
this.selectForTimezone.value = this.timezoneList[timezoneIndex].name;
|
this.selectForTimezone.value = this.timezoneList[timezoneIndex].name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<div class="layout-container" fxLayout="column">
|
<div class="layout-container" fxLayout="column">
|
||||||
<div class="layout-header" fxFlex="50px" fxLayout="row">
|
<div class="layout-header" fxFlex="50px" fxLayout="row">
|
||||||
<div fxFlex="1 1 auto">
|
<div fxFlex="1 1 auto" class="layout-header-container">
|
||||||
<ng-content
|
<ng-content
|
||||||
class="layout-header-content"
|
class="layout-header-content"
|
||||||
select="[appLayoutsDefaultDialog='header']"
|
select="[appLayoutsDefaultDialog='header']"
|
||||||
|
|
|
@ -10,6 +10,11 @@
|
||||||
font-size: 1.143em;
|
font-size: 1.143em;
|
||||||
border-bottom: 1px solid #666;
|
border-bottom: 1px solid #666;
|
||||||
margin: 0 16px;
|
margin: 0 16px;
|
||||||
|
&-container {
|
||||||
|
flex: 1 1 auto;
|
||||||
|
box-sizing: border-box;
|
||||||
|
width: calc(100% - 30px);
|
||||||
|
}
|
||||||
.layout-header-content {
|
.layout-header-content {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
|
|
@ -1,5 +1,9 @@
|
||||||
<div class="layout-container" fxLayout="row">
|
<div
|
||||||
<div class="navitab-page" fxFlex="0 0 60px">
|
class="layout-container"
|
||||||
|
fxLayout="row"
|
||||||
|
[ngClass]="'electron==' ? 'electron' : ''"
|
||||||
|
>
|
||||||
|
<div class="navitab-page">
|
||||||
<div class="gnb">
|
<div class="gnb">
|
||||||
<mat-toolbar class="mat-gnb-toolbar"
|
<mat-toolbar class="mat-gnb-toolbar"
|
||||||
><img
|
><img
|
||||||
|
@ -16,7 +20,7 @@
|
||||||
class="global-menu"
|
class="global-menu"
|
||||||
(selectedTabChange)="onSelectedTabChange($event)"
|
(selectedTabChange)="onSelectedTabChange($event)"
|
||||||
>
|
>
|
||||||
<mat-tab aria-label="Group">
|
<mat-tab [aria-label]="NavigationType.Group">
|
||||||
<ng-template mat-tab-label>
|
<ng-template mat-tab-label>
|
||||||
<div
|
<div
|
||||||
class="icon-item"
|
class="icon-item"
|
||||||
|
@ -65,7 +69,7 @@
|
||||||
</div>
|
</div>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
</mat-tab>
|
</mat-tab>
|
||||||
<mat-tab aria-label="Chat">
|
<mat-tab [aria-label]="NavigationType.Chat">
|
||||||
<ng-template mat-tab-label>
|
<ng-template mat-tab-label>
|
||||||
<div
|
<div
|
||||||
class="icon-item"
|
class="icon-item"
|
||||||
|
@ -102,7 +106,7 @@
|
||||||
</div>
|
</div>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
</mat-tab>
|
</mat-tab>
|
||||||
<mat-tab aria-label="Organization">
|
<mat-tab [aria-label]="NavigationType.Organization">
|
||||||
<ng-template mat-tab-label>
|
<ng-template mat-tab-label>
|
||||||
<div
|
<div
|
||||||
class="icon-item"
|
class="icon-item"
|
||||||
|
@ -158,7 +162,7 @@
|
||||||
</ng-template>
|
</ng-template>
|
||||||
</mat-tab>
|
</mat-tab>
|
||||||
|
|
||||||
<mat-tab aria-label="Message">
|
<!-- <mat-tab [aria-label]="NavigationType.Message">
|
||||||
<ng-template mat-tab-label>
|
<ng-template mat-tab-label>
|
||||||
<div
|
<div
|
||||||
class="icon-item"
|
class="icon-item"
|
||||||
|
@ -195,9 +199,9 @@
|
||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
</mat-tab>
|
</mat-tab> -->
|
||||||
|
|
||||||
<mat-tab aria-label="Call">
|
<mat-tab [aria-label]="NavigationType.Call">
|
||||||
<ng-template mat-tab-label>
|
<ng-template mat-tab-label>
|
||||||
<div
|
<div
|
||||||
class="icon-item"
|
class="icon-item"
|
||||||
|
@ -247,6 +251,7 @@
|
||||||
mode="side"
|
mode="side"
|
||||||
opened="true"
|
opened="true"
|
||||||
[disableClose]="true"
|
[disableClose]="true"
|
||||||
|
(openedChange)="onOpenStart($event)"
|
||||||
>
|
>
|
||||||
<ucap-float-action-button
|
<ucap-float-action-button
|
||||||
*ngIf="fabButtonShow"
|
*ngIf="fabButtonShow"
|
||||||
|
@ -254,7 +259,10 @@
|
||||||
[useCustomDefaultIcon]="fabUseCustomDefaultIcon"
|
[useCustomDefaultIcon]="fabUseCustomDefaultIcon"
|
||||||
(buttonClick)="onClickFab($event)"
|
(buttonClick)="onClickFab($event)"
|
||||||
>
|
>
|
||||||
<div *ngIf="tabIndex === 'group'" ucapFloatActionButton="mainIcon">
|
<div
|
||||||
|
*ngIf="curNavi === NavigationType.Group"
|
||||||
|
ucapFloatActionButton="mainIcon"
|
||||||
|
>
|
||||||
<mat-icon class="ico-font-float">
|
<mat-icon class="ico-font-float">
|
||||||
<svg
|
<svg
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
@ -303,7 +311,10 @@
|
||||||
</svg>
|
</svg>
|
||||||
</mat-icon>
|
</mat-icon>
|
||||||
</div>
|
</div>
|
||||||
<div *ngIf="tabIndex === 'chat'" ucapFloatActionButton="mainIcon">
|
<div
|
||||||
|
*ngIf="curNavi === NavigationType.Chat"
|
||||||
|
ucapFloatActionButton="mainIcon"
|
||||||
|
>
|
||||||
<mat-icon class="ico-font-float">
|
<mat-icon class="ico-font-float">
|
||||||
<svg
|
<svg
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
@ -341,7 +352,7 @@
|
||||||
</mat-icon>
|
</mat-icon>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
*ngIf="tabIndex === 'message'"
|
*ngIf="curNavi === NavigationType.Message"
|
||||||
ucapFloatActionButton="mainIcon"
|
ucapFloatActionButton="mainIcon"
|
||||||
>
|
>
|
||||||
<mat-icon class="ico-font-float">
|
<mat-icon class="ico-font-float">
|
||||||
|
@ -381,7 +392,10 @@
|
||||||
</svg>
|
</svg>
|
||||||
</mat-icon>
|
</mat-icon>
|
||||||
</div>
|
</div>
|
||||||
<div *ngIf="tabIndex === 'call'" ucapFloatActionButton="mainIcon">
|
<div
|
||||||
|
*ngIf="curNavi === NavigationType.Call"
|
||||||
|
ucapFloatActionButton="mainIcon"
|
||||||
|
>
|
||||||
<mat-icon class="ico-font-dialpad">dialpad</mat-icon>
|
<mat-icon class="ico-font-dialpad">dialpad</mat-icon>
|
||||||
</div>
|
</div>
|
||||||
</ucap-float-action-button>
|
</ucap-float-action-button>
|
||||||
|
@ -400,9 +414,11 @@
|
||||||
<div class="content-sidenav-top-bar" fxFlex="0 0 40px">
|
<div class="content-sidenav-top-bar" fxFlex="0 0 40px">
|
||||||
<app-layouts-top-bar>
|
<app-layouts-top-bar>
|
||||||
<div class="content-sidenav-top-bar-content">
|
<div class="content-sidenav-top-bar-content">
|
||||||
<div class="toolbar-info-area date-info">
|
<div class="toolbar-info-area date-info toolbar-drag-area">
|
||||||
|
<div class="today">
|
||||||
<span>Today</span>{{ moment().format('YYYY.MM.DD') }}
|
<span>Today</span>{{ moment().format('YYYY.MM.DD') }}
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
<div class="toolbar-info-area toolbar-ctrl">
|
<div class="toolbar-info-area toolbar-ctrl">
|
||||||
<!--Search-->
|
<!--Search-->
|
||||||
<div class="topbar-search">
|
<div class="topbar-search">
|
||||||
|
@ -418,15 +434,12 @@
|
||||||
<!--My Profile -->
|
<!--My Profile -->
|
||||||
<div
|
<div
|
||||||
class="my-profile"
|
class="my-profile"
|
||||||
matTooltip="프로필 버튼"
|
|
||||||
matTooltipPosition="below"
|
|
||||||
matTooltipHideDelay="1000"
|
|
||||||
[matMenuTriggerFor]="profileMenu"
|
[matMenuTriggerFor]="profileMenu"
|
||||||
#profileMenuTrigger="matMenuTrigger"
|
#profileMenuTrigger="matMenuTrigger"
|
||||||
>
|
>
|
||||||
<app-organization-profile-image-01
|
<app-organization-profile-image-01
|
||||||
[userInfo]="user.info"
|
[userInfo]="user.info"
|
||||||
[versionInfo]="versionInfo2Res"
|
[versionInfo]="versionInfo"
|
||||||
(openProfile)="onOpenProfile($event)"
|
(openProfile)="onOpenProfile($event)"
|
||||||
></app-organization-profile-image-01>
|
></app-organization-profile-image-01>
|
||||||
</div>
|
</div>
|
||||||
|
@ -445,7 +458,9 @@
|
||||||
<!--Footer-->
|
<!--Footer-->
|
||||||
<div class="footer">
|
<div class="footer">
|
||||||
<div class="foot-info version-info">
|
<div class="foot-info version-info">
|
||||||
<span class="var-txt current-ver">현재버전 0.0.11</span>
|
<span class="var-txt current-ver" (click)="onClickForOpenRoom()"
|
||||||
|
>현재버전 0.0.11</span
|
||||||
|
>
|
||||||
<span class="var-txt new-var">최신버전 0.0.11 </span>
|
<span class="var-txt new-var">최신버전 0.0.11 </span>
|
||||||
<button mat-icon-button aria-label="icon">
|
<button mat-icon-button aria-label="icon">
|
||||||
<mat-icon>get_app</mat-icon>
|
<mat-icon>get_app</mat-icon>
|
||||||
|
|
|
@ -8,13 +8,23 @@
|
||||||
.layout-container {
|
.layout-container {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
&.electron {
|
||||||
|
border: 1px solid #aaa;
|
||||||
|
}
|
||||||
|
|
||||||
.navitab-page {
|
.navitab-page {
|
||||||
//GNB /////////////////////////////////////
|
//GNB /////////////////////////////////////
|
||||||
|
display: flex;
|
||||||
|
flex: 0 0 auto;
|
||||||
|
width: 60px;
|
||||||
|
@include screen(xs) {
|
||||||
|
width: 60px;
|
||||||
|
}
|
||||||
|
|
||||||
.gnb {
|
.gnb {
|
||||||
//background-color: $gray-ref0;
|
//background-color: $gray-ref0;
|
||||||
background-color: #f1f2f6;
|
background-color: #f1f2f6;
|
||||||
width: 60px;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
@ -25,7 +35,7 @@
|
||||||
flex-basis: 40px;
|
flex-basis: 40px;
|
||||||
padding: 2px 12px 10px;
|
padding: 2px 12px 10px;
|
||||||
.img-logo {
|
.img-logo {
|
||||||
margin: 6px 0 0 1px;
|
margin: 10px 0 0 1px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.left-container {
|
.left-container {
|
||||||
|
@ -62,7 +72,7 @@
|
||||||
content: '';
|
content: '';
|
||||||
width: 30px;
|
width: 30px;
|
||||||
height: 30px;
|
height: 30px;
|
||||||
background-image: url(../../../assets/images/ico/btn_gnb_hompage.svg);
|
background-image: url(/assets/images/ico/btn_gnb_hompage.svg);
|
||||||
background-size: 30px;
|
background-size: 30px;
|
||||||
display: block;
|
display: block;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
@ -112,6 +122,9 @@
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding: 0 16px;
|
padding: 0 16px;
|
||||||
|
-webkit-app-region: drag;
|
||||||
|
-webkit-touch-callout: none;
|
||||||
|
-webkit-user-select: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -134,18 +147,28 @@
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
.toolbar-info-area {
|
.toolbar-info-area {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-grow: 1;
|
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
&.toolbar-drag-area {
|
||||||
|
-webkit-app-region: drag;
|
||||||
|
-webkit-touch-callout: none;
|
||||||
|
-webkit-user-select: none;
|
||||||
|
}
|
||||||
&.date-info {
|
&.date-info {
|
||||||
@include font-family($font-light);
|
@include font-family($font-light);
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
color: $gray-re70;
|
color: $gray-re70;
|
||||||
|
display: flex;
|
||||||
|
flex: 1 1 auto;
|
||||||
padding-left: 30px;
|
padding-left: 30px;
|
||||||
|
height: 100%;
|
||||||
@include screen(mid) {
|
@include screen(mid) {
|
||||||
padding-left: 16px;
|
padding-left: 16px;
|
||||||
display: none;
|
|
||||||
}
|
}
|
||||||
|
.today {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
span {
|
span {
|
||||||
width: 54px;
|
width: 54px;
|
||||||
height: 16px;
|
height: 16px;
|
||||||
|
@ -160,10 +183,17 @@
|
||||||
color: $lipstick;
|
color: $lipstick;
|
||||||
margin-right: 8px;
|
margin-right: 8px;
|
||||||
}
|
}
|
||||||
|
@include screen(mid) {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
&.toolbar-ctrl {
|
&.toolbar-ctrl {
|
||||||
flex-flow: row-reverse;
|
flex-flow: row-reverse;
|
||||||
|
margin-left: auto;
|
||||||
.topbar-search {
|
.topbar-search {
|
||||||
|
//개발예정으로 개발후 오픈
|
||||||
|
display: none;
|
||||||
order: 2;
|
order: 2;
|
||||||
margin-right: 8px;
|
margin-right: 8px;
|
||||||
.ico-search-icon {
|
.ico-search-icon {
|
||||||
|
@ -175,8 +205,8 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.my-profile {
|
.my-profile {
|
||||||
height: 30px;
|
height: 28px;
|
||||||
width: 30px;
|
width: 28px;
|
||||||
margin-right: 20px;
|
margin-right: 20px;
|
||||||
order: 1;
|
order: 1;
|
||||||
//profile /////////////
|
//profile /////////////
|
||||||
|
@ -239,6 +269,7 @@
|
||||||
@include font-family($font-light);
|
@include font-family($font-light);
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
&.version-info {
|
&.version-info {
|
||||||
|
display: none;
|
||||||
.var-txt {
|
.var-txt {
|
||||||
padding-left: 8px;
|
padding-left: 8px;
|
||||||
color: $gray-re70;
|
color: $gray-re70;
|
||||||
|
|
|
@ -3,7 +3,7 @@ import moment from 'moment';
|
||||||
import { Subject, of } from 'rxjs';
|
import { Subject, of } from 'rxjs';
|
||||||
import { takeUntil, filter, take, map, catchError } from 'rxjs/operators';
|
import { takeUntil, filter, take, map, catchError } from 'rxjs/operators';
|
||||||
|
|
||||||
import { Component, ViewChild, OnDestroy, OnInit } from '@angular/core';
|
import { Component, ViewChild, OnDestroy, OnInit, Inject } from '@angular/core';
|
||||||
import {
|
import {
|
||||||
Router,
|
Router,
|
||||||
RouterEvent,
|
RouterEvent,
|
||||||
|
@ -20,23 +20,43 @@ import { MatMenuTrigger } from '@angular/material/menu';
|
||||||
import { MatTabChangeEvent, MatTabGroup } from '@angular/material/tabs';
|
import { MatTabChangeEvent, MatTabGroup } from '@angular/material/tabs';
|
||||||
import { MatSidenav } from '@angular/material/sidenav';
|
import { MatSidenav } from '@angular/material/sidenav';
|
||||||
|
|
||||||
import { VersionInfo2Response } from '@ucap/api-public';
|
import { User, UserInfoSS } from '@ucap/domain-organization';
|
||||||
import { UserInfoSS } from '@ucap/protocol-query';
|
|
||||||
|
|
||||||
import { LogService } from '@ucap/ng-logger';
|
import { LogService } from '@ucap/ng-logger';
|
||||||
import { UserSelector } from '@ucap/ng-store-organization';
|
import { UserSelector } from '@ucap/ng-store-organization';
|
||||||
import { ConfigurationSelector } from '@ucap/ng-store-authentication';
|
import { ConfigurationSelector } from '@ucap/ng-store-authentication';
|
||||||
import { RoomSelector } from '@ucap/ng-store-chat';
|
import { RoomSelector } from '@ucap/ng-store-chat';
|
||||||
|
|
||||||
import { AppSelector } from '@app/store/state';
|
|
||||||
import { AppChatService } from '@app/services/app-chat.service';
|
|
||||||
import { QueryParams as ChatQueryParams } from '@app/pages/chat/types/params.type';
|
import { QueryParams as ChatQueryParams } from '@app/pages/chat/types/params.type';
|
||||||
import { CreateDialogComponent } from '@app/sections/group/dialogs/create.dialog.component';
|
|
||||||
import { AppAccountService } from '@app/services/app-account.service';
|
import { AppAccountService } from '@app/services/app-account.service';
|
||||||
|
import { AppCallService } from '@app/services/app-call.service';
|
||||||
|
import { AppUiService } from '@app/services/app-ui.service';
|
||||||
import { QueryParams as OrganizationParams } from '@app/pages/organization/types/params.type';
|
import { QueryParams as OrganizationParams } from '@app/pages/organization/types/params.type';
|
||||||
import { User } from '@ucap/protocol-info';
|
import { AddUserDialogComponent } from '@app/sections/group/dialogs/add-user.dialog.component';
|
||||||
|
import {
|
||||||
|
CreateDialogComponent as ChatCreateDialogComponent,
|
||||||
|
CreateDialogData as ChatCreateDialogData,
|
||||||
|
CreateDialogResult as ChatCreateDialogResult
|
||||||
|
} from '@app/sections/chat/dialogs/create.dialog.component';
|
||||||
|
import { UCAP_NATIVE_SERVICE } from '@ucap/ng-native';
|
||||||
|
import { NativeService } from '@ucap/native';
|
||||||
|
import { AppActions } from '@app/store/actions';
|
||||||
|
import { NavigationType } from '@app/types';
|
||||||
|
import { I18nService } from '@ucap/ng-i18n';
|
||||||
|
import {
|
||||||
|
DialpadDialogComponent,
|
||||||
|
DialpadDialogData,
|
||||||
|
DialpadDialogResult
|
||||||
|
} from '@app/sections/call/dialogs/dialpad.dialog.component';
|
||||||
|
import { VersionInfo } from '@ucap/domain-authentication';
|
||||||
|
|
||||||
const NAVS = ['group', 'chat', 'organization', 'message'];
|
const NAVS = [
|
||||||
|
NavigationType.Group,
|
||||||
|
NavigationType.Chat,
|
||||||
|
NavigationType.Organization,
|
||||||
|
NavigationType.Message,
|
||||||
|
NavigationType.Call
|
||||||
|
];
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-layouts-default',
|
selector: 'app-layouts-default',
|
||||||
|
@ -48,16 +68,21 @@ export class DefaultLayoutComponent implements OnInit, OnDestroy {
|
||||||
navTabGroup: MatTabGroup;
|
navTabGroup: MatTabGroup;
|
||||||
|
|
||||||
@ViewChild('leftSidenav', { static: true })
|
@ViewChild('leftSidenav', { static: true })
|
||||||
leftSidenav: MatSidenav;
|
set leftSidenav(leftSidenav: MatSidenav) {
|
||||||
|
this._leftSidenav = leftSidenav;
|
||||||
isShowLeftSideNav = false;
|
this.appUiService.leftSidenav = leftSidenav;
|
||||||
|
}
|
||||||
|
get leftSidenav(): MatSidenav {
|
||||||
|
return this._leftSidenav;
|
||||||
|
}
|
||||||
|
// tslint:disable-next-line: variable-name
|
||||||
|
_leftSidenav: MatSidenav;
|
||||||
|
|
||||||
@ViewChild('profileMenuTrigger', { static: true })
|
@ViewChild('profileMenuTrigger', { static: true })
|
||||||
profileMenuTrigger: MatMenuTrigger;
|
profileMenuTrigger: MatMenuTrigger;
|
||||||
|
|
||||||
showStatusbar = true;
|
showStatusbar = true;
|
||||||
|
|
||||||
tabIndex: string;
|
|
||||||
queryParams: Params;
|
queryParams: Params;
|
||||||
|
|
||||||
unreadCountChat = 0;
|
unreadCountChat = 0;
|
||||||
|
@ -66,23 +91,30 @@ export class DefaultLayoutComponent implements OnInit, OnDestroy {
|
||||||
fabButtonShow = true;
|
fabButtonShow = true;
|
||||||
fabUseCustomDefaultIcon = true; // default in this prj
|
fabUseCustomDefaultIcon = true; // default in this prj
|
||||||
fabButtons: { icon: string; tooltip?: string; divisionType?: string }[];
|
fabButtons: { icon: string; tooltip?: string; divisionType?: string }[];
|
||||||
versionInfo2Res: VersionInfo2Response;
|
versionInfo: VersionInfo;
|
||||||
user: User;
|
user: User;
|
||||||
|
|
||||||
|
/** Navigation */
|
||||||
|
NavigationType = NavigationType;
|
||||||
|
initMenu = NavigationType.Group;
|
||||||
|
curNavi: NavigationType;
|
||||||
|
|
||||||
moment = moment;
|
moment = moment;
|
||||||
|
|
||||||
private ngOnDestroySubject: Subject<void> = new Subject();
|
private ngOnDestroySubject: Subject<void> = new Subject();
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private router: Router,
|
private router: Router,
|
||||||
|
private i18nSevice: I18nService,
|
||||||
private activatedRoute: ActivatedRoute,
|
private activatedRoute: ActivatedRoute,
|
||||||
private store: Store<any>,
|
private store: Store<any>,
|
||||||
private appAccountService: AppAccountService,
|
private appAccountService: AppAccountService,
|
||||||
private appChatService: AppChatService,
|
private appCallService: AppCallService,
|
||||||
|
private appUiService: AppUiService,
|
||||||
private logService: LogService,
|
private logService: LogService,
|
||||||
public dialog: MatDialog
|
public dialog: MatDialog,
|
||||||
|
@Inject(UCAP_NATIVE_SERVICE) private nativeService: NativeService
|
||||||
) {
|
) {
|
||||||
this.setFabInitial(NAVS[0]);
|
this.setFabInitial(this.initMenu);
|
||||||
this.router.events
|
this.router.events
|
||||||
.pipe(
|
.pipe(
|
||||||
takeUntil(this.ngOnDestroySubject),
|
takeUntil(this.ngOnDestroySubject),
|
||||||
|
@ -97,7 +129,7 @@ export class DefaultLayoutComponent implements OnInit, OnDestroy {
|
||||||
if (!p || !p.segments || 0 === p.segments.length) {
|
if (!p || !p.segments || 0 === p.segments.length) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
const index = p.segments[0].path;
|
const index = p.segments[0].path as NavigationType;
|
||||||
this.setTabGroup(index);
|
this.setTabGroup(index);
|
||||||
this.setFabInitial(index);
|
this.setFabInitial(index);
|
||||||
}
|
}
|
||||||
|
@ -116,32 +148,14 @@ export class DefaultLayoutComponent implements OnInit, OnDestroy {
|
||||||
this.store
|
this.store
|
||||||
.pipe(
|
.pipe(
|
||||||
takeUntil(this.ngOnDestroySubject),
|
takeUntil(this.ngOnDestroySubject),
|
||||||
select(ConfigurationSelector.versionInfo2Response)
|
select(ConfigurationSelector.versionInfo)
|
||||||
)
|
)
|
||||||
.subscribe((versionInfo2Res) => {
|
.subscribe((versionInfo) => {
|
||||||
this.versionInfo2Res = versionInfo2Res;
|
this.versionInfo = versionInfo;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.store
|
|
||||||
.pipe(takeUntil(this.ngOnDestroySubject), select(AppSelector.windowSize))
|
|
||||||
.subscribe((size) => {
|
|
||||||
if (size.width < 780) {
|
|
||||||
if (this.leftSidenav.opened) {
|
|
||||||
this.leftSidenav.close();
|
|
||||||
}
|
|
||||||
this.isShowLeftSideNav = false;
|
|
||||||
this.leftSidenav.mode = 'over';
|
|
||||||
} else {
|
|
||||||
if (!this.leftSidenav.opened) {
|
|
||||||
this.leftSidenav.open();
|
|
||||||
}
|
|
||||||
this.isShowLeftSideNav = true;
|
|
||||||
this.leftSidenav.mode = 'side';
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
this.store
|
this.store
|
||||||
.pipe(takeUntil(this.ngOnDestroySubject), select(UserSelector.user))
|
.pipe(takeUntil(this.ngOnDestroySubject), select(UserSelector.user))
|
||||||
.subscribe((user) => {
|
.subscribe((user) => {
|
||||||
|
@ -156,6 +170,31 @@ export class DefaultLayoutComponent implements OnInit, OnDestroy {
|
||||||
.subscribe((unreadTotal) => {
|
.subscribe((unreadTotal) => {
|
||||||
this.unreadCountChat = unreadTotal;
|
this.unreadCountChat = unreadTotal;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// this.store
|
||||||
|
// .pipe(
|
||||||
|
// takeUntil(this.ngOnDestroySubject),
|
||||||
|
// select(PresenceSelector.selectAllStatusBulkInfo)
|
||||||
|
// )
|
||||||
|
// .subscribe((allBulkInfo) => {
|
||||||
|
// // .includes(String(this.user.info.seq))
|
||||||
|
// if (!allBulkInfo || (!!allBulkInfo && allBulkInfo.length === 0)) {
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
// const userStatusinfo = allBulkInfo.filter(
|
||||||
|
// (bulkInfo) => bulkInfo.userSeq === String(this.user.info.seq)
|
||||||
|
// )[0];
|
||||||
|
|
||||||
|
// const status = PresenceUtil.isOnline(userStatusinfo, PresenceType.PC);
|
||||||
|
// if (!status && userStatusinfo.pcStatus === StatusCode.Offline) {
|
||||||
|
// this.store.dispatch(
|
||||||
|
// PresenceActions.bulkInfo({
|
||||||
|
// divCd: 'myBulk',
|
||||||
|
// userSeqs: [String(this.user.info.seq)]
|
||||||
|
// })
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
// });
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnDestroy(): void {
|
ngOnDestroy(): void {
|
||||||
|
@ -170,14 +209,13 @@ export class DefaultLayoutComponent implements OnInit, OnDestroy {
|
||||||
}
|
}
|
||||||
|
|
||||||
onSelectedTabChange(event: MatTabChangeEvent) {
|
onSelectedTabChange(event: MatTabChangeEvent) {
|
||||||
const commands: any = [
|
const naviMenu: NavigationType = event.tab.ariaLabel as NavigationType;
|
||||||
NAVS[event.index],
|
const commands: any = [naviMenu, { outlets: { content: 'index' } }];
|
||||||
{ outlets: { content: 'index' } }
|
|
||||||
];
|
|
||||||
const orgInitialParams: Params = {};
|
const orgInitialParams: Params = {};
|
||||||
|
|
||||||
|
// CASE :: Chat.
|
||||||
if (
|
if (
|
||||||
event.index === 1 && // is chat.
|
naviMenu === NavigationType.Chat && // is chat.
|
||||||
!!this.queryParams &&
|
!!this.queryParams &&
|
||||||
!!this.queryParams[ChatQueryParams.ROOM_ID]
|
!!this.queryParams[ChatQueryParams.ROOM_ID]
|
||||||
) {
|
) {
|
||||||
|
@ -185,55 +223,45 @@ export class DefaultLayoutComponent implements OnInit, OnDestroy {
|
||||||
this.queryParams = undefined;
|
this.queryParams = undefined;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// if (!!this.tabIndex && this.tabIndex === 'chat') {
|
|
||||||
// if (!!this.queryParams && !!this.queryParams[ChatQueryParams.ROOM_ID]) {
|
|
||||||
// return;
|
|
||||||
// } else {
|
|
||||||
|
|
||||||
// }
|
// CASE :: Organization.
|
||||||
// } else {
|
if (naviMenu === NavigationType.Organization && !!this.user) {
|
||||||
// }
|
|
||||||
|
|
||||||
if (event.index === 2 && !!this.user) {
|
|
||||||
orgInitialParams[OrganizationParams.DEPT_SEQ] = String(
|
orgInitialParams[OrganizationParams.DEPT_SEQ] = String(
|
||||||
this.user.departmentCode
|
this.user.departmentCode
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.router.navigate(commands, { queryParams: orgInitialParams });
|
this.router.navigate(commands, { queryParams: orgInitialParams });
|
||||||
if (!this.isShowLeftSideNav) {
|
this.appUiService.openLeftSidenavOnNarrowMode();
|
||||||
this.leftSidenav.open();
|
this.setFabInitial(naviMenu);
|
||||||
}
|
|
||||||
this.setFabInitial(NAVS[event.index]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onClickToggleLeftSidenav() {
|
onClickToggleLeftSidenav() {
|
||||||
if (!this.isShowLeftSideNav) {
|
this.appUiService.toggleLeftSidenavOnNarrowMode();
|
||||||
this.leftSidenav.toggle();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
setFabInitial(type: string) {
|
setFabInitial(type: NavigationType) {
|
||||||
this.tabIndex = type;
|
this.curNavi = type;
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 'group':
|
case NavigationType.Group:
|
||||||
{
|
{
|
||||||
this.fabButtonShow = true;
|
this.fabButtonShow = true;
|
||||||
this.fabButtons = [
|
this.fabButtons = [
|
||||||
{
|
{
|
||||||
icon: 'add',
|
icon: 'add',
|
||||||
tooltip: '그룹 추가',
|
tooltip: this.i18nSevice.t('group:dialog.title.addNewBuddy'),
|
||||||
divisionType: 'GROUP_NEW_ADD'
|
divisionType: 'GROUP_NEW_ADD'
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'chat':
|
case NavigationType.Chat:
|
||||||
{
|
{
|
||||||
this.fabButtonShow = true;
|
this.fabButtonShow = true;
|
||||||
this.fabButtons = [
|
this.fabButtons = [
|
||||||
{
|
{
|
||||||
icon: 'chat',
|
icon: 'chat',
|
||||||
tooltip: '대화 추가',
|
tooltip: this.i18nSevice.t('chat:dialog.title.newChatRoom'),
|
||||||
divisionType: 'CAHT_NEW_ADD'
|
divisionType: 'CAHT_NEW_ADD'
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
@ -247,12 +275,12 @@ export class DefaultLayoutComponent implements OnInit, OnDestroy {
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'organization':
|
case NavigationType.Organization:
|
||||||
{
|
{
|
||||||
this.fabButtonShow = false;
|
this.fabButtonShow = false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'message':
|
case NavigationType.Message:
|
||||||
{
|
{
|
||||||
this.fabButtonShow = true;
|
this.fabButtonShow = true;
|
||||||
this.fabButtons = [
|
this.fabButtons = [
|
||||||
|
@ -264,11 +292,18 @@ export class DefaultLayoutComponent implements OnInit, OnDestroy {
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
// case MainMenu.Call:
|
case NavigationType.Call:
|
||||||
// {
|
{
|
||||||
// this.fabButtonShow = false;
|
this.fabButtonShow = true;
|
||||||
// }
|
this.fabButtons = [
|
||||||
// break;
|
{
|
||||||
|
icon: 'dialpad',
|
||||||
|
tooltip: this.i18nSevice.t('call:label.dialpad'),
|
||||||
|
divisionType: 'OPEN_DIALPAD'
|
||||||
|
}
|
||||||
|
];
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
default: {
|
default: {
|
||||||
this.fabButtonShow = false;
|
this.fabButtonShow = false;
|
||||||
|
@ -286,10 +321,14 @@ export class DefaultLayoutComponent implements OnInit, OnDestroy {
|
||||||
switch (btn.divisionType) {
|
switch (btn.divisionType) {
|
||||||
case 'GROUP_NEW_ADD':
|
case 'GROUP_NEW_ADD':
|
||||||
{
|
{
|
||||||
const dialogRef = this.dialog.open(CreateDialogComponent, {
|
const dialogRef = this.dialog.open(AddUserDialogComponent, {
|
||||||
panelClass: 'max-create-dialog'
|
panelClass: 'max-create-dialog'
|
||||||
});
|
});
|
||||||
|
|
||||||
|
dialogRef
|
||||||
|
.afterOpened()
|
||||||
|
.pipe(take(1))
|
||||||
|
.subscribe(() => dialogRef.componentInstance.psUpdate());
|
||||||
dialogRef
|
dialogRef
|
||||||
.afterClosed()
|
.afterClosed()
|
||||||
.pipe(
|
.pipe(
|
||||||
|
@ -304,7 +343,14 @@ export class DefaultLayoutComponent implements OnInit, OnDestroy {
|
||||||
break;
|
break;
|
||||||
case 'CAHT_NEW_ADD':
|
case 'CAHT_NEW_ADD':
|
||||||
{
|
{
|
||||||
this.appChatService.newOpenRoomDialog();
|
const dialogRef = this.dialog.open<
|
||||||
|
ChatCreateDialogComponent,
|
||||||
|
ChatCreateDialogData,
|
||||||
|
ChatCreateDialogResult
|
||||||
|
>(ChatCreateDialogComponent, {
|
||||||
|
panelClass: 'max-create-dialog',
|
||||||
|
data: {}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'CHAT_NEW_TIMER_ADD':
|
case 'CHAT_NEW_TIMER_ADD':
|
||||||
|
@ -320,6 +366,19 @@ export class DefaultLayoutComponent implements OnInit, OnDestroy {
|
||||||
this.logService.debug('MESSAGE_NEW');
|
this.logService.debug('MESSAGE_NEW');
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'OPEN_DIALPAD':
|
||||||
|
{
|
||||||
|
this.dialog.open<
|
||||||
|
DialpadDialogComponent,
|
||||||
|
DialpadDialogData,
|
||||||
|
DialpadDialogResult
|
||||||
|
>(DialpadDialogComponent, {
|
||||||
|
panelClass: 'mid-create-dialog',
|
||||||
|
data: {}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -350,9 +409,21 @@ export class DefaultLayoutComponent implements OnInit, OnDestroy {
|
||||||
this.profileMenuTrigger.closeMenu();
|
this.profileMenuTrigger.closeMenu();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onClickForOpenRoom() {
|
||||||
|
this.nativeService.chat_openRoom('/chat/chatroom?roomId=1000');
|
||||||
|
}
|
||||||
|
|
||||||
private setTabGroup(url: string) {
|
private setTabGroup(url: string) {
|
||||||
if (!!this.navTabGroup) {
|
if (!!this.navTabGroup) {
|
||||||
this.navTabGroup.selectedIndex = NAVS.findIndex((v) => url === v);
|
this.navTabGroup.selectedIndex = NAVS.findIndex((v) => url === v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onOpenStart(opened: boolean) {
|
||||||
|
this.store.dispatch(
|
||||||
|
AppActions.openedLiftSideNav({
|
||||||
|
opened
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<div class="layout-container" fxFlexFill fxLayout="column">
|
<div class="layout-container" fxFlexFill fxLayout="column">
|
||||||
<div *ngIf="showTopbar" class="top-bar" fxFlex="50px">
|
<div *ngIf="showTopbar" class="top-bar" fxFlex="50px">
|
||||||
<app-layouts-top-bar></app-layouts-top-bar>
|
<app-layouts-top-bar class="no-navi-top-bar"></app-layouts-top-bar>
|
||||||
</div>
|
</div>
|
||||||
<div class="layout-content" fxFlex="1 1 auto">
|
<div class="layout-content" fxFlex="1 1 auto">
|
||||||
<router-outlet></router-outlet>
|
<router-outlet></router-outlet>
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
<div class="title-bar">
|
<div class="title-bar">
|
||||||
<ucap-title-bar
|
<ucap-title-bar
|
||||||
[platform]="platform"
|
[platform]="platform"
|
||||||
(closed)="onClosedTitleBar()"
|
[windowState]="windowState"
|
||||||
(maximized)="onMaximizedTitleBar()"
|
(closed)="onClosed()"
|
||||||
(minimized)="onMinimizedTitleBar()"
|
(maximized)="onMaximized($event)"
|
||||||
|
(minimized)="onMinimized()"
|
||||||
>
|
>
|
||||||
<ng-content></ng-content>
|
<ng-content></ng-content>
|
||||||
</ucap-title-bar>
|
</ucap-title-bar>
|
||||||
|
|
|
@ -67,9 +67,15 @@ export class TopBarComponent implements OnInit, OnDestroy {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onClosedTitleBar() {}
|
onClosed() {
|
||||||
|
this.nativeService.window_close();
|
||||||
|
}
|
||||||
|
|
||||||
onMaximizedTitleBar() {}
|
onMaximized(altKey: boolean) {
|
||||||
|
this.nativeService.window_maximize(altKey);
|
||||||
|
}
|
||||||
|
|
||||||
onMinimizedTitleBar() {}
|
onMinimized() {
|
||||||
|
this.nativeService.window_minimize();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,9 @@ import { MatTooltipModule } from '@angular/material/tooltip';
|
||||||
import { PerfectScrollbarModule } from 'ngx-perfect-scrollbar';
|
import { PerfectScrollbarModule } from 'ngx-perfect-scrollbar';
|
||||||
|
|
||||||
import { I18nModule, UCAP_I18N_NAMESPACE } from '@ucap/ng-i18n';
|
import { I18nModule, UCAP_I18N_NAMESPACE } from '@ucap/ng-i18n';
|
||||||
import { UiModule } from '@ucap/ng-ui';
|
|
||||||
|
import { UiButtonModule } from '@ucap/ng-ui/button';
|
||||||
|
import { UiNativeModule } from '@ucap/ng-ui/native';
|
||||||
|
|
||||||
import { AppOrganizationModule } from '@app/ucap/organization/organization.module';
|
import { AppOrganizationModule } from '@app/ucap/organization/organization.module';
|
||||||
|
|
||||||
|
@ -45,7 +47,9 @@ import { DIALOGS } from './dialogs';
|
||||||
PerfectScrollbarModule,
|
PerfectScrollbarModule,
|
||||||
|
|
||||||
I18nModule,
|
I18nModule,
|
||||||
UiModule,
|
|
||||||
|
UiButtonModule,
|
||||||
|
UiNativeModule,
|
||||||
|
|
||||||
AppOrganizationModule
|
AppOrganizationModule
|
||||||
],
|
],
|
||||||
|
|
|
@ -1,4 +1,7 @@
|
||||||
|
import { SortViewType } from '@app/pages/group/types/sort-view.type';
|
||||||
|
|
||||||
export interface GroupOpenInfo {
|
export interface GroupOpenInfo {
|
||||||
lastGroupSeq: number;
|
lastGroupSeq: number;
|
||||||
groupSeqs: number[];
|
groupSeqs: number[];
|
||||||
|
showType: SortViewType;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { LoginSession as UCAPLoginSession } from '@ucap/core';
|
import { LoginSession as UCAPLoginSession } from '@ucap/domain-authentication';
|
||||||
import { GroupOpenInfo } from './group-open-info';
|
import { GroupOpenInfo } from './group-open-info';
|
||||||
|
|
||||||
export interface LoginSession extends UCAPLoginSession {
|
export interface LoginSession extends UCAPLoginSession {
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import {
|
import {
|
||||||
GeneralSetting as UCAPGeneralSetting,
|
GeneralSetting as UCAPGeneralSetting,
|
||||||
NotificationSetting as UCAPNotificationSetting,
|
NotificationSetting as UCAPNotificationSetting
|
||||||
ChatSetting as UCAPChatSetting,
|
} from '@ucap/domain-common';
|
||||||
PresenceSetting as UCAPPresenceSetting
|
import { PresenceSetting as UCAPPresenceSetting } from '@ucap/domain-status';
|
||||||
} from '@ucap/protocol-option';
|
import { ChatSetting as UCAPChatSetting } from '@ucap/domain-chat';
|
||||||
|
|
||||||
// tslint:disable-next-line: no-empty-interface
|
// tslint:disable-next-line: no-empty-interface
|
||||||
export interface GeneralSetting extends UCAPGeneralSetting {}
|
export interface GeneralSetting extends UCAPGeneralSetting {}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { UserStore as UCAPUserStore } from '@ucap/core';
|
import { UserStore as UCAPUserStore } from '@ucap/domain-authentication';
|
||||||
|
|
||||||
import { Settings } from './settings';
|
import { Settings } from './settings';
|
||||||
|
|
||||||
|
|
|
@ -14,25 +14,25 @@ $login-bg-h: 100/1080;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
|
||||||
background-color: $bg-gray;
|
background-color: $bg-gray;
|
||||||
background-image: url(../../../../assets/images/bg/bg_login_circle_square01.svg),
|
background-image: url(/assets/images/bg/bg_login_circle_square01.svg),
|
||||||
url(../../../../assets/images/bg/bg_login_circle_stroke01.svg),
|
url(/assets/images/bg/bg_login_circle_stroke01.svg),
|
||||||
url(../../../../assets/images/bg/bg_login_circle01.svg),
|
url(/assets/images/bg/bg_login_circle01.svg),
|
||||||
url(../../../../assets/images/bg/bg_login_circle03.svg),
|
url(/assets/images/bg/bg_login_circle03.svg),
|
||||||
url(../../../../assets/images/bg/bg_login_circle_diagonal01.svg),
|
url(/assets/images/bg/bg_login_circle_diagonal01.svg),
|
||||||
url(../../../../assets/images/bg/bg_login_circle_square02.svg),
|
url(/assets/images/bg/bg_login_circle_square02.svg),
|
||||||
url(../../../../assets/images/bg/bg_login_circle04.svg),
|
url(/assets/images/bg/bg_login_circle04.svg),
|
||||||
url(../../../../assets/images/bg/bg_login_circle05.svg),
|
url(/assets/images/bg/bg_login_circle05.svg),
|
||||||
url(../../../../assets/images/bg/bg_login_circle06.svg),
|
url(/assets/images/bg/bg_login_circle06.svg),
|
||||||
url(../../../../assets/images/bg/bg_login_circle07.svg),
|
url(/assets/images/bg/bg_login_circle07.svg),
|
||||||
url(../../../../assets/images/bg/bg_login_circle08.svg),
|
url(/assets/images/bg/bg_login_circle08.svg),
|
||||||
url(../../../../assets/images/bg/bg_login_circle_diagonal02.svg),
|
url(/assets/images/bg/bg_login_circle_diagonal02.svg),
|
||||||
url(../../../../assets/images/bg/bg_login_circle_diagonal03.svg),
|
url(/assets/images/bg/bg_login_circle_diagonal03.svg),
|
||||||
url(../../../../assets/images/bg/bg_login_circle_stroke02.svg),
|
url(/assets/images/bg/bg_login_circle_stroke02.svg),
|
||||||
url(../../../../assets/images/bg/bg_login_circle_stroke03.svg),
|
url(/assets/images/bg/bg_login_circle_stroke03.svg),
|
||||||
url(../../../../assets/images/bg/bg_login_circle_stroke04.svg),
|
url(/assets/images/bg/bg_login_circle_stroke04.svg),
|
||||||
url(../../../../assets/images/bg/bg_login_circle_stroke05.svg),
|
url(/assets/images/bg/bg_login_circle_stroke05.svg),
|
||||||
url(../../../../assets/images/bg/bg_login_polygon01.svg),
|
url(/assets/images/bg/bg_login_polygon01.svg),
|
||||||
url(../../../../assets/images/bg/bg_login_polygon02.svg);
|
url(/assets/images/bg/bg_login_polygon02.svg);
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
background-position: unquote($login-bg-w * 323 + '%')
|
background-position: unquote($login-bg-w * 323 + '%')
|
||||||
unquote($login-bg-h * 179 + '%'),
|
unquote($login-bg-h * 179 + '%'),
|
||||||
|
|
|
@ -1 +1,22 @@
|
||||||
<div class="logout-container">Logout</div>
|
<div class="logout-container">
|
||||||
|
<div class="logout-content">
|
||||||
|
<div class="logout-title"></div>
|
||||||
|
|
||||||
|
<p class="guide-text">
|
||||||
|
서비스를 이용하시려면 다시 로그인하여 주시기 바랍니다.<br />
|
||||||
|
<span
|
||||||
|
>항상 더 좋은 서비스로 고객님께 보답하는 M-Messenger가 되겠습니다.</span
|
||||||
|
>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<!--<p class="guide-text">
|
||||||
|
다른 기기에서 동일한 계정으로 로그인되었습니다.<br />본인이 아닌 경우
|
||||||
|
비밀번호 변경을 하시기 바랍니다.
|
||||||
|
<span
|
||||||
|
>항상 더 좋은 서비스로 고객님께 보답하는 M-Messenger가 되겠습니다.</span
|
||||||
|
>
|
||||||
|
</p>-->
|
||||||
|
|
||||||
|
<span class="guide-move">OO초 후 로그인 페이지로 자동 이동 됩니다 </span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
|
@ -3,4 +3,57 @@
|
||||||
.logout-container {
|
.logout-container {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
background-color: #f3f4f5;
|
||||||
|
background-image: url(/assets/images/ico/img_logout.png);
|
||||||
|
background-position: 50% bottom;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-size: 90% auto;
|
||||||
|
@include screen(xs) {
|
||||||
|
background-size: 100% auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logout-content {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
max-width: 80%;
|
||||||
|
transform: translateY(-70%);
|
||||||
|
.logout-title {
|
||||||
|
display: block;
|
||||||
|
width: 250px;
|
||||||
|
height: 62px;
|
||||||
|
text-align: center;
|
||||||
|
background: url(/assets/images/ico/img_logout_text.svg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.guide-text {
|
||||||
|
font-size: 1.6em;
|
||||||
|
color: #666;
|
||||||
|
font-weight: 600;
|
||||||
|
text-align: center;
|
||||||
|
@include screen(xs) {
|
||||||
|
font-size: 1.4em;
|
||||||
|
}
|
||||||
|
|
||||||
|
span {
|
||||||
|
display: inline-flex;
|
||||||
|
font-size: 0.7em;
|
||||||
|
color: #999;
|
||||||
|
font-weight: normal;
|
||||||
|
margin-top: 0.7em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.guide-move {
|
||||||
|
display: inline-flex;
|
||||||
|
padding: 0.8em 1.4em;
|
||||||
|
border-radius: 100px;
|
||||||
|
background-color: #fd578a;
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,12 +3,19 @@ import { Routes, RouterModule } from '@angular/router';
|
||||||
|
|
||||||
import { IndexPageComponent } from './components/index.page.component';
|
import { IndexPageComponent } from './components/index.page.component';
|
||||||
import { SidenavPageComponent } from './components/sidenav.page.component';
|
import { SidenavPageComponent } from './components/sidenav.page.component';
|
||||||
|
import { CallHistoryPageComponent } from './components/call-history.page.component';
|
||||||
|
|
||||||
const routes: Routes = [
|
const routes: Routes = [
|
||||||
{
|
{
|
||||||
path: 'index',
|
path: 'index',
|
||||||
outlet: 'content',
|
outlet: 'content',
|
||||||
component: IndexPageComponent
|
// component: IndexPageComponent
|
||||||
|
component: CallHistoryPageComponent
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'callhistory',
|
||||||
|
outlet: 'content',
|
||||||
|
component: CallHistoryPageComponent
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '',
|
path: '',
|
||||||
|
|
|
@ -3,18 +3,52 @@ import { CommonModule } from '@angular/common';
|
||||||
|
|
||||||
import { FlexLayoutModule } from '@angular/flex-layout';
|
import { FlexLayoutModule } from '@angular/flex-layout';
|
||||||
|
|
||||||
|
import { MatButtonModule } from '@angular/material/button';
|
||||||
|
import { MatIconModule } from '@angular/material/icon';
|
||||||
|
import { MatTabsModule } from '@angular/material/tabs';
|
||||||
|
|
||||||
|
import { UiDateModule } from '@ucap/ng-ui/date';
|
||||||
|
import { UiPhoneModule } from '@ucap/ng-ui/phone';
|
||||||
|
|
||||||
|
import { I18nModule, UCAP_I18N_NAMESPACE } from '@ucap/ng-i18n';
|
||||||
|
import { OrganizationUiModule } from '@ucap/ng-ui-organization';
|
||||||
|
|
||||||
|
import { AppOrganizationModule } from '@app/ucap/organization/organization.module';
|
||||||
|
import { AppCallSectionModule } from '@app/sections/call/call.section.module';
|
||||||
|
|
||||||
import { AppCallRoutingPageModule } from './call-routing.page.module';
|
import { AppCallRoutingPageModule } from './call-routing.page.module';
|
||||||
|
import { COMPONENTS } from './components';
|
||||||
import { IndexPageComponent } from './components/index.page.component';
|
import { AppGroupModule } from '@app/ucap/group/group.module';
|
||||||
import { SidenavPageComponent } from './components/sidenav.page.component';
|
|
||||||
|
|
||||||
export const COMPONENTS = [IndexPageComponent, SidenavPageComponent];
|
|
||||||
|
|
||||||
export { IndexPageComponent, SidenavPageComponent };
|
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [CommonModule, FlexLayoutModule, AppCallRoutingPageModule],
|
imports: [
|
||||||
|
CommonModule,
|
||||||
|
FlexLayoutModule,
|
||||||
|
|
||||||
|
MatButtonModule,
|
||||||
|
MatIconModule,
|
||||||
|
MatTabsModule,
|
||||||
|
|
||||||
|
I18nModule,
|
||||||
|
|
||||||
|
UiDateModule,
|
||||||
|
UiPhoneModule,
|
||||||
|
|
||||||
|
OrganizationUiModule,
|
||||||
|
|
||||||
|
AppOrganizationModule,
|
||||||
|
|
||||||
|
AppCallSectionModule,
|
||||||
|
AppCallRoutingPageModule,
|
||||||
|
AppGroupModule
|
||||||
|
],
|
||||||
declarations: [...COMPONENTS],
|
declarations: [...COMPONENTS],
|
||||||
entryComponents: []
|
entryComponents: [],
|
||||||
|
providers: [
|
||||||
|
{
|
||||||
|
provide: UCAP_I18N_NAMESPACE,
|
||||||
|
useValue: ['call', 'common']
|
||||||
|
}
|
||||||
|
]
|
||||||
})
|
})
|
||||||
export class AppCallPageModule {}
|
export class AppCallPageModule {}
|
||||||
|
|
|
@ -0,0 +1,58 @@
|
||||||
|
<div class="contents-main" fxFlexFill fxLayout="column">
|
||||||
|
<div class="subtitle" fxFlex="0 0 50px" fxLayout="row">
|
||||||
|
<div class="title">{{ 'call:label.callHistory' | ucapI18n }}</div>
|
||||||
|
<div class="call-info" fxLayout="row">
|
||||||
|
<div class="info send">
|
||||||
|
<mat-icon>call_made</mat-icon>{{ 'call:label.send' | ucapI18n }}
|
||||||
|
</div>
|
||||||
|
<div class="info receive">
|
||||||
|
<mat-icon>call_received</mat-icon>{{ 'call:label.recieve' | ucapI18n }}
|
||||||
|
</div>
|
||||||
|
<div class="info away">
|
||||||
|
<mat-icon>call_missed</mat-icon>{{ 'call:label.missed' | ucapI18n }}
|
||||||
|
</div>
|
||||||
|
<div class="info unanswered">
|
||||||
|
<mat-icon>call_missed_outgoing</mat-icon
|
||||||
|
>{{ 'call:label.unanswered' | ucapI18n }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="user-title" fxFlex="0 0 90px" fxLayout="row">
|
||||||
|
<div class="user-profile-info">
|
||||||
|
<div class="profile-image">
|
||||||
|
<app-group-profile-image-01
|
||||||
|
[userInfo]="userInfo"
|
||||||
|
[versionInfo]="versionInfo"
|
||||||
|
(openProfile)="onOpenProfile($event)"
|
||||||
|
></app-group-profile-image-01>
|
||||||
|
</div>
|
||||||
|
<div class="user-info">
|
||||||
|
<div class="user-n-g">
|
||||||
|
<div class="user-name">
|
||||||
|
{{ userInfo | ucapOrganizationTranslate: 'name':undefined:'' }}
|
||||||
|
</div>
|
||||||
|
<div class="user-grade">
|
||||||
|
{{ userInfo | ucapOrganizationTranslate: 'grade':undefined:' ' }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="dept-name">
|
||||||
|
{{ userInfo | ucapOrganizationTranslate: 'deptName':undefined:' ' }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="user-call-info" fxLayout="row">
|
||||||
|
<div *ngIf="!!userInfo && !!userInfo.hpNumber" class="mobile">
|
||||||
|
{{ userInfo.hpNumber | ucapPhoneNumber }}
|
||||||
|
<img src="assets/images/ico/btn_list_mobile_a24.svg" alt="" />
|
||||||
|
</div>
|
||||||
|
<div *ngIf="!!userInfo && !!userInfo.lineNumber" class="lineNumber">
|
||||||
|
{{ userInfo.lineNumber | ucapPhoneNumber }}
|
||||||
|
<img src="assets/images/ico/btn_list_call_a24.svg" alt="" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="call-info-container" fxFlex="1 1 auto">
|
||||||
|
<app-sections-call-info></app-sections-call-info>
|
||||||
|
</div>
|
||||||
|
</div>
|
|
@ -0,0 +1,33 @@
|
||||||
|
@import '~@ucap/lg-scss/mixins';
|
||||||
|
|
||||||
|
.contents-main {
|
||||||
|
position: relative;
|
||||||
|
.subtitle {
|
||||||
|
box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.16);
|
||||||
|
position: relative;
|
||||||
|
z-index: 4;
|
||||||
|
}
|
||||||
|
.message-box-container {
|
||||||
|
overflow: hidden;
|
||||||
|
height: 100%;
|
||||||
|
.message-area {
|
||||||
|
position: relative;
|
||||||
|
height: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
.message-input {
|
||||||
|
max-height: 70%;
|
||||||
|
overflow-x: hidden;
|
||||||
|
overflow-y: auto;
|
||||||
|
padding: 1px 0;
|
||||||
|
background-color: $white;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.rightDrawer {
|
||||||
|
min-width: 360px;
|
||||||
|
max-width: 100%;
|
||||||
|
@include screen(xs) {
|
||||||
|
min-width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
import { TestBed, async } from '@angular/core/testing';
|
||||||
|
import { RouterTestingModule } from '@angular/router/testing';
|
||||||
|
import { CallHistoryPageComponent } from './call-history.page.component';
|
||||||
|
|
||||||
|
describe('app::pages::chat::CallHistoryPageComponent', () => {
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
imports: [RouterTestingModule],
|
||||||
|
declarations: [CallHistoryPageComponent]
|
||||||
|
}).compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should create the app', () => {
|
||||||
|
const fixture = TestBed.createComponent(CallHistoryPageComponent);
|
||||||
|
const app = fixture.componentInstance;
|
||||||
|
expect(app).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it(`should have as title 'ucap-lg-web'`, () => {
|
||||||
|
const fixture = TestBed.createComponent(CallHistoryPageComponent);
|
||||||
|
const app = fixture.componentInstance;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should render title', () => {
|
||||||
|
const fixture = TestBed.createComponent(CallHistoryPageComponent);
|
||||||
|
fixture.detectChanges();
|
||||||
|
const compiled = fixture.nativeElement;
|
||||||
|
expect(compiled.querySelector('.content span').textContent).toContain(
|
||||||
|
'ucap-lg-web app is running!'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
129
src/app/pages/call/components/call-history.page.component.ts
Normal file
129
src/app/pages/call/components/call-history.page.component.ts
Normal file
|
@ -0,0 +1,129 @@
|
||||||
|
import {
|
||||||
|
Component,
|
||||||
|
OnInit,
|
||||||
|
OnDestroy,
|
||||||
|
ChangeDetectionStrategy,
|
||||||
|
ChangeDetectorRef
|
||||||
|
} from '@angular/core';
|
||||||
|
import { ActivatedRoute, Params } from '@angular/router';
|
||||||
|
|
||||||
|
import { Subject } from 'rxjs';
|
||||||
|
import { takeUntil, withLatestFrom } from 'rxjs/operators';
|
||||||
|
import { QueryParams } from '../types/params.type';
|
||||||
|
import { Store, select } from '@ngrx/store';
|
||||||
|
|
||||||
|
import { UserInfoSS } from '@ucap/domain-organization';
|
||||||
|
|
||||||
|
import { UserSelector } from '@ucap/ng-store-organization';
|
||||||
|
import { AppOrganizationService } from '@app/services/app-organization.service';
|
||||||
|
|
||||||
|
import { ConfigurationSelector } from '@ucap/ng-store-authentication';
|
||||||
|
|
||||||
|
import {
|
||||||
|
ProfileDialogComponent,
|
||||||
|
ProfileDialogData,
|
||||||
|
ProfileDialogResult
|
||||||
|
} from '@app/sections/organization/dialogs/profile.dialog.component';
|
||||||
|
import { MatDialog } from '@angular/material/dialog';
|
||||||
|
import { VersionInfo } from '@ucap/domain-authentication';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-pages-call-history',
|
||||||
|
templateUrl: './call-history.page.component.html',
|
||||||
|
styleUrls: ['./call-history.page.component.scss'],
|
||||||
|
changeDetection: ChangeDetectionStrategy.OnPush
|
||||||
|
})
|
||||||
|
export class CallHistoryPageComponent implements OnInit, OnDestroy {
|
||||||
|
isMe: boolean;
|
||||||
|
userSeq: string;
|
||||||
|
userInfo: UserInfoSS;
|
||||||
|
|
||||||
|
versionInfo: VersionInfo;
|
||||||
|
|
||||||
|
private ngOnDestroySubject: Subject<void> = new Subject();
|
||||||
|
constructor(
|
||||||
|
private dialog: MatDialog,
|
||||||
|
private store: Store<any>,
|
||||||
|
private appOrganizationService: AppOrganizationService,
|
||||||
|
private activatedRoute: ActivatedRoute,
|
||||||
|
private changeDetectorRef: ChangeDetectorRef
|
||||||
|
) {}
|
||||||
|
|
||||||
|
ngOnInit(): void {
|
||||||
|
this.activatedRoute.queryParams
|
||||||
|
.pipe(
|
||||||
|
takeUntil(this.ngOnDestroySubject),
|
||||||
|
withLatestFrom(this.store.pipe(select(UserSelector.user)))
|
||||||
|
)
|
||||||
|
.subscribe(([params, user]) => {
|
||||||
|
const seqParam = params[QueryParams.ID];
|
||||||
|
|
||||||
|
// initializing by userSeq Change.
|
||||||
|
if (this.userSeq !== seqParam) {
|
||||||
|
}
|
||||||
|
|
||||||
|
// setting userSeq.
|
||||||
|
this.userSeq = !!seqParam
|
||||||
|
? seqParam
|
||||||
|
: !!user
|
||||||
|
? String(user.info.seq)
|
||||||
|
: undefined;
|
||||||
|
|
||||||
|
if (!!user && this.userSeq === String(user.info.seq)) {
|
||||||
|
this.isMe = true;
|
||||||
|
} else {
|
||||||
|
this.isMe = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!!this.userSeq) {
|
||||||
|
const self = this;
|
||||||
|
this.appOrganizationService
|
||||||
|
.getUserInfo({ userSeq: this.userSeq, user })
|
||||||
|
.then((result) => {
|
||||||
|
console.log('getUserInfo : ', result);
|
||||||
|
self.userInfo = result.userInfo;
|
||||||
|
})
|
||||||
|
.catch((e) => {
|
||||||
|
self.userInfo = undefined;
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
this.changeDetectorRef.markForCheck();
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.userInfo = undefined;
|
||||||
|
this.changeDetectorRef.markForCheck();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.store
|
||||||
|
.pipe(
|
||||||
|
takeUntil(this.ngOnDestroySubject),
|
||||||
|
select(ConfigurationSelector.versionInfo)
|
||||||
|
)
|
||||||
|
.subscribe((versionInfo) => {
|
||||||
|
this.versionInfo = versionInfo;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnDestroy(): void {
|
||||||
|
if (!!this.ngOnDestroySubject) {
|
||||||
|
this.ngOnDestroySubject.next();
|
||||||
|
this.ngOnDestroySubject.complete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onOpenProfile(userInfo: UserInfoSS): void {
|
||||||
|
if (!!userInfo) {
|
||||||
|
this.dialog.open<
|
||||||
|
ProfileDialogComponent,
|
||||||
|
ProfileDialogData,
|
||||||
|
ProfileDialogResult
|
||||||
|
>(ProfileDialogComponent, {
|
||||||
|
panelClass: 'mid-create-dialog',
|
||||||
|
data: {
|
||||||
|
userSeq: userInfo.seq
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1 +1,39 @@
|
||||||
Index page of call is works!
|
<div class="index-page-call-info">
|
||||||
|
<div class="ico-page-call">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="100%" viewBox="0 0 166 142">
|
||||||
|
<g transform="translate(-152.267 -127.865)">
|
||||||
|
<path
|
||||||
|
d="M0 0H166V142H0z"
|
||||||
|
data-name="square-01"
|
||||||
|
transform="translate(152.267 127.865)"
|
||||||
|
style="fill: none;"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="M45.694 2a43.788 43.788 0 0 1 33.84 71.495l8.744 8.756a4.269 4.269 0 0 1-3.235 7.311H45.694a43.781 43.781 0 0 1 0-87.562z"
|
||||||
|
data-name="comment-dots-01"
|
||||||
|
transform="translate(199.283 158.998)"
|
||||||
|
style="stroke: #bababa; stroke-width: 4px; fill: #fff;"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="M26.015 2A24.012 24.012 0 0 0 7.458 41.206l-4.8 4.8a2.341 2.341 0 0 0 1.774 4.009h21.583a24.009 24.009 0 0 0 0-48.015z"
|
||||||
|
data-name="comment-dots-02"
|
||||||
|
transform="translate(167.028 170.336)"
|
||||||
|
style="fill: #999;"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="M33.725 5.917a5.628 5.628 0 1 1 11.242 0 5.628 5.628 0 1 1-11.242 0zm-16.862 0A5.775 5.775 0 0 1 22.483 0 5.775 5.775 0 0 1 28.1 5.917a5.774 5.774 0 0 1-5.621 5.917 5.774 5.774 0 0 1-5.617-5.917zM0 5.917A5.775 5.775 0 0 1 5.621 0a5.775 5.775 0 0 1 5.621 5.917 5.774 5.774 0 0 1-5.621 5.917A5.774 5.774 0 0 1 0 5.917z"
|
||||||
|
transform="translate(223.585 197.682)"
|
||||||
|
style="fill: #bababa;"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="M13.476 22.894l-7.509-6.82L3.41 18.38l10.066 9.143L35.086 7.9l-2.539-2.31z"
|
||||||
|
transform="translate(174.515 180.942)"
|
||||||
|
style="fill: #fff;"
|
||||||
|
/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<p class="call-index-copy">
|
||||||
|
{{ 'call:noSelectHistory' | ucapI18n }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
@import '~@ucap/lg-scss/mixins';
|
||||||
|
.index-page-call-info {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
.ico-page-call {
|
||||||
|
width: 166px;
|
||||||
|
height: 142px;
|
||||||
|
margin-top: -80px;
|
||||||
|
}
|
||||||
|
.call-index-copy {
|
||||||
|
font-size: 1.429em;
|
||||||
|
color: #666;
|
||||||
|
padding: 10px 20px;
|
||||||
|
border-top: 1px solid #ccc;
|
||||||
|
border-bottom: 1px solid #ccc;
|
||||||
|
margin: 50px 0 0;
|
||||||
|
}
|
||||||
|
@include screen(xs) {
|
||||||
|
.ico-page-call {
|
||||||
|
width: 120px;
|
||||||
|
height: auto;
|
||||||
|
margin-top: -40px;
|
||||||
|
}
|
||||||
|
.call-index-copy {
|
||||||
|
font-size: 1.2em;
|
||||||
|
margin: 20px 0 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,9 @@
|
||||||
import { IndexPageComponent } from './index.page.component';
|
import { IndexPageComponent } from './index.page.component';
|
||||||
import { SidenavPageComponent } from './sidenav.page.component';
|
import { SidenavPageComponent } from './sidenav.page.component';
|
||||||
|
import { CallHistoryPageComponent } from './call-history.page.component';
|
||||||
|
|
||||||
export const COMPONENTS = [IndexPageComponent, SidenavPageComponent];
|
export const COMPONENTS = [
|
||||||
|
IndexPageComponent,
|
||||||
|
SidenavPageComponent,
|
||||||
|
CallHistoryPageComponent
|
||||||
|
];
|
||||||
|
|
|
@ -1,3 +1,21 @@
|
||||||
<div fxFlexFill>
|
<div class="sidenav-container call" fxFlexFill fxLayout="column">
|
||||||
sidenav page of call is works!
|
<div class="title-section" fxFlex="0 0 50px" fxLayout="row">
|
||||||
|
<div class="title">
|
||||||
|
<h3 fxFlex="1 1 auto">{{ 'call:label.call' | ucapI18n }}</h3>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="extra-box" fxFlex="0 0 50px">
|
||||||
|
<app-organization-search-for-tenant
|
||||||
|
[isBackspaceCanceled]="isBackspaceCanceled"
|
||||||
|
[(searchData)]="companySearchData"
|
||||||
|
(canceled)="onSearchCancel()"
|
||||||
|
>
|
||||||
|
</app-organization-search-for-tenant>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div fxFlex="1 1 auto">
|
||||||
|
<app-sections-call-list
|
||||||
|
[searchObj]="companySearchData"
|
||||||
|
></app-sections-call-list>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
@import '~@ucap/lg-scss/mixins';
|
||||||
|
|
||||||
|
.sidenav-container.call {
|
||||||
|
overflow: hidden;
|
||||||
|
display: flex;
|
||||||
|
flex-flow: column;
|
||||||
|
align-content: flex-start;
|
||||||
|
background-color: #f1f2f6;
|
||||||
|
|
||||||
|
.title-section {
|
||||||
|
display: flex;
|
||||||
|
flex-flow: column;
|
||||||
|
background-color: $white;
|
||||||
|
.title {
|
||||||
|
display: flex;
|
||||||
|
flex-flow: row nowrap;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 0 0 0 17px;
|
||||||
|
background-color: $white;
|
||||||
|
align-items: center;
|
||||||
|
width: 100%;
|
||||||
|
h3 {
|
||||||
|
@include font-family-txt(18, left, $lipstick);
|
||||||
|
align-items: center;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,13 +1,109 @@
|
||||||
import { Component, Inject } from '@angular/core';
|
import { Subject, combineLatest } from 'rxjs';
|
||||||
import { Router } from '@angular/router';
|
import { takeUntil } from 'rxjs/operators';
|
||||||
|
|
||||||
|
import {
|
||||||
|
Component,
|
||||||
|
OnInit,
|
||||||
|
OnDestroy,
|
||||||
|
ChangeDetectionStrategy,
|
||||||
|
ChangeDetectorRef
|
||||||
|
} from '@angular/core';
|
||||||
|
|
||||||
|
import { Store, select } from '@ngrx/store';
|
||||||
|
|
||||||
|
import { User } from '@ucap/domain-organization';
|
||||||
|
import { LoginSession, LoginInfo } from '@ucap/domain-authentication';
|
||||||
|
import { SearchType, SearchDirectionByDateType } from '@ucap/domain-call';
|
||||||
|
import { CallHistoryInfoRequest } from '@ucap/api-contact';
|
||||||
|
|
||||||
import { LogService } from '@ucap/ng-logger';
|
import { LogService } from '@ucap/ng-logger';
|
||||||
|
import { CallActions } from '@ucap/ng-store-call';
|
||||||
|
|
||||||
|
import { UserSelector } from '@ucap/ng-store-organization';
|
||||||
|
import { LoginSelector } from '@ucap/ng-store-authentication';
|
||||||
|
|
||||||
|
import { SearchData } from '@app/ucap/organization/models/search-data';
|
||||||
|
import { AppAuthenticationService } from '@app/services/app-authentication.service';
|
||||||
|
|
||||||
|
import moment from 'moment';
|
||||||
|
import { environment } from '@environments';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-pages-call-sidenav',
|
selector: 'app-pages-call-sidenav',
|
||||||
templateUrl: './sidenav.page.component.html',
|
templateUrl: './sidenav.page.component.html',
|
||||||
styleUrls: ['./sidenav.page.component.scss']
|
styleUrls: ['./sidenav.page.component.scss'],
|
||||||
|
changeDetection: ChangeDetectionStrategy.OnPush
|
||||||
})
|
})
|
||||||
export class SidenavPageComponent {
|
export class SidenavPageComponent implements OnInit, OnDestroy {
|
||||||
constructor(private logService: LogService) {}
|
set companySearchData(searchData: SearchData) {
|
||||||
|
if (!!searchData && searchData.searchWord !== '') {
|
||||||
|
this._companySearchData = { ...searchData, bySearch: true };
|
||||||
|
} else {
|
||||||
|
this._companySearchData = { ...searchData, bySearch: false };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
get companySearchData() {
|
||||||
|
return this._companySearchData;
|
||||||
|
}
|
||||||
|
// tslint:disable-next-line: variable-name
|
||||||
|
_companySearchData: SearchData;
|
||||||
|
isBackspaceCanceled = true;
|
||||||
|
|
||||||
|
user: User;
|
||||||
|
loginInfo: LoginInfo;
|
||||||
|
loginSession: LoginSession;
|
||||||
|
|
||||||
|
private ngOnDestroySubject: Subject<void> = new Subject();
|
||||||
|
constructor(
|
||||||
|
private store: Store<any>,
|
||||||
|
private appAuthenticationService: AppAuthenticationService,
|
||||||
|
private changeDetectorRef: ChangeDetectorRef,
|
||||||
|
private logService: LogService
|
||||||
|
) {}
|
||||||
|
|
||||||
|
ngOnInit(): void {
|
||||||
|
combineLatest([
|
||||||
|
this.store.pipe(select(UserSelector.user)),
|
||||||
|
this.store.pipe(select(LoginSelector.loginInfo))
|
||||||
|
])
|
||||||
|
.pipe(takeUntil(this.ngOnDestroySubject))
|
||||||
|
.subscribe(([user, loginInfo]) => {
|
||||||
|
if (!!user && !!loginInfo) {
|
||||||
|
this.user = user;
|
||||||
|
this.loginInfo = loginInfo;
|
||||||
|
this.loginSession = this.appAuthenticationService.getLoginSession();
|
||||||
|
|
||||||
|
this._retrieveCallHistory();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnDestroy(): void {
|
||||||
|
if (!!this.ngOnDestroySubject) {
|
||||||
|
this.ngOnDestroySubject.next();
|
||||||
|
this.ngOnDestroySubject.complete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onSearchCancel() {
|
||||||
|
this.companySearchData = { ...this.companySearchData, searchWord: '' };
|
||||||
|
}
|
||||||
|
|
||||||
|
private _retrieveCallHistory() {
|
||||||
|
const searchStartDate = moment(new Date()).format('YYYY-MM-DD_HH:mm:ss');
|
||||||
|
const req: CallHistoryInfoRequest = {
|
||||||
|
userSeq: String(this.user.info.seq),
|
||||||
|
deviceType: this.loginSession.deviceType,
|
||||||
|
token: this.loginInfo.tokenString,
|
||||||
|
searchType: SearchType.All,
|
||||||
|
searchUserSeq: '',
|
||||||
|
searchNumber: '',
|
||||||
|
searchDate: '',
|
||||||
|
searchStartDate,
|
||||||
|
searchListCount:
|
||||||
|
environment.productConfig.call.historyRequestDefaultCount,
|
||||||
|
searchDirection: SearchDirectionByDateType.Before
|
||||||
|
};
|
||||||
|
this.store.dispatch(CallActions.callHistory({ req }));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
3
src/app/pages/call/types/params.type.ts
Normal file
3
src/app/pages/call/types/params.type.ts
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
export enum QueryParams {
|
||||||
|
ID = 'id'
|
||||||
|
}
|
|
@ -14,7 +14,10 @@ import { AppChatSectionModule } from '@app/sections/chat/chat.section.module';
|
||||||
|
|
||||||
import { AppChatRoutingPageModule } from './chat-routing.page.module';
|
import { AppChatRoutingPageModule } from './chat-routing.page.module';
|
||||||
|
|
||||||
import { UiModule } from '@ucap/ng-ui';
|
import { UiCoreModule } from '@ucap/ng-ui/core';
|
||||||
|
import { UiDateModule } from '@ucap/ng-ui/date';
|
||||||
|
import { UiViewerModule } from '@ucap/ng-ui/viewer';
|
||||||
|
|
||||||
import { COMPONENTS } from './components';
|
import { COMPONENTS } from './components';
|
||||||
import { UCAP_I18N_NAMESPACE, I18nModule } from '@ucap/ng-i18n';
|
import { UCAP_I18N_NAMESPACE, I18nModule } from '@ucap/ng-i18n';
|
||||||
|
|
||||||
|
@ -30,11 +33,14 @@ import { UCAP_I18N_NAMESPACE, I18nModule } from '@ucap/ng-i18n';
|
||||||
MatSidenavModule,
|
MatSidenavModule,
|
||||||
MatTooltipModule,
|
MatTooltipModule,
|
||||||
|
|
||||||
|
UiCoreModule,
|
||||||
|
UiDateModule,
|
||||||
|
UiViewerModule,
|
||||||
|
|
||||||
AppChatSectionModule,
|
AppChatSectionModule,
|
||||||
AppChatRoutingPageModule,
|
AppChatRoutingPageModule,
|
||||||
|
|
||||||
I18nModule,
|
I18nModule
|
||||||
UiModule
|
|
||||||
],
|
],
|
||||||
declarations: [...COMPONENTS],
|
declarations: [...COMPONENTS],
|
||||||
entryComponents: [],
|
entryComponents: [],
|
||||||
|
|
|
@ -8,12 +8,23 @@
|
||||||
</div>
|
</div>
|
||||||
<app-sections-chat-chat-search
|
<app-sections-chat-chat-search
|
||||||
[isChatSearch]="isChatSearch"
|
[isChatSearch]="isChatSearch"
|
||||||
|
(chatSearch)="onChatSearch($event)"
|
||||||
(closeChatSearch)="isChatSearch = false"
|
(closeChatSearch)="isChatSearch = false"
|
||||||
></app-sections-chat-chat-search>
|
></app-sections-chat-chat-search>
|
||||||
<mat-drawer-container autosize fxFlex="1 1 auto" fxLayout="column">
|
<mat-drawer-container autosize fxFlex="1 1 auto" fxLayout="column">
|
||||||
<div class="message-box-container" fxFlex="1 1 auto" fxLayout="column">
|
<div
|
||||||
|
class="message-box-container"
|
||||||
|
fxFlex="1 1 auto"
|
||||||
|
fxLayout="column"
|
||||||
|
ucapFileUploadFor01
|
||||||
|
(fileSelected)="onFileSelected($event)"
|
||||||
|
(fileDragEnter)="onFileDragEnter($event)"
|
||||||
|
(fileDragOver)="onFileDragOver($event)"
|
||||||
|
(fileDragLeave)="onFileDragLeave($event)"
|
||||||
|
>
|
||||||
<div class="message-area" fxFlex="1 1 auto">
|
<div class="message-area" fxFlex="1 1 auto">
|
||||||
<app-sections-chat-message
|
<app-sections-chat-message
|
||||||
|
#chatMessageSections
|
||||||
[roomId]="roomId"
|
[roomId]="roomId"
|
||||||
[translationSimpleview]="translationSimpleview"
|
[translationSimpleview]="translationSimpleview"
|
||||||
[eventSendTrigger$]="eventSendTriggerSubject.asObservable()"
|
[eventSendTrigger$]="eventSendTriggerSubject.asObservable()"
|
||||||
|
@ -21,9 +32,11 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="message-input" fxFlex="0 0 auto">
|
<div class="message-input" fxFlex="0 0 auto">
|
||||||
<app-sections-chat-form
|
<app-sections-chat-form
|
||||||
|
#chatForm
|
||||||
[roomId]="roomId"
|
[roomId]="roomId"
|
||||||
(changeTranslationSimpleview)="translationSimpleview = $event"
|
(changeTranslationSimpleview)="translationSimpleview = $event"
|
||||||
(eventSendTrigger)="eventSendTriggerSubject.next($event)"
|
(eventSendTrigger)="eventSendTriggerSubject.next($event)"
|
||||||
|
(openFormSelector)="onOpenFormSelector()"
|
||||||
></app-sections-chat-form>
|
></app-sections-chat-form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,15 +1,25 @@
|
||||||
|
import { Subject, BehaviorSubject } from 'rxjs';
|
||||||
|
import { takeUntil } from 'rxjs/operators';
|
||||||
|
|
||||||
import { Component, ViewChild, OnInit, OnDestroy } from '@angular/core';
|
import { Component, ViewChild, OnInit, OnDestroy } from '@angular/core';
|
||||||
import { ActivatedRoute, Params } from '@angular/router';
|
import { ActivatedRoute, Params } from '@angular/router';
|
||||||
|
|
||||||
|
import { Store } from '@ngrx/store';
|
||||||
|
|
||||||
import { MatDrawer } from '@angular/material/sidenav';
|
import { MatDrawer } from '@angular/material/sidenav';
|
||||||
|
|
||||||
import { Subscription, Subject, BehaviorSubject } from 'rxjs';
|
import { ChattingActions } from '@ucap/ng-store-chat';
|
||||||
|
|
||||||
|
import { MessageSectionComponent } from '@app/sections/chat/components/message.section.component';
|
||||||
|
import {
|
||||||
|
FormSectionComponent,
|
||||||
|
SelectorType
|
||||||
|
} from '@app/sections/chat/components/form.section.component';
|
||||||
|
|
||||||
import { QueryParams } from '../types/params.type';
|
import { QueryParams } from '../types/params.type';
|
||||||
import { ChatDrawType } from '../types/chat-draw.type';
|
import { ChatDrawType } from '../types/chat-draw.type';
|
||||||
import { takeUntil } from 'rxjs/operators';
|
|
||||||
import { DrawInfo } from '../models/draw-info';
|
import { DrawInfo } from '../models/draw-info';
|
||||||
import { Store } from '@ngrx/store';
|
import { SearchInfo } from '../models/search-info';
|
||||||
import { RoomActions, ChattingActions } from '@ucap/ng-store-chat';
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-pages-chat-room',
|
selector: 'app-pages-chat-room',
|
||||||
|
@ -18,6 +28,11 @@ import { RoomActions, ChattingActions } from '@ucap/ng-store-chat';
|
||||||
})
|
})
|
||||||
export class ChatRoomPageComponent implements OnInit, OnDestroy {
|
export class ChatRoomPageComponent implements OnInit, OnDestroy {
|
||||||
isChatSearch = false;
|
isChatSearch = false;
|
||||||
|
searchObj: SearchInfo = {
|
||||||
|
isShowSearch: false,
|
||||||
|
searchWord: ''
|
||||||
|
};
|
||||||
|
|
||||||
roomId: string;
|
roomId: string;
|
||||||
translationSimpleview = false;
|
translationSimpleview = false;
|
||||||
|
|
||||||
|
@ -25,9 +40,15 @@ export class ChatRoomPageComponent implements OnInit, OnDestroy {
|
||||||
returnDrawerType: ChatDrawType | null;
|
returnDrawerType: ChatDrawType | null;
|
||||||
eventSendTriggerSubject: BehaviorSubject<any> = new BehaviorSubject<any>(0);
|
eventSendTriggerSubject: BehaviorSubject<any> = new BehaviorSubject<any>(0);
|
||||||
|
|
||||||
|
@ViewChild('chatMessageSections', { static: false })
|
||||||
|
chatMessageSections: MessageSectionComponent;
|
||||||
|
|
||||||
@ViewChild('chatRightDrawer', { static: false })
|
@ViewChild('chatRightDrawer', { static: false })
|
||||||
chatRightDrawer: MatDrawer;
|
chatRightDrawer: MatDrawer;
|
||||||
|
|
||||||
|
@ViewChild('chatForm', { static: false })
|
||||||
|
chatForm: FormSectionComponent;
|
||||||
|
|
||||||
ChatDrawType = ChatDrawType;
|
ChatDrawType = ChatDrawType;
|
||||||
|
|
||||||
private ngOnDestroySubject: Subject<void> = new Subject();
|
private ngOnDestroySubject: Subject<void> = new Subject();
|
||||||
|
@ -42,11 +63,20 @@ export class ChatRoomPageComponent implements OnInit, OnDestroy {
|
||||||
.pipe(takeUntil(this.ngOnDestroySubject))
|
.pipe(takeUntil(this.ngOnDestroySubject))
|
||||||
.subscribe((params: Params) => {
|
.subscribe((params: Params) => {
|
||||||
const seqParam = params[QueryParams.ROOM_ID];
|
const seqParam = params[QueryParams.ROOM_ID];
|
||||||
|
|
||||||
// initializing by roomId Change.
|
// initializing by roomId Change.
|
||||||
if (this.roomId !== seqParam) {
|
if (this.roomId !== seqParam) {
|
||||||
|
// close Right Drawer.
|
||||||
if (!!this.chatRightDrawer) {
|
if (!!this.chatRightDrawer) {
|
||||||
this.chatRightDrawer.close();
|
this.chatRightDrawer.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// close Chat Search area.
|
||||||
|
this.isChatSearch = false;
|
||||||
|
this.searchObj = {
|
||||||
|
isShowSearch: false,
|
||||||
|
searchWord: ''
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// setting roomId.
|
// setting roomId.
|
||||||
|
@ -68,6 +98,14 @@ export class ChatRoomPageComponent implements OnInit, OnDestroy {
|
||||||
this.store.dispatch(ChattingActions.clearActiveRoomId({}));
|
this.store.dispatch(ChattingActions.clearActiveRoomId({}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** About Form Selector */
|
||||||
|
onOpenFormSelector() {
|
||||||
|
if (!!this.chatMessageSections) {
|
||||||
|
this.chatMessageSections.refreshAndScrollToBottom();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** About Right drawer */
|
||||||
onRightDrawerToggle(type: DrawInfo | null): void {
|
onRightDrawerToggle(type: DrawInfo | null): void {
|
||||||
this.drawerType = type.chatDrawType;
|
this.drawerType = type.chatDrawType;
|
||||||
this.returnDrawerType = !!type.returnDrawType ? type.returnDrawType : null;
|
this.returnDrawerType = !!type.returnDrawType ? type.returnDrawType : null;
|
||||||
|
@ -78,4 +116,28 @@ export class ChatRoomPageComponent implements OnInit, OnDestroy {
|
||||||
this.returnDrawerType = null;
|
this.returnDrawerType = null;
|
||||||
this.chatRightDrawer.close();
|
this.chatRightDrawer.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** About File Drag & Drop */
|
||||||
|
onFileSelected(fileList: FileList) {
|
||||||
|
if (!!this.chatForm) {
|
||||||
|
this.chatForm.onDragAndDropFileupload(fileList); // direct upload
|
||||||
|
// this.chatForm.onDragAndDropStandbyFileupload(fileList); // standby and confirm upload.(complate not yet)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
onFileDragEnter(event: DataTransferItemList) {
|
||||||
|
// if (!!this.chatForm) {
|
||||||
|
// this.chatForm.onOpenSelector(SelectorType.FILEUPLOAD);
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
onFileDragOver(event: DragEvent) {}
|
||||||
|
onFileDragLeave(event: DragEvent) {
|
||||||
|
// if (!!this.chatForm) {
|
||||||
|
// this.chatForm.clearSelector();
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
/** About Chat search. */
|
||||||
|
onChatSearch(search: SearchInfo) {
|
||||||
|
this.searchObj = search;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
@import '~@ucap/lg-scss/mixins';
|
||||||
.index-page-chat-info {
|
.index-page-chat-info {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
@ -18,4 +19,15 @@
|
||||||
border-bottom: 1px solid #ccc;
|
border-bottom: 1px solid #ccc;
|
||||||
margin: 50px 0 0;
|
margin: 50px 0 0;
|
||||||
}
|
}
|
||||||
|
@include screen(xs) {
|
||||||
|
.ico-page-chat {
|
||||||
|
width: 120px;
|
||||||
|
height: auto;
|
||||||
|
margin-top: -40px;
|
||||||
|
}
|
||||||
|
.chat-index-copy {
|
||||||
|
font-size: 1.2em;
|
||||||
|
margin: 20px 0 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,10 +10,12 @@
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-flow: row nowrap;
|
flex-flow: row nowrap;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
padding: 0 5px 0 17px;
|
|
||||||
background-color: $white;
|
|
||||||
align-items: center;
|
align-items: center;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
height: 50px;
|
||||||
|
min-height: 50px;
|
||||||
|
padding: 0 5px 0 17px;
|
||||||
|
background-color: $white;
|
||||||
h3 {
|
h3 {
|
||||||
@include font-family-txt(18, left, $lipstick);
|
@include font-family-txt(18, left, $lipstick);
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
|
@ -1,24 +1,32 @@
|
||||||
|
import { Subject, of } from 'rxjs';
|
||||||
|
import { takeUntil, take, map, catchError } from 'rxjs/operators';
|
||||||
|
|
||||||
import { Component, ChangeDetectorRef, OnInit, OnDestroy } from '@angular/core';
|
import { Component, ChangeDetectorRef, OnInit, OnDestroy } from '@angular/core';
|
||||||
|
import { ActivatedRoute, Params } from '@angular/router';
|
||||||
|
|
||||||
|
import { Store, select } from '@ngrx/store';
|
||||||
|
|
||||||
|
import { MatDialog } from '@angular/material/dialog';
|
||||||
|
|
||||||
|
import { RoomInfo } from '@ucap/domain-chat';
|
||||||
|
|
||||||
|
import { ExitAllRequest } from '@ucap/protocol-room';
|
||||||
|
|
||||||
import { LogService } from '@ucap/ng-logger';
|
import { LogService } from '@ucap/ng-logger';
|
||||||
import { Subject, of } from 'rxjs';
|
import { I18nService } from '@ucap/ng-i18n';
|
||||||
import { Store, select } from '@ngrx/store';
|
|
||||||
import { takeUntil, take, map, catchError } from 'rxjs/operators';
|
|
||||||
import { RoomSelector, RoomActions } from '@ucap/ng-store-chat';
|
import { RoomSelector, RoomActions } from '@ucap/ng-store-chat';
|
||||||
import { RoomInfo, ExitAllRequest } from '@ucap/protocol-room';
|
|
||||||
import { MatDialog } from '@angular/material/dialog';
|
|
||||||
import {
|
import {
|
||||||
ConfirmDialogComponent,
|
ConfirmDialogComponent,
|
||||||
ConfirmDialogData,
|
ConfirmDialogData,
|
||||||
ConfirmDialogResult
|
ConfirmDialogResult
|
||||||
} from '@ucap/ng-ui';
|
} from '@ucap/ng-ui/core';
|
||||||
import { I18nService } from '@ucap/ng-i18n';
|
|
||||||
import { SearchInfo } from '../models/search-info';
|
|
||||||
import { ActivatedRoute, Params } from '@angular/router';
|
|
||||||
import { QueryParams } from '../types/params.type';
|
|
||||||
import { AppChatService } from '@app/services/app-chat.service';
|
import { AppChatService } from '@app/services/app-chat.service';
|
||||||
import { SessionStorageService } from '@ucap/ng-web-storage';
|
import { AppRoomSelector } from '@app/store/state';
|
||||||
import { AppKey } from '@app/types';
|
|
||||||
|
import { SearchInfo } from '../models/search-info';
|
||||||
|
import { QueryParams } from '../types/params.type';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-pages-chat-sidenav',
|
selector: 'app-pages-chat-sidenav',
|
||||||
|
@ -46,14 +54,18 @@ export class SidenavPageComponent implements OnInit, OnDestroy {
|
||||||
private dialog: MatDialog,
|
private dialog: MatDialog,
|
||||||
private i18nService: I18nService,
|
private i18nService: I18nService,
|
||||||
private logService: LogService,
|
private logService: LogService,
|
||||||
private sessionStorageService: SessionStorageService,
|
|
||||||
private activatedRoute: ActivatedRoute,
|
private activatedRoute: ActivatedRoute,
|
||||||
private appChatService: AppChatService,
|
private appChatService: AppChatService,
|
||||||
private changeDetectorRef: ChangeDetectorRef
|
private changeDetectorRef: ChangeDetectorRef
|
||||||
) {
|
) {
|
||||||
this.historyRoomId = this.sessionStorageService.get<string>(
|
this.store
|
||||||
AppKey.HistoryRoomId
|
.pipe(
|
||||||
);
|
takeUntil(this.ngOnDestroySubject),
|
||||||
|
select(AppRoomSelector.historyRoomId)
|
||||||
|
)
|
||||||
|
.subscribe((historyRoomId) => {
|
||||||
|
this.historyRoomId = historyRoomId;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
|
@ -62,10 +74,9 @@ export class SidenavPageComponent implements OnInit, OnDestroy {
|
||||||
.subscribe((params: Params) => {
|
.subscribe((params: Params) => {
|
||||||
const seqParam = params[QueryParams.ROOM_ID];
|
const seqParam = params[QueryParams.ROOM_ID];
|
||||||
|
|
||||||
this.sessionStorageService.set<string>(
|
if (!!seqParam) {
|
||||||
AppKey.HistoryRoomId,
|
this.appChatService.setHistoryRoomId(seqParam);
|
||||||
!!seqParam ? seqParam : undefined
|
}
|
||||||
);
|
|
||||||
|
|
||||||
if (
|
if (
|
||||||
seqParam === undefined &&
|
seqParam === undefined &&
|
||||||
|
|
|
@ -22,7 +22,8 @@
|
||||||
>
|
>
|
||||||
<app-organization-profile-01
|
<app-organization-profile-01
|
||||||
[userSeq]="userSeq"
|
[userSeq]="userSeq"
|
||||||
(openChat)="onOpenCaht($event)"
|
[companyList]="companyList"
|
||||||
|
(openChat)="onOpenChat($event)"
|
||||||
(sendMessage)="onSendMessage($event)"
|
(sendMessage)="onSendMessage($event)"
|
||||||
(sendCall)="onSendCall($event)"
|
(sendCall)="onSendCall($event)"
|
||||||
(sendSms)="onSendSms($event)"
|
(sendSms)="onSendSms($event)"
|
||||||
|
|
|
@ -48,9 +48,10 @@
|
||||||
position: fixed;
|
position: fixed;
|
||||||
height: 49px;
|
height: 49px;
|
||||||
top: 40px;
|
top: 40px;
|
||||||
left: 75px;
|
left: 60px;
|
||||||
z-index: 10;
|
z-index: 10;
|
||||||
width: calc(100% - 90px);
|
width: calc(100% - 60px);
|
||||||
|
background-color: rgba(255, 255, 255, 0.3);
|
||||||
a {
|
a {
|
||||||
width: 50%;
|
width: 50%;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
|
@ -66,11 +67,11 @@
|
||||||
.profile-container {
|
.profile-container {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
flex: 1 0 460px !important;
|
flex: 0 0 460px !important;
|
||||||
max-width: inherit !important;
|
max-width: inherit !important;
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
@include screen(custom, min, 1540) {
|
@include screen(custom, min, 1540) {
|
||||||
flex: 1 0 44% !important;
|
flex: 0 0 44% !important;
|
||||||
}
|
}
|
||||||
@include screen(lg) {
|
@include screen(lg) {
|
||||||
flex: 1 0 auto !important;
|
flex: 1 0 auto !important;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { Subject } from 'rxjs';
|
import { Subject } from 'rxjs';
|
||||||
import { takeUntil } from 'rxjs/operators';
|
import { takeUntil, take, map } from 'rxjs/operators';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Component,
|
Component,
|
||||||
|
@ -14,22 +14,29 @@ import { MatDialog } from '@angular/material/dialog';
|
||||||
|
|
||||||
import { Store, select } from '@ngrx/store';
|
import { Store, select } from '@ngrx/store';
|
||||||
|
|
||||||
import { FileUploadItem } from '@ucap/api';
|
import { FileUploadItem } from '@ucap/domain-common';
|
||||||
|
import {
|
||||||
|
UserInfoSS,
|
||||||
|
UserInfoF,
|
||||||
|
UserInfoUpdateType,
|
||||||
|
User,
|
||||||
|
Company
|
||||||
|
} from '@ucap/domain-organization';
|
||||||
|
|
||||||
import { FileProfileSaveRequest } from '@ucap/api-common';
|
import { FileProfileSaveRequest } from '@ucap/api-common';
|
||||||
import { VersionInfo2Response } from '@ucap/api-public';
|
|
||||||
import { UserInfoSS, UserInfoF } from '@ucap/protocol-query';
|
import { ConferenceCreateRequest } from '@ucap/api-prompt';
|
||||||
import { UserInfoUpdateType, User } from '@ucap/protocol-info';
|
|
||||||
import { LoginResponse } from '@ucap/protocol-authentication';
|
|
||||||
|
|
||||||
import { LogService } from '@ucap/ng-logger';
|
import { LogService } from '@ucap/ng-logger';
|
||||||
import { I18nService } from '@ucap/ng-i18n';
|
import { I18nService } from '@ucap/ng-i18n';
|
||||||
import { UserSelector } from '@ucap/ng-store-organization';
|
import { UserSelector, CompanySelector } from '@ucap/ng-store-organization';
|
||||||
|
import { BuddySelector } from '@ucap/ng-store-group';
|
||||||
import {
|
import {
|
||||||
LoginSelector,
|
LoginSelector,
|
||||||
ConfigurationSelector
|
ConfigurationSelector
|
||||||
} from '@ucap/ng-store-authentication';
|
} from '@ucap/ng-store-authentication';
|
||||||
|
|
||||||
import { UserInfoTypes } from '@app/types';
|
import { UserInfoTypes, GroupManageType } from '@app/types';
|
||||||
import { AppFileService } from '@app/services/app-file.service';
|
import { AppFileService } from '@app/services/app-file.service';
|
||||||
import { AppAuthenticationService } from '@app/services/app-authentication.service';
|
import { AppAuthenticationService } from '@app/services/app-authentication.service';
|
||||||
import { AppGroupService } from '@app/services/app-group.service';
|
import { AppGroupService } from '@app/services/app-group.service';
|
||||||
|
@ -37,6 +44,13 @@ import { AppGroupService } from '@app/services/app-group.service';
|
||||||
import { QueryParams } from '../types/params.type';
|
import { QueryParams } from '../types/params.type';
|
||||||
import { AppChatService } from '@app/services/app-chat.service';
|
import { AppChatService } from '@app/services/app-chat.service';
|
||||||
|
|
||||||
|
import {
|
||||||
|
EditUserDialogComponent,
|
||||||
|
EditUserDialogData,
|
||||||
|
EditUserDialogResult
|
||||||
|
} from '@app/sections/group/dialogs/edit-user.dialog.component';
|
||||||
|
import { LoginInfo, VersionInfo } from '@ucap/domain-authentication';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-pages-group-index',
|
selector: 'app-pages-group-index',
|
||||||
templateUrl: './index.page.component.html',
|
templateUrl: './index.page.component.html',
|
||||||
|
@ -65,11 +79,13 @@ export class IndexPageComponent implements OnInit, OnDestroy {
|
||||||
|
|
||||||
userSeq: string = undefined;
|
userSeq: string = undefined;
|
||||||
user: User;
|
user: User;
|
||||||
loginRes: LoginResponse;
|
loginInfo: LoginInfo;
|
||||||
versionInfo2Res: VersionInfo2Response;
|
versionInfo: VersionInfo;
|
||||||
activeLink = 0;
|
activeLink = 0;
|
||||||
tabName: string;
|
tabName: string;
|
||||||
profileName: string;
|
profileName: string;
|
||||||
|
buddyList: UserInfoTypes[];
|
||||||
|
companyList: Company[];
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.activatedRoute.queryParams
|
this.activatedRoute.queryParams
|
||||||
|
@ -91,18 +107,36 @@ export class IndexPageComponent implements OnInit, OnDestroy {
|
||||||
this._refreshProfile();
|
this._refreshProfile();
|
||||||
});
|
});
|
||||||
this.store
|
this.store
|
||||||
.pipe(takeUntil(this.ngOnDestroySubject), select(LoginSelector.loginRes))
|
.pipe(takeUntil(this.ngOnDestroySubject), select(LoginSelector.loginInfo))
|
||||||
.subscribe((loginRes) => {
|
.subscribe((loginInfo) => {
|
||||||
this.loginRes = loginRes;
|
this.loginInfo = loginInfo;
|
||||||
});
|
});
|
||||||
|
|
||||||
this.store
|
this.store
|
||||||
.pipe(
|
.pipe(
|
||||||
takeUntil(this.ngOnDestroySubject),
|
takeUntil(this.ngOnDestroySubject),
|
||||||
select(ConfigurationSelector.versionInfo2Response)
|
select(ConfigurationSelector.versionInfo)
|
||||||
)
|
)
|
||||||
.subscribe((versionInfo2Res) => {
|
.subscribe((versionInfo) => {
|
||||||
this.versionInfo2Res = versionInfo2Res;
|
this.versionInfo = versionInfo;
|
||||||
|
});
|
||||||
|
|
||||||
|
this.store
|
||||||
|
.pipe(takeUntil(this.ngOnDestroySubject), select(BuddySelector.buddies))
|
||||||
|
.subscribe((buddies) => {
|
||||||
|
this.buddyList = buddies;
|
||||||
|
});
|
||||||
|
|
||||||
|
this.store
|
||||||
|
.pipe(
|
||||||
|
takeUntil(this.ngOnDestroySubject),
|
||||||
|
select(CompanySelector.companyList)
|
||||||
|
)
|
||||||
|
.subscribe((companyList) => {
|
||||||
|
if (!companyList) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.companyList = companyList;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -113,7 +147,7 @@ export class IndexPageComponent implements OnInit, OnDestroy {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onOpenCaht(userInfo: UserInfoSS) {
|
onOpenChat(userInfo: UserInfoSS) {
|
||||||
this.appChatService.newOpenRoom(
|
this.appChatService.newOpenRoom(
|
||||||
[Number(userInfo.seq) as any],
|
[Number(userInfo.seq) as any],
|
||||||
false,
|
false,
|
||||||
|
@ -123,15 +157,48 @@ export class IndexPageComponent implements OnInit, OnDestroy {
|
||||||
onSendMessage(userInfo: UserInfoSS) {}
|
onSendMessage(userInfo: UserInfoSS) {}
|
||||||
onSendCall(call: string) {}
|
onSendCall(call: string) {}
|
||||||
onSendSms(employeeNum: string) {}
|
onSendSms(employeeNum: string) {}
|
||||||
onCreateConference(userSeq: number) {}
|
onCreateConference(userSeq: number) {
|
||||||
|
const loginSession = this.appAuthenticationService.getLoginSession();
|
||||||
|
const req: ConferenceCreateRequest = {
|
||||||
|
userSeq: String(this.user.info.seq),
|
||||||
|
deviceType: loginSession.deviceType,
|
||||||
|
tokenKey: this.loginInfo.tokenString,
|
||||||
|
targetUserSeqs: [userSeq]
|
||||||
|
};
|
||||||
|
this.appChatService.openVideoConference(req);
|
||||||
|
}
|
||||||
onToggleFavorit(params: { userInfo: UserInfoSS; isFavorite: boolean }) {
|
onToggleFavorit(params: { userInfo: UserInfoSS; isFavorite: boolean }) {
|
||||||
this.appGroupService.updateBuddy(params.userInfo, params.isFavorite);
|
this.appGroupService.updateBuddy(params.userInfo, params.isFavorite);
|
||||||
}
|
}
|
||||||
onToggleBuddy(params: { userInfo: UserInfoSS; isBuddy: boolean }) {
|
onToggleBuddy(params: { userInfo: UserInfoSS; isBuddy: boolean }) {
|
||||||
this.appGroupService
|
if (params.isBuddy) {
|
||||||
.updateBuddyByToggle(params)
|
// 동료추가
|
||||||
.then((isRemoveBuddy) => {
|
const dialogRef = this.dialog.open<
|
||||||
if (isRemoveBuddy) {
|
EditUserDialogComponent,
|
||||||
|
EditUserDialogData,
|
||||||
|
EditUserDialogResult
|
||||||
|
>(EditUserDialogComponent, {
|
||||||
|
panelClass: 'max-create-dialog',
|
||||||
|
data: {
|
||||||
|
title: this.i18nService.t('group:dialog.title.addBuddy'),
|
||||||
|
type: GroupManageType.Add,
|
||||||
|
userInfos: [params.userInfo]
|
||||||
|
}
|
||||||
|
});
|
||||||
|
dialogRef
|
||||||
|
.afterClosed()
|
||||||
|
.pipe(
|
||||||
|
take(1),
|
||||||
|
map((result: EditUserDialogResult) => {
|
||||||
|
if (!!result) {
|
||||||
|
this.appGroupService.addBuddy(result);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
)
|
||||||
|
.subscribe();
|
||||||
|
} else {
|
||||||
|
// 동료삭제
|
||||||
|
this.appGroupService.removeBuddy(params.userInfo).then(() => {
|
||||||
this.router.navigate(
|
this.router.navigate(
|
||||||
[
|
[
|
||||||
'group',
|
'group',
|
||||||
|
@ -143,9 +210,8 @@ export class IndexPageComponent implements OnInit, OnDestroy {
|
||||||
queryParams: { id: Number(params.userInfo.seq) }
|
queryParams: { id: Number(params.userInfo.seq) }
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
})
|
|
||||||
.catch((reson) => this.logService.error(reson));
|
|
||||||
}
|
}
|
||||||
onUploadProfileImage(profileImageFileUploadItem: FileUploadItem) {
|
onUploadProfileImage(profileImageFileUploadItem: FileUploadItem) {
|
||||||
const loginSession = this.appAuthenticationService.getLoginSession();
|
const loginSession = this.appAuthenticationService.getLoginSession();
|
||||||
|
@ -153,14 +219,14 @@ export class IndexPageComponent implements OnInit, OnDestroy {
|
||||||
const profile = {
|
const profile = {
|
||||||
userSeq: String(this.user.info.seq),
|
userSeq: String(this.user.info.seq),
|
||||||
deviceType: loginSession.deviceType,
|
deviceType: loginSession.deviceType,
|
||||||
token: this.loginRes.tokenString,
|
token: this.loginInfo.tokenString,
|
||||||
file: profileImageFileUploadItem.file,
|
file: profileImageFileUploadItem.file,
|
||||||
fileUploadItem: profileImageFileUploadItem
|
fileUploadItem: profileImageFileUploadItem
|
||||||
} as FileProfileSaveRequest;
|
} as FileProfileSaveRequest;
|
||||||
|
|
||||||
this.appFileServie.fileProfileSave(
|
this.appFileServie.fileProfileSave(
|
||||||
profile,
|
profile,
|
||||||
this.versionInfo2Res.profileUploadUrl
|
this.versionInfo.profileUploadUrl
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
onUpdateIntro(intro: string) {
|
onUpdateIntro(intro: string) {
|
||||||
|
@ -168,6 +234,15 @@ export class IndexPageComponent implements OnInit, OnDestroy {
|
||||||
}
|
}
|
||||||
|
|
||||||
onUpdateNickname(params: { userInfo: UserInfoTypes; nickname: string }) {
|
onUpdateNickname(params: { userInfo: UserInfoTypes; nickname: string }) {
|
||||||
|
const isBuddy = this.appGroupService.checkBuddy(
|
||||||
|
this.buddyList,
|
||||||
|
params.userInfo
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!isBuddy) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
this.appGroupService.updateNickname(
|
this.appGroupService.updateNickname(
|
||||||
params.userInfo as UserInfoF,
|
params.userInfo as UserInfoF,
|
||||||
params.nickname
|
params.nickname
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="extra-box" fxFlex="0 0 50px">
|
<div class="extra-box" fxFlex="0 0 50px">
|
||||||
<app-organization-search-for-tenant
|
<app-organization-search-for-tenant
|
||||||
|
[isBackspaceCanceled]="isBackspaceCanceled"
|
||||||
[(searchData)]="companySearchData"
|
[(searchData)]="companySearchData"
|
||||||
(canceled)="onSearchCancel()"
|
(canceled)="onSearchCancel()"
|
||||||
>
|
>
|
||||||
|
@ -34,6 +35,7 @@
|
||||||
[searchData]="companySearchData"
|
[searchData]="companySearchData"
|
||||||
[showType]="showType"
|
[showType]="showType"
|
||||||
(clickUser)="onClickUser($event)"
|
(clickUser)="onClickUser($event)"
|
||||||
|
(openProfile)="onOpenProfile($event)"
|
||||||
></app-sections-group-list>
|
></app-sections-group-list>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { of, Subject } from 'rxjs';
|
import { of, Subject } from 'rxjs';
|
||||||
import { take, map, catchError } from 'rxjs/operators';
|
import { take, map, catchError, takeUntil } from 'rxjs/operators';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Component,
|
Component,
|
||||||
|
@ -7,7 +7,8 @@ import {
|
||||||
OnDestroy,
|
OnDestroy,
|
||||||
ChangeDetectorRef,
|
ChangeDetectorRef,
|
||||||
ViewChild,
|
ViewChild,
|
||||||
ChangeDetectionStrategy
|
ChangeDetectionStrategy,
|
||||||
|
NgZone
|
||||||
} from '@angular/core';
|
} from '@angular/core';
|
||||||
import { ActivatedRoute, Router } from '@angular/router';
|
import { ActivatedRoute, Router } from '@angular/router';
|
||||||
|
|
||||||
|
@ -15,14 +16,19 @@ import { Store } from '@ngrx/store';
|
||||||
|
|
||||||
import { MatDialog } from '@angular/material/dialog';
|
import { MatDialog } from '@angular/material/dialog';
|
||||||
|
|
||||||
|
import { UserInfo } from '@ucap/domain-organization';
|
||||||
|
|
||||||
import { LogService } from '@ucap/ng-logger';
|
import { LogService } from '@ucap/ng-logger';
|
||||||
import { I18nService } from '@ucap/ng-i18n';
|
import { I18nService } from '@ucap/ng-i18n';
|
||||||
|
|
||||||
import { SearchData } from '@app/ucap/organization/models/search-data';
|
import { SearchData } from '@app/ucap/organization/models/search-data';
|
||||||
|
|
||||||
|
import { LoginSession } from '@app/models/login-session';
|
||||||
|
import { AppUiService } from '@app/services/app-ui.service';
|
||||||
|
import { AppAuthenticationService } from '@app/services/app-authentication.service';
|
||||||
import { CreateDialogComponent } from '@app/sections/group/dialogs/create.dialog.component';
|
import { CreateDialogComponent } from '@app/sections/group/dialogs/create.dialog.component';
|
||||||
import { ListSectionComponent } from '@app/sections/group/components/list.section.component';
|
import { ListSectionComponent } from '@app/sections/group/components/list.section.component';
|
||||||
import { UserInfo } from '@ucap/protocol-sync';
|
|
||||||
import { SortViewType } from '../types/sort-view.type';
|
import { SortViewType } from '../types/sort-view.type';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
|
@ -47,25 +53,43 @@ export class SidenavPageComponent implements OnInit, OnDestroy {
|
||||||
}
|
}
|
||||||
// tslint:disable-next-line: variable-name
|
// tslint:disable-next-line: variable-name
|
||||||
_companySearchData: SearchData;
|
_companySearchData: SearchData;
|
||||||
|
isBackspaceCanceled = true;
|
||||||
showType: SortViewType;
|
showType: SortViewType;
|
||||||
sortViewType = SortViewType;
|
sortViewType = SortViewType;
|
||||||
|
|
||||||
private ngOnDestroySubject: Subject<void> = new Subject();
|
private ngOnDestroySubject: Subject<void> = new Subject();
|
||||||
|
private loginSession: LoginSession;
|
||||||
constructor(
|
constructor(
|
||||||
private activatedRoute: ActivatedRoute,
|
private activatedRoute: ActivatedRoute,
|
||||||
private router: Router,
|
private router: Router,
|
||||||
|
private appAuthenticationService: AppAuthenticationService,
|
||||||
private logService: LogService,
|
private logService: LogService,
|
||||||
private i18nService: I18nService,
|
private i18nService: I18nService,
|
||||||
private store: Store<any>,
|
private store: Store<any>,
|
||||||
private changeDetectorRef: ChangeDetectorRef,
|
private changeDetectorRef: ChangeDetectorRef,
|
||||||
public dialog: MatDialog
|
public dialog: MatDialog,
|
||||||
|
private appUiService: AppUiService,
|
||||||
|
private ngZone: NgZone
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.showType = SortViewType.all;
|
this.showType = SortViewType.all;
|
||||||
this.showGroupMenuIcon(SortViewType.all);
|
this.showGroupMenuIcon(SortViewType.all);
|
||||||
|
|
||||||
|
this.appAuthenticationService
|
||||||
|
.getLoginSession$()
|
||||||
|
.pipe(takeUntil(this.ngOnDestroySubject))
|
||||||
|
.subscribe((loginSession) => {
|
||||||
|
this.loginSession = loginSession;
|
||||||
|
if (
|
||||||
|
!!this.loginSession &&
|
||||||
|
!!this.loginSession.groupInfo &&
|
||||||
|
!!this.loginSession.groupInfo.showType
|
||||||
|
) {
|
||||||
|
this.showType = this.loginSession.groupInfo.showType;
|
||||||
|
this.showGroupMenuIcon(this.loginSession.groupInfo.showType);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnDestroy(): void {
|
ngOnDestroy(): void {
|
||||||
|
@ -132,6 +156,21 @@ export class SidenavPageComponent implements OnInit, OnDestroy {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
!!this.loginSession &&
|
||||||
|
!!this.loginSession.groupInfo &&
|
||||||
|
!!this.loginSession.groupInfo.showType
|
||||||
|
) {
|
||||||
|
this.appAuthenticationService.setLoginSession({
|
||||||
|
...this.loginSession,
|
||||||
|
groupInfo: {
|
||||||
|
groupSeqs: [],
|
||||||
|
lastGroupSeq: 0,
|
||||||
|
showType: this.showType
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
onSearchCancel() {
|
onSearchCancel() {
|
||||||
this.companySearchData = { ...this.companySearchData, searchWord: '' };
|
this.companySearchData = { ...this.companySearchData, searchWord: '' };
|
||||||
|
@ -146,6 +185,7 @@ export class SidenavPageComponent implements OnInit, OnDestroy {
|
||||||
}
|
}
|
||||||
|
|
||||||
onClickUser(userInfo: UserInfo) {
|
onClickUser(userInfo: UserInfo) {
|
||||||
|
this.ngZone.run(() => {
|
||||||
this.router.navigate(
|
this.router.navigate(
|
||||||
[
|
[
|
||||||
'group',
|
'group',
|
||||||
|
@ -157,5 +197,12 @@ export class SidenavPageComponent implements OnInit, OnDestroy {
|
||||||
queryParams: { id: Number(userInfo.seq) }
|
queryParams: { id: Number(userInfo.seq) }
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
this.appUiService.closeLeftSidenavOnNarrowMode();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
onOpenProfile(userInfo: UserInfo) {
|
||||||
|
this.onClickUser(userInfo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@ import { MatIconModule } from '@angular/material/icon';
|
||||||
import { MatMenuModule } from '@angular/material/menu';
|
import { MatMenuModule } from '@angular/material/menu';
|
||||||
import { MatTabsModule } from '@angular/material/tabs';
|
import { MatTabsModule } from '@angular/material/tabs';
|
||||||
|
|
||||||
import { UiModule } from '@ucap/ng-ui';
|
// import { UiModule } from '@ucap/ng-ui';
|
||||||
|
|
||||||
import { AppOrganizationModule } from '@app/ucap/organization/organization.module';
|
import { AppOrganizationModule } from '@app/ucap/organization/organization.module';
|
||||||
|
|
||||||
|
@ -34,7 +34,6 @@ import { I18nModule, UCAP_I18N_NAMESPACE } from '@ucap/ng-i18n';
|
||||||
AppGroupSectionModule,
|
AppGroupSectionModule,
|
||||||
AppGroupRoutingPageModule,
|
AppGroupRoutingPageModule,
|
||||||
|
|
||||||
UiModule,
|
|
||||||
I18nModule
|
I18nModule
|
||||||
],
|
],
|
||||||
declarations: [...COMPONENTS],
|
declarations: [...COMPONENTS],
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
width: 200px;
|
width: 200px;
|
||||||
height: 200px;
|
height: 200px;
|
||||||
margin-top: -100px;
|
margin-top: -100px;
|
||||||
background-image: url(../../../../assets/images/ico/img_coming_soon.png);
|
background-image: url(/assets/images/ico/img_coming_soon.png);
|
||||||
background-size: 100% auto;
|
background-size: 100% auto;
|
||||||
}
|
}
|
||||||
.coming-soon-index-copy {
|
.coming-soon-index-copy {
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
<!-- search start-->
|
<!-- search start-->
|
||||||
<div fxFlex="0 0 50px">
|
<div fxFlex="0 0 50px">
|
||||||
<app-organization-search-for-tenant
|
<app-organization-search-for-tenant
|
||||||
|
[isBackspaceCanceled]="isBackspaceCanceled"
|
||||||
[(searchData)]="companySearchData"
|
[(searchData)]="companySearchData"
|
||||||
(canceled)="onCanceledSearch()"
|
(canceled)="onCanceledSearch()"
|
||||||
>
|
>
|
||||||
|
|
|
@ -12,11 +12,11 @@ import { ActivatedRoute, Router, Params } from '@angular/router';
|
||||||
|
|
||||||
import { ParamsUtil } from '@ucap/ng-core';
|
import { ParamsUtil } from '@ucap/ng-core';
|
||||||
|
|
||||||
|
import { UserStore } from '@app/models/user-store';
|
||||||
import { AppAuthenticationService } from '@app/services/app-authentication.service';
|
import { AppAuthenticationService } from '@app/services/app-authentication.service';
|
||||||
import { SearchData } from '@app/ucap/organization/models/search-data';
|
import { SearchData } from '@app/ucap/organization/models/search-data';
|
||||||
|
|
||||||
import { QueryParams } from '../types/params.type';
|
import { QueryParams } from '../types/params.type';
|
||||||
import { UserStore } from '@app/models/user-store';
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-pages-organization-index',
|
selector: 'app-pages-organization-index',
|
||||||
|
@ -36,7 +36,7 @@ export class IndexPageComponent implements OnInit, OnDestroy {
|
||||||
_companySearchData: SearchData;
|
_companySearchData: SearchData;
|
||||||
|
|
||||||
deptSearchData: SearchData;
|
deptSearchData: SearchData;
|
||||||
|
isBackspaceCanceled = true;
|
||||||
deptSeq: string;
|
deptSeq: string;
|
||||||
|
|
||||||
private ngOnDestroySubject: Subject<void> = new Subject();
|
private ngOnDestroySubject: Subject<void> = new Subject();
|
||||||
|
@ -107,6 +107,7 @@ export class IndexPageComponent implements OnInit, OnDestroy {
|
||||||
|
|
||||||
onCanceledSearch() {
|
onCanceledSearch() {
|
||||||
const queryParams: Params = {};
|
const queryParams: Params = {};
|
||||||
|
|
||||||
queryParams[QueryParams.DEPT_SEQ] = String(this.deptSeq);
|
queryParams[QueryParams.DEPT_SEQ] = String(this.deptSeq);
|
||||||
this._navigate(queryParams);
|
this._navigate(queryParams);
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
<div fxFlex="1 1 auto">
|
<div fxFlex="1 1 auto">
|
||||||
<app-organization-tree
|
<app-organization-tree
|
||||||
[initialExpanded]="initialExpanded"
|
[initialExpanded]="initialExpanded"
|
||||||
|
[windowSizeMode]="windowSizeMode"
|
||||||
(clicked)="onClickedTree($event)"
|
(clicked)="onClickedTree($event)"
|
||||||
></app-organization-tree>
|
></app-organization-tree>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -12,12 +12,17 @@ import { Router, ActivatedRoute, Params } from '@angular/router';
|
||||||
|
|
||||||
import { Store, select } from '@ngrx/store';
|
import { Store, select } from '@ngrx/store';
|
||||||
|
|
||||||
|
import { DeptInfo } from '@ucap/domain-organization';
|
||||||
|
|
||||||
import { LogService } from '@ucap/ng-logger';
|
import { LogService } from '@ucap/ng-logger';
|
||||||
import { DeptInfo } from '@ucap/protocol-query';
|
|
||||||
|
|
||||||
import { DepartmentSelector, UserSelector } from '@ucap/ng-store-organization';
|
import { DepartmentSelector, UserSelector } from '@ucap/ng-store-organization';
|
||||||
import { LoginSelector } from '@ucap/ng-store-authentication';
|
import { LoginSelector } from '@ucap/ng-store-authentication';
|
||||||
|
|
||||||
|
import { AppUiService } from '@app/services/app-ui.service';
|
||||||
|
import { AppSelector } from '@app/store/state';
|
||||||
|
import { WindowSizeMode } from '@app/types/window-size-mode.type';
|
||||||
|
|
||||||
import { environment } from '@environments';
|
import { environment } from '@environments';
|
||||||
|
|
||||||
import { QueryParams } from '../types/params.type';
|
import { QueryParams } from '../types/params.type';
|
||||||
|
@ -32,6 +37,7 @@ export class SidenavPageComponent implements OnInit, OnDestroy {
|
||||||
initialExpanded: number;
|
initialExpanded: number;
|
||||||
displayRoot = false;
|
displayRoot = false;
|
||||||
displayRootDept: DeptInfo;
|
displayRootDept: DeptInfo;
|
||||||
|
windowSizeMode: WindowSizeMode;
|
||||||
|
|
||||||
private ngOnDestroySubject: Subject<void> = new Subject();
|
private ngOnDestroySubject: Subject<void> = new Subject();
|
||||||
|
|
||||||
|
@ -40,6 +46,7 @@ export class SidenavPageComponent implements OnInit, OnDestroy {
|
||||||
private activatedRoute: ActivatedRoute,
|
private activatedRoute: ActivatedRoute,
|
||||||
private store: Store<any>,
|
private store: Store<any>,
|
||||||
private changeDetectorRef: ChangeDetectorRef,
|
private changeDetectorRef: ChangeDetectorRef,
|
||||||
|
private appUiService: AppUiService,
|
||||||
private logService: LogService
|
private logService: LogService
|
||||||
) {
|
) {
|
||||||
this.logService.info('app-pages-ogranization-sidenav');
|
this.logService.info('app-pages-ogranization-sidenav');
|
||||||
|
@ -91,6 +98,15 @@ export class SidenavPageComponent implements OnInit, OnDestroy {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.store
|
||||||
|
.pipe(
|
||||||
|
takeUntil(this.ngOnDestroySubject),
|
||||||
|
select(AppSelector.windowSizeMode)
|
||||||
|
)
|
||||||
|
.subscribe((windowSizeMode) => {
|
||||||
|
this.windowSizeMode = windowSizeMode;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnDestroy(): void {
|
ngOnDestroy(): void {
|
||||||
|
@ -103,7 +119,6 @@ export class SidenavPageComponent implements OnInit, OnDestroy {
|
||||||
onClickedTree(node: DeptInfo) {
|
onClickedTree(node: DeptInfo) {
|
||||||
const queryParams: Params = {};
|
const queryParams: Params = {};
|
||||||
queryParams[QueryParams.DEPT_SEQ] = String(node.seq);
|
queryParams[QueryParams.DEPT_SEQ] = String(node.seq);
|
||||||
|
|
||||||
this.router.navigate(
|
this.router.navigate(
|
||||||
[
|
[
|
||||||
'organization',
|
'organization',
|
||||||
|
@ -115,5 +130,6 @@ export class SidenavPageComponent implements OnInit, OnDestroy {
|
||||||
queryParams
|
queryParams
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
this.appUiService.closeLeftSidenavOnNarrowMode();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@ import { AppOrganizationRoutingPageModule } from './organization-routing.page.mo
|
||||||
|
|
||||||
import { COMPONENTS } from './components';
|
import { COMPONENTS } from './components';
|
||||||
import { I18nModule, UCAP_I18N_NAMESPACE } from '@ucap/ng-i18n';
|
import { I18nModule, UCAP_I18N_NAMESPACE } from '@ucap/ng-i18n';
|
||||||
import { UiModule } from '@ucap/ng-ui';
|
// import { UiModule } from '@ucap/ng-ui';
|
||||||
import { OrganizationUiModule } from '@ucap/ng-ui-organization';
|
import { OrganizationUiModule } from '@ucap/ng-ui-organization';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
|
@ -30,8 +30,7 @@ import { OrganizationUiModule } from '@ucap/ng-ui-organization';
|
||||||
AppOrganizationRoutingPageModule,
|
AppOrganizationRoutingPageModule,
|
||||||
|
|
||||||
I18nModule,
|
I18nModule,
|
||||||
OrganizationUiModule,
|
OrganizationUiModule
|
||||||
UiModule
|
|
||||||
],
|
],
|
||||||
declarations: [...COMPONENTS],
|
declarations: [...COMPONENTS],
|
||||||
entryComponents: [],
|
entryComponents: [],
|
||||||
|
|
|
@ -101,13 +101,13 @@ export class AppSessionResolver implements Resolve<void> {
|
||||||
|
|
||||||
this.store.dispatch(
|
this.store.dispatch(
|
||||||
ConfigurationActions.versionInfo2Success({
|
ConfigurationActions.versionInfo2Success({
|
||||||
res: versionInfo2Res
|
versionInfo: versionInfo2Res.versionInfo
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
this.store.dispatch(
|
this.store.dispatch(
|
||||||
ConfigurationActions.urlInfoSuccess({
|
ConfigurationActions.urlInfoSuccess({
|
||||||
res: urlInfoRes
|
urlInfo: urlInfoRes.urlInfo
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -128,7 +128,9 @@ export class AppSessionResolver implements Resolve<void> {
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
this.protocolService.connect(versionInfo2Res.serverIp);
|
this.protocolService.connect(
|
||||||
|
versionInfo2Res.versionInfo.serverIp
|
||||||
|
);
|
||||||
},
|
},
|
||||||
(error) => {
|
(error) => {
|
||||||
reject(error);
|
reject(error);
|
||||||
|
|
|
@ -13,7 +13,7 @@ import { MatSelectModule } from '@angular/material/select';
|
||||||
import { MatTabsModule } from '@angular/material/tabs';
|
import { MatTabsModule } from '@angular/material/tabs';
|
||||||
|
|
||||||
import { I18nModule } from '@ucap/ng-i18n';
|
import { I18nModule } from '@ucap/ng-i18n';
|
||||||
import { UiModule } from '@ucap/ng-ui';
|
// import { UiModule } from '@ucap/ng-ui';
|
||||||
import { AuthenticationUiModule } from '@ucap/ng-ui-authentication';
|
import { AuthenticationUiModule } from '@ucap/ng-ui-authentication';
|
||||||
import { OrganizationUiModule } from '@ucap/ng-ui-organization';
|
import { OrganizationUiModule } from '@ucap/ng-ui-organization';
|
||||||
|
|
||||||
|
@ -38,7 +38,6 @@ import { COMPONENTS } from './components';
|
||||||
|
|
||||||
I18nModule,
|
I18nModule,
|
||||||
|
|
||||||
UiModule,
|
|
||||||
AuthenticationUiModule,
|
AuthenticationUiModule,
|
||||||
OrganizationUiModule,
|
OrganizationUiModule,
|
||||||
|
|
||||||
|
|
63
src/app/sections/call/call.section.module.ts
Normal file
63
src/app/sections/call/call.section.module.ts
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
import { CommonModule } from '@angular/common';
|
||||||
|
|
||||||
|
import { FlexLayoutModule } from '@angular/flex-layout';
|
||||||
|
|
||||||
|
import { ScrollingModule } from '@angular/cdk/scrolling';
|
||||||
|
|
||||||
|
import { MatButtonModule } from '@angular/material/button';
|
||||||
|
import { MatIconModule } from '@angular/material/icon';
|
||||||
|
import { MatTooltipModule } from '@angular/material/tooltip';
|
||||||
|
import { MatTabsModule } from '@angular/material/tabs';
|
||||||
|
import { MatProgressBarModule } from '@angular/material/progress-bar';
|
||||||
|
|
||||||
|
import { PerfectScrollbarModule } from 'ngx-perfect-scrollbar';
|
||||||
|
|
||||||
|
import { I18nModule, UCAP_I18N_NAMESPACE } from '@ucap/ng-i18n';
|
||||||
|
// import { UiModule } from '@ucap/ng-ui';
|
||||||
|
import { CallUiModule } from '@ucap/ng-ui-call';
|
||||||
|
import { OrganizationUiModule } from '@ucap/ng-ui-organization';
|
||||||
|
|
||||||
|
import { AppLayoutsModule } from '@app/layouts/layouts.module';
|
||||||
|
import { AppOrganizationModule } from '@app/ucap/organization/organization.module';
|
||||||
|
import { AppGroupSectionModule } from '../group/group.section.module';
|
||||||
|
|
||||||
|
import { COMPONENTS } from './components';
|
||||||
|
import { DIALOGS } from './dialogs';
|
||||||
|
import { AppCallModule } from '@app/ucap/call/call.module';
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
imports: [
|
||||||
|
CommonModule,
|
||||||
|
FlexLayoutModule,
|
||||||
|
|
||||||
|
MatIconModule,
|
||||||
|
MatButtonModule,
|
||||||
|
MatTooltipModule,
|
||||||
|
MatTabsModule,
|
||||||
|
MatProgressBarModule,
|
||||||
|
|
||||||
|
PerfectScrollbarModule,
|
||||||
|
ScrollingModule,
|
||||||
|
|
||||||
|
I18nModule,
|
||||||
|
|
||||||
|
AppLayoutsModule,
|
||||||
|
AppGroupSectionModule,
|
||||||
|
AppOrganizationModule,
|
||||||
|
AppCallModule,
|
||||||
|
|
||||||
|
CallUiModule,
|
||||||
|
OrganizationUiModule
|
||||||
|
],
|
||||||
|
exports: [...COMPONENTS, ...DIALOGS],
|
||||||
|
declarations: [...COMPONENTS, ...DIALOGS],
|
||||||
|
entryComponents: [...DIALOGS],
|
||||||
|
providers: [
|
||||||
|
{
|
||||||
|
provide: UCAP_I18N_NAMESPACE,
|
||||||
|
useValue: ['call', 'common']
|
||||||
|
}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
export class AppCallSectionModule {}
|
4
src/app/sections/call/components/index.ts
Normal file
4
src/app/sections/call/components/index.ts
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
import { InfoSectionComponent } from './info.section.component';
|
||||||
|
import { ListSectionComponent } from './list.section.component';
|
||||||
|
|
||||||
|
export const COMPONENTS = [InfoSectionComponent, ListSectionComponent];
|
28
src/app/sections/call/components/info.section.component.html
Normal file
28
src/app/sections/call/components/info.section.component.html
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
<div class="app-sections-call-info-container" fxLayout="row">
|
||||||
|
<div class="history-all" fxFlex="1 1 auto">
|
||||||
|
<div class="subtitle2">{{ 'call:label.callHistory' | ucapI18n }}</div>
|
||||||
|
<div class="list-container">
|
||||||
|
<app-call-time-line
|
||||||
|
[historyList]="originalHistoryList"
|
||||||
|
></app-call-time-line>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="history-other" fxFlex="44%">
|
||||||
|
<div class="history-away">
|
||||||
|
<div class="subtitle2">{{ 'call:label.missed' | ucapI18n }}</div>
|
||||||
|
<div class="list-container">
|
||||||
|
<app-call-time-line
|
||||||
|
[historyList]="awayHistoryList"
|
||||||
|
></app-call-time-line>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="history-noreply">
|
||||||
|
<div class="subtitle2">{{ 'call:label.unanswered' | ucapI18n }}</div>
|
||||||
|
<div class="list-container">
|
||||||
|
<app-call-time-line
|
||||||
|
[historyList]="unansweredHistoryList"
|
||||||
|
></app-call-time-line>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
|
@ -0,0 +1,32 @@
|
||||||
|
import { TestBed, async } from '@angular/core/testing';
|
||||||
|
import { RouterTestingModule } from '@angular/router/testing';
|
||||||
|
import { InfoSectionComponent } from './info.section.component';
|
||||||
|
|
||||||
|
describe('app::sections::group::InfoSectionComponent', () => {
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
imports: [RouterTestingModule],
|
||||||
|
declarations: [InfoSectionComponent]
|
||||||
|
}).compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should create the app', () => {
|
||||||
|
const fixture = TestBed.createComponent(InfoSectionComponent);
|
||||||
|
const app = fixture.componentInstance;
|
||||||
|
expect(app).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it(`should have as title 'ucap-lg-web'`, () => {
|
||||||
|
const fixture = TestBed.createComponent(InfoSectionComponent);
|
||||||
|
const app = fixture.componentInstance;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should render title', () => {
|
||||||
|
const fixture = TestBed.createComponent(InfoSectionComponent);
|
||||||
|
fixture.detectChanges();
|
||||||
|
const compiled = fixture.nativeElement;
|
||||||
|
expect(compiled.querySelector('.content span').textContent).toContain(
|
||||||
|
'ucap-lg-web app is running!'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
106
src/app/sections/call/components/info.section.component.ts
Normal file
106
src/app/sections/call/components/info.section.component.ts
Normal file
|
@ -0,0 +1,106 @@
|
||||||
|
import {
|
||||||
|
Component,
|
||||||
|
OnInit,
|
||||||
|
OnDestroy,
|
||||||
|
ChangeDetectionStrategy,
|
||||||
|
ChangeDetectorRef,
|
||||||
|
Input
|
||||||
|
} from '@angular/core';
|
||||||
|
import { Store, select } from '@ngrx/store';
|
||||||
|
import { Subject, combineLatest } from 'rxjs';
|
||||||
|
import { takeUntil, withLatestFrom } from 'rxjs/operators';
|
||||||
|
import { CallSelector } from '@ucap/ng-store-call';
|
||||||
|
import { CallHistory, CallResultType } from '@ucap/domain-call';
|
||||||
|
import { ActivatedRoute } from '@angular/router';
|
||||||
|
import { UserSelector } from '@ucap/ng-store-organization';
|
||||||
|
import { QueryParams } from '@app/pages/call/types/params.type';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-sections-call-info',
|
||||||
|
templateUrl: './info.section.component.html',
|
||||||
|
styleUrls: ['./info.section.component.scss'],
|
||||||
|
changeDetection: ChangeDetectionStrategy.OnPush
|
||||||
|
})
|
||||||
|
export class InfoSectionComponent implements OnInit, OnDestroy {
|
||||||
|
isMe: boolean;
|
||||||
|
userSeq: string;
|
||||||
|
|
||||||
|
originalHistoryList: CallHistory[];
|
||||||
|
awayHistoryList: CallHistory[];
|
||||||
|
unansweredHistoryList: CallHistory[];
|
||||||
|
|
||||||
|
private ngOnDestroySubject: Subject<void> = new Subject();
|
||||||
|
constructor(
|
||||||
|
private store: Store<any>,
|
||||||
|
private activatedRoute: ActivatedRoute,
|
||||||
|
private changeDetectorRef: ChangeDetectorRef
|
||||||
|
) {}
|
||||||
|
|
||||||
|
ngOnInit(): void {
|
||||||
|
combineLatest([
|
||||||
|
this.activatedRoute.queryParams,
|
||||||
|
this.store.pipe(select(CallSelector.callHistory))
|
||||||
|
])
|
||||||
|
.pipe(
|
||||||
|
takeUntil(this.ngOnDestroySubject),
|
||||||
|
withLatestFrom(this.store.pipe(select(UserSelector.user)))
|
||||||
|
)
|
||||||
|
.subscribe(([[params, callHistory], user]) => {
|
||||||
|
let existParams = false;
|
||||||
|
if (!!params) {
|
||||||
|
const seqParam = params[QueryParams.ID];
|
||||||
|
// initializing by userSeq Change.
|
||||||
|
if (this.userSeq !== seqParam) {
|
||||||
|
}
|
||||||
|
// setting userSeq.
|
||||||
|
this.userSeq = !!seqParam
|
||||||
|
? seqParam
|
||||||
|
: !!user
|
||||||
|
? String(user.info.seq)
|
||||||
|
: undefined;
|
||||||
|
if (!!user && this.userSeq === String(user.info.seq)) {
|
||||||
|
this.isMe = true;
|
||||||
|
} else {
|
||||||
|
this.isMe = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.originalHistoryList = callHistory;
|
||||||
|
|
||||||
|
this.getFiltered();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnDestroy(): void {
|
||||||
|
if (!!this.ngOnDestroySubject) {
|
||||||
|
this.ngOnDestroySubject.next();
|
||||||
|
this.ngOnDestroySubject.complete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getFiltered(): void {
|
||||||
|
// original
|
||||||
|
this.originalHistoryList = this.originalHistoryList.filter((item) => {
|
||||||
|
let result = true;
|
||||||
|
if (!this.isMe && !!this.userSeq) {
|
||||||
|
if (!!item.sendYn && item.sendYn === true) {
|
||||||
|
result = item.calledUserSeq === this.userSeq;
|
||||||
|
} else {
|
||||||
|
result = item.callingUserSeq === this.userSeq;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
});
|
||||||
|
|
||||||
|
// away
|
||||||
|
this.awayHistoryList = this.originalHistoryList.filter(
|
||||||
|
(item) => item.callResult === CallResultType.Away
|
||||||
|
);
|
||||||
|
// unanswered
|
||||||
|
this.unansweredHistoryList = this.originalHistoryList.filter(
|
||||||
|
(item) => item.callResult === CallResultType.Missed
|
||||||
|
);
|
||||||
|
|
||||||
|
this.changeDetectorRef.markForCheck();
|
||||||
|
}
|
||||||
|
}
|
132
src/app/sections/call/components/list.section.component.html
Normal file
132
src/app/sections/call/components/list.section.component.html
Normal file
|
@ -0,0 +1,132 @@
|
||||||
|
<div fxFlexFill class="list-container">
|
||||||
|
<div class="select-call-section-content">
|
||||||
|
<mat-tab-group
|
||||||
|
#selectUserTabGroup
|
||||||
|
mat-stretch-tabs
|
||||||
|
class="tap-container tab_num2"
|
||||||
|
>
|
||||||
|
<mat-tab>
|
||||||
|
<ng-template mat-tab-label>
|
||||||
|
<p>
|
||||||
|
<mat-icon>history</mat-icon>
|
||||||
|
</p>
|
||||||
|
</ng-template>
|
||||||
|
<ng-template matTabContent>
|
||||||
|
<div fxFlexFill class="select-tap">
|
||||||
|
<div class="sub-title">
|
||||||
|
{{ 'call:label.callHistory' | ucapI18n
|
||||||
|
}}<strong>{{ filteredCallHistory.length }}</strong>
|
||||||
|
</div>
|
||||||
|
<div class="btns">
|
||||||
|
<button
|
||||||
|
mat-button
|
||||||
|
[ngClass]="filteringByTypeClass(CallHistorySearchType.All)"
|
||||||
|
(click)="filteringByType(CallHistorySearchType.All)"
|
||||||
|
>
|
||||||
|
{{ 'call:label.all' | ucapI18n }}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
mat-button
|
||||||
|
[ngClass]="filteringByTypeClass(CallHistorySearchType.Send)"
|
||||||
|
(click)="filteringByType(CallHistorySearchType.Send)"
|
||||||
|
>
|
||||||
|
{{ 'call:label.send' | ucapI18n }}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
mat-button
|
||||||
|
[ngClass]="filteringByTypeClass(CallHistorySearchType.Receive)"
|
||||||
|
(click)="filteringByType(CallHistorySearchType.Receive)"
|
||||||
|
>
|
||||||
|
{{ 'call:label.recieve' | ucapI18n }}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
mat-button
|
||||||
|
[ngClass]="filteringByTypeClass(CallHistorySearchType.Missed)"
|
||||||
|
(click)="filteringByType(CallHistorySearchType.Missed)"
|
||||||
|
>
|
||||||
|
{{ 'call:label.missed' | ucapI18n }}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
mat-button
|
||||||
|
[ngClass]="
|
||||||
|
filteringByTypeClass(CallHistorySearchType.UnAnswered)
|
||||||
|
"
|
||||||
|
(click)="filteringByType(CallHistorySearchType.UnAnswered)"
|
||||||
|
>
|
||||||
|
{{ 'call:label.unanswered' | ucapI18n }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="list">
|
||||||
|
<app-call-history-expansion [itemList]="filteredCallHistory">
|
||||||
|
</app-call-history-expansion>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</ng-template>
|
||||||
|
</mat-tab>
|
||||||
|
<mat-tab>
|
||||||
|
<ng-template mat-tab-label>
|
||||||
|
<p>
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="21"
|
||||||
|
height="19"
|
||||||
|
viewBox="0 0 21 19"
|
||||||
|
>
|
||||||
|
<g
|
||||||
|
id="icon_gnb_organiztion_g32"
|
||||||
|
transform="translate(-12.917 -220.25)"
|
||||||
|
>
|
||||||
|
<g class="prefix__cls-1" transform="translate(19.917 220.25)">
|
||||||
|
<circle cx="3.5" cy="3.5" r="3.5" class="prefix__cls-3" />
|
||||||
|
<circle cx="3.5" cy="3.5" r="2.5" class="prefix__cls-4" />
|
||||||
|
</g>
|
||||||
|
<g class="prefix__cls-1" transform="translate(12.917 232.25)">
|
||||||
|
<circle cx="3.5" cy="3.5" r="3.5" class="prefix__cls-3" />
|
||||||
|
<circle cx="3.5" cy="3.5" r="2.5" class="prefix__cls-4" />
|
||||||
|
</g>
|
||||||
|
<g class="prefix__cls-1" transform="translate(19.917 232.25)">
|
||||||
|
<circle cx="3.5" cy="3.5" r="3.5" class="prefix__cls-3" />
|
||||||
|
<circle cx="3.5" cy="3.5" r="2.5" class="prefix__cls-4" />
|
||||||
|
</g>
|
||||||
|
<g class="prefix__cls-1" transform="translate(26.917 232.25)">
|
||||||
|
<circle cx="3.5" cy="3.5" r="3.5" class="prefix__cls-3" />
|
||||||
|
<circle cx="3.5" cy="3.5" r="2.5" class="prefix__cls-4" />
|
||||||
|
</g>
|
||||||
|
<path
|
||||||
|
d="M16.5 233.312v-3.437h13.833v3.438"
|
||||||
|
transform="translate(0 -1.087)"
|
||||||
|
style="
|
||||||
|
stroke-linecap: round;
|
||||||
|
stroke-linejoin: round;
|
||||||
|
stroke: #999;
|
||||||
|
stroke-width: 2px;
|
||||||
|
fill: none;
|
||||||
|
"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="M0 0L0 6"
|
||||||
|
class="prefix__cls-1"
|
||||||
|
transform="translate(23.417 226.75)"
|
||||||
|
/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
</p>
|
||||||
|
</ng-template>
|
||||||
|
<ng-template matTabContent>
|
||||||
|
<div fxFlexFill class="select-tap">
|
||||||
|
<div class="sub-title">
|
||||||
|
{{ 'call:label.organization' | ucapI18n }}
|
||||||
|
</div>
|
||||||
|
<div class="list">
|
||||||
|
<app-organization-profile-navigation-list
|
||||||
|
[checkable]="false"
|
||||||
|
[useFAB]="true"
|
||||||
|
>
|
||||||
|
</app-organization-profile-navigation-list>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</ng-template>
|
||||||
|
</mat-tab>
|
||||||
|
</mat-tab-group>
|
||||||
|
</div>
|
||||||
|
</div>
|
|
@ -0,0 +1,4 @@
|
||||||
|
.list-container {
|
||||||
|
height: calc(100% - 100px) !important;
|
||||||
|
min-height: auto !important;
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
import { TestBed, async } from '@angular/core/testing';
|
||||||
|
import { RouterTestingModule } from '@angular/router/testing';
|
||||||
|
import { ListSectionComponent } from './list.section.component';
|
||||||
|
|
||||||
|
describe('app::sections::group::ListSectionComponent', () => {
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
imports: [RouterTestingModule],
|
||||||
|
declarations: [ListSectionComponent]
|
||||||
|
}).compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should create the app', () => {
|
||||||
|
const fixture = TestBed.createComponent(ListSectionComponent);
|
||||||
|
const app = fixture.componentInstance;
|
||||||
|
expect(app).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it(`should have as title 'ucap-lg-web'`, () => {
|
||||||
|
const fixture = TestBed.createComponent(ListSectionComponent);
|
||||||
|
const app = fixture.componentInstance;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should render title', () => {
|
||||||
|
const fixture = TestBed.createComponent(ListSectionComponent);
|
||||||
|
fixture.detectChanges();
|
||||||
|
const compiled = fixture.nativeElement;
|
||||||
|
expect(compiled.querySelector('.content span').textContent).toContain(
|
||||||
|
'ucap-lg-web app is running!'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
114
src/app/sections/call/components/list.section.component.ts
Normal file
114
src/app/sections/call/components/list.section.component.ts
Normal file
|
@ -0,0 +1,114 @@
|
||||||
|
import { Subject } from 'rxjs';
|
||||||
|
|
||||||
|
import {
|
||||||
|
Component,
|
||||||
|
OnInit,
|
||||||
|
OnDestroy,
|
||||||
|
ChangeDetectionStrategy,
|
||||||
|
ChangeDetectorRef,
|
||||||
|
Input
|
||||||
|
} from '@angular/core';
|
||||||
|
|
||||||
|
import { LogService } from '@ucap/ng-logger';
|
||||||
|
|
||||||
|
import { SearchData } from '@app/ucap/organization/models/search-data';
|
||||||
|
import { Store, select } from '@ngrx/store';
|
||||||
|
import { takeUntil } from 'rxjs/operators';
|
||||||
|
import { CallSelector } from '@ucap/ng-store-call';
|
||||||
|
import {
|
||||||
|
CallHistory,
|
||||||
|
CallHistorySearchType,
|
||||||
|
CallResultType
|
||||||
|
} from '@ucap/domain-call';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-sections-call-list',
|
||||||
|
templateUrl: './list.section.component.html',
|
||||||
|
styleUrls: ['./list.section.component.scss'],
|
||||||
|
changeDetection: ChangeDetectionStrategy.OnPush
|
||||||
|
})
|
||||||
|
export class ListSectionComponent implements OnInit, OnDestroy {
|
||||||
|
@Input()
|
||||||
|
set searchObj(obj: SearchData) {
|
||||||
|
this._getFiltered();
|
||||||
|
}
|
||||||
|
get searchObj(): SearchData {
|
||||||
|
return this._searchObj;
|
||||||
|
}
|
||||||
|
// tslint:disable-next-line: variable-name
|
||||||
|
_searchObj: SearchData;
|
||||||
|
|
||||||
|
callHistory: CallHistory[];
|
||||||
|
filteredCallHistory: CallHistory[];
|
||||||
|
|
||||||
|
searchType = CallHistorySearchType.All;
|
||||||
|
CallHistorySearchType = CallHistorySearchType;
|
||||||
|
|
||||||
|
private ngOnDestroySubject: Subject<void> = new Subject();
|
||||||
|
constructor(
|
||||||
|
private store: Store<any>,
|
||||||
|
private changeDetectorRef: ChangeDetectorRef,
|
||||||
|
private logService: LogService
|
||||||
|
) {}
|
||||||
|
|
||||||
|
ngOnInit(): void {
|
||||||
|
this.store
|
||||||
|
.pipe(
|
||||||
|
takeUntil(this.ngOnDestroySubject),
|
||||||
|
select(CallSelector.callHistory)
|
||||||
|
)
|
||||||
|
.subscribe((callHistory) => {
|
||||||
|
this.callHistory = callHistory;
|
||||||
|
this._getFiltered();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnDestroy(): void {
|
||||||
|
if (!!this.ngOnDestroySubject) {
|
||||||
|
this.ngOnDestroySubject.next();
|
||||||
|
this.ngOnDestroySubject.complete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
filteringByTypeClass(searchType: CallHistorySearchType): string {
|
||||||
|
return this.searchType === searchType ? 'cdk-active' : '';
|
||||||
|
}
|
||||||
|
filteringByType(searchType: CallHistorySearchType) {
|
||||||
|
this.searchType = searchType;
|
||||||
|
this._getFiltered();
|
||||||
|
}
|
||||||
|
|
||||||
|
private _getFiltered() {
|
||||||
|
if (!!this.callHistory && this.callHistory.length > 0) {
|
||||||
|
switch (this.searchType) {
|
||||||
|
case CallHistorySearchType.Send:
|
||||||
|
this.filteredCallHistory = this.callHistory.filter(
|
||||||
|
(item) => !!item.sendYn
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case CallHistorySearchType.Receive:
|
||||||
|
this.filteredCallHistory = this.callHistory.filter(
|
||||||
|
(item) => !item.sendYn
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case CallHistorySearchType.Missed:
|
||||||
|
this.filteredCallHistory = this.callHistory.filter(
|
||||||
|
(item) => item.callResult === CallResultType.Away
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case CallHistorySearchType.UnAnswered:
|
||||||
|
this.filteredCallHistory = this.callHistory.filter(
|
||||||
|
(item) => item.callResult === CallResultType.Missed
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// case CallHistorySearchType.All:
|
||||||
|
this.filteredCallHistory = this.callHistory;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.filteredCallHistory = [];
|
||||||
|
}
|
||||||
|
this.changeDetectorRef.markForCheck();
|
||||||
|
}
|
||||||
|
}
|
14
src/app/sections/call/dialogs/dialpad.dialog.component.html
Normal file
14
src/app/sections/call/dialogs/dialpad.dialog.component.html
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
<div class="dialog-container">
|
||||||
|
<app-layouts-default-dialog
|
||||||
|
[disableClose]="false"
|
||||||
|
(closed)="onClosed($event)"
|
||||||
|
class="ucap-dialog-call-dialpad-container"
|
||||||
|
>
|
||||||
|
<div appLayoutsDefaultDialog="header">
|
||||||
|
{{ 'call:label.dialpad' | ucapI18n }}
|
||||||
|
</div>
|
||||||
|
<div class="dialog-body" appLayoutsDefaultDialog="body">
|
||||||
|
<ucap-call-dialpad (sendCall)="onSendCall($event)"></ucap-call-dialpad>
|
||||||
|
</div>
|
||||||
|
</app-layouts-default-dialog>
|
||||||
|
</div>
|
75
src/app/sections/call/dialogs/dialpad.dialog.component.scss
Normal file
75
src/app/sections/call/dialogs/dialpad.dialog.component.scss
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
@import '~@ucap/lg-scss/mixins';
|
||||||
|
.dialog-container {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
.dialog-body {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
.profile {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
padding-bottom: 10px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
border-bottom: 1px solid #ccc;
|
||||||
|
.profile-image {
|
||||||
|
border-radius: 50%;
|
||||||
|
overflow: hidden;
|
||||||
|
width: 36px;
|
||||||
|
height: 36px;
|
||||||
|
margin-left: 0;
|
||||||
|
background-color: #ffe8cb;
|
||||||
|
img {
|
||||||
|
max-width: 100%;
|
||||||
|
height: auto;
|
||||||
|
vertical-align: top;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.user-info {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-start;
|
||||||
|
justify-content: flex-start;
|
||||||
|
padding-left: 16px;
|
||||||
|
.user-n-g {
|
||||||
|
display: flex;
|
||||||
|
flex-flow: row-reverse nowrap;
|
||||||
|
align-items: flex-end;
|
||||||
|
height: 22px;
|
||||||
|
.user-name {
|
||||||
|
@include ellipsis-column(1);
|
||||||
|
height: 22px;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 600;
|
||||||
|
order: 1;
|
||||||
|
-ms-flex-order: 1;
|
||||||
|
}
|
||||||
|
.user-grade {
|
||||||
|
@include ellipsis(1);
|
||||||
|
align-self: stretch;
|
||||||
|
font: {
|
||||||
|
size: 13px;
|
||||||
|
}
|
||||||
|
margin-left: 4px;
|
||||||
|
order: 0;
|
||||||
|
-ms-flex-order: 0;
|
||||||
|
}
|
||||||
|
.write-date {
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.contents {
|
||||||
|
width: 100%;
|
||||||
|
height: calc(100% - 60px);
|
||||||
|
overflow: hidden;
|
||||||
|
perfect-scrollbar {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
padding-right: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
import { By } from '@angular/platform-browser';
|
||||||
|
import { DebugElement } from '@angular/core';
|
||||||
|
|
||||||
|
import { TextDetailDialogComponent } from './text-detail.dialog.component';
|
||||||
|
|
||||||
|
describe('ucap::ui-organization::CreateChatDialogComponent', () => {
|
||||||
|
let component: TextDetailDialogComponent;
|
||||||
|
let fixture: ComponentFixture<TextDetailDialogComponent>;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [TextDetailDialogComponent]
|
||||||
|
}).compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(TextDetailDialogComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
86
src/app/sections/call/dialogs/dialpad.dialog.component.ts
Normal file
86
src/app/sections/call/dialogs/dialpad.dialog.component.ts
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
import {
|
||||||
|
Component,
|
||||||
|
OnInit,
|
||||||
|
OnDestroy,
|
||||||
|
ChangeDetectionStrategy,
|
||||||
|
ChangeDetectorRef,
|
||||||
|
Inject
|
||||||
|
} from '@angular/core';
|
||||||
|
|
||||||
|
import {
|
||||||
|
MatDialogRef,
|
||||||
|
MAT_DIALOG_DATA,
|
||||||
|
MatDialog
|
||||||
|
} from '@angular/material/dialog';
|
||||||
|
|
||||||
|
import { Subject } from 'rxjs';
|
||||||
|
import { Store, select } from '@ngrx/store';
|
||||||
|
import { takeUntil } from 'rxjs/operators';
|
||||||
|
|
||||||
|
import { User } from '@ucap/domain-organization';
|
||||||
|
import { UserSelector } from '@ucap/ng-store-organization';
|
||||||
|
import { LoginSelector } from '@ucap/ng-store-authentication';
|
||||||
|
import { AppCallService } from '@app/services/app-call.service';
|
||||||
|
import { AppAuthenticationService } from '@app/services/app-authentication.service';
|
||||||
|
import { LoginSession, LoginInfo } from '@ucap/domain-authentication';
|
||||||
|
|
||||||
|
export interface DialpadDialogData {}
|
||||||
|
export interface DialpadDialogResult {}
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-dialog-call-dialpad',
|
||||||
|
templateUrl: './dialpad.dialog.component.html',
|
||||||
|
styleUrls: ['./dialpad.dialog.component.scss'],
|
||||||
|
changeDetection: ChangeDetectionStrategy.OnPush
|
||||||
|
})
|
||||||
|
export class DialpadDialogComponent implements OnInit, OnDestroy {
|
||||||
|
loginSession: LoginSession;
|
||||||
|
loginInfo: LoginInfo;
|
||||||
|
user: User;
|
||||||
|
|
||||||
|
private ngOnDestroySubject: Subject<void> = new Subject();
|
||||||
|
constructor(
|
||||||
|
private store: Store<any>,
|
||||||
|
public dialogRef: MatDialogRef<DialpadDialogData, DialpadDialogResult>,
|
||||||
|
@Inject(MAT_DIALOG_DATA) public data: DialpadDialogData,
|
||||||
|
private appCallService: AppCallService,
|
||||||
|
private appAuthenticationService: AppAuthenticationService,
|
||||||
|
private changeDetectorRef: ChangeDetectorRef
|
||||||
|
) {}
|
||||||
|
|
||||||
|
ngOnInit(): void {
|
||||||
|
this.loginSession = this.appAuthenticationService.getLoginSession();
|
||||||
|
this.store
|
||||||
|
.pipe(takeUntil(this.ngOnDestroySubject), select(UserSelector.user))
|
||||||
|
.subscribe((user) => {
|
||||||
|
this.user = user;
|
||||||
|
});
|
||||||
|
|
||||||
|
this.store
|
||||||
|
.pipe(takeUntil(this.ngOnDestroySubject), select(LoginSelector.loginInfo))
|
||||||
|
.subscribe((loginInfo) => {
|
||||||
|
this.loginInfo = loginInfo;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnDestroy(): void {
|
||||||
|
if (!!this.ngOnDestroySubject) {
|
||||||
|
this.ngOnDestroySubject.next();
|
||||||
|
this.ngOnDestroySubject.complete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onSendCall(calleeNumber: string) {
|
||||||
|
this.appCallService.sendClicktocall(
|
||||||
|
this.loginInfo,
|
||||||
|
this.user,
|
||||||
|
this.loginSession.deviceType,
|
||||||
|
calleeNumber
|
||||||
|
);
|
||||||
|
this.dialogRef.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
onClosed(event: MouseEvent): void {
|
||||||
|
this.dialogRef.close();
|
||||||
|
}
|
||||||
|
}
|
3
src/app/sections/call/dialogs/index.ts
Normal file
3
src/app/sections/call/dialogs/index.ts
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
import { DialpadDialogComponent } from './dialpad.dialog.component';
|
||||||
|
|
||||||
|
export const DIALOGS = [DialpadDialogComponent];
|
|
@ -4,8 +4,6 @@ import { ReactiveFormsModule, FormsModule } from '@angular/forms';
|
||||||
|
|
||||||
import { FlexLayoutModule } from '@angular/flex-layout';
|
import { FlexLayoutModule } from '@angular/flex-layout';
|
||||||
|
|
||||||
import { ScrollingModule } from '@angular/cdk/scrolling';
|
|
||||||
|
|
||||||
import { MatRippleModule } from '@angular/material/core';
|
import { MatRippleModule } from '@angular/material/core';
|
||||||
import { MatAutocompleteModule } from '@angular/material/autocomplete';
|
import { MatAutocompleteModule } from '@angular/material/autocomplete';
|
||||||
import { MatBadgeModule } from '@angular/material/badge';
|
import { MatBadgeModule } from '@angular/material/badge';
|
||||||
|
@ -30,7 +28,12 @@ import { MatProgressBarModule } from '@angular/material/progress-bar';
|
||||||
import { PerfectScrollbarModule } from 'ngx-perfect-scrollbar';
|
import { PerfectScrollbarModule } from 'ngx-perfect-scrollbar';
|
||||||
|
|
||||||
import { I18nModule, UCAP_I18N_NAMESPACE } from '@ucap/ng-i18n';
|
import { I18nModule, UCAP_I18N_NAMESPACE } from '@ucap/ng-i18n';
|
||||||
import { UiModule } from '@ucap/ng-ui';
|
|
||||||
|
import { UiCoreModule } from '@ucap/ng-ui/core';
|
||||||
|
import { UiDateModule } from '@ucap/ng-ui/date';
|
||||||
|
import { UiViewerModule } from '@ucap/ng-ui/viewer';
|
||||||
|
import { UiscrollingModule } from '@ucap/ng-ui/scrolling';
|
||||||
|
|
||||||
import { ChatUiModule } from '@ucap/ng-ui-chat';
|
import { ChatUiModule } from '@ucap/ng-ui-chat';
|
||||||
import { OrganizationUiModule } from '@ucap/ng-ui-organization';
|
import { OrganizationUiModule } from '@ucap/ng-ui-organization';
|
||||||
import { AppOrganizationModule } from '@app/ucap/organization/organization.module';
|
import { AppOrganizationModule } from '@app/ucap/organization/organization.module';
|
||||||
|
@ -42,6 +45,7 @@ import { AppGroupSectionModule } from '../group/group.section.module';
|
||||||
import { COMPONENTS } from './components';
|
import { COMPONENTS } from './components';
|
||||||
import { DIALOGS } from './dialogs';
|
import { DIALOGS } from './dialogs';
|
||||||
import { DRAWERS } from './drawers';
|
import { DRAWERS } from './drawers';
|
||||||
|
import { DIRECTIVES } from './directives';
|
||||||
import { AppGroupModule } from '@app/ucap/group/group.module';
|
import { AppGroupModule } from '@app/ucap/group/group.module';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
|
@ -73,10 +77,13 @@ import { AppGroupModule } from '@app/ucap/group/group.module';
|
||||||
MatProgressBarModule,
|
MatProgressBarModule,
|
||||||
|
|
||||||
PerfectScrollbarModule,
|
PerfectScrollbarModule,
|
||||||
ScrollingModule,
|
|
||||||
|
|
||||||
I18nModule,
|
I18nModule,
|
||||||
UiModule,
|
|
||||||
|
UiCoreModule,
|
||||||
|
UiDateModule,
|
||||||
|
UiViewerModule,
|
||||||
|
UiscrollingModule,
|
||||||
|
|
||||||
AppLayoutsModule,
|
AppLayoutsModule,
|
||||||
AppGroupSectionModule,
|
AppGroupSectionModule,
|
||||||
|
@ -87,8 +94,8 @@ import { AppGroupModule } from '@app/ucap/group/group.module';
|
||||||
AppChatModule,
|
AppChatModule,
|
||||||
AppGroupModule
|
AppGroupModule
|
||||||
],
|
],
|
||||||
exports: [...COMPONENTS, ...DIALOGS, ...DRAWERS],
|
exports: [...COMPONENTS, ...DIALOGS, ...DRAWERS, ...DIRECTIVES],
|
||||||
declarations: [...COMPONENTS, ...DIALOGS, ...DRAWERS],
|
declarations: [...COMPONENTS, ...DIALOGS, ...DRAWERS, ...DIRECTIVES],
|
||||||
entryComponents: [...DIALOGS, ...DRAWERS],
|
entryComponents: [...DIALOGS, ...DRAWERS],
|
||||||
providers: [
|
providers: [
|
||||||
{
|
{
|
||||||
|
|
|
@ -3,15 +3,13 @@
|
||||||
<app-chat-selector-sticker
|
<app-chat-selector-sticker
|
||||||
*ngSwitchCase="SelectorType.STICKER"
|
*ngSwitchCase="SelectorType.STICKER"
|
||||||
(selectedSticker)="onSelectedSticker($event)"
|
(selectedSticker)="onSelectedSticker($event)"
|
||||||
(closed)="selectorType = SelectorType.EMPTY"
|
(closed)="clearSelector()"
|
||||||
>
|
>
|
||||||
</app-chat-selector-sticker>
|
</app-chat-selector-sticker>
|
||||||
|
|
||||||
<app-chat-selector-translation
|
<app-chat-selector-translation
|
||||||
*ngSwitchCase="SelectorType.TRANSLATION"
|
*ngSwitchCase="SelectorType.TRANSLATION"
|
||||||
(closed)="
|
(closed)="clearSelector()"
|
||||||
selectorType = SelectorType.EMPTY; translationPreviewInfo = null
|
|
||||||
"
|
|
||||||
[destLocale]="destLocale"
|
[destLocale]="destLocale"
|
||||||
[simpleView]="translationSimpleview"
|
[simpleView]="translationSimpleview"
|
||||||
[preView]="translationPreview"
|
[preView]="translationPreview"
|
||||||
|
@ -26,18 +24,36 @@
|
||||||
<app-chat-selector-file-upload
|
<app-chat-selector-file-upload
|
||||||
#fileUploadSelector
|
#fileUploadSelector
|
||||||
*ngSwitchCase="SelectorType.FILEUPLOAD"
|
*ngSwitchCase="SelectorType.FILEUPLOAD"
|
||||||
(closed)="selectorType = SelectorType.EMPTY"
|
(closed)="clearSelector()"
|
||||||
>
|
>
|
||||||
</app-chat-selector-file-upload>
|
</app-chat-selector-file-upload>
|
||||||
|
|
||||||
<app-chat-selector-email-send
|
<app-chat-selector-email-send
|
||||||
*ngSwitchCase="SelectorType.EMAILSENDER"
|
*ngSwitchCase="SelectorType.EMAILSENDER"
|
||||||
(sendEventEmail)="onSendEventEmail($event)"
|
(sendEventEmail)="onSendEventEmail($event)"
|
||||||
(closed)="selectorType = SelectorType.EMPTY"
|
(closed)="clearSelector()"
|
||||||
></app-chat-selector-email-send>
|
></app-chat-selector-email-send>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<div class="chat-form-area ucap-mat-input-container">
|
<div class="chat-form-area ucap-mat-input-container">
|
||||||
|
<!-- <div class="message-text" fxFlex floatLabel="never" appearance="none">
|
||||||
|
<textarea
|
||||||
|
#messageInput
|
||||||
|
placeholder="{{ 'chat:label.inputChatMessage' | ucapI18n }}"
|
||||||
|
name="message"
|
||||||
|
(keydown)="textareaResize($event, messageInput)"
|
||||||
|
(keydown.enter)="onKeydown($event)"
|
||||||
|
></textarea>
|
||||||
|
</div> -->
|
||||||
|
<!-- <mat-form-field
|
||||||
|
class="message-text"
|
||||||
|
fxFlex
|
||||||
|
floatLabel="never"
|
||||||
|
appearance="none"
|
||||||
|
>
|
||||||
|
<mat-label>{{ 'chat:label.inputChatMessage' | ucapI18n }}</mat-label>
|
||||||
|
<textarea matInput #messageInput></textarea>
|
||||||
|
</mat-form-field> -->
|
||||||
<mat-form-field
|
<mat-form-field
|
||||||
class="message-text"
|
class="message-text"
|
||||||
fxFlex
|
fxFlex
|
||||||
|
@ -45,19 +61,13 @@
|
||||||
appearance="none"
|
appearance="none"
|
||||||
>
|
>
|
||||||
<mat-label>{{ 'chat:label.inputChatMessage' | ucapI18n }}</mat-label>
|
<mat-label>{{ 'chat:label.inputChatMessage' | ucapI18n }}</mat-label>
|
||||||
<!-- <textarea
|
<textarea
|
||||||
matInput
|
matInput
|
||||||
#messageInput
|
#messageInput
|
||||||
name="message"
|
name="message"
|
||||||
[matTextareaAutosize]="true"
|
[matTextareaAutosize]="true"
|
||||||
(keydown.enter)="onKeydown($event)"
|
(keydown.enter)="onKeydown($event)"
|
||||||
></textarea> -->
|
></textarea>
|
||||||
<input
|
|
||||||
matInput
|
|
||||||
#messageInput
|
|
||||||
name="message"
|
|
||||||
(keydown.enter)="onKeydown($event)"
|
|
||||||
/>
|
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
|
|
||||||
<input
|
<input
|
||||||
|
@ -94,7 +104,7 @@
|
||||||
</button>
|
</button>
|
||||||
<!-- <button
|
<!-- <button
|
||||||
mat-icon-button
|
mat-icon-button
|
||||||
*ngIf="!!authRes && !!authRes.useCapturePcScreen"
|
*ngIf="!!userPermission && !!userPermission.useCapturePcScreen"
|
||||||
aria-label="screenshot"
|
aria-label="screenshot"
|
||||||
matTooltipPosition="above"
|
matTooltipPosition="above"
|
||||||
matTooltip="{{ 'label.screenshot' | ucapI18n }}"
|
matTooltip="{{ 'label.screenshot' | ucapI18n }}"
|
||||||
|
@ -115,7 +125,7 @@
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
mat-icon-button
|
mat-icon-button
|
||||||
*ngIf="!!authRes && !!authRes.canSendEmail"
|
*ngIf="!!userPermission && !!userPermission.canSendEmail"
|
||||||
aria-label="emailSend"
|
aria-label="emailSend"
|
||||||
matTooltipPosition="above"
|
matTooltipPosition="above"
|
||||||
matTooltip="{{ 'label.emailSend' | ucapI18n }}"
|
matTooltip="{{ 'label.emailSend' | ucapI18n }}"
|
||||||
|
@ -126,7 +136,7 @@
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
mat-icon-button
|
mat-icon-button
|
||||||
*ngIf="!!authRes && !!authRes.canTranslation"
|
*ngIf="!!userPermission && !!userPermission.canTranslation"
|
||||||
aria-label="translation"
|
aria-label="translation"
|
||||||
matTooltipPosition="above"
|
matTooltipPosition="above"
|
||||||
matTooltip="{{ 'label.translation' | ucapI18n }}"
|
matTooltip="{{ 'label.translation' | ucapI18n }}"
|
||||||
|
@ -137,7 +147,7 @@
|
||||||
</button>
|
</button>
|
||||||
<!-- <button
|
<!-- <button
|
||||||
mat-icon-button
|
mat-icon-button
|
||||||
*ngIf="!!authRes && !!authRes.useGams"
|
*ngIf="!!userPermission && !!userPermission.useGams"
|
||||||
aria-label="gams"
|
aria-label="gams"
|
||||||
matTooltipPosition="above"
|
matTooltipPosition="above"
|
||||||
matTooltip="{{ 'label.gams' | ucapI18n }}"
|
matTooltip="{{ 'label.gams' | ucapI18n }}"
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
max-height: 100%;
|
max-height: 100%;
|
||||||
min-height: 20px;
|
min-height: 20px;
|
||||||
background-color: $white;
|
background-color: $white;
|
||||||
padding-left: 30px;
|
padding: 0 20px;
|
||||||
font-size: 0.929em;
|
font-size: 0.929em;
|
||||||
margin: 8px 0;
|
margin: 8px 0;
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
|
@ -19,11 +19,15 @@
|
||||||
@include screen(xs) {
|
@include screen(xs) {
|
||||||
padding-left: 16px;
|
padding-left: 16px;
|
||||||
}
|
}
|
||||||
|
.message-text {
|
||||||
|
@include font-family($font-regular);
|
||||||
textarea {
|
textarea {
|
||||||
min-height: 22px;
|
min-height: 22px;
|
||||||
|
margin: 0;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
.button-area {
|
.button-area {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
|
|
|
@ -18,28 +18,29 @@ import { Store, select } from '@ngrx/store';
|
||||||
|
|
||||||
import { MatDialog } from '@angular/material/dialog';
|
import { MatDialog } from '@angular/material/dialog';
|
||||||
|
|
||||||
|
import { FileUploadItem } from '@ucap/domain-common';
|
||||||
|
import { User } from '@ucap/domain-organization';
|
||||||
|
import { UserPermission } from '@ucap/domain-authorization';
|
||||||
|
import {
|
||||||
|
RoomInfo,
|
||||||
|
EventType,
|
||||||
|
MassTranslationEventJson,
|
||||||
|
TranslationEventJson
|
||||||
|
} from '@ucap/domain-chat';
|
||||||
|
|
||||||
import { StickerFilesInfo } from '@ucap/ng-core';
|
import { StickerFilesInfo } from '@ucap/ng-core';
|
||||||
import { StatusCode, FileUploadItem } from '@ucap/api';
|
import { StatusCode } from '@ucap/api';
|
||||||
import {
|
import {
|
||||||
TranslationSaveResponse,
|
TranslationSaveResponse,
|
||||||
TranslationSaveRequest
|
TranslationSaveRequest
|
||||||
} from '@ucap/api-common';
|
} from '@ucap/api-common';
|
||||||
import { VersionInfo2Response } from '@ucap/api-public';
|
|
||||||
import {
|
import {
|
||||||
SendEventMailType,
|
SendEventMailType,
|
||||||
SendEventEmailRequest,
|
SendEventEmailRequest,
|
||||||
SendEventEmailResponse,
|
SendEventEmailResponse,
|
||||||
StatusCode as PiStatusCode
|
StatusCode as PiStatusCode
|
||||||
} from '@ucap/pi';
|
} from '@ucap/pi';
|
||||||
import { RoomInfo } from '@ucap/protocol-room';
|
|
||||||
import {
|
|
||||||
EventType,
|
|
||||||
MassTranslationEventJson,
|
|
||||||
TranslationEventJson
|
|
||||||
} from '@ucap/protocol-event';
|
|
||||||
import { LoginResponse } from '@ucap/protocol-authentication';
|
|
||||||
import { AuthResponse } from '@ucap/protocol-query';
|
|
||||||
import { User } from '@ucap/protocol-info';
|
|
||||||
|
|
||||||
import { I18nService } from '@ucap/ng-i18n';
|
import { I18nService } from '@ucap/ng-i18n';
|
||||||
import { LogService } from '@ucap/ng-logger';
|
import { LogService } from '@ucap/ng-logger';
|
||||||
|
@ -61,7 +62,7 @@ import {
|
||||||
ConfirmDialogComponent,
|
ConfirmDialogComponent,
|
||||||
ConfirmDialogData,
|
ConfirmDialogData,
|
||||||
ConfirmDialogResult
|
ConfirmDialogResult
|
||||||
} from '@ucap/ng-ui';
|
} from '@ucap/ng-ui/core';
|
||||||
|
|
||||||
import { LoginSession } from '@app/models/login-session';
|
import { LoginSession } from '@app/models/login-session';
|
||||||
import { AppAuthenticationService } from '@app/services/app-authentication.service';
|
import { AppAuthenticationService } from '@app/services/app-authentication.service';
|
||||||
|
@ -70,6 +71,7 @@ import { FileUploadSelectorComponent } from '@app/ucap/chat/components/file-uplo
|
||||||
import { AppChatService } from '@app/services/app-chat.service';
|
import { AppChatService } from '@app/services/app-chat.service';
|
||||||
|
|
||||||
import { environment } from '@environments';
|
import { environment } from '@environments';
|
||||||
|
import { LoginInfo, VersionInfo } from '@ucap/domain-authentication';
|
||||||
|
|
||||||
export enum SelectorType {
|
export enum SelectorType {
|
||||||
EMPTY = '',
|
EMPTY = '',
|
||||||
|
@ -107,14 +109,17 @@ export class FormSectionComponent implements OnInit, OnDestroy {
|
||||||
@Output()
|
@Output()
|
||||||
changeTranslationSimpleview = new EventEmitter<boolean>();
|
changeTranslationSimpleview = new EventEmitter<boolean>();
|
||||||
|
|
||||||
|
@Output()
|
||||||
|
openFormSelector = new EventEmitter<string>();
|
||||||
|
|
||||||
@Output()
|
@Output()
|
||||||
eventSendTrigger = new EventEmitter<any>();
|
eventSendTrigger = new EventEmitter<any>();
|
||||||
|
|
||||||
versionInfo2Res: VersionInfo2Response;
|
versionInfo: VersionInfo;
|
||||||
loginSession: LoginSession;
|
loginSession: LoginSession;
|
||||||
loginRes: LoginResponse;
|
loginInfo: LoginInfo;
|
||||||
user: User;
|
user: User;
|
||||||
authRes: AuthResponse;
|
userPermission: UserPermission;
|
||||||
|
|
||||||
currentRoomInfo: RoomInfo;
|
currentRoomInfo: RoomInfo;
|
||||||
|
|
||||||
|
@ -125,8 +130,8 @@ export class FormSectionComponent implements OnInit, OnDestroy {
|
||||||
|
|
||||||
/** About Translation */
|
/** About Translation */
|
||||||
isTranslationProcess = false;
|
isTranslationProcess = false;
|
||||||
translationSimpleview = true;
|
translationSimpleview = false;
|
||||||
translationPreview = true;
|
translationPreview = false;
|
||||||
destLocale = 'en'; // default English :: en
|
destLocale = 'en'; // default English :: en
|
||||||
translationPreviewInfo: {
|
translationPreviewInfo: {
|
||||||
previewInfo: TranslationSaveResponse | null;
|
previewInfo: TranslationSaveResponse | null;
|
||||||
|
@ -159,10 +164,10 @@ export class FormSectionComponent implements OnInit, OnDestroy {
|
||||||
this.store
|
this.store
|
||||||
.pipe(
|
.pipe(
|
||||||
takeUntil(this.ngOnDestroySubject),
|
takeUntil(this.ngOnDestroySubject),
|
||||||
select(ConfigurationSelector.versionInfo2Response)
|
select(ConfigurationSelector.versionInfo)
|
||||||
)
|
)
|
||||||
.subscribe((versionInfo2Res) => {
|
.subscribe((versionInfo) => {
|
||||||
this.versionInfo2Res = versionInfo2Res;
|
this.versionInfo = versionInfo;
|
||||||
});
|
});
|
||||||
|
|
||||||
this.store
|
this.store
|
||||||
|
@ -172,18 +177,18 @@ export class FormSectionComponent implements OnInit, OnDestroy {
|
||||||
});
|
});
|
||||||
|
|
||||||
this.store
|
this.store
|
||||||
.pipe(takeUntil(this.ngOnDestroySubject), select(LoginSelector.loginRes))
|
.pipe(takeUntil(this.ngOnDestroySubject), select(LoginSelector.loginInfo))
|
||||||
.subscribe((loginRes) => {
|
.subscribe((loginInfo) => {
|
||||||
this.loginRes = loginRes;
|
this.loginInfo = loginInfo;
|
||||||
});
|
});
|
||||||
|
|
||||||
this.store
|
this.store
|
||||||
.pipe(
|
.pipe(
|
||||||
takeUntil(this.ngOnDestroySubject),
|
takeUntil(this.ngOnDestroySubject),
|
||||||
select(AuthorizationSelector.authResponse)
|
select(AuthorizationSelector.userPermission)
|
||||||
)
|
)
|
||||||
.subscribe((authRes) => {
|
.subscribe((userPermission) => {
|
||||||
this.authRes = authRes;
|
this.userPermission = userPermission;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -206,9 +211,10 @@ export class FormSectionComponent implements OnInit, OnDestroy {
|
||||||
this.selectorType = SelectorType.EMPTY;
|
this.selectorType = SelectorType.EMPTY;
|
||||||
this.translationSimpleview = false;
|
this.translationSimpleview = false;
|
||||||
this.changeTranslationSimpleview.emit(false);
|
this.changeTranslationSimpleview.emit(false);
|
||||||
this.translationPreview = true;
|
this.translationPreview = false;
|
||||||
this.destLocale = 'en'; // default English :: en
|
this.destLocale = 'en'; // default English :: en
|
||||||
this.translationPreviewInfo = null;
|
this.translationPreviewInfo = null;
|
||||||
|
this.selectedSticker = undefined;
|
||||||
|
|
||||||
this.store
|
this.store
|
||||||
.pipe(
|
.pipe(
|
||||||
|
@ -225,11 +231,19 @@ export class FormSectionComponent implements OnInit, OnDestroy {
|
||||||
/** About Selector */
|
/** About Selector */
|
||||||
onOpenSelector(type: SelectorType): void {
|
onOpenSelector(type: SelectorType): void {
|
||||||
this.selectorType = type;
|
this.selectorType = type;
|
||||||
this.changeDetectorRef.markForCheck();
|
|
||||||
|
this.selectedSticker = null;
|
||||||
|
this.translationPreviewInfo = null;
|
||||||
|
|
||||||
|
this.changeDetectorRef.detectChanges();
|
||||||
|
this.openFormSelector.emit(type);
|
||||||
}
|
}
|
||||||
clearSelector(): void {
|
clearSelector(): void {
|
||||||
this.selectorType = SelectorType.EMPTY;
|
this.selectorType = SelectorType.EMPTY;
|
||||||
|
|
||||||
this.selectedSticker = null;
|
this.selectedSticker = null;
|
||||||
|
this.translationPreviewInfo = null;
|
||||||
|
|
||||||
this.changeDetectorRef.markForCheck();
|
this.changeDetectorRef.markForCheck();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -246,62 +260,6 @@ export class FormSectionComponent implements OnInit, OnDestroy {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onChangeFileInput(): void {
|
|
||||||
const self = this;
|
|
||||||
const fileList = this.fileInput.nativeElement.files;
|
|
||||||
|
|
||||||
this.appFileService
|
|
||||||
.validUploadFile(fileList, this.versionInfo2Res?.fileAllowSize)
|
|
||||||
.then((result) => {
|
|
||||||
if (!result) {
|
|
||||||
self.fileInput.nativeElement.value = '';
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
// selector open
|
|
||||||
self.onOpenSelector(SelectorType.FILEUPLOAD);
|
|
||||||
self.changeDetectorRef.detectChanges();
|
|
||||||
|
|
||||||
// FileuploadItem Init. & FileSelector Init.
|
|
||||||
const fileUploadItems = FileUploadItem.fromFiles(fileList);
|
|
||||||
if (!!self.fileUploadSelector) {
|
|
||||||
self.fileUploadSelector.onFileSelected(fileUploadItems);
|
|
||||||
}
|
|
||||||
self.fileInput.nativeElement.value = '';
|
|
||||||
|
|
||||||
// File Upload..
|
|
||||||
self.appChatService
|
|
||||||
.sendMessageOfAttachFile(
|
|
||||||
self.loginRes,
|
|
||||||
self.user,
|
|
||||||
self.loginSession.deviceType,
|
|
||||||
self.currentRoomInfo.roomId,
|
|
||||||
fileUploadItems
|
|
||||||
)
|
|
||||||
.then((success) => {
|
|
||||||
if (!!success) {
|
|
||||||
self.clearSelector();
|
|
||||||
if (!!self.fileUploadSelector) {
|
|
||||||
self.fileUploadSelector.onUploadComplete();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch((err) => {
|
|
||||||
self.clearSelector();
|
|
||||||
if (!!self.fileUploadSelector) {
|
|
||||||
self.fileUploadSelector.onUploadComplete();
|
|
||||||
}
|
|
||||||
|
|
||||||
const msg = this.i18nService.t('common:file.errors.failToUpload');
|
|
||||||
alert(msg);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch((err) => {
|
|
||||||
self.fileInput.nativeElement.value = '';
|
|
||||||
self.logService.error(`validUploadFile ${err}`);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
onKeydown(event: KeyboardEvent) {
|
onKeydown(event: KeyboardEvent) {
|
||||||
// if (event.key === 'PageUp' || event.key === 'PageDown') {
|
// if (event.key === 'PageUp' || event.key === 'PageDown') {
|
||||||
// event.preventDefault();
|
// event.preventDefault();
|
||||||
|
@ -311,10 +269,17 @@ export class FormSectionComponent implements OnInit, OnDestroy {
|
||||||
// this.send();
|
// this.send();
|
||||||
// }
|
// }
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
event.stopPropagation();
|
|
||||||
this.send();
|
this.send();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
textareaResize(event: KeyboardEvent, obj) {
|
||||||
|
const self = obj;
|
||||||
|
setTimeout(() => {
|
||||||
|
self.style.height = '1px';
|
||||||
|
self.style.height = self.scrollHeight + 'px';
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
onSelectedSticker(stickerInfo: StickerFilesInfo) {
|
onSelectedSticker(stickerInfo: StickerFilesInfo) {
|
||||||
this.selectedSticker = stickerInfo;
|
this.selectedSticker = stickerInfo;
|
||||||
this.focus(false);
|
this.focus(false);
|
||||||
|
@ -412,7 +377,7 @@ export class FormSectionComponent implements OnInit, OnDestroy {
|
||||||
) {
|
) {
|
||||||
/** CASE : MASS TEXT */
|
/** CASE : MASS TEXT */
|
||||||
this.appChatService.sendMessageOfMassText(
|
this.appChatService.sendMessageOfMassText(
|
||||||
this.loginRes,
|
this.loginInfo,
|
||||||
this.user,
|
this.user,
|
||||||
this.loginSession.deviceType,
|
this.loginSession.deviceType,
|
||||||
roomId,
|
roomId,
|
||||||
|
@ -437,7 +402,7 @@ export class FormSectionComponent implements OnInit, OnDestroy {
|
||||||
this.commonApiService
|
this.commonApiService
|
||||||
.translationSave({
|
.translationSave({
|
||||||
userSeq: String(this.user.info.seq),
|
userSeq: String(this.user.info.seq),
|
||||||
token: this.loginRes.tokenString,
|
token: this.loginInfo.tokenString,
|
||||||
deviceType: this.loginSession.deviceType,
|
deviceType: this.loginSession.deviceType,
|
||||||
original: message,
|
original: message,
|
||||||
roomId: this.roomId,
|
roomId: this.roomId,
|
||||||
|
@ -547,6 +512,7 @@ export class FormSectionComponent implements OnInit, OnDestroy {
|
||||||
sentMessage
|
sentMessage
|
||||||
);
|
);
|
||||||
this.translationPreviewInfo = undefined;
|
this.translationPreviewInfo = undefined;
|
||||||
|
this.eventSendTrigger.emit(0);
|
||||||
this.focus();
|
this.focus();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -580,7 +546,7 @@ export class FormSectionComponent implements OnInit, OnDestroy {
|
||||||
const req: SendEventEmailRequest = {
|
const req: SendEventEmailRequest = {
|
||||||
userSeq: String(this.user.info.seq),
|
userSeq: String(this.user.info.seq),
|
||||||
deviceType: this.loginSession.deviceType,
|
deviceType: this.loginSession.deviceType,
|
||||||
tokenKey: this.loginRes.tokenString,
|
tokenKey: this.loginInfo.tokenString,
|
||||||
roomSeq: this._roomId,
|
roomSeq: this._roomId,
|
||||||
eventSeq: String(eventList[0].seq),
|
eventSeq: String(eventList[0].seq),
|
||||||
sendType: type
|
sendType: type
|
||||||
|
@ -624,4 +590,100 @@ export class FormSectionComponent implements OnInit, OnDestroy {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* About File Upload
|
||||||
|
*/
|
||||||
|
/** FileInput change event. */
|
||||||
|
onChangeFileInput(): void {
|
||||||
|
const fileList = this.fileInput.nativeElement.files;
|
||||||
|
this._fileSend(fileList);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** DragAndDrop :: Add fileupload queue. not sending. */
|
||||||
|
onDragAndDropStandbyFileupload(fileList: FileList) {
|
||||||
|
const self = this;
|
||||||
|
this.appFileService
|
||||||
|
.validUploadFile(fileList, this.versionInfo?.fileAllowSize)
|
||||||
|
.then((result) => {
|
||||||
|
if (!result) {
|
||||||
|
self.fileInput.nativeElement.value = '';
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
// selector open
|
||||||
|
self.onOpenSelector(SelectorType.FILEUPLOAD);
|
||||||
|
|
||||||
|
// FileuploadItem Init. & FileSelector Init.
|
||||||
|
const fileUploadItems = FileUploadItem.fromFiles(fileList);
|
||||||
|
if (!!self.fileUploadSelector) {
|
||||||
|
self.fileUploadSelector.onFileSelected(fileUploadItems);
|
||||||
|
}
|
||||||
|
self.fileInput.nativeElement.value = '';
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
self.fileInput.nativeElement.value = '';
|
||||||
|
self.logService.error(`validUploadFile ${err}`);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** DragAndDrop :: fileUpload direct. */
|
||||||
|
onDragAndDropFileupload(fileList: FileList): void {
|
||||||
|
this._fileSend(fileList);
|
||||||
|
}
|
||||||
|
|
||||||
|
private _fileSend(fileList: FileList) {
|
||||||
|
const self = this;
|
||||||
|
this.appFileService
|
||||||
|
.validUploadFile(fileList, this.versionInfo?.fileAllowSize)
|
||||||
|
.then((result) => {
|
||||||
|
if (!result) {
|
||||||
|
self.fileInput.nativeElement.value = '';
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
// selector open
|
||||||
|
self.onOpenSelector(SelectorType.FILEUPLOAD);
|
||||||
|
self.changeDetectorRef.detectChanges();
|
||||||
|
|
||||||
|
// FileuploadItem Init. & FileSelector Init.
|
||||||
|
const fileUploadItems = FileUploadItem.fromFiles(fileList);
|
||||||
|
if (!!self.fileUploadSelector) {
|
||||||
|
self.fileUploadSelector.onFileSelected(fileUploadItems);
|
||||||
|
}
|
||||||
|
self.fileInput.nativeElement.value = '';
|
||||||
|
|
||||||
|
// File Upload..
|
||||||
|
self.appChatService
|
||||||
|
.sendMessageOfAttachFile(
|
||||||
|
self.loginInfo,
|
||||||
|
self.user,
|
||||||
|
self.loginSession.deviceType,
|
||||||
|
self.currentRoomInfo.roomId,
|
||||||
|
fileUploadItems
|
||||||
|
)
|
||||||
|
.then((success) => {
|
||||||
|
if (!!success) {
|
||||||
|
self.eventSendTrigger.emit(0);
|
||||||
|
self.clearSelector();
|
||||||
|
if (!!self.fileUploadSelector) {
|
||||||
|
self.fileUploadSelector.onUploadComplete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
self.clearSelector();
|
||||||
|
if (!!self.fileUploadSelector) {
|
||||||
|
self.fileUploadSelector.onUploadComplete();
|
||||||
|
}
|
||||||
|
|
||||||
|
const msg = this.i18nService.t('common:file.errors.failToUpload');
|
||||||
|
alert(msg);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
self.fileInput.nativeElement.value = '';
|
||||||
|
self.logService.error(`validUploadFile ${err}`);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,19 @@
|
||||||
<mat-toolbar class="info-chat-toolbar">
|
<mat-toolbar class="info-chat-toolbar">
|
||||||
<mat-toolbar-row class="info-chat-toolbar-content">
|
<mat-toolbar-row class="info-chat-toolbar-content">
|
||||||
<div class="chat-room-profile">
|
<div class="chat-room-profile">
|
||||||
<div class="profile-image">
|
<div
|
||||||
|
class="profile-image"
|
||||||
|
(click)="onOpenProfile()"
|
||||||
|
[style.cursor]="
|
||||||
|
!!currentRoomInfo && currentRoomInfo.roomType === RoomType.Single
|
||||||
|
? 'pointer'
|
||||||
|
: 'default'
|
||||||
|
"
|
||||||
|
>
|
||||||
<img
|
<img
|
||||||
class="thumbnail"
|
class="thumbnail"
|
||||||
ucapImage
|
ucapImage
|
||||||
[base]="versionInfo2Res?.profileRoot"
|
[base]="versionInfo?.profileRoot"
|
||||||
[path]="roomImage"
|
[path]="roomImage"
|
||||||
[default]="
|
[default]="
|
||||||
currentRoomInfo?.roomType === RoomType.Multi
|
currentRoomInfo?.roomType === RoomType.Multi
|
||||||
|
|
|
@ -13,15 +13,16 @@ import {
|
||||||
} from '@angular/core';
|
} from '@angular/core';
|
||||||
|
|
||||||
import { Store, select } from '@ngrx/store';
|
import { Store, select } from '@ngrx/store';
|
||||||
import { Dictionary } from '@ngrx/entity';
|
|
||||||
|
|
||||||
import { MatDialog } from '@angular/material/dialog';
|
import { MatDialog } from '@angular/material/dialog';
|
||||||
|
|
||||||
import { LocaleCode } from '@ucap/core';
|
import { LocaleCode } from '@ucap/domain-common';
|
||||||
|
import { User } from '@ucap/domain-organization';
|
||||||
|
import { RoomInfo, RoomType } from '@ucap/domain-chat';
|
||||||
|
|
||||||
import { I18nService } from '@ucap/ng-i18n';
|
import { I18nService } from '@ucap/ng-i18n';
|
||||||
import { VersionInfo2Response } from '@ucap/api-public';
|
|
||||||
import { RoomInfo, RoomType, UpdateRequest } from '@ucap/protocol-room';
|
import { UpdateRequest } from '@ucap/protocol-room';
|
||||||
import { User } from '@ucap/protocol-info';
|
|
||||||
|
|
||||||
import { UserSelector } from '@ucap/ng-store-organization';
|
import { UserSelector } from '@ucap/ng-store-organization';
|
||||||
import { ConfigurationSelector } from '@ucap/ng-store-authentication';
|
import { ConfigurationSelector } from '@ucap/ng-store-authentication';
|
||||||
|
@ -40,6 +41,12 @@ import {
|
||||||
import { AppChatService } from '@app/services/app-chat.service';
|
import { AppChatService } from '@app/services/app-chat.service';
|
||||||
import { ChatDrawType } from '@app/pages/chat/types/chat-draw.type';
|
import { ChatDrawType } from '@app/pages/chat/types/chat-draw.type';
|
||||||
import { DrawInfo } from '@app/pages/chat/models/draw-info';
|
import { DrawInfo } from '@app/pages/chat/models/draw-info';
|
||||||
|
import {
|
||||||
|
ProfileDialogComponent,
|
||||||
|
ProfileDialogData,
|
||||||
|
ProfileDialogResult
|
||||||
|
} from '@app/sections/organization/dialogs/profile.dialog.component';
|
||||||
|
import { VersionInfo } from '@ucap/domain-authentication';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-sections-chat-info',
|
selector: 'app-sections-chat-info',
|
||||||
|
@ -53,11 +60,13 @@ export class InfoSectionComponent implements OnInit, OnDestroy {
|
||||||
|
|
||||||
@Input()
|
@Input()
|
||||||
set roomId(roomId: string) {
|
set roomId(roomId: string) {
|
||||||
|
if (this._roomId !== roomId) {
|
||||||
this._roomId = roomId;
|
this._roomId = roomId;
|
||||||
|
|
||||||
this.roomIdSubject.next(roomId);
|
this.roomIdSubject.next(roomId);
|
||||||
|
|
||||||
this.initializeRoomData();
|
this.initializeRoomData();
|
||||||
|
}
|
||||||
|
|
||||||
// request selected room
|
// request selected room
|
||||||
if (!!this.roomId) {
|
if (!!this.roomId) {
|
||||||
|
@ -81,7 +90,7 @@ export class InfoSectionComponent implements OnInit, OnDestroy {
|
||||||
@Output()
|
@Output()
|
||||||
rightDrawerToggle = new EventEmitter<DrawInfo>();
|
rightDrawerToggle = new EventEmitter<DrawInfo>();
|
||||||
|
|
||||||
versionInfo2Res: VersionInfo2Response;
|
versionInfo: VersionInfo;
|
||||||
user: User;
|
user: User;
|
||||||
|
|
||||||
defaultProfileImage: string;
|
defaultProfileImage: string;
|
||||||
|
@ -123,10 +132,10 @@ export class InfoSectionComponent implements OnInit, OnDestroy {
|
||||||
this.store
|
this.store
|
||||||
.pipe(
|
.pipe(
|
||||||
takeUntil(this.ngOnDestroySubject),
|
takeUntil(this.ngOnDestroySubject),
|
||||||
select(ConfigurationSelector.versionInfo2Response)
|
select(ConfigurationSelector.versionInfo)
|
||||||
)
|
)
|
||||||
.subscribe((versionInfo2Res) => {
|
.subscribe((versionInfo) => {
|
||||||
this.versionInfo2Res = versionInfo2Res;
|
this.versionInfo = versionInfo;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -240,6 +249,36 @@ export class InfoSectionComponent implements OnInit, OnDestroy {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onOpenProfile(): void {
|
||||||
|
if (
|
||||||
|
!!this.currentRoomInfo &&
|
||||||
|
this.currentRoomInfo.roomType === RoomType.Single
|
||||||
|
) {
|
||||||
|
const returnValue = this.appChatService.getRoomUserList01(
|
||||||
|
this.user,
|
||||||
|
this.roomUsersMap,
|
||||||
|
this.roomUsersShortMap
|
||||||
|
);
|
||||||
|
if (
|
||||||
|
!!returnValue &&
|
||||||
|
!!returnValue.existUsers &&
|
||||||
|
returnValue.users.length > 0
|
||||||
|
) {
|
||||||
|
const userSeq = String(returnValue.users[0].seq);
|
||||||
|
this.dialog.open<
|
||||||
|
ProfileDialogComponent,
|
||||||
|
ProfileDialogData,
|
||||||
|
ProfileDialogResult
|
||||||
|
>(ProfileDialogComponent, {
|
||||||
|
panelClass: 'mid-create-dialog',
|
||||||
|
data: {
|
||||||
|
userSeq
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
getShowContextMenu(menuType: string) {
|
getShowContextMenu(menuType: string) {
|
||||||
if (
|
if (
|
||||||
['EVENT', 'ROOM_USERS', 'CHANGE_ROOM_USERS', 'ADD_GROUP', 'SETTING'].some(
|
['EVENT', 'ROOM_USERS', 'CHANGE_ROOM_USERS', 'ADD_GROUP', 'SETTING'].some(
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
.list-container {
|
.list-container {
|
||||||
height: calc(100% - 90px) !important;
|
height: calc(100% - 100px) !important;
|
||||||
min-height: auto !important;
|
min-height: auto !important;
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,12 +11,15 @@ import {
|
||||||
EventEmitter,
|
EventEmitter,
|
||||||
Output
|
Output
|
||||||
} from '@angular/core';
|
} from '@angular/core';
|
||||||
|
import { Router, ActivatedRoute, Params } from '@angular/router';
|
||||||
|
|
||||||
|
import { RoomInfo } from '@ucap/domain-chat';
|
||||||
|
|
||||||
import { LogService } from '@ucap/ng-logger';
|
import { LogService } from '@ucap/ng-logger';
|
||||||
import { RoomInfo } from '@ucap/protocol-room';
|
|
||||||
import { Router, ActivatedRoute, Params } from '@angular/router';
|
|
||||||
import { QueryParams } from '@app/pages/chat/types/params.type';
|
import { QueryParams } from '@app/pages/chat/types/params.type';
|
||||||
import { SearchInfo } from '@app/pages/chat/models/search-info';
|
import { SearchInfo } from '@app/pages/chat/models/search-info';
|
||||||
|
import { AppChatService } from '@app/services/app-chat.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-sections-chat-list',
|
selector: 'app-sections-chat-list',
|
||||||
|
@ -51,6 +54,7 @@ export class ListSectionComponent implements OnInit, OnDestroy {
|
||||||
constructor(
|
constructor(
|
||||||
private router: Router,
|
private router: Router,
|
||||||
private activatedRoute: ActivatedRoute,
|
private activatedRoute: ActivatedRoute,
|
||||||
|
private appChatService: AppChatService,
|
||||||
private changeDetectorRef: ChangeDetectorRef,
|
private changeDetectorRef: ChangeDetectorRef,
|
||||||
private logService: LogService
|
private logService: LogService
|
||||||
) {}
|
) {}
|
||||||
|
@ -76,17 +80,7 @@ export class ListSectionComponent implements OnInit, OnDestroy {
|
||||||
}
|
}
|
||||||
|
|
||||||
onOpenChatRoom(roomInfo: RoomInfo): void {
|
onOpenChatRoom(roomInfo: RoomInfo): void {
|
||||||
this.router.navigate(
|
this.appChatService.openRoombyRoomId(roomInfo.roomId);
|
||||||
[
|
|
||||||
'chat',
|
|
||||||
{
|
|
||||||
outlets: { content: 'chatroom' }
|
|
||||||
}
|
|
||||||
],
|
|
||||||
{
|
|
||||||
queryParams: { roomId: roomInfo.roomId }
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onSearchResultList(searchResultList: RoomInfo[]) {
|
onSearchResultList(searchResultList: RoomInfo[]) {
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
<div #chatMessagesContainer class="ucap-message-section">
|
<!-- <div class="ucap-message-section"> -->
|
||||||
<button
|
<button
|
||||||
mat-stroked-button
|
mat-stroked-button
|
||||||
color="accent"
|
color="accent"
|
||||||
class="icon-button-arrow top-position"
|
class="icon-button-arrow top-position"
|
||||||
(click)="gotoScrollToBottom()"
|
(click)="gotoScrollToBottom()"
|
||||||
>
|
>
|
||||||
<mat-icon>arrow_downward</mat-icon>
|
<mat-icon>arrow_downward</mat-icon>
|
||||||
</button>
|
</button>
|
||||||
<!--대화창 위로 보내기
|
<!--대화창 위로 보내기
|
||||||
<button
|
<button
|
||||||
mat-stroked-button
|
mat-stroked-button
|
||||||
color="accent"
|
color="accent"
|
||||||
|
@ -16,8 +16,21 @@
|
||||||
<mat-icon>arrow_upward</mat-icon>
|
<mat-icon>arrow_upward</mat-icon>
|
||||||
</button>-->
|
</button>-->
|
||||||
|
|
||||||
<div #chatMessagesList class="chat-area">
|
<ucap-virtual-scroll-viewport
|
||||||
<div class="ucap-chat-more-event" *ngIf="!!currentChatting?.remainEvent">
|
#vsList
|
||||||
|
fxFlexFill
|
||||||
|
class="ucap-message-section"
|
||||||
|
perfectScrollbar
|
||||||
|
measureSize
|
||||||
|
minBufferPx="200"
|
||||||
|
maxBufferPx="300"
|
||||||
|
(contentSizeChanged)="onContentSizeChanged($event)"
|
||||||
|
(measured)="onMeasured()"
|
||||||
|
(psYReachEnd)="isScrollReachBottom = true; resetRecentMessage()"
|
||||||
|
(psScrollUp)="isScrollReachBottom = false"
|
||||||
|
>
|
||||||
|
<ng-template ucapVirtualScrollHeader>
|
||||||
|
<div class="ucap-chat-more-event" *ngIf="!!isRemainEvent">
|
||||||
<button
|
<button
|
||||||
mat-button
|
mat-button
|
||||||
class="btn-more-pre bg-primary-chat"
|
class="btn-more-pre bg-primary-chat"
|
||||||
|
@ -28,31 +41,79 @@
|
||||||
>{{ 'event.showPreviousEvents' | ucapI18n }}
|
>{{ 'event.showPreviousEvents' | ucapI18n }}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
</ng-template>
|
||||||
|
<div class="chat-area">
|
||||||
<app-chat-message-box
|
<app-chat-message-box
|
||||||
*ngFor="let event of eventList"
|
*ucapVirtualFor="
|
||||||
|
let event of eventList;
|
||||||
|
keyOf: keyOf;
|
||||||
|
templateCacheSize: 0
|
||||||
|
"
|
||||||
[message]="event"
|
[message]="event"
|
||||||
[roomInfo]="currentRoomInfo"
|
[roomInfo]="currentRoomInfo"
|
||||||
[isMe]="event.senderSeq + '' === String(user?.info?.seq) + ''"
|
[loginSession]="loginSession"
|
||||||
|
[loginInfo]="loginInfo"
|
||||||
|
[user]="user"
|
||||||
|
[userPermission]="userPermission"
|
||||||
|
[isMe]="String(user?.info?.seq) === String(event.senderSeq)"
|
||||||
[translationSimpleview]="translationSimpleview"
|
[translationSimpleview]="translationSimpleview"
|
||||||
[senderInfo]="getSenderInfo(event.senderSeq)"
|
[senderInfo]="getSenderInfo(event.senderSeq)"
|
||||||
[defaultProfileImage]="defaultProfileImage"
|
[defaultProfileImage]="defaultProfileImage"
|
||||||
[profileImageRoot]="versionInfo2Res?.profileRoot"
|
[profileImageRoot]="versionInfo?.profileRoot"
|
||||||
|
[dateChanged]="getDateSplitter(event)"
|
||||||
|
[unreadCount]="getUnreadCount(event)"
|
||||||
|
(messageContextMenu)="onClickMessageContextMenu($event)"
|
||||||
|
(fileViewer)="onFileViewer($event)"
|
||||||
|
(fileSave)="onFileSave($event)"
|
||||||
|
(massTranslationDetail)="onMassTranslationDetail($event)"
|
||||||
|
(openProfile)="onOpenProfile($event)"
|
||||||
|
(joinConference)="onJoinConference($event)"
|
||||||
|
>
|
||||||
|
</app-chat-message-box>
|
||||||
|
<!-- <app-chat-message-box
|
||||||
|
*ngFor="let event of eventList; trackBy: trackByEvent"
|
||||||
|
[message]="event"
|
||||||
|
></app-chat-message-box> -->
|
||||||
|
<!-- <app-chat-message-box
|
||||||
|
*ngFor="let event of eventList; trackBy: trackByEvent"
|
||||||
|
[message]="event"
|
||||||
|
[roomInfo]="currentRoomInfo"
|
||||||
|
[loginInfo]="loginInfo"
|
||||||
|
[user]="user"
|
||||||
|
[loginSession]="loginSession"
|
||||||
|
[isMe]="String(user?.info?.seq) === String(event.senderSeq)"
|
||||||
|
[translationSimpleview]="translationSimpleview"
|
||||||
|
[senderInfo]="getSenderInfo(event.senderSeq)"
|
||||||
|
[defaultProfileImage]="defaultProfileImage"
|
||||||
|
[profileImageRoot]="versionInfo?.profileRoot"
|
||||||
[dateChanged]="getDateSplitter(event)"
|
[dateChanged]="getDateSplitter(event)"
|
||||||
[unreadCount]="getUnreadCount(event)"
|
[unreadCount]="getUnreadCount(event)"
|
||||||
(messageContextMenu)="onClickMessageContextMenu($event)"
|
(messageContextMenu)="onClickMessageContextMenu($event)"
|
||||||
(fileViewer)="onFileViewer($event)"
|
(fileViewer)="onFileViewer($event)"
|
||||||
(massTranslationDetail)="onMassTranslationDetail($event)"
|
(massTranslationDetail)="onMassTranslationDetail($event)"
|
||||||
(openProfile)="onOpenProfile($event)"
|
(openProfile)="onOpenProfile($event)"
|
||||||
></app-chat-message-box>
|
></app-chat-message-box> -->
|
||||||
|
<!-- <p *ngFor="let event of eventList; trackBy: trackByEvent">
|
||||||
<div *ngIf="false" class="recent-receive-message">
|
{{ event.seq }} / {{ event.type }}
|
||||||
<!-- 최근 메시지 영역 -->
|
</p> -->
|
||||||
|
<!-- <div *ngIf="!!recentUserInfo" class="recent-receive-message">
|
||||||
<app-chat-recent-message
|
<app-chat-recent-message
|
||||||
[senderInfo]="getSenderInfo(user?.info?.seq)"
|
[senderInfo]="recentUserInfo"
|
||||||
|
[message]="recentMessage"
|
||||||
[defaultProfileImage]="defaultProfileImage"
|
[defaultProfileImage]="defaultProfileImage"
|
||||||
[profileImageRoot]="versionInfo2Res?.profileRoot"
|
[profileImageRoot]="versionInfo?.profileRoot"
|
||||||
|
(gotoBottom)="gotoScrollToBottom()"
|
||||||
></app-chat-recent-message>
|
></app-chat-recent-message>
|
||||||
|
</div> -->
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</ucap-virtual-scroll-viewport>
|
||||||
|
<div *ngIf="!!recentUserInfo" class="recent-receive-message">
|
||||||
|
<app-chat-recent-message
|
||||||
|
[senderInfo]="recentUserInfo"
|
||||||
|
[message]="recentMessage"
|
||||||
|
[defaultProfileImage]="defaultProfileImage"
|
||||||
|
[profileImageRoot]="versionInfo?.profileRoot"
|
||||||
|
(gotoBottom)="gotoScrollToBottom()"
|
||||||
|
></app-chat-recent-message>
|
||||||
</div>
|
</div>
|
||||||
|
<!-- </div> -->
|
||||||
|
|
|
@ -1,5 +1,30 @@
|
||||||
@import '~@ucap/lg-scss/mixins';
|
@import '~@ucap/lg-scss/mixins';
|
||||||
|
|
||||||
|
.icon-button-arrow {
|
||||||
|
@include ucapMatButton(36px, 36px, 6px, 36px);
|
||||||
|
border-color: $lipstick;
|
||||||
|
background-color: rgba(255, 255, 255, 0.5);
|
||||||
|
box-shadow: 0 3px 6px 0 rgba(0, 0, 0, 0.16);
|
||||||
|
// position: sticky;
|
||||||
|
position: absolute;
|
||||||
|
right: 20px;
|
||||||
|
z-index: 5;
|
||||||
|
width: 36px;
|
||||||
|
// align-self: flex-end;
|
||||||
|
// margin-right: -10px;
|
||||||
|
&.top-position {
|
||||||
|
bottom: 90%;
|
||||||
|
order: 2;
|
||||||
|
}
|
||||||
|
&.bottom-position {
|
||||||
|
bottom: 30px;
|
||||||
|
order: 3;
|
||||||
|
}
|
||||||
|
&:hover {
|
||||||
|
background-color: rgba(255, 255, 255, 0.8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.ucap-message-section {
|
.ucap-message-section {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
@ -11,43 +36,30 @@
|
||||||
padding: 0 16px;
|
padding: 0 16px;
|
||||||
min-width: 100%;
|
min-width: 100%;
|
||||||
}
|
}
|
||||||
.icon-button-arrow {
|
|
||||||
@include ucapMatButton(36px, 36px, 6px, 36px);
|
.ucap-chat-more-event {
|
||||||
border-color: $lipstick;
|
padding: 20px 30px 0;
|
||||||
background-color: rgba(255, 255, 255, 0.5);
|
.btn-more-pre {
|
||||||
box-shadow: 0 3px 6px 0 rgba(0, 0, 0, 0.16);
|
@include ucapMatButton(100%, 30px, 2px, 30px);
|
||||||
position: sticky;
|
font-size: 0.857em;
|
||||||
z-index: 5;
|
@include screen(xs) {
|
||||||
width: 36px;
|
padding: 0 16px;
|
||||||
align-self: flex-end;
|
|
||||||
margin-right: -10px;
|
|
||||||
&.top-position {
|
|
||||||
bottom: 90%;
|
|
||||||
order: 2;
|
|
||||||
}
|
}
|
||||||
&.bottom-position {
|
|
||||||
bottom: 30px;
|
|
||||||
order: 3;
|
|
||||||
}
|
|
||||||
&:hover {
|
|
||||||
background-color: rgba(255, 255, 255, 0.8);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.chat-area {
|
.chat-area {
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
order: 1;
|
order: 1;
|
||||||
padding-top: 30px;
|
padding: 0 30px;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
.ucap-chat-more-event {
|
@include screen(xs) {
|
||||||
padding: 20px 0 0;
|
padding: 0 16px;
|
||||||
.btn-more-pre {
|
|
||||||
@include ucapMatButton(100%, 30px, 2px, 30px);
|
|
||||||
font-size: 0.857em;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.recent-receive-message {
|
}
|
||||||
|
.recent-receive-message {
|
||||||
transition: all 0.4s;
|
transition: all 0.4s;
|
||||||
position: sticky;
|
position: sticky;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
|
@ -56,9 +68,8 @@
|
||||||
margin: 0 -30px;
|
margin: 0 -30px;
|
||||||
background-color: rgba(0, 0, 0, 0.6);
|
background-color: rgba(0, 0, 0, 0.6);
|
||||||
color: #fff;
|
color: #fff;
|
||||||
|
width: 100%;
|
||||||
@include screen(xs) {
|
@include screen(xs) {
|
||||||
margin: 0 -15px;
|
margin: 0 -15px;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,23 @@
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
|
|
||||||
import { Subject, merge, combineLatest, Observable } from 'rxjs';
|
import {
|
||||||
import { takeUntil, take } from 'rxjs/operators';
|
Subject,
|
||||||
|
merge,
|
||||||
|
combineLatest,
|
||||||
|
Observable,
|
||||||
|
fromEvent,
|
||||||
|
interval
|
||||||
|
} from 'rxjs';
|
||||||
|
import {
|
||||||
|
takeUntil,
|
||||||
|
take,
|
||||||
|
tap,
|
||||||
|
withLatestFrom,
|
||||||
|
debounce,
|
||||||
|
debounceTime
|
||||||
|
} from 'rxjs/operators';
|
||||||
|
|
||||||
|
import { PerfectScrollbarDirective } from 'ngx-perfect-scrollbar';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Component,
|
Component,
|
||||||
|
@ -10,9 +26,9 @@ import {
|
||||||
ChangeDetectionStrategy,
|
ChangeDetectionStrategy,
|
||||||
ChangeDetectorRef,
|
ChangeDetectorRef,
|
||||||
Input,
|
Input,
|
||||||
AfterViewInit,
|
|
||||||
ViewChild,
|
ViewChild,
|
||||||
ElementRef
|
ElementRef,
|
||||||
|
Inject
|
||||||
} from '@angular/core';
|
} from '@angular/core';
|
||||||
|
|
||||||
import { Store, select } from '@ngrx/store';
|
import { Store, select } from '@ngrx/store';
|
||||||
|
@ -20,53 +36,72 @@ import { Dictionary } from '@ngrx/entity';
|
||||||
|
|
||||||
import { MatDialog, MatDialogRef } from '@angular/material/dialog';
|
import { MatDialog, MatDialogRef } from '@angular/material/dialog';
|
||||||
|
|
||||||
import { TransMassTalkDownloadRequest } from '@ucap/api-common';
|
import { DeviceType, FileDownloadItem } from '@ucap/domain-common';
|
||||||
import { VersionInfo2Response } from '@ucap/api-public';
|
import { User } from '@ucap/domain-organization';
|
||||||
import {
|
import {
|
||||||
Info,
|
Info,
|
||||||
EventJson,
|
EventJson,
|
||||||
EventType,
|
EventType,
|
||||||
FileType,
|
FileType,
|
||||||
MassTranslationEventJson
|
MassTranslationEventJson,
|
||||||
} from '@ucap/protocol-event';
|
FileEventJson,
|
||||||
import {
|
|
||||||
UserInfo as RoomUserInfo,
|
UserInfo as RoomUserInfo,
|
||||||
UserInfoShort as RoomUserInfoShort,
|
UserInfoShort as RoomUserInfoShort,
|
||||||
RoomInfo,
|
RoomInfo,
|
||||||
UpdateTimerSetRequest,
|
RoomType,
|
||||||
UpdateRequest,
|
FileInfo
|
||||||
RoomType
|
} from '@ucap/domain-chat';
|
||||||
} from '@ucap/protocol-room';
|
|
||||||
import { LoginResponse } from '@ucap/protocol-authentication';
|
import { TransMassTalkDownloadRequest } from '@ucap/api-common';
|
||||||
import { FileInfo } from '@ucap/protocol-file';
|
|
||||||
import { User } from '@ucap/protocol-info';
|
import {
|
||||||
|
ReadRequest,
|
||||||
|
SSVC_TYPE_EVENT_SEND_NOTI,
|
||||||
|
SendNotification
|
||||||
|
} from '@ucap/protocol-event';
|
||||||
|
import { UpdateTimerSetRequest, UpdateRequest } from '@ucap/protocol-room';
|
||||||
|
|
||||||
|
import { NativeService } from '@ucap/native';
|
||||||
|
|
||||||
import { I18nService } from '@ucap/ng-i18n';
|
import { I18nService } from '@ucap/ng-i18n';
|
||||||
|
|
||||||
import { UserSelector } from '@ucap/ng-store-organization';
|
import { UserSelector } from '@ucap/ng-store-organization';
|
||||||
import {
|
import {
|
||||||
LoginSelector,
|
LoginSelector,
|
||||||
ConfigurationSelector
|
ConfigurationSelector,
|
||||||
|
AuthorizationSelector
|
||||||
} from '@ucap/ng-store-authentication';
|
} from '@ucap/ng-store-authentication';
|
||||||
import {
|
import {
|
||||||
ChattingSelector,
|
ChattingSelector,
|
||||||
RoomSelector,
|
RoomSelector,
|
||||||
ChattingActions,
|
ChattingActions,
|
||||||
RoomActions,
|
RoomActions,
|
||||||
Chatting
|
ChatUtil
|
||||||
} from '@ucap/ng-store-chat';
|
} from '@ucap/ng-store-chat';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
ConfirmDialogComponent,
|
ConfirmDialogComponent,
|
||||||
ConfirmDialogData,
|
ConfirmDialogData,
|
||||||
ConfirmDialogResult,
|
ConfirmDialogResult,
|
||||||
ClipboardService,
|
AlertDialogComponent,
|
||||||
SelectFileInfo
|
AlertDialogData,
|
||||||
} from '@ucap/ng-ui';
|
AlertDialogResult,
|
||||||
|
ClipboardService
|
||||||
|
} from '@ucap/ng-ui/core';
|
||||||
|
import { SelectFileInfo } from '@ucap/ng-ui/viewer';
|
||||||
|
import {
|
||||||
|
VirtualScrollViewportComponent,
|
||||||
|
MeasureSizeVirtualScrollDirective
|
||||||
|
} from '@ucap/ng-ui/scrolling';
|
||||||
|
|
||||||
|
import { EventProtocolService } from '@ucap/ng-protocol-event';
|
||||||
|
import { UCAP_NATIVE_SERVICE } from '@ucap/ng-native';
|
||||||
|
import { LogService } from '@ucap/ng-logger';
|
||||||
|
|
||||||
import { LoginSession } from '@app/models/login-session';
|
import { LoginSession } from '@app/models/login-session';
|
||||||
import { AppChatService } from '@app/services/app-chat.service';
|
import { AppChatService } from '@app/services/app-chat.service';
|
||||||
import { AppAuthenticationService } from '@app/services/app-authentication.service';
|
import { AppAuthenticationService } from '@app/services/app-authentication.service';
|
||||||
|
import { AppOrganizationService } from '@app/services/app-organization.service';
|
||||||
|
import { AppFileService } from '@app/services/app-file.service';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
ProfileDialogComponent,
|
ProfileDialogComponent,
|
||||||
ProfileDialogData,
|
ProfileDialogData,
|
||||||
|
@ -78,16 +113,15 @@ import {
|
||||||
ForwardDialogData,
|
ForwardDialogData,
|
||||||
ForwardDialogResult
|
ForwardDialogResult
|
||||||
} from '../dialogs/forward.dialog.component';
|
} from '../dialogs/forward.dialog.component';
|
||||||
import {
|
import { FileViewerDialogData } from '../dialogs/file-viewer.dialog.component';
|
||||||
FileViewerDialogComponent,
|
|
||||||
FileViewerDialogData,
|
|
||||||
FileViewerDialogResult
|
|
||||||
} from '../dialogs/file-viewer.dialog.component';
|
|
||||||
import {
|
import {
|
||||||
SettingDialogComponent,
|
SettingDialogComponent,
|
||||||
SettingDialogData,
|
SettingDialogData,
|
||||||
SettingDialogResult
|
SettingDialogResult
|
||||||
} from '../dialogs/setting.dialog.component';
|
} from '../dialogs/setting.dialog.component';
|
||||||
|
import { ConferenceJoinRequest } from '@ucap/api-prompt';
|
||||||
|
import { LoginInfo, VersionInfo } from '@ucap/domain-authentication';
|
||||||
|
import { UserPermission } from '@ucap/domain-authorization';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-sections-chat-message',
|
selector: 'app-sections-chat-message',
|
||||||
|
@ -96,19 +130,20 @@ import {
|
||||||
|
|
||||||
changeDetection: ChangeDetectionStrategy.OnPush
|
changeDetection: ChangeDetectionStrategy.OnPush
|
||||||
})
|
})
|
||||||
export class MessageSectionComponent
|
export class MessageSectionComponent implements OnInit, OnDestroy {
|
||||||
implements OnInit, OnDestroy, AfterViewInit {
|
|
||||||
private roomIdSubject = new Subject<string>();
|
private roomIdSubject = new Subject<string>();
|
||||||
private ngOnDestroySubject: Subject<void> = new Subject();
|
private ngOnDestroySubject: Subject<void> = new Subject();
|
||||||
|
|
||||||
@Input()
|
@Input()
|
||||||
set roomId(roomId: string) {
|
set roomId(roomId: string) {
|
||||||
|
if (this._roomId !== roomId) {
|
||||||
this._roomId = roomId;
|
this._roomId = roomId;
|
||||||
|
|
||||||
this.roomIdSubject.next(roomId);
|
this.roomIdSubject.next(roomId);
|
||||||
|
|
||||||
this.initializeRoomData();
|
this.initializeRoomData();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
get roomId(): string {
|
get roomId(): string {
|
||||||
return this._roomId;
|
return this._roomId;
|
||||||
}
|
}
|
||||||
|
@ -121,13 +156,14 @@ export class MessageSectionComponent
|
||||||
@Input()
|
@Input()
|
||||||
eventSendTrigger$: Observable<any>;
|
eventSendTrigger$: Observable<any>;
|
||||||
|
|
||||||
versionInfo2Res: VersionInfo2Response;
|
versionInfo: VersionInfo;
|
||||||
loginRes: LoginResponse;
|
loginInfo: LoginInfo;
|
||||||
user: User;
|
user: User;
|
||||||
loginSession: LoginSession;
|
loginSession: LoginSession;
|
||||||
|
userPermission: UserPermission;
|
||||||
|
|
||||||
currentRoomInfo: RoomInfo;
|
currentRoomInfo: RoomInfo;
|
||||||
currentChatting: Chatting;
|
isRemainEvent = false;
|
||||||
currentFileInfoList: FileInfo[] = [];
|
currentFileInfoList: FileInfo[] = [];
|
||||||
roomUsers: RoomUserInfoShort[] = [];
|
roomUsers: RoomUserInfoShort[] = [];
|
||||||
// eventList$: Observable<Info<EventJson>[]>;
|
// eventList$: Observable<Info<EventJson>[]>;
|
||||||
|
@ -137,6 +173,10 @@ export class MessageSectionComponent
|
||||||
EventType = EventType;
|
EventType = EventType;
|
||||||
FileType = FileType;
|
FileType = FileType;
|
||||||
|
|
||||||
|
/** 최근 메시지 */
|
||||||
|
recentMessage: Info<EventJson>;
|
||||||
|
recentUserInfo: RoomUserInfoShort | RoomUserInfo | undefined;
|
||||||
|
|
||||||
/** Timer 대화방의 대화 삭제를 위한 interval */
|
/** Timer 대화방의 대화 삭제를 위한 interval */
|
||||||
interval: any;
|
interval: any;
|
||||||
|
|
||||||
|
@ -145,9 +185,25 @@ export class MessageSectionComponent
|
||||||
|
|
||||||
/** About Scroll */
|
/** About Scroll */
|
||||||
isInitScrollbottom = true;
|
isInitScrollbottom = true;
|
||||||
@ViewChild('chatMessagesContainer', { static: false })
|
isScrollReachBottom = false;
|
||||||
|
@ViewChild('chatMessagesContainer', { static: true })
|
||||||
chatMessagesContainer: ElementRef<HTMLElement>;
|
chatMessagesContainer: ElementRef<HTMLElement>;
|
||||||
|
|
||||||
|
@ViewChild('vsList', { static: false })
|
||||||
|
vsList: VirtualScrollViewportComponent;
|
||||||
|
|
||||||
|
@ViewChild('vsList', {
|
||||||
|
static: true,
|
||||||
|
read: MeasureSizeVirtualScrollDirective
|
||||||
|
})
|
||||||
|
measureSize: MeasureSizeVirtualScrollDirective;
|
||||||
|
|
||||||
|
@ViewChild(PerfectScrollbarDirective, {
|
||||||
|
static: true,
|
||||||
|
read: PerfectScrollbarDirective
|
||||||
|
})
|
||||||
|
psDirectiveRef: PerfectScrollbarDirective;
|
||||||
|
|
||||||
String = String;
|
String = String;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
|
@ -156,32 +212,109 @@ export class MessageSectionComponent
|
||||||
private changeDetectorRef: ChangeDetectorRef,
|
private changeDetectorRef: ChangeDetectorRef,
|
||||||
private dialog: MatDialog,
|
private dialog: MatDialog,
|
||||||
private i18nService: I18nService,
|
private i18nService: I18nService,
|
||||||
private appAuthenticationService: AppAuthenticationService
|
private eventProtocolService: EventProtocolService,
|
||||||
|
private appAuthenticationService: AppAuthenticationService,
|
||||||
|
private appOrganizationService: AppOrganizationService,
|
||||||
|
private appFileService: AppFileService,
|
||||||
|
@Inject(UCAP_NATIVE_SERVICE) private nativeService: NativeService,
|
||||||
|
private logService: LogService
|
||||||
) {
|
) {
|
||||||
this.defaultProfileImage = this.appChatService.defaultProfileImage;
|
this.defaultProfileImage = this.appChatService.defaultProfileImage;
|
||||||
|
|
||||||
|
// scroll handling when window size changing.
|
||||||
|
fromEvent(window, 'resize')
|
||||||
|
.pipe(takeUntil(this.ngOnDestroySubject), debounceTime(300))
|
||||||
|
.subscribe((event: any) => {
|
||||||
|
this.refreshAndScrollToBottom();
|
||||||
|
});
|
||||||
|
|
||||||
|
this.eventProtocolService.notification$
|
||||||
|
.pipe(
|
||||||
|
takeUntil(this.ngOnDestroySubject),
|
||||||
|
withLatestFrom(this.store.pipe(select(RoomSelector.rooms))),
|
||||||
|
tap(([notiOrRes, roomList]) => {
|
||||||
|
switch (notiOrRes.SSVC_TYPE) {
|
||||||
|
case SSVC_TYPE_EVENT_SEND_NOTI:
|
||||||
|
{
|
||||||
|
const noti = notiOrRes as SendNotification;
|
||||||
|
const roomId = noti.roomId;
|
||||||
|
const eventInfo = noti.info;
|
||||||
|
const trgtRoom = roomList.find(
|
||||||
|
(roomInfo) => roomInfo.roomId === roomId
|
||||||
|
);
|
||||||
|
|
||||||
|
const contents = ChatUtil.convertFinalEventMessage(
|
||||||
|
noti.eventType,
|
||||||
|
noti.info.sentMessageJson
|
||||||
|
);
|
||||||
|
|
||||||
|
this.logService.debug(
|
||||||
|
'Notification::eventProtocolService::SendNotification in message.section.components',
|
||||||
|
noti
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!!roomId && roomId === this.roomId) {
|
||||||
|
if (!!this.isScrollReachBottom) {
|
||||||
|
// Fires when I enter the event
|
||||||
|
this.isInitScrollbottom = true;
|
||||||
|
} else {
|
||||||
|
this.recentMessage = noti.info;
|
||||||
|
this.recentUserInfo = this.getSenderInfo(
|
||||||
|
Number(noti.SENDER_SEQ)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// ignore..
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
)
|
||||||
|
.subscribe();
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
|
this.vsList
|
||||||
|
.elementScrolled()
|
||||||
|
.pipe(takeUntil(this.ngOnDestroySubject))
|
||||||
|
.subscribe(() => {
|
||||||
|
if (!!this.psDirectiveRef) {
|
||||||
|
this.psDirectiveRef.update();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
this.store
|
this.store
|
||||||
.pipe(
|
.pipe(
|
||||||
takeUntil(this.ngOnDestroySubject),
|
takeUntil(this.ngOnDestroySubject),
|
||||||
select(ConfigurationSelector.versionInfo2Response)
|
select(AuthorizationSelector.userPermission)
|
||||||
)
|
)
|
||||||
.subscribe((versionInfo2Res) => (this.versionInfo2Res = versionInfo2Res));
|
.subscribe((userPermission) => {
|
||||||
|
this.userPermission = userPermission;
|
||||||
this.store
|
});
|
||||||
.pipe(takeUntil(this.ngOnDestroySubject), select(LoginSelector.loginRes))
|
|
||||||
.subscribe((loginRes) => (this.loginRes = loginRes));
|
|
||||||
|
|
||||||
this.store
|
|
||||||
.pipe(takeUntil(this.ngOnDestroySubject), select(UserSelector.user))
|
|
||||||
.subscribe((user) => (this.user = user));
|
|
||||||
|
|
||||||
this.eventSendTrigger$
|
this.eventSendTrigger$
|
||||||
.pipe(takeUntil(this.ngOnDestroySubject))
|
.pipe(takeUntil(this.ngOnDestroySubject))
|
||||||
.subscribe((_) => {
|
.subscribe((_) => {
|
||||||
// Fires when I enter the event
|
// Fires when I enter the event
|
||||||
this.gotoScrollToBottom();
|
this.isInitScrollbottom = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
this.nativeService
|
||||||
|
.window_onFocus$()
|
||||||
|
.pipe(takeUntil(this.ngOnDestroySubject))
|
||||||
|
.subscribe((isFocus) => {
|
||||||
|
if (!!this.roomId && !!this.eventList && this.eventList.length > 0) {
|
||||||
|
const roomId = this.roomId;
|
||||||
|
const lastReadSeq = this.eventList[this.eventList.length - 1].seq;
|
||||||
|
this.store.dispatch(
|
||||||
|
ChattingActions.read({
|
||||||
|
roomId,
|
||||||
|
lastReadSeq
|
||||||
|
} as ReadRequest)
|
||||||
|
);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -202,35 +335,21 @@ export class MessageSectionComponent
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ngAfterViewInit() {}
|
|
||||||
|
|
||||||
initializeRoomData() {
|
initializeRoomData() {
|
||||||
/** About initialize roomId */
|
/** About initialize roomId */
|
||||||
this.isInitScrollbottom = true;
|
this.isInitScrollbottom = true;
|
||||||
|
this.onClickInvalidateCache();
|
||||||
|
|
||||||
this.loginSession = this.appAuthenticationService.getLoginSession();
|
this.loginSession = this.appAuthenticationService.getLoginSession();
|
||||||
|
|
||||||
this.store
|
this.store
|
||||||
.pipe(
|
.pipe(take(1), select(ConfigurationSelector.versionInfo))
|
||||||
takeUntil(merge(this.ngOnDestroySubject, this.roomIdSubject)),
|
.subscribe((versionInfo) => (this.versionInfo = versionInfo));
|
||||||
select(RoomSelector.room, this.roomId)
|
this.store
|
||||||
)
|
.pipe(take(1), select(LoginSelector.loginInfo))
|
||||||
.subscribe((room) => {
|
.subscribe((loginInfo) => (this.loginInfo = loginInfo));
|
||||||
this.currentRoomInfo = room;
|
this.store
|
||||||
|
.pipe(take(1), select(UserSelector.user))
|
||||||
// About Interval
|
.subscribe((user) => (this.user = user));
|
||||||
if (!!this.interval) {
|
|
||||||
clearInterval(this.interval);
|
|
||||||
this.interval = undefined;
|
|
||||||
}
|
|
||||||
if (!!this.currentRoomInfo && !!this.currentRoomInfo.isTimeRoom) {
|
|
||||||
this.interval = setInterval(() => {
|
|
||||||
this.store.dispatch(
|
|
||||||
ChattingActions.intervalClearEvent({ roomId: this.roomId })
|
|
||||||
);
|
|
||||||
}, 1000);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
this.store
|
this.store
|
||||||
.pipe(
|
.pipe(
|
||||||
|
@ -250,7 +369,12 @@ export class MessageSectionComponent
|
||||||
select(ChattingSelector.chatting, this.roomId)
|
select(ChattingSelector.chatting, this.roomId)
|
||||||
)
|
)
|
||||||
.subscribe((chatting) => {
|
.subscribe((chatting) => {
|
||||||
this.currentChatting = chatting;
|
if (!!chatting && !!chatting.remainEvent) {
|
||||||
|
this.isRemainEvent = chatting.remainEvent;
|
||||||
|
} else {
|
||||||
|
this.isRemainEvent = false;
|
||||||
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
!!chatting &&
|
!!chatting &&
|
||||||
!!chatting.fileInfoList &&
|
!!chatting.fileInfoList &&
|
||||||
|
@ -285,12 +409,6 @@ export class MessageSectionComponent
|
||||||
.subscribe((eventList) => {
|
.subscribe((eventList) => {
|
||||||
if (!!eventList && eventList.length > 0) {
|
if (!!eventList && eventList.length > 0) {
|
||||||
this.eventList = eventList;
|
this.eventList = eventList;
|
||||||
this.changeDetectorRef.markForCheck();
|
|
||||||
|
|
||||||
if (!!this.isInitScrollbottom) {
|
|
||||||
this.gotoScrollToBottom();
|
|
||||||
this.isInitScrollbottom = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -301,11 +419,46 @@ export class MessageSectionComponent
|
||||||
])
|
])
|
||||||
.pipe(takeUntil(merge(this.ngOnDestroySubject, this.roomIdSubject)))
|
.pipe(takeUntil(merge(this.ngOnDestroySubject, this.roomIdSubject)))
|
||||||
.subscribe(([roomInfo, standbyRooms]) => {
|
.subscribe(([roomInfo, standbyRooms]) => {
|
||||||
|
// get room info.
|
||||||
|
if (!!roomInfo) {
|
||||||
|
if (
|
||||||
|
!!this.currentRoomInfo &&
|
||||||
|
this.currentRoomInfo.roomId === roomInfo.roomId
|
||||||
|
) {
|
||||||
|
this.currentRoomInfo = {
|
||||||
|
...this.currentRoomInfo,
|
||||||
|
roomName: roomInfo.roomName,
|
||||||
|
joinUserCount: roomInfo.joinUserCount,
|
||||||
|
isJoinRoom: roomInfo.isJoinRoom,
|
||||||
|
expiredFileStdSeq: roomInfo.expiredFileStdSeq,
|
||||||
|
timeRoomInterval: roomInfo.timeRoomInterval
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
// all refresh
|
||||||
|
this.currentRoomInfo = roomInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
// About Interval
|
||||||
|
if (!!this.interval) {
|
||||||
|
clearInterval(this.interval);
|
||||||
|
this.interval = undefined;
|
||||||
|
}
|
||||||
|
if (!!this.currentRoomInfo && !!this.currentRoomInfo.isTimeRoom) {
|
||||||
|
this.interval = setInterval(() => {
|
||||||
|
this.store.dispatch(
|
||||||
|
ChattingActions.intervalClearEvent({ roomId: this.roomId })
|
||||||
|
);
|
||||||
|
}, 1000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// new room setting popup
|
||||||
if (
|
if (
|
||||||
!!roomInfo &&
|
!!roomInfo &&
|
||||||
roomInfo.roomId === this.roomId &&
|
roomInfo.roomId === this.roomId &&
|
||||||
roomInfo.roomType !== RoomType.Mytalk &&
|
roomInfo.roomType !== RoomType.Mytalk &&
|
||||||
roomInfo.roomType !== RoomType.Single &&
|
(roomInfo.roomType !== RoomType.Single ||
|
||||||
|
(roomInfo.roomType === RoomType.Single && !!roomInfo.isTimeRoom)) &&
|
||||||
!!standbyRooms &&
|
!!standbyRooms &&
|
||||||
standbyRooms.length > 0 &&
|
standbyRooms.length > 0 &&
|
||||||
standbyRooms.findIndex((roomId) => roomId === this.roomId) > -1
|
standbyRooms.findIndex((roomId) => roomId === this.roomId) > -1
|
||||||
|
@ -337,13 +490,57 @@ export class MessageSectionComponent
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** About scrolling */
|
||||||
|
keyOf = (item: Info<EventJson>): string | number => {
|
||||||
|
return item.seq;
|
||||||
|
};
|
||||||
|
|
||||||
|
onMeasured() {
|
||||||
|
if (!!this.isInitScrollbottom) {
|
||||||
|
this.gotoScrollToBottom();
|
||||||
|
this.isInitScrollbottom = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onContentSizeChanged(size: number) {
|
||||||
|
if (!!this.psDirectiveRef) {
|
||||||
|
this.psDirectiveRef.update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onClickScrollTo(i: string) {
|
||||||
|
const index = Number(i);
|
||||||
|
// const offset = this.vsList.offsetForIndex(index, 'start');
|
||||||
|
// this.psDirectiveRef.scrollToY(offset);
|
||||||
|
// console.log('offset', offset, this.psDirectiveRef.ps().element.scrollTop);
|
||||||
|
|
||||||
|
this.vsList.scrollToIndex(index, 'center');
|
||||||
|
}
|
||||||
|
|
||||||
|
onClickInvalidateCache() {
|
||||||
|
if (!!this.measureSize) {
|
||||||
|
this.measureSize.invalidateMeasurements();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
gotoScrollToBottom() {
|
gotoScrollToBottom() {
|
||||||
if (!!this.chatMessagesContainer) {
|
// recent message reset;
|
||||||
const self = this;
|
this.resetRecentMessage();
|
||||||
setTimeout(() => {
|
|
||||||
self.chatMessagesContainer.nativeElement.scrollTop =
|
// scrolling.
|
||||||
self.chatMessagesContainer.nativeElement.scrollHeight;
|
if (!!this.vsList && !!this.eventList && this.eventList.length > 0) {
|
||||||
}, 500);
|
this.vsList.scrollToIndex(this.eventList.length - 1, 'end');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
refreshAndScrollToBottom() {
|
||||||
|
// if (!!this.vsList && !!this.isScrollReachBottom) {
|
||||||
|
// this.isInitScrollbottom = false;
|
||||||
|
// this.vsList.checkViewportSize();
|
||||||
|
// }
|
||||||
|
if (!!this.psDirectiveRef && !!this.isScrollReachBottom) {
|
||||||
|
this.psDirectiveRef.update();
|
||||||
|
this.psDirectiveRef.scrollToBottom();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -353,7 +550,7 @@ export class MessageSectionComponent
|
||||||
): RoomUserInfoShort | RoomUserInfo | undefined {
|
): RoomUserInfoShort | RoomUserInfo | undefined {
|
||||||
if (!!this.roomUsers && this.roomUsers.length) {
|
if (!!this.roomUsers && this.roomUsers.length) {
|
||||||
return this.roomUsers.find(
|
return this.roomUsers.find(
|
||||||
(userInfo) => userInfo.seq + '' === senderSeq + ''
|
(userInfo) => String(senderSeq) === String(userInfo.seq)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -366,8 +563,7 @@ export class MessageSectionComponent
|
||||||
|
|
||||||
if (curIndex === 0) {
|
if (curIndex === 0) {
|
||||||
return true;
|
return true;
|
||||||
}
|
} else if (curIndex > 0) {
|
||||||
if (curIndex > 0) {
|
|
||||||
if (!this.eventList[curIndex]) {
|
if (!this.eventList[curIndex]) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -376,16 +572,18 @@ export class MessageSectionComponent
|
||||||
'day'
|
'day'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Unread Count calculation */
|
/** Unread Count calculation */
|
||||||
getUnreadCount(message: Info<EventJson>): string | number {
|
getUnreadCount(message: Info<EventJson>): string | number {
|
||||||
const unreadCnt = this.roomUsers
|
const unreadCnt = this.roomUsers.filter(
|
||||||
.filter(
|
(user) =>
|
||||||
(user) => user.isJoinRoom && user.seq + '' !== message.senderSeq + ''
|
user.isJoinRoom &&
|
||||||
)
|
String(message.senderSeq) !== String(user.seq) &&
|
||||||
.filter((user) => user.lastReadEventSeq < message.seq).length;
|
user.lastReadEventSeq < message.seq
|
||||||
|
).length;
|
||||||
return unreadCnt === 0 ? '' : unreadCnt;
|
return unreadCnt === 0 ? '' : unreadCnt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -393,7 +591,7 @@ export class MessageSectionComponent
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
|
|
||||||
if (!!this.currentChatting.remainEvent) {
|
if (!!this.isRemainEvent) {
|
||||||
this.store.dispatch(
|
this.store.dispatch(
|
||||||
ChattingActions.moreEvents({
|
ChattingActions.moreEvents({
|
||||||
roomId: this.roomId
|
roomId: this.roomId
|
||||||
|
@ -422,7 +620,7 @@ export class MessageSectionComponent
|
||||||
this.appChatService.massTextDownload({
|
this.appChatService.massTextDownload({
|
||||||
userSeq: String(this.user.info.seq),
|
userSeq: String(this.user.info.seq),
|
||||||
deviceType: this.loginSession.deviceType,
|
deviceType: this.loginSession.deviceType,
|
||||||
token: this.loginRes.tokenString,
|
token: this.loginInfo.tokenString,
|
||||||
eventMassSeq: params.message.seq
|
eventMassSeq: params.message.seq
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -525,7 +723,7 @@ export class MessageSectionComponent
|
||||||
break;
|
break;
|
||||||
case 'FORWARD_TO_ME':
|
case 'FORWARD_TO_ME':
|
||||||
{
|
{
|
||||||
if (this.loginRes.talkWithMeBotSeq > -1) {
|
if (this.loginInfo.talkWithMeBotSeq > -1) {
|
||||||
const seqs = this.user.talkWithMeBotSeq as any;
|
const seqs = this.user.talkWithMeBotSeq as any;
|
||||||
this.store.dispatch(
|
this.store.dispatch(
|
||||||
ChattingActions.forward({
|
ChattingActions.forward({
|
||||||
|
@ -580,7 +778,7 @@ export class MessageSectionComponent
|
||||||
}) {
|
}) {
|
||||||
const req = {
|
const req = {
|
||||||
userSeq: String(this.user.info.seq),
|
userSeq: String(this.user.info.seq),
|
||||||
token: this.loginRes.tokenString,
|
token: this.loginInfo.tokenString,
|
||||||
deviceType: this.loginSession.deviceType,
|
deviceType: this.loginSession.deviceType,
|
||||||
eventTransSeq: params.message.sentMessageJson.translationSeq.toString()
|
eventTransSeq: params.message.sentMessageJson.translationSeq.toString()
|
||||||
} as TransMassTalkDownloadRequest;
|
} as TransMassTalkDownloadRequest;
|
||||||
|
@ -592,16 +790,133 @@ export class MessageSectionComponent
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
onFileViewer(selectFileInfo: SelectFileInfo) {
|
onFileViewer(params: {
|
||||||
|
selectFileInfo: SelectFileInfo;
|
||||||
|
senderInfo: RoomUserInfoShort | RoomUserInfo;
|
||||||
|
}) {
|
||||||
|
const self = this;
|
||||||
|
this.appOrganizationService
|
||||||
|
.getUserInfo({ userSeq: String(params.senderInfo.seq), user: this.user })
|
||||||
|
.then((result) => {
|
||||||
|
let isValid = false;
|
||||||
|
if (
|
||||||
|
!!result &&
|
||||||
|
!!result.userInfo &&
|
||||||
|
!!self.userPermission &&
|
||||||
|
self.userPermission.fileTransferAllowedCompanyList.indexOf(
|
||||||
|
result.userInfo.companyCode
|
||||||
|
) > -1
|
||||||
|
) {
|
||||||
|
isValid = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!!isValid) {
|
||||||
const data: FileViewerDialogData = {
|
const data: FileViewerDialogData = {
|
||||||
fileInfos: this.currentFileInfoList,
|
fileInfos: self.currentFileInfoList,
|
||||||
selectFileInfo,
|
selectFileInfo: params.selectFileInfo,
|
||||||
downloadUrl: this.versionInfo2Res.downloadUrl,
|
downloadUrl: self.versionInfo.downloadUrl,
|
||||||
deviceType: this.loginSession.deviceType,
|
deviceType: self.loginSession.deviceType,
|
||||||
token: this.loginRes.tokenString,
|
token: self.loginInfo.tokenString,
|
||||||
userSeq: String(this.user.info.seq)
|
userSeq: String(self.user.info.seq)
|
||||||
};
|
};
|
||||||
this.appChatService.openFileviwer(data);
|
self.appChatService.openFileviwer(data);
|
||||||
|
} else {
|
||||||
|
self._openAlert(
|
||||||
|
self.i18nService.t('common:file.errors.disapprovalCompany')
|
||||||
|
);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((reason) => {
|
||||||
|
self._openAlert(
|
||||||
|
self.i18nService.t('common:file.errors.disapprovalCompany')
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
onFileSave(params: {
|
||||||
|
fileInfo: FileEventJson;
|
||||||
|
fileDownloadItem: FileDownloadItem;
|
||||||
|
type: string;
|
||||||
|
senderInfo: RoomUserInfoShort | RoomUserInfo;
|
||||||
|
}): void {
|
||||||
|
const self = this;
|
||||||
|
this.appOrganizationService
|
||||||
|
.getUserInfo({ userSeq: String(params.senderInfo.seq), user: this.user })
|
||||||
|
.then((rst) => {
|
||||||
|
let isValid = false;
|
||||||
|
if (
|
||||||
|
!!rst &&
|
||||||
|
!!rst.userInfo &&
|
||||||
|
!!self.userPermission &&
|
||||||
|
self.userPermission.fileTransferAllowedCompanyList.indexOf(
|
||||||
|
rst.userInfo.companyCode
|
||||||
|
) > -1
|
||||||
|
) {
|
||||||
|
isValid = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!!isValid) {
|
||||||
|
if (
|
||||||
|
params.type === 'saveAs' &&
|
||||||
|
self.loginSession.deviceType === DeviceType.PC
|
||||||
|
) {
|
||||||
|
self.nativeService
|
||||||
|
.file_selectForSave({ defaultPath: params.fileInfo.fileName })
|
||||||
|
.then((result) => {
|
||||||
|
if (!!result) {
|
||||||
|
if (!!result.canceled) {
|
||||||
|
// 취소함.
|
||||||
|
} else {
|
||||||
|
self.appFileService.saveFile(
|
||||||
|
{
|
||||||
|
fileInfo: params.fileInfo,
|
||||||
|
fileDownloadItem: params.fileDownloadItem,
|
||||||
|
type: params.type,
|
||||||
|
fileName: params.fileInfo.fileName,
|
||||||
|
fileDownloadUrl: undefined,
|
||||||
|
savePath: result.filePath
|
||||||
|
},
|
||||||
|
self.loginInfo,
|
||||||
|
self.user,
|
||||||
|
self.loginSession
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((reason) => {
|
||||||
|
// self.snackBarService.open(
|
||||||
|
// self.translateService.instant(
|
||||||
|
// 'common:file.errors.failToSpecifyPath'
|
||||||
|
// ),
|
||||||
|
// self.translateService.instant('common:file.errors.label')
|
||||||
|
// );
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
self.appFileService.saveFile(
|
||||||
|
{
|
||||||
|
fileInfo: params.fileInfo,
|
||||||
|
fileDownloadItem: params.fileDownloadItem,
|
||||||
|
type: params.type,
|
||||||
|
fileName: params.fileInfo.fileName,
|
||||||
|
fileDownloadUrl: undefined,
|
||||||
|
savePath: undefined
|
||||||
|
},
|
||||||
|
self.loginInfo,
|
||||||
|
self.user,
|
||||||
|
self.loginSession
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
self._openAlert(
|
||||||
|
self.i18nService.t('common:file.errors.disapprovalCompany')
|
||||||
|
);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((reason) => {
|
||||||
|
self._openAlert(
|
||||||
|
self.i18nService.t('common:file.errors.disapprovalCompany')
|
||||||
|
);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private _standByRoomSetting(result: SettingDialogResult) {
|
private _standByRoomSetting(result: SettingDialogResult) {
|
||||||
|
@ -640,4 +955,33 @@ export class MessageSectionComponent
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onJoinConference(conferenceSeq: number): void {
|
||||||
|
const loginSession = this.appAuthenticationService.getLoginSession();
|
||||||
|
const req: ConferenceJoinRequest = {
|
||||||
|
userSeq: String(this.user.info.seq),
|
||||||
|
deviceType: loginSession.deviceType,
|
||||||
|
tokenKey: this.loginInfo.tokenString,
|
||||||
|
conferenceSeq
|
||||||
|
};
|
||||||
|
this.appChatService.joinVideoConference(req);
|
||||||
|
}
|
||||||
|
|
||||||
|
private _openAlert(msg: string) {
|
||||||
|
this.dialog.open<AlertDialogComponent, AlertDialogData, AlertDialogResult>(
|
||||||
|
AlertDialogComponent,
|
||||||
|
{
|
||||||
|
panelClass: 'min-create-dialog',
|
||||||
|
data: {
|
||||||
|
title: this.i18nService.t('common:file.errors.title'),
|
||||||
|
message: msg
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
resetRecentMessage() {
|
||||||
|
this.recentMessage = undefined;
|
||||||
|
this.recentUserInfo = undefined;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,9 +12,17 @@
|
||||||
#searchWordInput
|
#searchWordInput
|
||||||
type="text"
|
type="text"
|
||||||
formControlName="searchInput"
|
formControlName="searchInput"
|
||||||
[matAutocomplete]="auto"
|
(keyup.backspace)="onKeyupBackspace($event)"
|
||||||
(keydown.enter)="onKeyDownEnter($event, searchWordInput.value)"
|
(keydown.enter)="onKeyDownEnter($event, searchWordInput.value)"
|
||||||
/>
|
/>
|
||||||
|
<!-- <input
|
||||||
|
matInput
|
||||||
|
#searchWordInput
|
||||||
|
type="text"
|
||||||
|
formControlName="searchInput"
|
||||||
|
[matAutocomplete]="auto"
|
||||||
|
(keydown.enter)="onKeyDownEnter($event, searchWordInput.value)"
|
||||||
|
/> -->
|
||||||
<mat-autocomplete #auto="matAutocomplete">
|
<mat-autocomplete #auto="matAutocomplete">
|
||||||
<mat-option
|
<mat-option
|
||||||
*ngFor="let filteredRecommendedWord of filteredRecommendedWordList"
|
*ngFor="let filteredRecommendedWord of filteredRecommendedWordList"
|
||||||
|
|
|
@ -9,7 +9,8 @@ import {
|
||||||
EventEmitter,
|
EventEmitter,
|
||||||
ChangeDetectorRef,
|
ChangeDetectorRef,
|
||||||
ChangeDetectionStrategy,
|
ChangeDetectionStrategy,
|
||||||
ViewChild
|
ViewChild,
|
||||||
|
ElementRef
|
||||||
} from '@angular/core';
|
} from '@angular/core';
|
||||||
import { FormGroup, FormBuilder } from '@angular/forms';
|
import { FormGroup, FormBuilder } from '@angular/forms';
|
||||||
|
|
||||||
|
@ -17,7 +18,7 @@ import { Store, select } from '@ngrx/store';
|
||||||
|
|
||||||
import { MatAutocompleteTrigger } from '@angular/material/autocomplete';
|
import { MatAutocompleteTrigger } from '@angular/material/autocomplete';
|
||||||
|
|
||||||
import { User } from '@ucap/protocol-info';
|
import { User } from '@ucap/domain-organization';
|
||||||
|
|
||||||
import { LogService } from '@ucap/ng-logger';
|
import { LogService } from '@ucap/ng-logger';
|
||||||
|
|
||||||
|
@ -45,6 +46,8 @@ export class SearchSectionComponent implements OnInit, OnDestroy {
|
||||||
recommendedWordList: string[];
|
recommendedWordList: string[];
|
||||||
filteredRecommendedWordList: string[];
|
filteredRecommendedWordList: string[];
|
||||||
|
|
||||||
|
@ViewChild('searchWordInput', { static: true })
|
||||||
|
searchWordInput: ElementRef<HTMLInputElement>;
|
||||||
@ViewChild(MatAutocompleteTrigger) autocomplete: MatAutocompleteTrigger;
|
@ViewChild(MatAutocompleteTrigger) autocomplete: MatAutocompleteTrigger;
|
||||||
|
|
||||||
private ngOnDestroySubject: Subject<void> = new Subject();
|
private ngOnDestroySubject: Subject<void> = new Subject();
|
||||||
|
@ -148,11 +151,20 @@ export class SearchSectionComponent implements OnInit, OnDestroy {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onKeyupBackspace(event: Event) {
|
||||||
|
if (this.searchWordInput.nativeElement.value === '') {
|
||||||
|
this.searchCancel.emit();
|
||||||
|
}
|
||||||
|
event.stopPropagation();
|
||||||
|
}
|
||||||
|
|
||||||
onKeyDownEnter(event: KeyboardEvent, searchWord: string) {
|
onKeyDownEnter(event: KeyboardEvent, searchWord: string) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
|
|
||||||
|
if (!!this.autocomplete) {
|
||||||
this.autocomplete.closePanel();
|
this.autocomplete.closePanel();
|
||||||
|
}
|
||||||
|
|
||||||
this.keyDownEnter.emit({ searchWord });
|
this.keyDownEnter.emit({ searchWord });
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,19 +6,19 @@
|
||||||
>
|
>
|
||||||
<div appLayoutsDefaultDialog="header">
|
<div appLayoutsDefaultDialog="header">
|
||||||
<span *ngIf="stepper.selectedIndex === 0">
|
<span *ngIf="stepper.selectedIndex === 0">
|
||||||
{{ 'dialog.title.newChatRoom' | ucapI18n }}
|
{{ 'chat:dialog.title.newChatRoom' | ucapI18n }}
|
||||||
</span>
|
</span>
|
||||||
<span *ngIf="stepper.selectedIndex !== 0">
|
<span *ngIf="stepper.selectedIndex !== 0">
|
||||||
{{ (!!isTimer ? 'dialog.timerRoom' : 'dialog.normalRoom') | ucapI18n }}
|
{{ (!!isTimer ? 'chat:dialog.timerRoom' : 'chat:dialog.normalRoom') | ucapI18n }}
|
||||||
</span>
|
</span>
|
||||||
<div appLayoutsDefaultDialog="sub-header" class="sub-header-tit">
|
<span appLayoutsDefaultDialog="sub-header" class="sub-header-tit">
|
||||||
<span *ngIf="stepper.selectedIndex === 0">
|
<span *ngIf="stepper.selectedIndex === 0">
|
||||||
{{ 'dialog.title.subSelectRoomType' | ucapI18n }}
|
{{ 'chat:dialog.title.subSelectRoomType' | ucapI18n }}
|
||||||
</span>
|
</span>
|
||||||
<span *ngIf="stepper.selectedIndex !== 0">
|
<span *ngIf="stepper.selectedIndex !== 0">
|
||||||
{{ 'dialog.title.subSelectUser' | ucapI18n }}
|
{{ 'chat:dialog.title.subSelectUser' | ucapI18n }}
|
||||||
|
</span>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="dialog-body" appLayoutsDefaultDialog="body">
|
<div class="dialog-body" appLayoutsDefaultDialog="body">
|
||||||
|
@ -31,12 +31,12 @@
|
||||||
<mat-step label="Select room type" fxFlexFill>
|
<mat-step label="Select room type" fxFlexFill>
|
||||||
<div class="ucap-dialog-select-room-type">
|
<div class="ucap-dialog-select-room-type">
|
||||||
<div class="normal-room room-type">
|
<div class="normal-room room-type">
|
||||||
<span class="title">{{ 'dialog.normalRoom' | ucapI18n }}</span>
|
<span class="title">{{ 'chat:dialog.normalRoom' | ucapI18n }}</span>
|
||||||
<div class="img"></div>
|
<div class="img"></div>
|
||||||
<div
|
<div
|
||||||
class="description"
|
class="description"
|
||||||
[innerHTML]="
|
[innerHTML]="
|
||||||
'dialog.normalRoomDescription'
|
'chat:dialog.normalRoomDescription'
|
||||||
| ucapI18n: { maxCount: maxChatRoomUser }
|
| ucapI18n: { maxCount: maxChatRoomUser }
|
||||||
"
|
"
|
||||||
></div>
|
></div>
|
||||||
|
@ -69,12 +69,12 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="room-type timer-room">
|
<div class="room-type timer-room">
|
||||||
<span class="title">{{ 'dialog.timerRoom' | ucapI18n }}</span>
|
<span class="title">{{ 'chat:dialog.timerRoom' | ucapI18n }}</span>
|
||||||
<div class="img"></div>
|
<div class="img"></div>
|
||||||
<div
|
<div
|
||||||
class="description"
|
class="description"
|
||||||
[innerHTML]="
|
[innerHTML]="
|
||||||
'dialog.timerRoomDescription'
|
'chat:dialog.timerRoomDescription'
|
||||||
| ucapI18n: { maxCount: maxChatRoomUser }
|
| ucapI18n: { maxCount: maxChatRoomUser }
|
||||||
"
|
"
|
||||||
></div>
|
></div>
|
||||||
|
@ -113,8 +113,9 @@
|
||||||
[isDialog]="true"
|
[isDialog]="true"
|
||||||
[checkable]="true"
|
[checkable]="true"
|
||||||
[selectedUserList]="selectedUserList"
|
[selectedUserList]="selectedUserList"
|
||||||
(toggleCheckUser)="onChangeUserList($event)"
|
[filteredTimerChatAuth]="isTimer"
|
||||||
(toggleCheckGroup)="onChangeGroupList($event)"
|
(toggleCheckUser)="onToggleCheckUser($event)"
|
||||||
|
(toggleCheckGroup)="onToggleCheckGroup($event)"
|
||||||
></app-group-select-user>
|
></app-group-select-user>
|
||||||
</div>
|
</div>
|
||||||
<div class="ucap-dialog-organization-profile-selection">
|
<div class="ucap-dialog-organization-profile-selection">
|
||||||
|
@ -130,7 +131,7 @@
|
||||||
class="selected-head-area"
|
class="selected-head-area"
|
||||||
>
|
>
|
||||||
<p>
|
<p>
|
||||||
{{ 'dialog.selectedUserList' | ucapI18n }}
|
{{ 'chat:dialog.selectedUserList' | ucapI18n }}
|
||||||
</p>
|
</p>
|
||||||
<span
|
<span
|
||||||
>(<em class="number">{{ selectedUserList?.length }}</em
|
>(<em class="number">{{ selectedUserList?.length }}</em
|
||||||
|
@ -144,7 +145,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div appLayoutsDefaultDialog="action" class="btn-box">
|
<div appLayoutsDefaultDialog="action" class="btn-box">
|
||||||
<button mat-button mat-stroked-button (click)="onCancel(stepper)">
|
<button mat-button mat-stroked-button (click)="onCancel(stepper)">
|
||||||
{{ 'dialog.button.cancel' | ucapI18n }}
|
{{ 'chat:dialog.button.cancel' | ucapI18n }}
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
mat-flat-button
|
mat-flat-button
|
||||||
|
@ -153,7 +154,7 @@
|
||||||
[disabled]="this.isTimer === undefined"
|
[disabled]="this.isTimer === undefined"
|
||||||
(click)="onConfirm(stepper)"
|
(click)="onConfirm(stepper)"
|
||||||
>
|
>
|
||||||
{{ 'dialog.button.selectRoomUser' | ucapI18n }}
|
{{ 'chat:dialog.button.selectRoomUser' | ucapI18n }}
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
mat-flat-button
|
mat-flat-button
|
||||||
|
@ -162,7 +163,7 @@
|
||||||
[disabled]="selectedUserList.length === 0"
|
[disabled]="selectedUserList.length === 0"
|
||||||
(click)="onOpenRoom(stepper)"
|
(click)="onOpenRoom(stepper)"
|
||||||
>
|
>
|
||||||
{{ 'dialog.button.openRoom' | ucapI18n }}
|
{{ 'chat:dialog.button.openRoom' | ucapI18n }}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</app-layouts-default-dialog>
|
</app-layouts-default-dialog>
|
||||||
|
|
|
@ -80,7 +80,7 @@
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
width: 48%;
|
width: 48%;
|
||||||
height: 210px;
|
height: 200px;
|
||||||
border: 1px solid #999999;
|
border: 1px solid #999999;
|
||||||
background-color: #f7f8fa;
|
background-color: #f7f8fa;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
@ -98,7 +98,7 @@
|
||||||
width: 60px;
|
width: 60px;
|
||||||
height: 60px;
|
height: 60px;
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
background-image: url(../../../../assets/images/ico/icon_normal_chat_g60.svg);
|
background-image: url(/assets/images/ico/icon_normal_chat_g60.svg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
&.timer-room {
|
&.timer-room {
|
||||||
|
@ -106,7 +106,7 @@
|
||||||
width: 60px;
|
width: 60px;
|
||||||
height: 60px;
|
height: 60px;
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
background-image: url(../../../../assets/images/ico/icon_timer_chat_g60.svg);
|
background-image: url(/assets/images/ico/icon_timer_chat_g60.svg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.selecter {
|
.selecter {
|
||||||
|
|
|
@ -6,9 +6,7 @@ import {
|
||||||
OnDestroy,
|
OnDestroy,
|
||||||
ChangeDetectionStrategy,
|
ChangeDetectionStrategy,
|
||||||
ChangeDetectorRef,
|
ChangeDetectorRef,
|
||||||
Inject,
|
Inject
|
||||||
Input,
|
|
||||||
ViewChild
|
|
||||||
} from '@angular/core';
|
} from '@angular/core';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
@ -17,32 +15,24 @@ import {
|
||||||
MatDialog
|
MatDialog
|
||||||
} from '@angular/material/dialog';
|
} from '@angular/material/dialog';
|
||||||
|
|
||||||
import { UserInfo, GroupDetailData } from '@ucap/protocol-sync';
|
import { UserInfo, UserInfoSS } from '@ucap/domain-organization';
|
||||||
import {
|
import { GroupInfoDetail } from '@ucap/domain-group';
|
||||||
UserInfoSS,
|
|
||||||
UserInfoF,
|
|
||||||
UserInfoDN,
|
|
||||||
AuthResponse
|
|
||||||
} from '@ucap/protocol-query';
|
|
||||||
import { UserInfo as RoomUserInfo } from '@ucap/protocol-room';
|
|
||||||
import { MatStepper } from '@angular/material/stepper';
|
import { MatStepper } from '@angular/material/stepper';
|
||||||
import { I18nService } from '@ucap/ng-i18n';
|
import { I18nService } from '@ucap/ng-i18n';
|
||||||
import {
|
import {
|
||||||
AlertDialogComponent,
|
AlertDialogComponent,
|
||||||
AlertDialogData,
|
AlertDialogData,
|
||||||
AlertDialogResult
|
AlertDialogResult
|
||||||
} from '@ucap/ng-ui';
|
} from '@ucap/ng-ui/core';
|
||||||
import { environment } from '@environments';
|
import { environment } from '@environments';
|
||||||
import { Store, select } from '@ngrx/store';
|
import { Store, select } from '@ngrx/store';
|
||||||
import { takeUntil } from 'rxjs/operators';
|
import { takeUntil } from 'rxjs/operators';
|
||||||
import { AuthorizationSelector } from '@ucap/ng-store-authentication';
|
import { AuthorizationSelector } from '@ucap/ng-store-authentication';
|
||||||
|
import { AppGroupService } from '@app/services/app-group.service';
|
||||||
export type UserInfoTypes =
|
import { UserInfoTypes } from '@app/types';
|
||||||
| UserInfo
|
import { AppChatService } from '@app/services/app-chat.service';
|
||||||
| UserInfoSS
|
import { UserPermission } from '@ucap/domain-authorization';
|
||||||
| UserInfoF
|
|
||||||
| UserInfoDN
|
|
||||||
| RoomUserInfo;
|
|
||||||
|
|
||||||
export interface CreateDialogData {}
|
export interface CreateDialogData {}
|
||||||
export interface CreateDialogResult {
|
export interface CreateDialogResult {
|
||||||
|
@ -62,7 +52,7 @@ export class CreateDialogComponent implements OnInit, OnDestroy {
|
||||||
|
|
||||||
isTimer: boolean | undefined;
|
isTimer: boolean | undefined;
|
||||||
selectedUserList: UserInfoTypes[] = [];
|
selectedUserList: UserInfoTypes[] = [];
|
||||||
authRes: AuthResponse;
|
userPermission: UserPermission;
|
||||||
|
|
||||||
private ngOnDestroySubject: Subject<void> = new Subject();
|
private ngOnDestroySubject: Subject<void> = new Subject();
|
||||||
|
|
||||||
|
@ -72,7 +62,9 @@ export class CreateDialogComponent implements OnInit, OnDestroy {
|
||||||
private i18nService: I18nService,
|
private i18nService: I18nService,
|
||||||
public dialog: MatDialog,
|
public dialog: MatDialog,
|
||||||
private store: Store<any>,
|
private store: Store<any>,
|
||||||
private changeDetectorRef: ChangeDetectorRef
|
private changeDetectorRef: ChangeDetectorRef,
|
||||||
|
private appGroupService: AppGroupService,
|
||||||
|
private appChatService: AppChatService
|
||||||
) {
|
) {
|
||||||
this.maxChatRoomUser = environment.productConfig.chat.maxChatRoomUser;
|
this.maxChatRoomUser = environment.productConfig.chat.maxChatRoomUser;
|
||||||
}
|
}
|
||||||
|
@ -81,11 +73,11 @@ export class CreateDialogComponent implements OnInit, OnDestroy {
|
||||||
this.store
|
this.store
|
||||||
.pipe(
|
.pipe(
|
||||||
takeUntil(this.ngOnDestroySubject),
|
takeUntil(this.ngOnDestroySubject),
|
||||||
select(AuthorizationSelector.authResponse)
|
select(AuthorizationSelector.userPermission)
|
||||||
)
|
)
|
||||||
.subscribe((authRes) => {
|
.subscribe((userPermission) => {
|
||||||
this.authRes = authRes;
|
this.userPermission = userPermission;
|
||||||
if (!!this.authRes && !this.authRes.canTimerChat) {
|
if (!!this.userPermission && !this.userPermission.canTimerChat) {
|
||||||
this.isTimer = false;
|
this.isTimer = false;
|
||||||
this.currentStep = 1;
|
this.currentStep = 1;
|
||||||
}
|
}
|
||||||
|
@ -103,7 +95,7 @@ export class CreateDialogComponent implements OnInit, OnDestroy {
|
||||||
this.dialogRef.close();
|
this.dialogRef.close();
|
||||||
}
|
}
|
||||||
onCancel(stepper: MatStepper) {
|
onCancel(stepper: MatStepper) {
|
||||||
if (!!this.authRes && !this.authRes.canTimerChat) {
|
if (!!this.userPermission && !this.userPermission.canTimerChat) {
|
||||||
// close.
|
// close.
|
||||||
} else if (stepper.selectedIndex > 0) {
|
} else if (stepper.selectedIndex > 0) {
|
||||||
stepper.previous();
|
stepper.previous();
|
||||||
|
@ -135,93 +127,51 @@ export class CreateDialogComponent implements OnInit, OnDestroy {
|
||||||
|
|
||||||
this.selectedUserList.map((user) => userSeqs.push(user.seq.toString()));
|
this.selectedUserList.map((user) => userSeqs.push(user.seq.toString()));
|
||||||
|
|
||||||
if (this.selectedUserList.length >= this.maxChatRoomUser) {
|
// validation and openRoom
|
||||||
this.dialog.open<
|
this.appChatService.newOpenRoom(userSeqs, this.isTimer);
|
||||||
AlertDialogComponent,
|
|
||||||
AlertDialogData,
|
|
||||||
AlertDialogResult
|
|
||||||
>(AlertDialogComponent, {
|
|
||||||
panelClass: 'min-create-dialog',
|
|
||||||
data: {
|
|
||||||
title: this.i18nService.t('chat:errors.label'),
|
|
||||||
html: this.i18nService.t('chat:errors.maxCountOfRoomMemberWith', {
|
|
||||||
maxCount: this.maxChatRoomUser
|
|
||||||
})
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Open Room.
|
if (this.selectedUserList.length >= this.maxChatRoomUser) {
|
||||||
|
// not close popup..
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
this.dialogRef.close({ userSeqs, isTimer: this.isTimer });
|
this.dialogRef.close({ userSeqs, isTimer: this.isTimer });
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
onChangeUserList(datas: { checked: boolean; userInfo: UserInfoSS }[]) {
|
onToggleCheckUser(datas: { checked: boolean; userInfo: UserInfoSS }[]) {
|
||||||
if (!datas || 0 === datas.length) {
|
const resList = this.appGroupService.getToggleCheckUser(
|
||||||
|
datas,
|
||||||
|
this.selectedUserList
|
||||||
|
);
|
||||||
|
if (!resList) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.selectedUserList = resList;
|
||||||
|
}
|
||||||
|
onToggleCheckGroup(params: {
|
||||||
|
isChecked: boolean;
|
||||||
|
groupBuddyList: { group: GroupInfoDetail; buddyList: UserInfo[] };
|
||||||
|
}) {
|
||||||
|
const resList = this.appGroupService.getToggleCheckGroup(
|
||||||
|
params,
|
||||||
|
this.selectedUserList
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!resList) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const pushs: UserInfoSS[] = [];
|
this.selectedUserList = resList;
|
||||||
const pops: UserInfoSS[] = [];
|
|
||||||
|
|
||||||
datas.forEach((d) => {
|
|
||||||
const i = this.selectedUserList.findIndex(
|
|
||||||
(u) => String(u.seq) === String(d.userInfo.seq)
|
|
||||||
);
|
|
||||||
if (d.checked) {
|
|
||||||
if (-1 === i) {
|
|
||||||
pushs.push(d.userInfo);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (-1 < i) {
|
|
||||||
pops.push(d.userInfo);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (0 < pushs.length) {
|
|
||||||
this.selectedUserList = [...this.selectedUserList, ...pushs];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (0 < pops.length) {
|
|
||||||
this.selectedUserList = this.selectedUserList.filter(
|
|
||||||
(u) => -1 === pops.findIndex((p) => String(p.seq) === String(u.seq))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
onChangeGroupList(params: {
|
|
||||||
isChecked: boolean;
|
|
||||||
groupBuddyList: { group: GroupDetailData; buddyList: UserInfo[] };
|
|
||||||
}) {
|
|
||||||
if (params.isChecked) {
|
|
||||||
params.groupBuddyList.buddyList.forEach((item) => {
|
|
||||||
if (
|
|
||||||
this.selectedUserList.filter(
|
|
||||||
(user) => String(user.seq) === String(item.seq)
|
|
||||||
).length === 0
|
|
||||||
) {
|
|
||||||
this.selectedUserList = [...this.selectedUserList, item];
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
this.selectedUserList = this.selectedUserList.filter(
|
|
||||||
(item) =>
|
|
||||||
params.groupBuddyList.buddyList.filter(
|
|
||||||
(del) => String(del.seq) === String(item.seq)
|
|
||||||
).length === 0
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
onRemovedProfileSelection(userInfo: UserInfo) {
|
onRemovedProfileSelection(userInfo: UserInfo) {
|
||||||
const i = this.selectedUserList.findIndex(
|
const resUserList = this.appGroupService.removedProfileSelection(
|
||||||
(u) => String(u.seq) === String(userInfo.seq)
|
userInfo,
|
||||||
|
this.selectedUserList
|
||||||
);
|
);
|
||||||
|
|
||||||
if (-1 < i) {
|
if (!resUserList) {
|
||||||
this.selectedUserList = this.selectedUserList.filter(
|
|
||||||
(u) => String(u.seq) !== String(userInfo.seq)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
this.selectedUserList = resUserList;
|
||||||
}
|
}
|
||||||
removableForSelection = (userInfo: UserInfo) => {
|
removableForSelection = (userInfo: UserInfo) => {
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -7,23 +7,25 @@ import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
|
||||||
|
|
||||||
import { select, Store } from '@ngrx/store';
|
import { select, Store } from '@ngrx/store';
|
||||||
|
|
||||||
import { DeviceType, LoginSession } from '@ucap/core';
|
import { DeviceType, FileDownloadItem } from '@ucap/domain-common';
|
||||||
import { FileDownloadItem } from '@ucap/api';
|
import { User } from '@ucap/domain-organization';
|
||||||
import { LoginResponse } from '@ucap/protocol-authentication';
|
import { LoginSession, LoginInfo } from '@ucap/domain-authentication';
|
||||||
import { FileEventJson } from '@ucap/protocol-event';
|
import { FileEventJson, FileInfo, isMedia } from '@ucap/domain-chat';
|
||||||
import { FileInfo, isMedia } from '@ucap/protocol-file';
|
|
||||||
import { User } from '@ucap/protocol-info';
|
|
||||||
|
|
||||||
import { LogService } from '@ucap/ng-logger';
|
import { LogService } from '@ucap/ng-logger';
|
||||||
import { CommonApiService } from '@ucap/ng-api-common';
|
import { CommonApiService } from '@ucap/ng-api-common';
|
||||||
|
|
||||||
import { UserSelector } from '@ucap/ng-store-organization';
|
import { UserSelector } from '@ucap/ng-store-organization';
|
||||||
import { LoginSelector } from '@ucap/ng-store-authentication';
|
import {
|
||||||
|
LoginSelector,
|
||||||
|
AuthorizationSelector
|
||||||
|
} from '@ucap/ng-store-authentication';
|
||||||
|
|
||||||
import { SelectFileInfo } from '@ucap/ng-ui';
|
import { SelectFileInfo } from '@ucap/ng-ui/viewer';
|
||||||
|
|
||||||
import { AppFileService } from '@app/services/app-file.service';
|
import { AppFileService } from '@app/services/app-file.service';
|
||||||
import { AppAuthenticationService } from '@app/services/app-authentication.service';
|
import { AppAuthenticationService } from '@app/services/app-authentication.service';
|
||||||
|
import { UserPermission } from '@ucap/domain-authorization';
|
||||||
|
|
||||||
export interface FileViewerDialogData {
|
export interface FileViewerDialogData {
|
||||||
fileInfos: FileInfo[];
|
fileInfos: FileInfo[];
|
||||||
|
@ -51,9 +53,10 @@ export class FileViewerDialogComponent implements OnInit, OnDestroy {
|
||||||
};
|
};
|
||||||
currentFileInfo: FileInfo;
|
currentFileInfo: FileInfo;
|
||||||
|
|
||||||
loginRes: LoginResponse;
|
loginInfo: LoginInfo;
|
||||||
user: User;
|
user: User;
|
||||||
loginSession: LoginSession;
|
loginSession: LoginSession;
|
||||||
|
userPermission: UserPermission;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private store: Store<any>,
|
private store: Store<any>,
|
||||||
|
@ -96,14 +99,54 @@ export class FileViewerDialogComponent implements OnInit, OnDestroy {
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.store
|
this.store
|
||||||
.pipe(takeUntil(this.ngOnDestroySubject), select(LoginSelector.loginRes))
|
.pipe(takeUntil(this.ngOnDestroySubject), select(LoginSelector.loginInfo))
|
||||||
.subscribe((loginRes) => (this.loginRes = loginRes));
|
.subscribe((loginInfo) => (this.loginInfo = loginInfo));
|
||||||
|
|
||||||
this.store
|
this.store
|
||||||
.pipe(takeUntil(this.ngOnDestroySubject), select(UserSelector.user))
|
.pipe(takeUntil(this.ngOnDestroySubject), select(UserSelector.user))
|
||||||
.subscribe((user) => (this.user = user));
|
.subscribe((user) => (this.user = user));
|
||||||
|
|
||||||
this.loginSession = this.appAuthenticationService.getLoginSession();
|
this.loginSession = this.appAuthenticationService.getLoginSession();
|
||||||
|
|
||||||
|
// auth.fileTransferAllowedCompanyList check.
|
||||||
|
this.store
|
||||||
|
.pipe(
|
||||||
|
takeUntil(this.ngOnDestroySubject),
|
||||||
|
select(AuthorizationSelector.userPermission)
|
||||||
|
)
|
||||||
|
.subscribe((userPermission) => {
|
||||||
|
if (!!userPermission) {
|
||||||
|
this.userPermission = userPermission;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
!!userPermission &&
|
||||||
|
!!this.data.fileInfos &&
|
||||||
|
this.data.fileInfos.length > 0
|
||||||
|
) {
|
||||||
|
this.fileInfo = {
|
||||||
|
fileInfos: this.data.fileInfos
|
||||||
|
.filter((item) => {
|
||||||
|
// filtered userPermission.fileTransferAllowedCompanyList
|
||||||
|
if (
|
||||||
|
!!userPermission.fileTransferAllowedCompanyList &&
|
||||||
|
userPermission.fileTransferAllowedCompanyList.length > 0
|
||||||
|
) {
|
||||||
|
return (
|
||||||
|
userPermission.fileTransferAllowedCompanyList.indexOf(
|
||||||
|
item.sentMessageJson.companyCode
|
||||||
|
) > -1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
})
|
||||||
|
.sort((a, b) =>
|
||||||
|
a.eventSeq < b.eventSeq ? 1 : a.eventSeq > b.eventSeq ? -1 : 0
|
||||||
|
),
|
||||||
|
selectFileInfo: this.data.selectFileInfo
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnDestroy(): void {
|
ngOnDestroy(): void {
|
||||||
|
@ -147,7 +190,7 @@ export class FileViewerDialogComponent implements OnInit, OnDestroy {
|
||||||
fileDownloadUrl: undefined,
|
fileDownloadUrl: undefined,
|
||||||
savePath: undefined
|
savePath: undefined
|
||||||
},
|
},
|
||||||
this.loginRes,
|
this.loginInfo,
|
||||||
this.user,
|
this.user,
|
||||||
this.loginSession
|
this.loginSession
|
||||||
);
|
);
|
||||||
|
|
|
@ -10,9 +10,14 @@
|
||||||
<div class="dialog-body" appLayoutsDefaultDialog="body" fxFlexFill>
|
<div class="dialog-body" appLayoutsDefaultDialog="body" fxFlexFill>
|
||||||
<div class="ucap-dialog-app-group-select-user">
|
<div class="ucap-dialog-app-group-select-user">
|
||||||
<!-- search start-->
|
<!-- search start-->
|
||||||
<div class="ucap-dialog-search">
|
<div
|
||||||
|
*ngIf="currentTabIndex === 0"
|
||||||
|
class="ucap-dialog-search"
|
||||||
|
[ngClass]="currentTabIndex === 0 ? 'ucap-dialog-search-disable' : ''"
|
||||||
|
>
|
||||||
<app-organization-search-for-tenant
|
<app-organization-search-for-tenant
|
||||||
placeholder="이름, 부서명, 전화번호, 이메일"
|
placeholder="이름, 부서명, 전화번호, 이메일"
|
||||||
|
[isBackspaceCanceled]="isBackspaceCanceled"
|
||||||
[(searchData)]="companySearchData"
|
[(searchData)]="companySearchData"
|
||||||
(canceled)="onCanceled()"
|
(canceled)="onCanceled()"
|
||||||
class="select-user-section-search"
|
class="select-user-section-search"
|
||||||
|
@ -24,7 +29,7 @@
|
||||||
<mat-tab-group
|
<mat-tab-group
|
||||||
mat-stretch-tabs
|
mat-stretch-tabs
|
||||||
class="tap-container tab_num2"
|
class="tap-container tab_num2"
|
||||||
(selectedIndexChange)="onSelectedIndexChange($event)"
|
[(selectedIndex)]="currentTabIndex"
|
||||||
>
|
>
|
||||||
<!--[S]그룹-->
|
<!--[S]그룹-->
|
||||||
<mat-tab>
|
<mat-tab>
|
||||||
|
@ -57,6 +62,8 @@
|
||||||
<div fxFlexFill class="ucap-dialog-chat-tap">
|
<div fxFlexFill class="ucap-dialog-chat-tap">
|
||||||
<perfect-scrollbar style="width: 100%; height: 100%;">
|
<perfect-scrollbar style="width: 100%; height: 100%;">
|
||||||
<app-chat-room-list
|
<app-chat-room-list
|
||||||
|
fxFlexFill
|
||||||
|
[selectedRoom]="selectedRoom"
|
||||||
[checkable]="true"
|
[checkable]="true"
|
||||||
(toggleRoom)="onToggleRoom($event)"
|
(toggleRoom)="onToggleRoom($event)"
|
||||||
></app-chat-room-list>
|
></app-chat-room-list>
|
||||||
|
@ -81,12 +88,13 @@
|
||||||
<div class="search-result-list">
|
<div class="search-result-list">
|
||||||
<perfect-scrollbar style="width: 100%; height: 100%;">
|
<perfect-scrollbar style="width: 100%; height: 100%;">
|
||||||
<app-group-profile-list
|
<app-group-profile-list
|
||||||
|
#appProfileList
|
||||||
[searchData]="companySearchData"
|
[searchData]="companySearchData"
|
||||||
[selectedUser]="selectedUserList"
|
[selectedUser]="selectedUserList"
|
||||||
[checkable]="true"
|
[checkable]="true"
|
||||||
[isDialog]="true"
|
[isDialog]="true"
|
||||||
(searched)="onSearched($event)"
|
(searched)="onSearched($event)"
|
||||||
(toggleCheck)="onToggleCheckUser($event)"
|
(toggleCheckUser)="onToggleCheckUser($event)"
|
||||||
class="ucap-dialog-search-result-container"
|
class="ucap-dialog-search-result-container"
|
||||||
></app-group-profile-list>
|
></app-group-profile-list>
|
||||||
</perfect-scrollbar>
|
</perfect-scrollbar>
|
||||||
|
@ -127,12 +135,7 @@
|
||||||
<button
|
<button
|
||||||
mat-flat-button
|
mat-flat-button
|
||||||
class="bg-primary-darkest"
|
class="bg-primary-darkest"
|
||||||
[disabled]="
|
[disabled]="checkDisableBtn()"
|
||||||
!(
|
|
||||||
!!selectedRoom ||
|
|
||||||
(!!selectedUserList && selectedUserList.length > 0)
|
|
||||||
)
|
|
||||||
"
|
|
||||||
(click)="onConfirm()"
|
(click)="onConfirm()"
|
||||||
>
|
>
|
||||||
{{ 'dialog.button.save' | ucapI18n }}
|
{{ 'dialog.button.save' | ucapI18n }}
|
||||||
|
|
|
@ -18,13 +18,16 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.forwrad-dialog-content {
|
.forwrad-dialog-content {
|
||||||
height: calc(100% - 50px);
|
flex: 1 1 auto;
|
||||||
|
// height: calc(100% - 50px);
|
||||||
.tap-container {
|
.tap-container {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.ucap-dialog-app-group-select-user {
|
.ucap-dialog-app-group-select-user {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
flex: 1 0 auto;
|
flex: 1 0 auto;
|
||||||
//width: 60%;
|
//width: 60%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
@ -35,6 +38,9 @@
|
||||||
height: 78%;
|
height: 78%;
|
||||||
margin-bottom: 2%;
|
margin-bottom: 2%;
|
||||||
}
|
}
|
||||||
|
.ucap-dialog-search {
|
||||||
|
flex: 0 0 50px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.ucap-dialog-organization-profile-selection {
|
.ucap-dialog-organization-profile-selection {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
|
@ -19,10 +19,13 @@ import {
|
||||||
|
|
||||||
import { Store, select } from '@ngrx/store';
|
import { Store, select } from '@ngrx/store';
|
||||||
|
|
||||||
import { VersionInfo2Response } from '@ucap/api-public';
|
import {
|
||||||
import { UserInfo, GroupDetailData } from '@ucap/protocol-sync';
|
UserInfo,
|
||||||
import { UserInfoSS, UserInfoF, UserInfoDN } from '@ucap/protocol-query';
|
UserInfoSS,
|
||||||
import { UserInfo as RoomUserInfo, RoomInfo } from '@ucap/protocol-room';
|
UserInfoF,
|
||||||
|
UserInfoDN
|
||||||
|
} from '@ucap/domain-organization';
|
||||||
|
import { UserInfo as RoomUserInfo, RoomInfo } from '@ucap/domain-chat';
|
||||||
|
|
||||||
import { I18nService } from '@ucap/ng-i18n';
|
import { I18nService } from '@ucap/ng-i18n';
|
||||||
|
|
||||||
|
@ -33,18 +36,16 @@ import {
|
||||||
AlertDialogComponent,
|
AlertDialogComponent,
|
||||||
AlertDialogData,
|
AlertDialogData,
|
||||||
AlertDialogResult
|
AlertDialogResult
|
||||||
} from '@ucap/ng-ui';
|
} from '@ucap/ng-ui/core';
|
||||||
|
|
||||||
import { SearchData } from '@app/ucap/organization/models/search-data';
|
import { SearchData } from '@app/ucap/organization/models/search-data';
|
||||||
import { Expansion02Component as AppExpansion02Component } from '@app/ucap/group/components/expansion-02.component';
|
import { Expansion02Component as AppExpansion02Component } from '@app/ucap/group/components/expansion-02.component';
|
||||||
|
import { ProfileListComponent as AppProfileListComponent } from '@app/ucap/group/components/profile-list.component';
|
||||||
import { environment } from '@environments';
|
import { environment } from '@environments';
|
||||||
|
import { AppGroupService } from '@app/services/app-group.service';
|
||||||
export type UserInfoTypes =
|
import { UserInfoTypes } from '@app/types';
|
||||||
| UserInfo
|
import { VersionInfo } from '@ucap/domain-authentication';
|
||||||
| UserInfoSS
|
import { GroupInfoDetail } from '@ucap/domain-group';
|
||||||
| UserInfoF
|
|
||||||
| UserInfoDN
|
|
||||||
| RoomUserInfo;
|
|
||||||
|
|
||||||
export interface ForwardDialogData {}
|
export interface ForwardDialogData {}
|
||||||
export interface ForwardDialogResult {
|
export interface ForwardDialogResult {
|
||||||
|
@ -63,6 +64,9 @@ export class ForwardDialogComponent implements OnInit, OnDestroy {
|
||||||
@ViewChild('appGroupExpansion', { static: false })
|
@ViewChild('appGroupExpansion', { static: false })
|
||||||
appGroupExpansion: AppExpansion02Component;
|
appGroupExpansion: AppExpansion02Component;
|
||||||
|
|
||||||
|
@ViewChild('appProfileList', { static: false })
|
||||||
|
appProfileList: AppProfileListComponent;
|
||||||
|
|
||||||
set companySearchData(searchData: SearchData) {
|
set companySearchData(searchData: SearchData) {
|
||||||
if (!!searchData && searchData.searchWord !== '') {
|
if (!!searchData && searchData.searchWord !== '') {
|
||||||
this._companySearchData = { ...searchData, bySearch: true };
|
this._companySearchData = { ...searchData, bySearch: true };
|
||||||
|
@ -85,13 +89,23 @@ export class ForwardDialogComponent implements OnInit, OnDestroy {
|
||||||
selectedRoom: RoomInfo;
|
selectedRoom: RoomInfo;
|
||||||
selectedUserList: UserInfoTypes[] = [];
|
selectedUserList: UserInfoTypes[] = [];
|
||||||
|
|
||||||
versionInfo2Res: VersionInfo2Response;
|
versionInfo: VersionInfo;
|
||||||
|
|
||||||
groupList: GroupDetailData[];
|
|
||||||
|
|
||||||
|
groupList: GroupInfoDetail[];
|
||||||
|
isBackspaceCanceled = true;
|
||||||
isSearch = false;
|
isSearch = false;
|
||||||
searchedList: UserInfoSS[] = [];
|
searchedList: UserInfoSS[] = [];
|
||||||
currentTabIndex: number;
|
|
||||||
|
set currentTabIndex(idx: number) {
|
||||||
|
this._currentTabIndex = idx;
|
||||||
|
// this._resetSelectedObject();
|
||||||
|
}
|
||||||
|
|
||||||
|
get currentTabIndex() {
|
||||||
|
return this._currentTabIndex;
|
||||||
|
}
|
||||||
|
// tslint:disable-next-line: variable-name
|
||||||
|
_currentTabIndex: number;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
public dialogRef: MatDialogRef<ForwardDialogData, ForwardDialogResult>,
|
public dialogRef: MatDialogRef<ForwardDialogData, ForwardDialogResult>,
|
||||||
|
@ -99,7 +113,8 @@ export class ForwardDialogComponent implements OnInit, OnDestroy {
|
||||||
private store: Store<any>,
|
private store: Store<any>,
|
||||||
private i18nService: I18nService,
|
private i18nService: I18nService,
|
||||||
public dialog: MatDialog,
|
public dialog: MatDialog,
|
||||||
private changeDetectorRef: ChangeDetectorRef
|
private changeDetectorRef: ChangeDetectorRef,
|
||||||
|
private appGroupService: AppGroupService
|
||||||
) {
|
) {
|
||||||
this.maxChatRoomUser = environment.productConfig.chat.maxChatRoomUser;
|
this.maxChatRoomUser = environment.productConfig.chat.maxChatRoomUser;
|
||||||
}
|
}
|
||||||
|
@ -108,10 +123,10 @@ export class ForwardDialogComponent implements OnInit, OnDestroy {
|
||||||
this.store
|
this.store
|
||||||
.pipe(
|
.pipe(
|
||||||
takeUntil(this.ngOnDestroySubject),
|
takeUntil(this.ngOnDestroySubject),
|
||||||
select(ConfigurationSelector.versionInfo2Response)
|
select(ConfigurationSelector.versionInfo)
|
||||||
)
|
)
|
||||||
.subscribe((versionInfo2Res) => {
|
.subscribe((versionInfo) => {
|
||||||
this.versionInfo2Res = versionInfo2Res;
|
this.versionInfo = versionInfo;
|
||||||
});
|
});
|
||||||
|
|
||||||
this.store
|
this.store
|
||||||
|
@ -119,6 +134,7 @@ export class ForwardDialogComponent implements OnInit, OnDestroy {
|
||||||
.subscribe((groups) => {
|
.subscribe((groups) => {
|
||||||
this.groupList = groups;
|
this.groupList = groups;
|
||||||
});
|
});
|
||||||
|
this.currentTabIndex = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnDestroy(): void {
|
ngOnDestroy(): void {
|
||||||
|
@ -147,68 +163,49 @@ export class ForwardDialogComponent implements OnInit, OnDestroy {
|
||||||
|
|
||||||
onSearched(searchedUserInfos: UserInfoSS[]): void {
|
onSearched(searchedUserInfos: UserInfoSS[]): void {
|
||||||
this.searchedList = searchedUserInfos;
|
this.searchedList = searchedUserInfos;
|
||||||
|
|
||||||
|
if (!!this.appProfileList) {
|
||||||
|
this.appProfileList.psUpdate();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onToggleCheckUser(datas: { checked: boolean; userInfo: UserInfoSS }[]) {
|
onToggleCheckUser(datas: { checked: boolean; userInfo: UserInfoSS }[]) {
|
||||||
if (!datas || 0 === datas.length) {
|
const resList = this.appGroupService.getToggleCheckUser(
|
||||||
|
datas,
|
||||||
|
this.selectedUserList
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!resList) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
this.selectedUserList = resList;
|
||||||
const pushs: UserInfoSS[] = [];
|
|
||||||
const pops: UserInfoSS[] = [];
|
|
||||||
|
|
||||||
datas.forEach((d) => {
|
|
||||||
const i = this.selectedUserList.findIndex(
|
|
||||||
(u) => u.seq === d.userInfo.seq
|
|
||||||
);
|
|
||||||
if (d.checked) {
|
|
||||||
if (-1 === i) {
|
|
||||||
pushs.push(d.userInfo);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (-1 < i) {
|
|
||||||
pops.push(d.userInfo);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (0 < pushs.length) {
|
|
||||||
this.selectedUserList = [...this.selectedUserList, ...pushs];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (0 < pops.length) {
|
|
||||||
this.selectedUserList = this.selectedUserList.filter(
|
|
||||||
(u) => -1 === pops.findIndex((p) => p.seq === u.seq)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onToggleCheckGroup(params: {
|
onToggleCheckGroup(params: {
|
||||||
isChecked: boolean;
|
isChecked: boolean;
|
||||||
groupBuddyList: { group: GroupDetailData; buddyList: UserInfo[] };
|
groupBuddyList: { group: GroupInfoDetail; buddyList: UserInfo[] };
|
||||||
}) {
|
}) {
|
||||||
if (params.isChecked) {
|
const resList = this.appGroupService.getToggleCheckGroup(
|
||||||
params.groupBuddyList.buddyList.forEach((item) => {
|
params,
|
||||||
if (
|
this.selectedUserList
|
||||||
this.selectedUserList.filter((user) => user.seq === item.seq)
|
|
||||||
.length === 0
|
|
||||||
) {
|
|
||||||
this.selectedUserList = [...this.selectedUserList, item];
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
this.selectedUserList = this.selectedUserList.filter(
|
|
||||||
(item) =>
|
|
||||||
params.groupBuddyList.buddyList.filter((del) => del.seq === item.seq)
|
|
||||||
.length === 0
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (!resList) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
this.selectedUserList = resList;
|
||||||
}
|
}
|
||||||
|
|
||||||
onCancel() {
|
onCancel() {
|
||||||
this.dialogRef.close({ choice: false });
|
this.dialogRef.close({ choice: false });
|
||||||
}
|
}
|
||||||
onConfirm() {
|
onConfirm() {
|
||||||
|
if (this.currentTabIndex === 0) {
|
||||||
|
this.selectedRoom = undefined;
|
||||||
|
} else {
|
||||||
|
this.selectedUserList = [];
|
||||||
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
!this.selectedRoom &&
|
!this.selectedRoom &&
|
||||||
!!this.selectedUserList &&
|
!!this.selectedUserList &&
|
||||||
|
@ -238,58 +235,8 @@ export class ForwardDialogComponent implements OnInit, OnDestroy {
|
||||||
onToggleRoom(roomInfo: RoomInfo): void {
|
onToggleRoom(roomInfo: RoomInfo): void {
|
||||||
if (!!roomInfo) {
|
if (!!roomInfo) {
|
||||||
this.selectedRoom = roomInfo;
|
this.selectedRoom = roomInfo;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
getCheckedByRoomInfo(roomInfo: RoomInfo): boolean {
|
|
||||||
if (
|
|
||||||
!!this.selectedRoom &&
|
|
||||||
this.selectedRoom.roomId.localeCompare(roomInfo.roomId) === 0
|
|
||||||
) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
onChangeUserList(data: { checked: boolean; userInfo: UserInfoSS }) {
|
|
||||||
const i = this.selectedUserList.findIndex(
|
|
||||||
(u) => String(u.seq) === String(data.userInfo.seq)
|
|
||||||
);
|
|
||||||
|
|
||||||
if (data.checked) {
|
|
||||||
if (-1 === i) {
|
|
||||||
this.selectedUserList = [...this.selectedUserList, data.userInfo];
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if (-1 < i) {
|
this.selectedRoom = undefined;
|
||||||
this.selectedUserList = this.selectedUserList.filter(
|
|
||||||
(u) => String(u.seq) !== String(data.userInfo.seq)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onChangeGroupList(params: {
|
|
||||||
isChecked: boolean;
|
|
||||||
groupBuddyList: { group: GroupDetailData; buddyList: UserInfo[] };
|
|
||||||
}) {
|
|
||||||
if (params.isChecked) {
|
|
||||||
params.groupBuddyList.buddyList.forEach((item) => {
|
|
||||||
if (
|
|
||||||
this.selectedUserList.filter(
|
|
||||||
(user) => String(user.seq) === String(item.seq)
|
|
||||||
).length === 0
|
|
||||||
) {
|
|
||||||
this.selectedUserList = [...this.selectedUserList, item];
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
this.selectedUserList = this.selectedUserList.filter(
|
|
||||||
(item) =>
|
|
||||||
params.groupBuddyList.buddyList.filter(
|
|
||||||
(del) => String(del.seq) === String(item.seq)
|
|
||||||
).length === 0
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -321,31 +268,62 @@ export class ForwardDialogComponent implements OnInit, OnDestroy {
|
||||||
}
|
}
|
||||||
|
|
||||||
onToggleSearchAllItem(value: boolean): void {
|
onToggleSearchAllItem(value: boolean): void {
|
||||||
|
const pushs: UserInfoSS[] = [];
|
||||||
|
const pops: UserInfoSS[] = [];
|
||||||
|
|
||||||
|
this.searchedList.forEach((user) => {
|
||||||
|
const i = this.selectedUserList.findIndex((u) => u.seq === user.seq);
|
||||||
|
|
||||||
|
if (-1 === i) {
|
||||||
|
pushs.push(user);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (-1 < i) {
|
||||||
|
pops.push(user);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
if (!!value) {
|
if (!!value) {
|
||||||
const targetRoomList = this.searchedList;
|
if (0 < pushs.length) {
|
||||||
this.selectedUserList = targetRoomList.slice();
|
this.selectedUserList = [...this.selectedUserList, ...pushs];
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
this.selectedUserList = [];
|
if (0 < pops.length) {
|
||||||
|
this.selectedUserList = this.selectedUserList.filter(
|
||||||
|
(u) => -1 === pops.findIndex((p) => p.seq === u.seq)
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
this.changeDetectorRef.markForCheck();
|
this.changeDetectorRef.markForCheck();
|
||||||
}
|
}
|
||||||
|
|
||||||
onCanceled() {
|
onCanceled() {
|
||||||
this.isSearch = false;
|
this.isSearch = false;
|
||||||
this.searchedList = [];
|
|
||||||
this.companySearchData = { ...this.companySearchData, searchWord: '' };
|
this.companySearchData = { ...this.companySearchData, searchWord: '' };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
checkDisableBtn(): boolean {
|
||||||
|
if (
|
||||||
|
this.currentTabIndex === 0 &&
|
||||||
|
!!this.selectedUserList &&
|
||||||
|
this.selectedUserList.length > 0
|
||||||
|
) {
|
||||||
|
return false;
|
||||||
|
} else if (this.currentTabIndex === 1 && !!this.selectedRoom) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
onRemovedProfileSelection(userInfo: UserInfo) {
|
onRemovedProfileSelection(userInfo: UserInfo) {
|
||||||
const i = this.selectedUserList.findIndex(
|
const resUserList = this.appGroupService.removedProfileSelection(
|
||||||
(u) => String(u.seq) === String(userInfo.seq)
|
userInfo,
|
||||||
|
this.selectedUserList
|
||||||
);
|
);
|
||||||
|
|
||||||
if (-1 < i) {
|
if (!resUserList) {
|
||||||
this.selectedUserList = this.selectedUserList.filter(
|
|
||||||
(u) => String(u.seq) !== String(userInfo.seq)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
this.selectedUserList = resUserList;
|
||||||
}
|
}
|
||||||
removableForSelection = (userInfo: UserInfo) => {
|
removableForSelection = (userInfo: UserInfo) => {
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import { Subject } from 'rxjs';
|
import { Subject } from 'rxjs';
|
||||||
|
import { takeUntil } from 'rxjs/operators';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Component,
|
Component,
|
||||||
|
@ -9,6 +10,8 @@ import {
|
||||||
Inject
|
Inject
|
||||||
} from '@angular/core';
|
} from '@angular/core';
|
||||||
|
|
||||||
|
import { Store, select } from '@ngrx/store';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
MatDialogRef,
|
MatDialogRef,
|
||||||
MAT_DIALOG_DATA,
|
MAT_DIALOG_DATA,
|
||||||
|
@ -16,11 +19,9 @@ import {
|
||||||
MatDialogConfig
|
MatDialogConfig
|
||||||
} from '@angular/material/dialog';
|
} from '@angular/material/dialog';
|
||||||
|
|
||||||
import { I18nService } from '@ucap/ng-i18n';
|
import { RoomInfo } from '@ucap/domain-chat';
|
||||||
|
|
||||||
import { Store, select } from '@ngrx/store';
|
import { I18nService } from '@ucap/ng-i18n';
|
||||||
import { takeUntil } from 'rxjs/operators';
|
|
||||||
import { RoomInfo } from '@ucap/protocol-room';
|
|
||||||
import { RoomSelector } from '@ucap/ng-store-chat';
|
import { RoomSelector } from '@ucap/ng-store-chat';
|
||||||
|
|
||||||
export interface SettingDialogData {
|
export interface SettingDialogData {
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
<div class="profile-image">
|
<div class="profile-image">
|
||||||
<img
|
<img
|
||||||
ucapImage
|
ucapImage
|
||||||
[base]="versionInfo2Res?.profileRoot"
|
[base]="versionInfo?.profileRoot"
|
||||||
[path]="userInfo.profileImageFile"
|
[path]="userInfo.profileImageFile"
|
||||||
[default]="defaultProfileImage"
|
[default]="defaultProfileImage"
|
||||||
/>
|
/>
|
||||||
|
@ -32,7 +32,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="contents">
|
<div class="contents">
|
||||||
<perfect-scrollbar
|
<perfect-scrollbar #perfectScroll
|
||||||
><div
|
><div
|
||||||
[innerHTML]="
|
[innerHTML]="
|
||||||
contents | ucapSafeHtml | ucapLinefeedToHtml | ucapLinky
|
contents | ucapSafeHtml | ucapLinefeedToHtml | ucapLinky
|
||||||
|
|
|
@ -5,7 +5,9 @@ import {
|
||||||
ChangeDetectionStrategy,
|
ChangeDetectionStrategy,
|
||||||
ChangeDetectorRef,
|
ChangeDetectorRef,
|
||||||
Inject,
|
Inject,
|
||||||
ElementRef
|
ElementRef,
|
||||||
|
ViewChild,
|
||||||
|
AfterViewInit
|
||||||
} from '@angular/core';
|
} from '@angular/core';
|
||||||
|
|
||||||
import { Subject, of, combineLatest } from 'rxjs';
|
import { Subject, of, combineLatest } from 'rxjs';
|
||||||
|
@ -18,16 +20,18 @@ import {
|
||||||
MatDialog
|
MatDialog
|
||||||
} from '@angular/material/dialog';
|
} from '@angular/material/dialog';
|
||||||
|
|
||||||
import { DeviceType } from '@ucap/core';
|
import { DeviceType } from '@ucap/domain-common';
|
||||||
import { StatusCode } from '@ucap/api';
|
|
||||||
import { NativeService } from '@ucap/native';
|
|
||||||
import { VersionInfo2Response } from '@ucap/api-public';
|
|
||||||
import { MassTalkDownloadRequest } from '@ucap/api-common';
|
|
||||||
import {
|
import {
|
||||||
UserInfo as RoomUserInfo,
|
UserInfo as RoomUserInfo,
|
||||||
UserInfoShort as RoomUserInfoShort
|
UserInfoShort as RoomUserInfoShort,
|
||||||
} from '@ucap/protocol-room';
|
Info,
|
||||||
import { Info, EventJson } from '@ucap/protocol-event';
|
EventJson
|
||||||
|
} from '@ucap/domain-chat';
|
||||||
|
|
||||||
|
import { StatusCode } from '@ucap/api';
|
||||||
|
import { NativeService } from '@ucap/native';
|
||||||
|
|
||||||
|
import { MassTalkDownloadRequest } from '@ucap/api-common';
|
||||||
|
|
||||||
import { CommonApiService } from '@ucap/ng-api-common';
|
import { CommonApiService } from '@ucap/ng-api-common';
|
||||||
import { LogService } from '@ucap/ng-logger';
|
import { LogService } from '@ucap/ng-logger';
|
||||||
|
@ -36,6 +40,8 @@ import { RoomSelector } from '@ucap/ng-store-chat';
|
||||||
import { ConfigurationSelector } from '@ucap/ng-store-authentication';
|
import { ConfigurationSelector } from '@ucap/ng-store-authentication';
|
||||||
|
|
||||||
import { AppChatService } from '@app/services/app-chat.service';
|
import { AppChatService } from '@app/services/app-chat.service';
|
||||||
|
import { PerfectScrollbarComponent } from 'ngx-perfect-scrollbar';
|
||||||
|
import { VersionInfo } from '@ucap/domain-authentication';
|
||||||
|
|
||||||
export type UserInfoTypes = RoomUserInfo | RoomUserInfoShort;
|
export type UserInfoTypes = RoomUserInfo | RoomUserInfoShort;
|
||||||
|
|
||||||
|
@ -55,13 +61,15 @@ export interface TextDetailDialogResult {}
|
||||||
styleUrls: ['./text-detail.dialog.component.scss'],
|
styleUrls: ['./text-detail.dialog.component.scss'],
|
||||||
changeDetection: ChangeDetectionStrategy.OnPush
|
changeDetection: ChangeDetectionStrategy.OnPush
|
||||||
})
|
})
|
||||||
export class TextDetailDialogComponent implements OnInit, OnDestroy {
|
export class TextDetailDialogComponent
|
||||||
|
implements OnInit, OnDestroy, AfterViewInit {
|
||||||
userInfo: UserInfoTypes;
|
userInfo: UserInfoTypes;
|
||||||
contents: string;
|
contents = '';
|
||||||
|
|
||||||
defaultProfileImage: string;
|
defaultProfileImage: string;
|
||||||
versionInfo2Res: VersionInfo2Response;
|
versionInfo: VersionInfo;
|
||||||
|
|
||||||
|
@ViewChild('perfectScroll') perfectScroll: PerfectScrollbarComponent;
|
||||||
private ngOnDestroySubject: Subject<void> = new Subject();
|
private ngOnDestroySubject: Subject<void> = new Subject();
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
|
@ -85,10 +93,10 @@ export class TextDetailDialogComponent implements OnInit, OnDestroy {
|
||||||
this.store
|
this.store
|
||||||
.pipe(
|
.pipe(
|
||||||
takeUntil(this.ngOnDestroySubject),
|
takeUntil(this.ngOnDestroySubject),
|
||||||
select(ConfigurationSelector.versionInfo2Response)
|
select(ConfigurationSelector.versionInfo)
|
||||||
)
|
)
|
||||||
.subscribe((versionInfo2Res) => {
|
.subscribe((versionInfo) => {
|
||||||
this.versionInfo2Res = versionInfo2Res;
|
this.versionInfo = versionInfo;
|
||||||
});
|
});
|
||||||
|
|
||||||
this.commonApiService
|
this.commonApiService
|
||||||
|
@ -107,6 +115,7 @@ export class TextDetailDialogComponent implements OnInit, OnDestroy {
|
||||||
this.changeDetectorRef.markForCheck();
|
this.changeDetectorRef.markForCheck();
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
|
this.psUpdate();
|
||||||
if (
|
if (
|
||||||
!!this.elementRef.nativeElement &&
|
!!this.elementRef.nativeElement &&
|
||||||
!!this.elementRef.nativeElement.querySelector('a')
|
!!this.elementRef.nativeElement.querySelector('a')
|
||||||
|
@ -154,6 +163,16 @@ export class TextDetailDialogComponent implements OnInit, OnDestroy {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ngAfterViewInit(): void {
|
||||||
|
this.psUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
|
psUpdate() {
|
||||||
|
if (!!this.perfectScroll) {
|
||||||
|
this.perfectScroll.directiveRef.update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
onClickEvent(event: MouseEvent) {
|
onClickEvent(event: MouseEvent) {
|
||||||
this.nativeService.platform_openDefaultBrowser(
|
this.nativeService.platform_openDefaultBrowser(
|
||||||
(event.target as HTMLAnchorElement).text
|
(event.target as HTMLAnchorElement).text
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
<div class="profile-image">
|
<div class="profile-image">
|
||||||
<img
|
<img
|
||||||
ucapImage
|
ucapImage
|
||||||
[base]="versionInfo2Res?.profileRoot"
|
[base]="versionInfo?.profileRoot"
|
||||||
[path]="userInfo.profileImageFile"
|
[path]="userInfo.profileImageFile"
|
||||||
[default]="defaultProfileImage"
|
[default]="defaultProfileImage"
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
import { Subject, of, combineLatest } from 'rxjs';
|
||||||
|
import { takeUntil } from 'rxjs/operators';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Component,
|
Component,
|
||||||
OnInit,
|
OnInit,
|
||||||
|
@ -9,7 +12,7 @@ import {
|
||||||
AfterViewInit
|
AfterViewInit
|
||||||
} from '@angular/core';
|
} from '@angular/core';
|
||||||
|
|
||||||
import { Subject, of, combineLatest } from 'rxjs';
|
import { Store, select } from '@ngrx/store';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
MatDialogRef,
|
MatDialogRef,
|
||||||
|
@ -17,21 +20,21 @@ import {
|
||||||
MatDialog
|
MatDialog
|
||||||
} from '@angular/material/dialog';
|
} from '@angular/material/dialog';
|
||||||
|
|
||||||
import { NativeService } from '@ucap/native';
|
|
||||||
import { VersionInfo2Response } from '@ucap/api-public';
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
UserInfo as RoomUserInfo,
|
UserInfo as RoomUserInfo,
|
||||||
UserInfoShort as RoomUserInfoShort
|
UserInfoShort as RoomUserInfoShort,
|
||||||
} from '@ucap/protocol-room';
|
Info,
|
||||||
|
MassTranslationEventJson
|
||||||
|
} from '@ucap/domain-chat';
|
||||||
|
|
||||||
|
import { NativeService } from '@ucap/native';
|
||||||
|
|
||||||
import { LogService } from '@ucap/ng-logger';
|
import { LogService } from '@ucap/ng-logger';
|
||||||
import { UCAP_NATIVE_SERVICE } from '@ucap/ng-native';
|
import { UCAP_NATIVE_SERVICE } from '@ucap/ng-native';
|
||||||
import { Store, select } from '@ngrx/store';
|
|
||||||
import { takeUntil } from 'rxjs/operators';
|
|
||||||
import { ConfigurationSelector } from '@ucap/ng-store-authentication';
|
import { ConfigurationSelector } from '@ucap/ng-store-authentication';
|
||||||
import { RoomSelector } from '@ucap/ng-store-chat';
|
import { RoomSelector } from '@ucap/ng-store-chat';
|
||||||
import { Info, MassTranslationEventJson } from '@ucap/protocol-event';
|
import { VersionInfo } from '@ucap/domain-authentication';
|
||||||
|
|
||||||
export type UserInfoTypes = RoomUserInfo | RoomUserInfoShort;
|
export type UserInfoTypes = RoomUserInfo | RoomUserInfoShort;
|
||||||
|
|
||||||
|
@ -55,7 +58,7 @@ export class TransDetailDialogComponent
|
||||||
contents: string;
|
contents: string;
|
||||||
|
|
||||||
defaultProfileImage: string;
|
defaultProfileImage: string;
|
||||||
versionInfo2Res: VersionInfo2Response;
|
versionInfo: VersionInfo;
|
||||||
|
|
||||||
private ngOnDestroySubject: Subject<void> = new Subject();
|
private ngOnDestroySubject: Subject<void> = new Subject();
|
||||||
|
|
||||||
|
@ -78,10 +81,10 @@ export class TransDetailDialogComponent
|
||||||
this.store
|
this.store
|
||||||
.pipe(
|
.pipe(
|
||||||
takeUntil(this.ngOnDestroySubject),
|
takeUntil(this.ngOnDestroySubject),
|
||||||
select(ConfigurationSelector.versionInfo2Response)
|
select(ConfigurationSelector.versionInfo)
|
||||||
)
|
)
|
||||||
.subscribe((versionInfo2Res) => {
|
.subscribe((versionInfo) => {
|
||||||
this.versionInfo2Res = versionInfo2Res;
|
this.versionInfo = versionInfo;
|
||||||
});
|
});
|
||||||
combineLatest([
|
combineLatest([
|
||||||
this.store.pipe(select(RoomSelector.roomUser, this.data.roomId)),
|
this.store.pipe(select(RoomSelector.roomUser, this.data.roomId)),
|
||||||
|
|
179
src/app/sections/chat/directives/file-upload-for.directive.ts
Normal file
179
src/app/sections/chat/directives/file-upload-for.directive.ts
Normal file
|
@ -0,0 +1,179 @@
|
||||||
|
import { Subject, fromEvent } from 'rxjs';
|
||||||
|
|
||||||
|
import {
|
||||||
|
Directive,
|
||||||
|
ElementRef,
|
||||||
|
EventEmitter,
|
||||||
|
HostListener,
|
||||||
|
Output,
|
||||||
|
Input,
|
||||||
|
AfterViewInit,
|
||||||
|
NgZone,
|
||||||
|
OnDestroy,
|
||||||
|
OnInit
|
||||||
|
} from '@angular/core';
|
||||||
|
|
||||||
|
import { FileUploadItem } from '@ucap/domain-common';
|
||||||
|
|
||||||
|
import { FileUploadQueueComponent } from '@ucap/ng-ui/file-upload';
|
||||||
|
import { takeUntil } from 'rxjs/operators';
|
||||||
|
|
||||||
|
@Directive({
|
||||||
|
selector: 'input[ucapFileUploadFor01], div[ucapFileUploadFor01]'
|
||||||
|
})
|
||||||
|
export class FileUploadForDirective
|
||||||
|
implements OnInit, OnDestroy, AfterViewInit {
|
||||||
|
@Input()
|
||||||
|
fileUploadQueue?: FileUploadQueueComponent;
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
validator?: (fileList: FileList) => Promise<boolean>;
|
||||||
|
|
||||||
|
@Output()
|
||||||
|
public fileDragEnter = new EventEmitter<DataTransferItemList>();
|
||||||
|
|
||||||
|
@Output()
|
||||||
|
public fileDragOver = new EventEmitter<void>();
|
||||||
|
|
||||||
|
@Output()
|
||||||
|
public fileDragLeave = new EventEmitter<void>();
|
||||||
|
|
||||||
|
@Output()
|
||||||
|
public fileSelected = new EventEmitter<FileUploadItem[] | FileList>();
|
||||||
|
|
||||||
|
dragOver = false;
|
||||||
|
|
||||||
|
private ngOnDestroySubject: Subject<void> = new Subject();
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private elementRef: ElementRef,
|
||||||
|
private readonly ngZone: NgZone
|
||||||
|
) {}
|
||||||
|
|
||||||
|
ngOnInit(): void {
|
||||||
|
fromEvent(window, 'dragenter')
|
||||||
|
.pipe(takeUntil(this.ngOnDestroySubject))
|
||||||
|
.subscribe((event: DragEvent) => {
|
||||||
|
if (!this.isFileDrag(event.dataTransfer)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.dragOver) {
|
||||||
|
this.fileDragEnter.emit(event.dataTransfer.items);
|
||||||
|
this.dragOver = true;
|
||||||
|
if (!!this.fileUploadQueue) {
|
||||||
|
this.fileUploadQueue.onDragEnter(event.dataTransfer.items);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
fromEvent(window, 'dragover')
|
||||||
|
.pipe(takeUntil(this.ngOnDestroySubject))
|
||||||
|
.subscribe((event: DragEvent) => {
|
||||||
|
if (!this.isFileDrag(event.dataTransfer)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// if (this.fileUploadQueue.isEventInElement(event)) {
|
||||||
|
// event.dataTransfer.dropEffect = 'copy';
|
||||||
|
// } else {
|
||||||
|
// event.dataTransfer.dropEffect = 'none';
|
||||||
|
// }
|
||||||
|
event.preventDefault();
|
||||||
|
});
|
||||||
|
|
||||||
|
fromEvent(window, 'dragleave')
|
||||||
|
.pipe(takeUntil(this.ngOnDestroySubject))
|
||||||
|
.subscribe((event: DragEvent) => {
|
||||||
|
if (!this.isFileDrag(event.dataTransfer)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event && event.pageX === 0 && event.pageY === 0) {
|
||||||
|
this.fileDragLeave.emit();
|
||||||
|
this.dragOver = false;
|
||||||
|
if (!!this.fileUploadQueue) {
|
||||||
|
this.fileUploadQueue.onDragLeave();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
fromEvent(window, 'drop')
|
||||||
|
.pipe(takeUntil(this.ngOnDestroySubject))
|
||||||
|
.subscribe((event: any) => {
|
||||||
|
if (!this.isFileDrag(event.dataTransfer)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const self = this;
|
||||||
|
const files: FileList = event.dataTransfer.files;
|
||||||
|
|
||||||
|
event.preventDefault();
|
||||||
|
event.stopPropagation();
|
||||||
|
this.elementRef.nativeElement.value = ''; // Case defined directive in 'input' type.
|
||||||
|
this.dragOver = false;
|
||||||
|
|
||||||
|
if (!!this.validator) {
|
||||||
|
this.validator(files)
|
||||||
|
.then(async (result) => {
|
||||||
|
if (!result) {
|
||||||
|
if (!!this.fileUploadQueue) {
|
||||||
|
this.fileUploadQueue.onUploadComplete();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
const fileUploadItems = FileUploadItem.fromFiles(files);
|
||||||
|
self.fileSelected.emit(fileUploadItems);
|
||||||
|
|
||||||
|
if (!!self.fileUploadQueue) {
|
||||||
|
self.fileUploadQueue.onDrop(fileUploadItems);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
if (!!this.fileUploadQueue) {
|
||||||
|
this.fileUploadQueue.onUploadComplete();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
const fileUploadItems = FileUploadItem.fromFiles(files);
|
||||||
|
this.fileSelected.emit(files);
|
||||||
|
|
||||||
|
if (!!this.fileUploadQueue) {
|
||||||
|
this.fileUploadQueue.onDrop(fileUploadItems);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnDestroy(): void {
|
||||||
|
if (!!this.ngOnDestroySubject) {
|
||||||
|
this.ngOnDestroySubject.next();
|
||||||
|
this.ngOnDestroySubject.complete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ngAfterViewInit(): void {}
|
||||||
|
|
||||||
|
// @HostListener('change')
|
||||||
|
// public onChange(): any {
|
||||||
|
// const files = this.elementRef.nativeElement.files;
|
||||||
|
// this.fileSelected.emit(FileUploadItem.fromFiles(files));
|
||||||
|
// this.elementRef.nativeElement.value = '';
|
||||||
|
// }
|
||||||
|
|
||||||
|
private isFileDrag(dataTransfer: DataTransfer): boolean {
|
||||||
|
if (0 >= dataTransfer.items.length) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// tslint:disable-next-line: prefer-for-of
|
||||||
|
for (let i = 0; i < dataTransfer.items.length; i++) {
|
||||||
|
const element = dataTransfer.items[i];
|
||||||
|
if ('file' !== element.kind) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user