| @@ -6,15 +6,17 @@ import { DashboardComponent } from './dashboard/dashboard.component'; | |||
| import { AuthGuard } from './service/auth-guard.service'; | |||
| import { TransactionListComponent } from './transaction-list/transaction-list.component'; | |||
| import { TransactionComponent } from './transaction/transaction.component'; | |||
| import {ListAllLoansComponent} from './list-all-loans/list-all-loans.component'; | |||
| const routes: Routes = [ | |||
| {path : '', component: DashboardComponent, canActivate: [AuthGuard]}, | |||
| {path : 'canvas', component: CanvasComponent}, | |||
| {path : 'dashboard', component: DashboardComponent, canActivate: [AuthGuard],}, | |||
| {path : 'dashboard', component: DashboardComponent, canActivate: [AuthGuard] }, | |||
| {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({ | |||
| @@ -22,5 +24,5 @@ const routes: Routes = [ | |||
| exports: [RouterModule] | |||
| }) | |||
| export class AppRoutingModule { | |||
| } | |||
| } | |||
| @@ -1,28 +1,4 @@ | |||
| <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> | |||
| @@ -2,10 +2,9 @@ import { Component, OnDestroy, OnInit, ViewChild, ViewEncapsulation } from '@ang | |||
| import { Subscription } from 'rxjs'; | |||
| import { LoanEditComponent } from './loan-edit/loan-edit.component'; | |||
| import { mainMenuItems } from './main-menu-items'; | |||
| import { AuthService } from './service/auth.service'; | |||
| import { MenuService } from './service/menu.service'; | |||
| import {apiV1LoginResponse} from './models/api-v1-login-response'; | |||
| import {WebSocketService} from './websocket'; | |||
| @Component({ | |||
| @@ -16,64 +15,40 @@ import {WebSocketService} from './websocket'; | |||
| }) | |||
| export class AppComponent implements OnInit , OnDestroy { | |||
| title = 'SFM broker'; | |||
| public login = false; | |||
| public items: any[] = mainMenuItems; | |||
| kendokaAvatar = './assets/img/avatar.png'; | |||
| private menutItemSub: Subscription; | |||
| @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) | |||
| .subscribe(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 | |||
| 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(); | |||
| 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 | |||
| ngOnDestroy() { | |||
| this.loginSub.unsubscribe(); | |||
| } | |||
| } | |||
| @@ -51,6 +51,7 @@ import { ChartPastYearMonthlyPerformanceComponent } from './chart-past-year-mont | |||
| import { ChartRecentTenLoansComponent } from './chart-recent-ten-loans/chart-recent-ten-loans.component'; | |||
| import { ChartTopBrokersComponent } from './chart-top-brokers/chart-top-brokers.component'; | |||
| import { ListAllLoansComponent } from './list-all-loans/list-all-loans.component'; | |||
| import { TopBarComponent } from './top-bar/top-bar.component'; | |||
| @@ -74,7 +75,8 @@ import { ListAllLoansComponent } from './list-all-loans/list-all-loans.component | |||
| ChartPastYearMonthlyPerformanceComponent, | |||
| ChartRecentTenLoansComponent, | |||
| ChartTopBrokersComponent, | |||
| ListAllLoansComponent | |||
| ListAllLoansComponent, | |||
| TopBarComponent | |||
| ], | |||
| imports: [ | |||
| BrowserModule, | |||
| @@ -10,25 +10,26 @@ export const mainMenuItems: any[] = [ | |||
| text: 'SFM', | |||
| icon: 'more-vertical', | |||
| 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: 'Loans', | |||
| icon: 'dollar', | |||
| 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', | |||
| icon: 'percent', | |||
| items: [ | |||
| { text: 'List All', icon: 'table', url: '#' }, | |||
| { text: '--', separator: "true" }, | |||
| { text: 'List All', icon: 'table', url: '#' }, | |||
| { text: '--', separator: "true" }, | |||
| { text: 'Import From ...', icon : 'upload'} | |||
| ] | |||
| }, | |||
| @@ -36,11 +37,11 @@ export const mainMenuItems: any[] = [ | |||
| text: 'Clients', | |||
| icon: 'user', | |||
| 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: '--', separator: "true" }, | |||
| { text: '--', separator: "true" }, | |||
| { text: 'Broadcast', icon:'email' }, | |||
| ] | |||
| }, | |||
| @@ -49,14 +50,14 @@ export const mainMenuItems: any[] = [ | |||
| text: 'Brokers', | |||
| fa: faUserCircle, | |||
| 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: '--', separator: "true" }, | |||
| { text: '--', separator: "true" }, | |||
| { text: 'Broadcast' , icon : 'email'}, | |||
| { text: '--', separator: "true" }, | |||
| { text: '--', separator: "true" }, | |||
| { text: 'UnPaid', fa : faMoneyCheck }, | |||
| ] | |||
| } | |||
| ]; | |||
| ]; | |||
| @@ -32,6 +32,8 @@ export class AuthService { | |||
| sfm.session, | |||
| sfm.sessionExpire | |||
| ); | |||
| this.loginSuccess.emit(this.loggedIn); | |||
| console.log ( 'auto login emit events', this.loggedIn); | |||
| } | |||
| // tslint:disable-next-line:typedef | |||
| @@ -5,5 +5,5 @@ import { EventEmitter, Injectable } from '@angular/core'; | |||
| export class MenuService { | |||
| itemClicked = new EventEmitter <any>(); | |||
| } | |||
| } | |||
| @@ -0,0 +1,25 @@ | |||
| <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> | |||
| @@ -0,0 +1,25 @@ | |||
| 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(); | |||
| }); | |||
| }); | |||
| @@ -0,0 +1,60 @@ | |||
| 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(); | |||
| } | |||
| } | |||