| @@ -1,12 +1,12 @@ | |||
| { | |||
| "name": "broker", | |||
| "version": "2.0.37", | |||
| "version": "2.0.39", | |||
| "lockfileVersion": 2, | |||
| "requires": true, | |||
| "packages": { | |||
| "": { | |||
| "name": "broker", | |||
| "version": "2.0.37", | |||
| "version": "2.0.39", | |||
| "dependencies": { | |||
| "@angular/animations": "^11.2.9", | |||
| "@angular/common": "^11.2.9", | |||
| @@ -1,6 +1,6 @@ | |||
| { | |||
| "name": "broker", | |||
| "version": "2.0.37", | |||
| "version": "2.0.39", | |||
| "scripts": { | |||
| "ng": "ng", | |||
| "versionIncrease": "npm --no-git-tag-version version patch", | |||
| @@ -1,2 +1,66 @@ | |||
| <p>loan-detail-basic-info works!</p> | |||
| basic info {{ Loan.Id}} | |||
| <form class="k-form" #basicInfoForm="ngForm" > | |||
| <div class="row"> | |||
| <div class="col-md-6"> | |||
| <kendo-formfield> | |||
| <kendo-label [for]="Lender" text="Lender Organization (Funding Agency)"> | |||
| </kendo-label> | |||
| <kendo-combobox name="Lender" | |||
| [(ngModel)] = "Loan.Lender" #Lender | |||
| [data]="lenderListView | async" | |||
| [allowCustom]="true" | |||
| [loading]="lenderNameService.loading"> | |||
| </kendo-combobox> | |||
| <kendo-formhint>info determined by trail income info</kendo-formhint> | |||
| <kendo-formerror>Error: Lender is required (info determined by trail income info) </kendo-formerror> | |||
| </kendo-formfield> | |||
| </div> | |||
| <div class="col-md-6"> | |||
| <kendo-formfield> | |||
| <kendo-label [for]="LenderLoanNumber" text="Lender's Loan identification"> | |||
| </kendo-label> | |||
| <kendo-textbox name="LenderLoanNumber" [(ngModel)] = "Loan.LenderLoanNumber" #LenderLoanNumber [clearButton]="true" > </kendo-textbox> | |||
| <kendo-formhint>Can not be empty especially when having income</kendo-formhint> | |||
| <kendo-formerror>Error: LenderLoanNumber is required (an not be empty especially when having income) </kendo-formerror> | |||
| </kendo-formfield> | |||
| <div class="vertical-spacer"></div> | |||
| </div> | |||
| <div class="col-md-6"> | |||
| <kendo-formfield> | |||
| <kendo-label [for]="Amount" text="Loan Limit"> </kendo-label> | |||
| <kendo-numerictextbox #Amount name="Amount" [min]="100" [max]="1000000000" [format]="'c0'" [(ngModel)]="Loan.Amount"></kendo-numerictextbox> | |||
| <kendo-formhint>E.g. 80000, cannot be changed after settlement</kendo-formhint> | |||
| <kendo-formerror>Error: Limit should be between 100 ~ 1,000,000,000</kendo-formerror> | |||
| </kendo-formfield> | |||
| </div> | |||
| <div class="col-md-6"> | |||
| <kendo-formfield> | |||
| <kendo-label [for]="Settlement" [optional]="false" text="Settlement Date"></kendo-label> | |||
| <kendo-datepicker #Settlement name="Settlement" | |||
| [(ngModel)]="Loan.Settlement" | |||
| [format]="'dd/MM/yyyy'" | |||
| [min]="minSettlement" [max]="maxSettlement"> | |||
| </kendo-datepicker> | |||
| <kendo-formhint>Date settled or expected to be settled</kendo-formhint> | |||
| </kendo-formfield> | |||
| </div> | |||
| <div class="col-sm-12"> | |||
| <kendo-formfield> | |||
| <kendo-label [for]="Description" [optional]="false" | |||
| text="Quick notes: ( < 1000 words ) " | |||
| (click)="showDemoDescription($event)"></kendo-label> | |||
| <kendo-editor #Description name="description" style="height: 300px;" [(ngModel)]="Loan.Description"></kendo-editor> | |||
| </kendo-formfield> | |||
| </div> | |||
| </div> | |||
| <div class="row align-items-center"> | |||
| <div class="col-sm-1 "> | |||
| <button kendoButton (click)="save(basicInfoForm)">Save</button> | |||
| </div> | |||
| <div class="col-sm-11 "> | |||
| <div *ngIf="errorMessage !== '' " class="text-danger">{{errorMessage}}</div> | |||
| </div> | |||
| </div> | |||
| </form> | |||
| @@ -0,0 +1,8 @@ | |||
| kendo-label{ | |||
| font-weight: bold; | |||
| background: #f9f9f9; | |||
| } | |||
| kendo-formhint, | |||
| kendo-formerror{ | |||
| background: #f9f9f9; | |||
| } | |||
| @@ -1,5 +1,11 @@ | |||
| import { Component, Input, OnInit } from '@angular/core'; | |||
| import {LoanModel} from '../../models/loan.model'; | |||
| import {NgForm} from '@angular/forms'; | |||
| import {HttpErrorResponse} from '@angular/common/http'; | |||
| import {Observable} from 'rxjs'; | |||
| import {LoanSingleService} from '../../service/loan.single.service'; | |||
| import {LenderNameService} from '../../service/lender-name.service'; | |||
| import { NotificationService } from '@progress/kendo-angular-notification'; | |||
| @Component({ | |||
| selector: 'app-loan-detail-basic-info', | |||
| @@ -8,9 +14,86 @@ import {LoanModel} from '../../models/loan.model'; | |||
| }) | |||
| export class LoanDetailBasicInfoComponent implements OnInit { | |||
| @Input() Loan: LoanModel; | |||
| constructor() { } | |||
| public lenderListView: Observable<string[]>; | |||
| public minSettlement: Date = new Date(2015, 0, 1); | |||
| public maxSettlement: Date = new Date(2030, 4, 31); | |||
| public errorMessage=''; | |||
| constructor( private service: LoanSingleService, | |||
| private notificationService: NotificationService, | |||
| public lenderNameService: LenderNameService) { | |||
| } | |||
| ngOnInit(): void { | |||
| this.lenderListView = this.lenderNameService; | |||
| this.lenderNameService.query(); | |||
| } | |||
| public save(basicInfoForm: NgForm): void { | |||
| if ( ! basicInfoForm.valid ) { | |||
| basicInfoForm.form.markAllAsTouched(); | |||
| return ; | |||
| } | |||
| this.errorMessage = ''; | |||
| this.service.updateBasicInfo(this.Loan).subscribe( | |||
| resp => { | |||
| if ( this.Loan.Id === '' ) { | |||
| this.Loan.Id = resp.Id; | |||
| } | |||
| this.showSuccess(this.Loan.Id + ' saved successfully'); | |||
| }, | |||
| err => { | |||
| this.errorMessage = err instanceof HttpErrorResponse ? err.statusText : 'unknown error occured'; | |||
| this.showError(this.errorMessage); | |||
| } | |||
| ); | |||
| } | |||
| public showDemoDescription($event): void{ | |||
| let DemoDescription = ` | |||
| <h1> Rich Text Editing </h1> | |||
| <table> | |||
| <tr> <td> | |||
| <ol> | |||
| <li>Text formatting</li> | |||
| <li>Bulleted and numbered lists</li> | |||
| <li>Hyperlinks</li> | |||
| <li>Cross-browser support</li> | |||
| <li>Identical HTML output across browsers</li> | |||
| </ol> | |||
| </td> <td width="20%" text-align="right"> | |||
| <img src="https://edge.alluremedia.com.au/uploads/businessinsider/2015/05/P2P-to-date.jpg" | |||
| width=300"> | |||
| </td> | |||
| </tr> | |||
| </table> | |||
| `; | |||
| this.Loan.Description = DemoDescription; | |||
| } | |||
| public showSuccess(msg : string ): void { | |||
| this.notificationService.show({ | |||
| content: msg, | |||
| cssClass: "button-notification", | |||
| animation: { type: "slide", duration: 400 }, | |||
| position: { horizontal: "center", vertical: "bottom" }, | |||
| type: { style: "success", icon: true }, | |||
| closable: true, | |||
| }); | |||
| } | |||
| public showError(err: string): void { | |||
| this.notificationService.show({ | |||
| content: err, | |||
| cssClass: "button-notification", | |||
| animation: { type: "slide", duration: 400 }, | |||
| position: { horizontal: "center", vertical: "bottom" }, | |||
| type: { style: "error", icon: true }, | |||
| closable: true, | |||
| }); | |||
| } | |||
| } | |||
| @@ -26,8 +26,11 @@ export class LoanModel { | |||
| public Lender?: string; | |||
| public LenderLoanNumber?: string; | |||
| public Client?: PeopleModel[]; | |||
| public ClientIds: string[]; | |||
| public Broker?: BrokerModel[]; | |||
| public BrokerIds: string[]; | |||
| public OtherRewarder?: PeopleModel[]; | |||
| public OtherRewarderIds: string[]; | |||
| public Reward?: RewardModel[]; | |||
| public RewardPeople?: PeopleModel[]; | |||
| public PayIn?: PayInModel[]; | |||
| @@ -69,18 +72,38 @@ export class LoanModel { | |||
| this.Client = []; | |||
| } | |||
| if ( payload.ClientIds && payload.ClientIds.length > 0 ){ | |||
| this.ClientIds = payload.ClientIds; | |||
| } else{ | |||
| this.ClientIds = []; | |||
| } | |||
| if (payload.Broker && payload.Broker.length > 0 ) { | |||
| this.setBroker(payload.Broker); | |||
| }else{ | |||
| this.Broker = []; | |||
| } | |||
| if ( payload.BrokerIds && payload.BrokerIds.length > 0 ){ | |||
| this.BrokerIds = payload.BrokerIds; | |||
| } else{ | |||
| this.BrokerIds = []; | |||
| } | |||
| if (payload.OtherRewarder && payload.OtherRewarder.length > 0 ) { | |||
| this.setOtherRewarder(payload.OtherRewarder); | |||
| }else{ | |||
| this.OtherRewarder = []; | |||
| } | |||
| if ( payload.OtherRewarderIds && payload.OtherRewarderIds.length > 0 ){ | |||
| this.OtherRewarderIds = payload.OtherRewarderIds; | |||
| } else{ | |||
| this.OtherRewarderIds = []; | |||
| } | |||
| if (payload.Reward && payload.Reward.length > 0 ) { | |||
| this.setReward(payload.Reward); | |||
| }else{ | |||
| @@ -211,7 +234,6 @@ export class LoanModel { | |||
| ); | |||
| }); | |||
| } | |||
| private setOtherRewarder(v: any[]): void{ | |||
| this.OtherRewarder = []; | |||
| v.forEach((c) => { | |||
| @@ -4,6 +4,7 @@ import { GridDataResult } from '@progress/kendo-angular-grid'; | |||
| import { Observable, BehaviorSubject } from 'rxjs'; | |||
| import { map, tap } from 'rxjs/operators'; | |||
| import {AuthService} from './auth.service'; | |||
| import {LoanModel} from '../models/loan.model'; | |||
| export abstract class LoanQueryService extends BehaviorSubject<GridDataResult> { | |||
| public loading: boolean; | |||
| @@ -20,8 +21,14 @@ export abstract class LoanQueryService extends BehaviorSubject<GridDataResult> { | |||
| } | |||
| public query(state: any): void { | |||
| this.fetch(this.tableName, state) | |||
| .subscribe(x => super.next(x)); | |||
| this.fetch(this.tableName, state).subscribe(x => { | |||
| var ret: GridDataResult = {total: x.total, data:[]}; | |||
| x.data.forEach( v => { | |||
| ret.data.push (new LoanModel(v)); //conver to LoanModel | |||
| }); | |||
| console.log(ret); | |||
| super.next(ret); | |||
| }); | |||
| } | |||
| protected fetch(tableName: string, state: any): Observable<GridDataResult> { | |||