| 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'; | import { TopBarComponent } from './top-bar/top-bar.component'; | ||||
| import {LoanSummaryService} from './service/loan_summary.service'; | |||||
| AuthGuard, | AuthGuard, | ||||
| AuthService, | AuthService, | ||||
| WebSocketService, | WebSocketService, | ||||
| LoanSummaryService, | |||||
| { | { | ||||
| provide: HTTP_INTERCEPTORS, | provide: HTTP_INTERCEPTORS, | ||||
| useClass: AuthHttpInterceptor, | useClass: AuthHttpInterceptor, |
| <p>list-all-loans works!</p> | |||||
| <kendo-grid | |||||
| [data]="view | async" | |||||
| [loading]="view.loading" | |||||
| [pageSize]="pageSize" | |||||
| [skip]="skip" | |||||
| [sortable]="true" | |||||
| [sort]="sort" | |||||
| [pageable]="true" | |||||
| [height]="1000" | |||||
| [navigable]="true" | |||||
| (dataStateChange)="dataStateChange($event)" | |||||
| class="fullheight_grid" | |||||
| > | |||||
| <kendo-grid-column field="Id" width="50" [class]="'topAlign'" [sortable]="false"> | |||||
| <ng-template kendoGridCellTemplate let-dataItem let-rowIndex="rowIndex+1" > | |||||
| <p title="{{dataItem.Id}}" > {{dataItem.Index}}</p> | |||||
| </ng-template> | |||||
| </kendo-grid-column> | |||||
| <kendo-grid-column-group title="People" [columnMenu]="false" [headerClass]="'colGroupPeople'"> | |||||
| <kendo-grid-column field="Client" width="220" title="Client(s)" [class]="'topAlign'" [headerClass]="'colClient'"> | |||||
| <ng-template kendoGridCellTemplate let-dataItem> | |||||
| <div *ngFor="let p of dataItem.Client, let idx=index "> | |||||
| <div class="customer-photo" [ngStyle]="{'background-image' : photoURL(dataItem.ClientIds[idx])}"></div> | |||||
| <div class="customer-name"> {{ p }}</div> | |||||
| </div> | |||||
| </ng-template> | |||||
| </kendo-grid-column> | |||||
| <kendo-grid-column field="Broker" width="220" title="Broker (s)" [class]="'topAlign'" [headerClass]="'colBroker'"> | |||||
| <ng-template kendoGridCellTemplate let-dataItem> | |||||
| <div *ngFor="let p of dataItem.Broker, let idx=index "> | |||||
| <div class="customer-photo" [ngStyle]="{'background-image' : photoURL(dataItem.BrokerIds[idx])}"></div> | |||||
| <div class="customer-name"> {{ p }}</div> | |||||
| </div> | |||||
| </ng-template> | |||||
| </kendo-grid-column> | |||||
| <kendo-grid-column field="OtherRewarder" width="220" title="Beneficiary(ies)" [class]="'topAlign'" [headerClass]="'colOtherRewarder'"> | |||||
| <ng-template kendoGridCellTemplate let-dataItem> | |||||
| <div *ngFor="let p of dataItem.OtherRewarder, let idx=index "> | |||||
| <div class="customer-photo" [ngStyle]="{'background-image' : photoURL(dataItem.OtherRewarderIds[idx])}"></div> | |||||
| <div class="customer-name"> {{ p }}</div> | |||||
| </div> | |||||
| </ng-template> | |||||
| </kendo-grid-column> | |||||
| </kendo-grid-column-group> | |||||
| <kendo-grid-column-group title="Loan Details" [columnMenu]="false" [headerClass]="'colGroupLoanDetails'"> | |||||
| <kendo-grid-column field="Rating" title="Rating" width="110" [resizable]="false" filter="numeric" [headerClass]="'colRating'" [class]="'topAlign colRating'"> | |||||
| <ng-template kendoGridCellTemplate let-dataItem> | |||||
| <kendo-rating | |||||
| [value]="dataItem.Rating" | |||||
| [max]="5" | |||||
| ></kendo-rating> | |||||
| </ng-template> | |||||
| </kendo-grid-column> | |||||
| <kendo-grid-column field="Item" [sortable]="true" [class]="'topAlign'" width="300"> | |||||
| </kendo-grid-column> | |||||
| <kendo-grid-column field="status" title="Status" [width]="180" [headerClass]="'colStatus'" [class]="'alignStatus colStatus'" [resizable]="false" filter="boolean" > | |||||
| <ng-template kendoGridCellTemplate let-dataItem> | |||||
| <span *ngIf="dataItem.Status != 'none'" class="badge badge-success">{{dataItem.Status}}</span> | |||||
| </ng-template> | |||||
| </kendo-grid-column> | |||||
| <kendo-grid-column field="Settlement" title="Settlement" [class]="'topAlign'" width="120"> | |||||
| </kendo-grid-column> | |||||
| </kendo-grid-column-group> | |||||
| <kendo-grid-column-group title="Lender Details" [columnMenu]="false" [headerClass]="'colGroupLenderDetails'"> | |||||
| <kendo-grid-column field="Amount" title="Amount($) " [sortable]="true" width="130" [headerClass]="'colAmount'" [class]="'topAlign colAmount'"> | |||||
| <ng-template kendoGridCellTemplate let-dataItem> | |||||
| <span [ngClass]="{'green text-bold': dataItem.Amount < 500000}">{{ dataItem.Amount | currency }}</span> | |||||
| </ng-template> | |||||
| </kendo-grid-column> | |||||
| <kendo-grid-column field="Balance" title="Balance($)" width="130" [class]="'topAlign'"> | |||||
| <ng-template kendoGridCellTemplate let-dataItem> | |||||
| <span *ngIf="dataItem.Balance > 0" [ngClass]="{'green text-bold': dataItem.Balance < 500000}">{{ dataItem.Balance | currency }}</span> | |||||
| </ng-template> | |||||
| </kendo-grid-column> | |||||
| <kendo-grid-column field="OffsetBalance" title="Offset Balance($)" width="140" [class]="'topAlign'"> | |||||
| <ng-template kendoGridCellTemplate let-dataItem> | |||||
| <span *ngIf="dataItem.OffsetBalance > 0" [ngClass]="{'red text-bold': dataItem.Percentage > 60}"> | |||||
| {{ dataItem.OffsetBalance | currency }} | |||||
| </span> | |||||
| </ng-template> | |||||
| </kendo-grid-column> | |||||
| <kendo-grid-column field="Trail" title="Income Trail($) " [sortable]="true" width="130" [headerClass]="'colTrail'" [class]="'topAlign colTrail'"> | |||||
| <ng-template kendoGridCellTemplate let-dataItem> | |||||
| <span *ngIf="dataItem.Trail > 0" [ngClass]="{'green text-bold': dataItem.Trail < 500000}">{{ dataItem.Trail | currency }}</span> | |||||
| </ng-template> | |||||
| </kendo-grid-column> | |||||
| <kendo-grid-column field="LastPayInDate" title="Recent Trail" width="120" [sortable]="true" [class]="'topAlign'"> | |||||
| </kendo-grid-column> | |||||
| </kendo-grid-column-group> | |||||
| <kendo-grid-column-group title="Income Distribution" [columnMenu]="false" [headerClass]="'colIncomeDistribution colPayOut'"> | |||||
| <kendo-grid-column field="PayOut" title="Paid ($)" width="140" [class]="'topAlign colPayOut'" [headerClass]="'colPayOut'"> | |||||
| <ng-template kendoGridCellTemplate let-dataItem> | |||||
| <span [ngClass]="{'red text-bold': dataItem.PayOut > dataItem.Trail}"> | |||||
| {{ dataItem.PayOut | currency }} | |||||
| </span> | |||||
| </ng-template> | |||||
| </kendo-grid-column> | |||||
| </kendo-grid-column-group> | |||||
| <div *kendoGridDetailTemplate="let dataItem"> | |||||
| <div style="height:100px; background-color: grey;"> {{ dataItem.Item }} details should be here.</div> | |||||
| <!-- category-details [category]="dataItem"></category-details --> | |||||
| </div> | |||||
| </kendo-grid> |
| .fullheight_grid { | |||||
| height: calc(100vh - 48px) !important; | |||||
| } | |||||
| .k-grid td:first-child{ | |||||
| vertical-align: top; | |||||
| } | |||||
| .k-grid td.topAlign{ | |||||
| vertical-align: top; | |||||
| } | |||||
| .k-grid td.alignStatus{ | |||||
| vertical-align: top; | |||||
| text-align: left; | |||||
| } | |||||
| .customer-photo{ | |||||
| display: inline-block; | |||||
| width: 32px; | |||||
| height: 32px; | |||||
| border-radius: 50%; | |||||
| background-size: 32px 35px; | |||||
| background-position: center center; | |||||
| vertical-align: middle; | |||||
| line-height: 32px; | |||||
| box-shadow: inset 0 0 1px #999, inset 0 0 10px rgba(0,0,0,.2); | |||||
| margin-left: 5px; | |||||
| } | |||||
| .customer-name { | |||||
| display: inline-block; | |||||
| vertical-align: middle; | |||||
| line-height: 32px; | |||||
| padding-left: 10px; | |||||
| } | |||||
| .k-grid-header .k-header.colGroupPeople, | |||||
| .k-grid-header .k-header.colClient, | |||||
| .k-grid-header .k-header.colBroker, | |||||
| .k-grid-header .k-header.colOtherRewarder | |||||
| { | |||||
| text-align:center; | |||||
| } | |||||
| .k-grid-header .k-header.colGroupLoanDetails, | |||||
| .k-grid-header .k-header.colGroupLenderDetails, | |||||
| .k-grid-header .k-header.colGroupIncomeDistribution{ | |||||
| border-left: 5px solid #ffeabe !important; | |||||
| } | |||||
| .colRating, .colAmount, .colPayOut{ | |||||
| border-left: 5px solid #ffeabe !important; | |||||
| } | |||||
| .colTrail{ | |||||
| font-width: 300; | |||||
| color: green ; | |||||
| //border-left: 2px solid green !important; | |||||
| //border-right: 2px solid green !important; | |||||
| border-bottom: 2px solid green !important; | |||||
| } | |||||
| .k-grid-header .k-header.colIncomeDistribution, | |||||
| .k-grid-header .k-header.colGroupLoanDetails{ | |||||
| background-color: #ffeabe; | |||||
| } | |||||
| .red { | |||||
| color: #d9534f; | |||||
| } | |||||
| .text-bold { | |||||
| font-weight: 600; | |||||
| } |
| it('should create', () => { | it('should create', () => { | ||||
| expect(component).toBeTruthy(); | expect(component).toBeTruthy(); | ||||
| }); | }); | ||||
| }); | }); |
| import { Component, OnInit } from '@angular/core'; | |||||
| import {Component, OnInit, ViewChild, ViewEncapsulation} from '@angular/core'; | |||||
| import {DataStateChangeEvent, GridComponent, GridDataResult} from '@progress/kendo-angular-grid'; | |||||
| import {Observable} from 'rxjs'; | |||||
| import {SortDescriptor} from '@progress/kendo-data-query'; | |||||
| import {LoanSummaryService} from '../service/loan_summary.service'; | |||||
| import {images} from '../transaction-list/images'; | |||||
| import {AuthService} from '../service/auth.service'; | |||||
| @Component({ | @Component({ | ||||
| selector: 'app-list-all-loans', | selector: 'app-list-all-loans', | ||||
| templateUrl: './list-all-loans.component.html', | templateUrl: './list-all-loans.component.html', | ||||
| styleUrls: ['./list-all-loans.component.scss'] | |||||
| styleUrls: ['./list-all-loans.component.scss'], | |||||
| encapsulation: ViewEncapsulation.None, | |||||
| }) | }) | ||||
| export class ListAllLoansComponent implements OnInit { | export class ListAllLoansComponent implements OnInit { | ||||
| public view: LoanSummaryService; | |||||
| public sort: Array<SortDescriptor> = []; | |||||
| public pageSize = 10; | |||||
| public skip = 0; | |||||
| constructor() { } | |||||
| @ViewChild(GridComponent, { static: true }) public grid: GridComponent; | |||||
| ngOnInit(): void { | |||||
| constructor(private service: LoanSummaryService, private auth: AuthService) { } | |||||
| public ngOnInit(): void { | |||||
| // Bind directly to the service as it is a Subject | |||||
| this.view = this.service; | |||||
| // Fetch the data with the initial state | |||||
| this.loadData(); | |||||
| } | |||||
| public dataStateChange({ skip, take, sort }: DataStateChangeEvent): void { | |||||
| // Save the current state of the Grid component | |||||
| this.skip = skip; | |||||
| this.pageSize = take; | |||||
| this.sort = sort; | |||||
| // Reload the data with the new state | |||||
| this.loadData(); | |||||
| // console.log(this.skip, this.pageSize, this.sort); | |||||
| // Expand the first row initially | |||||
| this.grid.expandRow(0); | |||||
| } | |||||
| private loadData(): void { | |||||
| this.service.query({ skip: this.skip, take: this.pageSize, sort: this.sort }); | |||||
| } | |||||
| private photoURL(peopleId: any): string { | |||||
| let url = this.auth.getUrl('avatar/') + peopleId; | |||||
| console.log(url, peopleId); | |||||
| return 'url("' + url + '")'; | |||||
| } | } | ||||
| } | } |
| import { Injectable } from '@angular/core'; | |||||
| import { HttpClient } from '@angular/common/http'; | |||||
| import { GridDataResult } from '@progress/kendo-angular-grid'; | |||||
| import { toODataString } from '@progress/kendo-data-query'; | |||||
| import { Observable, BehaviorSubject } from 'rxjs'; | |||||
| import { map, tap } from 'rxjs/operators'; | |||||
| import {AuthService} from './auth.service'; | |||||
| export abstract class LoanQueryService extends BehaviorSubject<GridDataResult> { | |||||
| public loading: boolean; | |||||
| private BASE_URL = ''; | |||||
| constructor( | |||||
| private http: HttpClient, | |||||
| private auth: AuthService, | |||||
| protected tableName: string | |||||
| ) { | |||||
| super(null); | |||||
| this.BASE_URL = this.auth.getUrl('grid/loan/'); | |||||
| } | |||||
| public query(state: any): void { | |||||
| this.fetch(this.tableName, state) | |||||
| .subscribe(x => super.next(x)); | |||||
| } | |||||
| protected fetch(tableName: string, state: any): Observable<GridDataResult> { | |||||
| const queryStr = `${toODataString(state)}&$count=true`; | |||||
| this.loading = true; | |||||
| return this.http | |||||
| .get<GridDataResult>(`${this.BASE_URL}${tableName}?${queryStr}`) | |||||
| .pipe( | |||||
| map(response => { | |||||
| console.log( response.data[0]['Settlement']); | |||||
| console.log( response.data[0]['LastPayInDate']); | |||||
| return response; | |||||
| }), | |||||
| tap(() => this.loading = false) | |||||
| ); | |||||
| } | |||||
| } | |||||
| @Injectable() | |||||
| export class ProductsService extends LoanQueryService { | |||||
| constructor(http: HttpClient, auth: AuthService) { super(http, auth, 'Products'); } | |||||
| public queryForCategory({ CategoryID }: { CategoryID: number }, state?: any): void { | |||||
| this.query(Object.assign({}, state, { | |||||
| filter: { | |||||
| filters: [{ | |||||
| field: 'CategoryID', operator: 'eq', value: CategoryID | |||||
| }], | |||||
| logic: 'and' | |||||
| } | |||||
| })); | |||||
| } | |||||
| public queryForProductName(ProductName: string, state?: any): void { | |||||
| this.query(Object.assign({}, state, { | |||||
| filter: { | |||||
| filters: [{ | |||||
| field: 'ProductName', operator: 'contains', value: ProductName | |||||
| }], | |||||
| logic: 'and' | |||||
| } | |||||
| })); | |||||
| } | |||||
| } | |||||
| @Injectable() | |||||
| export class LoanSummaryService extends LoanQueryService { | |||||
| constructor(http: HttpClient, auth: AuthService) { super(http, auth, 'full-loan-overview'); } | |||||
| queryAll(st?: any): Observable<GridDataResult> { | |||||
| const state = Object.assign({}, st); | |||||
| delete state.skip; | |||||
| delete state.take; | |||||
| return this.fetch(this.tableName, state); | |||||
| } | |||||
| } |