| import { AuthGuard } from './service/auth-guard.service'; | import { AuthGuard } from './service/auth-guard.service'; | ||||
| import { TransactionListComponent } from './transaction-list/transaction-list.component'; | import { TransactionListComponent } from './transaction-list/transaction-list.component'; | ||||
| import { TransactionComponent } from './transaction/transaction.component'; | import { TransactionComponent } from './transaction/transaction.component'; | ||||
| import {ListAllLoansComponent} from './list-all-loans/list-all-loans.component'; | |||||
| const routes: Routes = [ | const routes: Routes = [ | ||||
| {path : '', component: DashboardComponent, canActivate: [AuthGuard]}, | {path : '', component: DashboardComponent, canActivate: [AuthGuard]}, | ||||
| {path : 'canvas', component: CanvasComponent}, | {path : 'canvas', component: CanvasComponent}, | ||||
| {path : 'dashboard', component: DashboardComponent, canActivate: [AuthGuard],}, | |||||
| {path : 'dashboard', component: DashboardComponent, canActivate: [AuthGuard] }, | |||||
| {path : 'login', component: AuthComponent}, | {path : 'login', component: AuthComponent}, | ||||
| {path : 'transaction', component: TransactionComponent, canActivate: [AuthGuard],}, | |||||
| {path : 'transaction-list', component: TransactionListComponent, }, | |||||
| {path : 'transaction', component: TransactionComponent, canActivate: [AuthGuard]}, | |||||
| {path : 'transaction-list', component: TransactionListComponent, canActivate: [AuthGuard]}, | |||||
| {path : 'list-all-loans', component: ListAllLoansComponent, }, | |||||
| ]; | ]; | ||||
| @NgModule({ | @NgModule({ | ||||
| exports: [RouterModule] | exports: [RouterModule] | ||||
| }) | }) | ||||
| export class AppRoutingModule { | export class AppRoutingModule { | ||||
| } | |||||
| } |
| <kendo-appbar id='topBar' *ngIf='login' class='appbar' [position]="'top'" [positionMode]="'sticky'"> | |||||
| <kendo-appbar-section> | |||||
| <kendo-menu [items]="items" (select)="onSelect($event)"> | |||||
| <ng-template kendoMenuItemTemplate let-item="item"> | |||||
| <span class='main-menu-item'> | |||||
| <fa-icon *ngIf="menuItemHasFontawesome(item)" [icon]="item.fa"></fa-icon> | |||||
| {{ item.text }} </span> | |||||
| </ng-template> | |||||
| </kendo-menu> | |||||
| </kendo-appbar-section> | |||||
| <kendo-appbar-spacer></kendo-appbar-spacer> | |||||
| <kendo-appbar-section class="actions"> | |||||
| <kendo-badge-container> | |||||
| <button class="k-button k-button-clear"> | |||||
| <kendo-icon [name]="'bell'"></kendo-icon> | |||||
| </button> | |||||
| <kendo-badge [shape]="'dot'" [themeColor]="'warning'" [size]="'small'" [position]="'inside'"></kendo-badge> | |||||
| </kendo-badge-container> | |||||
| <span class="k-appbar-separator"></span> | |||||
| </kendo-appbar-section> | |||||
| <kendo-appbar-section> | |||||
| <kendo-avatar [imageSrc]="kendokaAvatar" [shape]="'circle'" [width]="'26px'" [height]="'26px'"></kendo-avatar> | |||||
| </kendo-appbar-section> | |||||
| </kendo-appbar> | |||||
| <app-top-bar></app-top-bar> | |||||
| <app-loan-edit #loanEditComponent></app-loan-edit> | <app-loan-edit #loanEditComponent></app-loan-edit> | ||||
| import { Subscription } from 'rxjs'; | import { Subscription } from 'rxjs'; | ||||
| import { LoanEditComponent } from './loan-edit/loan-edit.component'; | import { LoanEditComponent } from './loan-edit/loan-edit.component'; | ||||
| import { mainMenuItems } from './main-menu-items'; | |||||
| import { AuthService } from './service/auth.service'; | import { AuthService } from './service/auth.service'; | ||||
| import { MenuService } from './service/menu.service'; | import { MenuService } from './service/menu.service'; | ||||
| import {apiV1LoginResponse} from './models/api-v1-login-response'; | |||||
| import {WebSocketService} from './websocket'; | import {WebSocketService} from './websocket'; | ||||
| @Component({ | @Component({ | ||||
| }) | }) | ||||
| export class AppComponent implements OnInit , OnDestroy { | export class AppComponent implements OnInit , OnDestroy { | ||||
| title = 'SFM broker'; | title = 'SFM broker'; | ||||
| public login = false; | |||||
| public items: any[] = mainMenuItems; | |||||
| kendokaAvatar = './assets/img/avatar.png'; | |||||
| private menutItemSub: Subscription; | |||||
| @ViewChild('loanEditComponent', {static: true}) loanEdit: LoanEditComponent; | @ViewChild('loanEditComponent', {static: true}) loanEdit: LoanEditComponent; | ||||
| private loginSub: Subscription; | |||||
| constructor(private menuService: MenuService, private authService: AuthService, private wsService: WebSocketService){ | |||||
| constructor(private menuService: MenuService, private authService: AuthService, private wsService: WebSocketService){ | |||||
| wsService.createObservableSocket(this.authService.apiWsUrl) | wsService.createObservableSocket(this.authService.apiWsUrl) | ||||
| .subscribe(m => { | .subscribe(m => { | ||||
| console.log('websocket server send this :', m); | console.log('websocket server send this :', m); | ||||
| }); | }); | ||||
| } | |||||
| // check menuItem has fontawesome | |||||
| public menuItemHasFontawesome (item: any) : boolean { | |||||
| return item.hasOwnProperty('fa'); | |||||
| } | |||||
| // menuItem clicked | |||||
| public onSelect({ item }): void { | |||||
| if (!item.items) { | |||||
| this.menuService.itemClicked.emit(item); | |||||
| // console.log("emit on select : " + item.text); | |||||
| if ( item.popup == "loanEdit"){ | |||||
| this.loanEdit.somedata = "" + Math.random() + "changed"; | |||||
| this.loanEdit.open('dialog'); | |||||
| } | |||||
| if (item.text === 'Logout'){ | |||||
| this.authService.logout(); | |||||
| this.login = false; | |||||
| // this.authService.loginSuccess.emit("loggedout"); | |||||
| } | |||||
| } | |||||
| } | } | ||||
| // tslint:disable-next-line:typedef | // tslint:disable-next-line:typedef | ||||
| ngOnInit() { | ngOnInit() { | ||||
| this.loginSub = this.authService.loginSuccess.subscribe( | |||||
| (rsp: apiV1LoginResponse) => { | |||||
| this.login = rsp.login; | |||||
| } | |||||
| ); | |||||
| this.listenToMenuEvent(); | |||||
| // must be the last, as it may emit events | |||||
| this.authService.AutoLogin(); | this.authService.AutoLogin(); | ||||
| setTimeout(() => { | |||||
| const specialCommand = 'send dummy string for 500 times'; | |||||
| this.wsService.sendMessage(specialCommand + " cancelled"); | |||||
| } | |||||
| listenToMenuEvent(): void { | |||||
| this.menutItemSub = this.menuService.itemClicked.subscribe( | |||||
| (item:any) =>{ | |||||
| // console.log("emit on select : " + item.text); | |||||
| if ( item.popup === 'loanEdit'){ | |||||
| this.loanEdit.somedata = '' + Math.random() + 'changed'; | |||||
| this.loanEdit.open('dialog'); | |||||
| } | |||||
| } | |||||
| ); | |||||
| }, 2000); | |||||
| } | } | ||||
| // tslint:disable-next-line:typedef | // tslint:disable-next-line:typedef | ||||
| ngOnDestroy() { | ngOnDestroy() { | ||||
| this.loginSub.unsubscribe(); | |||||
| } | } | ||||
| } | } |
| import { ChartRecentTenLoansComponent } from './chart-recent-ten-loans/chart-recent-ten-loans.component'; | import { ChartRecentTenLoansComponent } from './chart-recent-ten-loans/chart-recent-ten-loans.component'; | ||||
| import { ChartTopBrokersComponent } from './chart-top-brokers/chart-top-brokers.component'; | import { ChartTopBrokersComponent } from './chart-top-brokers/chart-top-brokers.component'; | ||||
| import { ListAllLoansComponent } from './list-all-loans/list-all-loans.component'; | import { ListAllLoansComponent } from './list-all-loans/list-all-loans.component'; | ||||
| import { TopBarComponent } from './top-bar/top-bar.component'; | |||||
| ChartPastYearMonthlyPerformanceComponent, | ChartPastYearMonthlyPerformanceComponent, | ||||
| ChartRecentTenLoansComponent, | ChartRecentTenLoansComponent, | ||||
| ChartTopBrokersComponent, | ChartTopBrokersComponent, | ||||
| ListAllLoansComponent | |||||
| ListAllLoansComponent, | |||||
| TopBarComponent | |||||
| ], | ], | ||||
| imports: [ | imports: [ | ||||
| BrowserModule, | BrowserModule, |
| text: 'SFM', | text: 'SFM', | ||||
| icon: 'more-vertical', | icon: 'more-vertical', | ||||
| items: [ | items: [ | ||||
| { text: 'Summary', fa: faChartArea, url: './#dashboard'}, | |||||
| { text: '--', separator: "true" }, | |||||
| { text: 'Summary', fa: faChartArea, url: './#dashboard'}, | |||||
| { text: '--', separator: "true" }, | |||||
| { text: 'Logout', icon: 'logout', url: './#login'}] | { text: 'Logout', icon: 'logout', url: './#login'}] | ||||
| }, | }, | ||||
| { | { | ||||
| text: 'Loans', | text: 'Loans', | ||||
| icon: 'dollar', | icon: 'dollar', | ||||
| items: [ | items: [ | ||||
| { text: 'Add+', icon: 'plus', popup: "loanEdit" }, | |||||
| { text: 'Edit', icon: 'plus', url: "./#transaction" }, | |||||
| { text: 'List All', icon: 'table' ,url: './#transaction-list' }, | |||||
| { text: 'Add+', icon: 'plus', popup: "loanEdit" }, | |||||
| { text: 'Edit', icon: 'plus', url: "./#transaction" }, | |||||
| { text: 'List All old', icon: 'table' ,url: './#transaction-list' }, | |||||
| { text: 'List All New', icon: 'table' ,url: './#list-all-loans' }, | |||||
| ] | ] | ||||
| }, | }, | ||||
| { | { | ||||
| text: 'Trails', | text: 'Trails', | ||||
| icon: 'percent', | icon: 'percent', | ||||
| items: [ | items: [ | ||||
| { text: 'List All', icon: 'table', url: '#' }, | |||||
| { text: '--', separator: "true" }, | |||||
| { text: 'List All', icon: 'table', url: '#' }, | |||||
| { text: '--', separator: "true" }, | |||||
| { text: 'Import From ...', icon : 'upload'} | { text: 'Import From ...', icon : 'upload'} | ||||
| ] | ] | ||||
| }, | }, | ||||
| text: 'Clients', | text: 'Clients', | ||||
| icon: 'user', | icon: 'user', | ||||
| items: [ | items: [ | ||||
| { text: 'Add ', icon: 'plus', url: '#' }, | |||||
| { text: 'List All', fa: faIdCard }, | |||||
| { text: '--', separator: "true" }, | |||||
| { text: 'Add ', icon: 'plus', url: '#' }, | |||||
| { text: 'List All', fa: faIdCard }, | |||||
| { text: '--', separator: "true" }, | |||||
| { text: 'Search' ,icon: 'search'}, | { text: 'Search' ,icon: 'search'}, | ||||
| { text: '--', separator: "true" }, | |||||
| { text: '--', separator: "true" }, | |||||
| { text: 'Broadcast', icon:'email' }, | { text: 'Broadcast', icon:'email' }, | ||||
| ] | ] | ||||
| }, | }, | ||||
| text: 'Brokers', | text: 'Brokers', | ||||
| fa: faUserCircle, | fa: faUserCircle, | ||||
| items: [ | items: [ | ||||
| { text: 'Add ', icon: 'plus', url: '#' }, | |||||
| { text: 'List All', fa: faIdCardAlt}, | |||||
| { text: '--', separator: "true" }, | |||||
| { text: 'Add ', icon: 'plus', url: '#' }, | |||||
| { text: 'List All', fa: faIdCardAlt}, | |||||
| { text: '--', separator: "true" }, | |||||
| { text: 'Search' , icon: 'search'}, | { text: 'Search' , icon: 'search'}, | ||||
| { text: '--', separator: "true" }, | |||||
| { text: '--', separator: "true" }, | |||||
| { text: 'Broadcast' , icon : 'email'}, | { text: 'Broadcast' , icon : 'email'}, | ||||
| { text: '--', separator: "true" }, | |||||
| { text: '--', separator: "true" }, | |||||
| { text: 'UnPaid', fa : faMoneyCheck }, | { text: 'UnPaid', fa : faMoneyCheck }, | ||||
| ] | ] | ||||
| } | } | ||||
| ]; | |||||
| ]; |
| sfm.session, | sfm.session, | ||||
| sfm.sessionExpire | sfm.sessionExpire | ||||
| ); | ); | ||||
| this.loginSuccess.emit(this.loggedIn); | |||||
| console.log ( 'auto login emit events', this.loggedIn); | |||||
| } | } | ||||
| // tslint:disable-next-line:typedef | // tslint:disable-next-line:typedef |
| export class MenuService { | export class MenuService { | ||||
| itemClicked = new EventEmitter <any>(); | itemClicked = new EventEmitter <any>(); | ||||
| } | |||||
| } |
| <kendo-appbar id='topBar' *ngIf='login' class='appbar' [position]="'top'" [positionMode]="'sticky'"> | |||||
| <kendo-appbar-section> | |||||
| <kendo-menu [items]="items" (select)="onSelect($event)"> | |||||
| <ng-template kendoMenuItemTemplate let-item="item"> | |||||
| <span class='main-menu-item'> | |||||
| <fa-icon *ngIf="menuItemHasFontawesome(item)" [icon]="item.fa"></fa-icon> | |||||
| {{ item.text }} </span> | |||||
| </ng-template> | |||||
| </kendo-menu> | |||||
| </kendo-appbar-section> | |||||
| <kendo-appbar-spacer></kendo-appbar-spacer> | |||||
| <kendo-appbar-section class="actions"> | |||||
| <kendo-badge-container> | |||||
| <button class="k-button k-button-clear"> | |||||
| <kendo-icon [name]="'bell'"></kendo-icon> | |||||
| </button> | |||||
| <kendo-badge [shape]="'dot'" [themeColor]="'warning'" [size]="'small'" [position]="'inside'"></kendo-badge> | |||||
| </kendo-badge-container> | |||||
| <span class="k-appbar-separator"></span> | |||||
| </kendo-appbar-section> | |||||
| <kendo-appbar-section> | |||||
| <kendo-avatar [imageSrc]="Avatar" [shape]="'circle'" [width]="'26px'" [height]="'26px'"></kendo-avatar> | |||||
| </kendo-appbar-section> | |||||
| </kendo-appbar> |
| import { ComponentFixture, TestBed } from '@angular/core/testing'; | |||||
| import { TopBarComponent } from './top-bar.component'; | |||||
| describe('TopBarComponent', () => { | |||||
| let component: TopBarComponent; | |||||
| let fixture: ComponentFixture<TopBarComponent>; | |||||
| beforeEach(async () => { | |||||
| await TestBed.configureTestingModule({ | |||||
| declarations: [ TopBarComponent ] | |||||
| }) | |||||
| .compileComponents(); | |||||
| }); | |||||
| beforeEach(() => { | |||||
| fixture = TestBed.createComponent(TopBarComponent); | |||||
| component = fixture.componentInstance; | |||||
| fixture.detectChanges(); | |||||
| }); | |||||
| it('should create', () => { | |||||
| expect(component).toBeTruthy(); | |||||
| }); | |||||
| }); |
| import {Component, OnDestroy, OnInit} from '@angular/core'; | |||||
| import {MenuService} from '../service/menu.service'; | |||||
| import {AuthService} from '../service/auth.service'; | |||||
| import {mainMenuItems} from '../main-menu-items'; | |||||
| import {apiV1LoginResponse} from '../models/api-v1-login-response'; | |||||
| import {Subscription} from 'rxjs'; | |||||
| @Component({ | |||||
| selector: 'app-top-bar', | |||||
| templateUrl: './top-bar.component.html', | |||||
| styleUrls: ['./top-bar.component.scss'] | |||||
| }) | |||||
| export class TopBarComponent implements OnInit , OnDestroy { | |||||
| login = false; | |||||
| Avatar = './assets/img/avatar.png'; | |||||
| public items: any[] = mainMenuItems; | |||||
| private loginSub: Subscription; | |||||
| constructor(private menuService: MenuService, private authService: AuthService,) { } | |||||
| ngOnInit(): void { | |||||
| this.initAndSubLogin(); | |||||
| } | |||||
| public initAndSubLogin(): void{ | |||||
| this.login = this.authService.loggedIn.login; | |||||
| console.log('subscribe auto login'); | |||||
| this.loginSub = this.authService.loginSuccess.subscribe( | |||||
| (rsp: apiV1LoginResponse) => { | |||||
| this.login = rsp.login; | |||||
| console.log ('topbar received auth events', rsp); | |||||
| } | |||||
| ); | |||||
| } | |||||
| // check menuItem has fontawesome | |||||
| public menuItemHasFontawesome(item: any): boolean { | |||||
| return item.hasOwnProperty('fa'); | |||||
| } | |||||
| // menuItem clicked | |||||
| public onSelect({ item }): void { | |||||
| if (!item.items) { | |||||
| this.menuService.itemClicked.emit(item); | |||||
| // handle logout | |||||
| if (item.text === 'Logout'){ | |||||
| this.authService.logout(); | |||||
| this.login = false; | |||||
| // this.authService.loginSuccess.emit("loggedout"); | |||||
| } | |||||
| } | |||||
| } | |||||
| // tslint:disable-next-line:typedef | |||||
| ngOnDestroy() { | |||||
| this.loginSub.unsubscribe(); | |||||
| } | |||||
| } |