Browse Source

group check up for people-editing custom control.

tags/2.037
Patrick Sun 4 years ago
parent
commit
4cbb5b4c71
59 changed files with 6232 additions and 3534 deletions
  1. +4336
    -3027
      package-lock.json
  2. +61
    -57
      package.json
  3. +2
    -1
      src/app/app-routing.module.ts
  4. +1
    -1
      src/app/app.component.html
  5. +2
    -2
      src/app/app.component.ts
  6. +11
    -2
      src/app/app.module.ts
  7. +11
    -5
      src/app/auth/auth-http-interceptor.service.ts
  8. +1
    -0
      src/app/auth/auth.component.ts
  9. +2
    -2
      src/app/bkp-divider-shadow-bottom/bkp-divider-shadow-bottom.component.html
  10. +9
    -9
      src/app/bkp-divider-shadow-bottom/bkp-divider-shadow-bottom.component.scss
  11. +1
    -0
      src/app/canvas/canvas.component.html
  12. +2
    -2
      src/app/chart-recent-ten-loans/chart-recent-ten-loans.component.html
  13. +1
    -1
      src/app/chart-top-brokers/chart-top-brokers.component.html
  14. +3
    -2
      src/app/chart-top-brokers/chart-top-brokers.component.ts
  15. +46
    -5
      src/app/list-all-loans/list-all-loans.component.html
  16. +5
    -0
      src/app/list-all-loans/list-all-loans.component.ts
  17. +131
    -45
      src/app/loan-add-new/loan-add-new.component.html
  18. +1
    -4
      src/app/loan-add-new/loan-add-new.component.scss
  19. +48
    -51
      src/app/loan-add-new/loan-add-new.component.ts
  20. +6
    -0
      src/app/loan-detail/loan-detail.component.html
  21. +0
    -0
      src/app/loan-detail/loan-detail.component.scss
  22. +25
    -0
      src/app/loan-detail/loan-detail.component.spec.ts
  23. +16
    -0
      src/app/loan-detail/loan-detail.component.ts
  24. +94
    -68
      src/app/loan-edit/basicinfo/basicinfo.component.html
  25. +5
    -0
      src/app/loan-edit/basicinfo/basicinfo.component.scss
  26. +84
    -13
      src/app/loan-edit/basicinfo/basicinfo.component.ts
  27. +1
    -1
      src/app/loan-edit/hint-card/hint-card.component.html
  28. +2
    -1
      src/app/loan-edit/hint-card/hint-card.component.ts
  29. +55
    -132
      src/app/loan-edit/loan-edit.component.html
  30. +9
    -1
      src/app/loan-edit/loan-edit.component.scss
  31. +54
    -51
      src/app/loan-edit/loan-edit.component.ts
  32. +59
    -1
      src/app/loan-edit/people-reward/people-reward.component.html
  33. +20
    -0
      src/app/loan-edit/people-reward/people-reward.component.scss
  34. +224
    -5
      src/app/loan-edit/people-reward/people-reward.component.ts
  35. +41
    -0
      src/app/loan-edit/people-select/people-select.component.html
  36. +9
    -0
      src/app/loan-edit/people-select/people-select.component.scss
  37. +25
    -0
      src/app/loan-edit/people-select/people-select.component.spec.ts
  38. +186
    -0
      src/app/loan-edit/people-select/people-select.component.ts
  39. +71
    -1
      src/app/loan-edit/trail-income/trail-income.component.html
  40. +4
    -0
      src/app/loan-edit/trail-income/trail-income.component.scss
  41. +84
    -4
      src/app/loan-edit/trail-income/trail-income.component.ts
  42. +4
    -6
      src/app/main-menu-items.ts
  43. +19
    -0
      src/app/models/broker.model.ts
  44. +121
    -0
      src/app/models/loan.model.ts
  45. +4
    -0
      src/app/models/pay-in.model.ts
  46. +18
    -0
      src/app/models/payout-audit.model.ts
  47. +29
    -0
      src/app/models/payout.model.ts
  48. +3
    -0
      src/app/models/people-map.model.ts
  49. +57
    -0
      src/app/models/people.model.ts
  50. +39
    -0
      src/app/models/reward.model.ts
  51. +10
    -0
      src/app/rating-input/rating-input.component.html
  52. +11
    -0
      src/app/rating-input/rating-input.component.scss
  53. +25
    -0
      src/app/rating-input/rating-input.component.spec.ts
  54. +65
    -0
      src/app/rating-input/rating-input.component.ts
  55. +2
    -2
      src/app/rating-input/rating.component.ts
  56. +36
    -18
      src/app/service/auth.service.ts
  57. +28
    -0
      src/app/service/loan.single.service.ts
  58. +3
    -4
      src/app/service/loan_summary.service.ts
  59. +10
    -10
      src/app/transaction-list/transaction-list.component.html

+ 4336
- 3027
package-lock.json
File diff suppressed because it is too large
View File


+ 61
- 57
package.json View File

@@ -4,76 +4,80 @@
"scripts": {
"ng": "ng",
"start": "ng serve --proxy-config proxy.conf.json",
"build": "ng build",
"build": "ng build ",
"buildsfm": "ng build --prod --base-href=/broker/ --deploy-url=/broker/ ",
"test": "ng test",
"lint": "ng lint",
"e2e": "ng e2e"
},
"private": true,
"dependencies": {
"@angular/animations": "~10.2.0",
"@angular/common": "~10.2.0",
"@angular/compiler": "~10.2.0",
"@angular/core": "~10.2.0",
"@angular/forms": "~10.2.0",
"@angular/localize": "~10.2.0",
"@angular/platform-browser": "~10.2.0",
"@angular/platform-browser-dynamic": "~10.2.0",
"@angular/router": "~10.2.0",
"@fortawesome/angular-fontawesome": "^0.7.0",
"@fortawesome/fontawesome-svg-core": "^1.2.28",
"@fortawesome/free-solid-svg-icons": "^5.13.0",
"@progress/kendo-angular-buttons": "^5.1.1",
"@progress/kendo-angular-charts": "^4.2.1",
"@progress/kendo-angular-common": "^1.2.1",
"@progress/kendo-angular-dateinputs": "^4.0.0",
"@progress/kendo-angular-dialog": "^4.1.1",
"@progress/kendo-angular-dropdowns": "^4.2.4",
"@progress/kendo-angular-editor": "^1.2.5",
"@progress/kendo-angular-excel-export": "^3.0.0",
"@progress/kendo-angular-grid": "^4.8.0",
"@progress/kendo-angular-icons": "^0.2.1",
"@progress/kendo-angular-indicators": "^0.2.0",
"@progress/kendo-angular-inputs": "^6.4.0",
"@progress/kendo-angular-intl": "^2.0.0",
"@progress/kendo-angular-l10n": "^2.0.0",
"@progress/kendo-angular-label": "^2.3.3",
"@progress/kendo-angular-layout": "4.1.5 - 5",
"@progress/kendo-angular-menu": "^2.0.4",
"@progress/kendo-angular-navigation": "^0.2.0",
"@progress/kendo-angular-notification": "^2.1.3",
"@progress/kendo-angular-pdf-export": "^2.0.0",
"@progress/kendo-angular-popup": "^3.0.0",
"@progress/kendo-angular-progressbar": "^0.2.3",
"@progress/kendo-data-query": "^1.0.0",
"@progress/kendo-drawing": "^1.5.12",
"@progress/kendo-svg-icons": "^0.0.3",
"@angular/animations": "~11.2.5",
"@angular/common": "~11.2.5",
"@angular/compiler": "~11.2.5",
"@angular/core": "~11.2.5",
"@angular/forms": "~11.2.5",
"@angular/localize": "~11.2.5",
"@angular/platform-browser": "~11.2.5",
"@angular/platform-browser-dynamic": "~11.2.5",
"@angular/router": "~11.2.5",
"@fortawesome/angular-fontawesome": "^0.8.2",
"@fortawesome/fontawesome-svg-core": "^1.2.34",
"@fortawesome/free-solid-svg-icons": "^5.15.2",
"@progress/kendo-angular-buttons": "^6.1.0",
"@progress/kendo-angular-charts": "^5.1.0",
"@progress/kendo-angular-common": "^2.0.0",
"@progress/kendo-angular-dateinputs": "^5.1.0",
"@progress/kendo-angular-dialog": "^5.0.0",
"@progress/kendo-angular-dropdowns": "^5.1.0",
"@progress/kendo-angular-editor": "^2.0.1",
"@progress/kendo-angular-excel-export": "^4.0.0",
"@progress/kendo-angular-grid": "^5.0.3",
"@progress/kendo-angular-icons": "^0.4.2",
"@progress/kendo-angular-indicators": "^1.0.0",
"@progress/kendo-angular-inputs": "^7.1.2",
"@progress/kendo-angular-intl": "^3.1.0",
"@progress/kendo-angular-l10n": "^3.0.0",
"@progress/kendo-angular-label": "^3.0.1",
"@progress/kendo-angular-layout": "6",
"@progress/kendo-angular-menu": "^3.0.0",
"@progress/kendo-angular-navigation": "^1.0.0",
"@progress/kendo-angular-notification": "^3.0.0",
"@progress/kendo-angular-pdf-export": "^3.0.0",
"@progress/kendo-angular-popup": "^4.0.0",
"@progress/kendo-angular-progressbar": "^2.0.0",
"@progress/kendo-angular-toolbar": "^4.0.0",
"@progress/kendo-angular-treeview": "^5.1.0",
"@progress/kendo-data-query": "^1.5.4",
"@progress/kendo-drawing": "^1.9.4",
"@progress/kendo-licensing": "^1.1.3",
"@progress/kendo-svg-icons": "^0.1.2",
"@progress/kendo-theme-default": "latest",
"bootstrap": "^3.4.1",
"hammerjs": "^2.0.0",
"bootstrap": "^4.6.0",
"hammerjs": "^2.0.8",
"rxjs": "^6.6.6",
"tslib": "^2.0.0",
"zone.js": "~0.10.2",
"@progress/kendo-angular-toolbar": "^3.0.1"
"ts-debounce": "^3.0.0",
"tslib": "^2.1.0",
"zone.js": "~0.11.4"
},
"devDependencies": {
"@angular-devkit/build-angular": "~0.1002.0",
"@angular/cli": "~10.2.0",
"@angular/compiler-cli": "~10.2.0",
"@types/node": "^12.11.1",
"@types/jasmine": "~3.5.0",
"@types/jasminewd2": "~2.0.3",
"codelyzer": "^6.0.0",
"@angular-devkit/build-angular": "~0.1102.4",
"@angular/cli": "~11.2.4",
"@angular/compiler-cli": "~11.2.5",
"@types/jasmine": "~3.6.6",
"@types/jasminewd2": "~2.0.8",
"@types/node": "^14.14.33",
"codelyzer": "^6.0.1",
"jasmine-core": "~3.6.0",
"jasmine-spec-reporter": "~5.0.0",
"karma": "~5.0.0",
"jasmine-spec-reporter": "~6.0.0",
"karma": "~6.2.0",
"karma-chrome-launcher": "~3.1.0",
"karma-coverage-istanbul-reporter": "~3.0.2",
"karma-jasmine": "~4.0.0",
"karma-jasmine-html-reporter": "^1.5.0",
"karma-coverage-istanbul-reporter": "~3.0.3",
"karma-jasmine": "~4.0.1",
"karma-jasmine-html-reporter": "^1.5.4",
"protractor": "~7.0.0",
"ts-node": "~8.3.0",
"ts-node": "~9.1.1",
"tslint": "~6.1.0",
"typescript": "~4.0.2"
"typescript": "^4.1.5"
}
}

+ 2
- 1
src/app/app-routing.module.ts View File

@@ -8,6 +8,7 @@ import { TransactionListComponent } from './transaction-list/transaction-list.co
import { TransactionComponent } from './transaction/transaction.component';
import {ListAllLoansComponent} from './list-all-loans/list-all-loans.component';
import {LoanAddNewComponent} from './loan-add-new/loan-add-new.component';
import {LoanEditComponent} from './loan-edit/loan-edit.component';


const routes: Routes = [
@@ -18,7 +19,7 @@ const routes: Routes = [
{path : 'transaction', component: TransactionComponent, canActivate: [AuthGuard]},
{path : 'transaction-list', component: TransactionListComponent, canActivate: [AuthGuard]},
{path : 'list-all-loans', component: ListAllLoansComponent, },
{path : 'start-a-new-loan', component: LoanAddNewComponent, },
{path : 'start-a-new-loan', component: LoanEditComponent, },
];

@NgModule({

+ 1
- 1
src/app/app.component.html View File

@@ -1,6 +1,6 @@
<app-top-bar></app-top-bar>

<app-loan-edit #loanEditComponent></app-loan-edit>
<app-loan-add-new #loanEditComponent></app-loan-add-new>

<router-outlet></router-outlet>


+ 2
- 2
src/app/app.component.ts View File

@@ -38,8 +38,8 @@ export class AppComponent implements OnInit , OnDestroy {
(item:any) =>{
// console.log("emit on select : " + item.text);
if ( item.popup === 'loanEdit'){
this.loanEdit.somedata = '' + Math.random() + 'changed';
this.loanEdit.open('dialog');
// this.loanEdit.somedata = '' + Math.random() + 'changed';
// this.loanEdit.open('dialog');
}
}
);

+ 11
- 2
src/app/app.module.ts View File

@@ -40,7 +40,7 @@ import { DropDownsModule } from '@progress/kendo-angular-dropdowns';
import { TransactionComponent } from './transaction/transaction.component';
import { TransactionListComponent } from './transaction-list/transaction-list.component';
import { ExcelExportModule } from '@progress/kendo-angular-excel-export';
import { RatingComponent } from './transaction-list/rating.component';
import { RatingComponent } from './rating-input/rating.component';
import { TransDetailsComponent } from './trans-details/trans-details.component';
import { TransTailsComponent } from './trans-details/trans-tails/trans-tails.component';
import {AuthHttpInterceptor} from './auth/auth-http-interceptor.service';
@@ -59,6 +59,10 @@ import { BasicinfoComponent } from './loan-edit/basicinfo/basicinfo.component';
import { PeopleRewardComponent } from './loan-edit/people-reward/people-reward.component';
import { TrailIncomeComponent } from './loan-edit/trail-income/trail-income.component';
import { HintCardComponent } from './loan-edit/hint-card/hint-card.component';
import { PeopleSelectComponent } from './loan-edit/people-select/people-select.component';
import { LoanDetailComponent } from './loan-detail/loan-detail.component';
import {LoanSingleService} from './service/loan.single.service';
import { RatingInputComponent } from './rating-input/rating-input.component';



@@ -89,10 +93,14 @@ import { HintCardComponent } from './loan-edit/hint-card/hint-card.component';
BasicinfoComponent,
PeopleRewardComponent,
TrailIncomeComponent,
HintCardComponent
HintCardComponent,
PeopleSelectComponent,
LoanDetailComponent,
RatingInputComponent
],
imports: [
BrowserModule,
BrowserAnimationsModule,
FormsModule,
CommonModule,
HttpClientModule,
@@ -126,6 +134,7 @@ import { HintCardComponent } from './loan-edit/hint-card/hint-card.component';
AuthService,
WebSocketService,
LoanSummaryService,
LoanSingleService,
{
provide: HTTP_INTERCEPTORS,
useClass: AuthHttpInterceptor,

+ 11
- 5
src/app/auth/auth-http-interceptor.service.ts View File

@@ -1,5 +1,5 @@
import {Injectable} from '@angular/core';
import {HttpEvent, HttpEventType, HttpHandler, HttpInterceptor, HttpRequest} from '@angular/common/http';
import {HttpEvent, HttpEventType, HttpHandler, HttpInterceptor, HttpRequest, HttpResponse} from '@angular/common/http';
import {Observable} from 'rxjs';
import {AuthService} from '../service/auth.service';
import {tap} from 'rxjs/operators';
@@ -13,6 +13,7 @@ export class AuthHttpInterceptor implements HttpInterceptor {

intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
let h = req.headers;

if (this.auth.loggedIn.hasValidSession()) {
h = h.set('Biukop-Session', this.auth.loggedIn.session);
}
@@ -27,11 +28,16 @@ export class AuthHttpInterceptor implements HttpInterceptor {
});
return next.handle(authReq).pipe(
tap(event => {
//console.log(event);
// console.log(event);
if (event.type === HttpEventType.Response){
console.log('Response received');
//console.log(event.body);
//this.auth.logout();
const bs = event.headers.get('biukop-session');
if (bs !== undefined){
if ( this.auth.loggedIn.session !== bs ){
this.auth.loggedIn.session = bs;
this.auth.saveSessionInfo();
console.log('switch session:' , bs);
}
}
}
})
);

+ 1
- 0
src/app/auth/auth.component.ts View File

@@ -23,6 +23,7 @@ export class AuthComponent implements OnInit, OnDestroy{
constructor(private authService: AuthService, private router: Router, private notificationService: NotificationService) { }

ngOnInit(): void {
this.authService.logout();
this.loginSub = this.authService.loginSuccess.subscribe(
responseData => {
// console.log(responseData);

+ 2
- 2
src/app/bkp-divider-shadow-bottom/bkp-divider-shadow-bottom.component.html View File

@@ -1,3 +1,3 @@
<div class="h-divider">
<div class="shadow"></div>
</div>
<div class="biukop-shadow"></div>
</div>

+ 9
- 9
src/app/bkp-divider-shadow-bottom/bkp-divider-shadow-bottom.component.scss View File

@@ -6,13 +6,13 @@
width: 100%;
position: relative;
}
.h-divider .shadow {
.h-divider .biukop-shadow {
overflow: hidden;
height: 20px;
}
.h-divider .shadow:after {
.h-divider .biukop-shadow:after {
content: '';
display: block;
margin: -25px auto 0;
@@ -21,7 +21,7 @@
border-radius: 125px/12px;
box-shadow: 0 0 8px black;
}
.h-divider .text {
width: 100px;
height: 45px;
@@ -35,7 +35,7 @@
box-shadow: 0 2px 4px #999;
background: white;
}
.h-divider .text i {
position: absolute;
top: 4px;
@@ -49,7 +49,7 @@
font-style: normal;
color: #999;
}
.h-divider .text2 {
width: 70px;
height: 70px;
@@ -62,7 +62,7 @@
box-shadow: 0 2px 4px #999;
background: white;
}
.h-divider img {
position: absolute;
margin: 4px;
@@ -71,4 +71,4 @@
border: 1px dashed #aaa;
}
/* end of horizontal dividor */
/* end of horizontal dividor */

+ 1
- 0
src/app/canvas/canvas.component.html View File

@@ -24,6 +24,7 @@
<kendo-icon [name]="'photo-camera'" [size]="'medium'"></kendo-icon>


<app-people-select></app-people-select>
<button kendoButton (click)="onButtonClick()">Default</button>

<bkp-divider-text>some text</bkp-divider-text>

+ 2
- 2
src/app/chart-recent-ten-loans/chart-recent-ten-loans.component.html View File

@@ -15,10 +15,10 @@
</kendo-grid-column>
<kendo-grid-column field="Rating" title="Rating" width="110" [resizable]="false" filter="numeric">
<ng-template kendoGridCellTemplate let-dataItem>
<kendo-rating
<app-biukop-rating
[value]="dataItem.Rating"
[max]="5"
></kendo-rating>
></app-biukop-rating>
</ng-template>
</kendo-grid-column>


+ 1
- 1
src/app/chart-top-brokers/chart-top-brokers.component.html View File

@@ -3,7 +3,7 @@
</kendo-grid-column>
<kendo-grid-column field="First" title="Broker Name" minResizableWidth="250" >
<ng-template kendoGridCellTemplate let-dataItem>
<div class="customer-photo" [ngStyle]="{'background-image' : photoURL(dataItem)}"></div>
<div class="customer-photo" [ngStyle]="{'background-image' : photoURL(dataItem.Id)}"></div>
<div class="customer-name"> {{ dataItem.First }} , {{ dataItem.Last }} </div>
</ng-template>
</kendo-grid-column>

+ 3
- 2
src/app/chart-top-brokers/chart-top-brokers.component.ts View File

@@ -18,7 +18,8 @@ export class ChartTopBrokersComponent implements OnInit {
this.gridData = this.http.get<TopBrokerModel[]>(this.auth.getUrl('chart/top-broker'));
}

private photoURL(dataItem: any): string {
return 'url("https://via.placeholder.com/48")';
private photoURL(peopleId: any): string {
const url = this.auth.getUrl('avatar/') + peopleId;
return 'url("' + url + '")';
}
}

+ 46
- 5
src/app/list-all-loans/list-all-loans.component.html View File

@@ -14,6 +14,11 @@
(filterChange)="filterChange($event)"
class="fullheight_grid"
>
<ng-template kendoGridToolbarTemplate>
<button kendoGridExcelCommand type="button" icon="file-excel" style="float:right;">Export to Excel</button>
<button kendoGridPDFCommand icon="file-pdf" style="float:right;">Export to PDF</button>
</ng-template>

<kendo-grid-column field="Id" width="50" [class]="'topAlign'" [sortable]="false" [filterable]="false">
<ng-template kendoGridCellTemplate let-dataItem let-rowIndex="rowIndex" >
<p title="{{dataItem.Id}}" > {{dataItem.Index}}</p>
@@ -73,10 +78,10 @@
<kendo-grid-column-group title="Loan Details" [columnMenu]="false" [headerClass]="'colGroupLoanDetails'">
<kendo-grid-column field="Rating" title="Rating" width="150" [resizable]="false" [filterable]="false" [headerClass]="'colRating'" [class]="'topAlign colRating'">
<ng-template kendoGridCellTemplate let-dataItem>
<kendo-rating
<app-biukop-rating
[value]="dataItem.Rating"
[max]="5"
></kendo-rating>
></app-biukop-rating>
</ng-template>
</kendo-grid-column>

@@ -193,10 +198,46 @@
</kendo-grid-column>
</kendo-grid-column-group>

<ng-template kendoGridDetailTemplate let-dataItem let-rowIndex="rowIndex" [kendoGridDetailTemplateShowIf]="allowEdit.bind(this)">
<!-- <ng-template kendoGridDetailTemplate let-dataItem let-rowIndex="rowIndex" [kendoGridDetailTemplateShowIf]="allowEdit.bind(this)">-->
<!-- <category-details [category]="dataItem"></category-details>-->
<div style="background-color:yellow;"> {{dataItem.Id}}</div>
</ng-template>
<!-- <app-loan-detail [dataItem]="dataItem"> </app-loan-detail>-->
<!-- </ng-template>-->

<kendo-grid-pdf fileName="Transaction.pdf" [allPages]="true" [repeatHeaders]="true"></kendo-grid-pdf>
<kendo-grid-excel fileName="Transaction.xlsx" [fetchData]="allData">
<kendo-excelexport-column field="Index" title="Index">

</kendo-excelexport-column>
<kendo-excelexport-column field="ClientNames" title="Client">
</kendo-excelexport-column>
<kendo-excelexport-column field="BrokerNames" title="Broker">
</kendo-excelexport-column>
<kendo-excelexport-column field="OtherRewarderNames" title="Beneficiary">
</kendo-excelexport-column>
<kendo-excelexport-column field="Amount" title="Amount">
</kendo-excelexport-column>
<kendo-excelexport-column field="Status" title="Status">
</kendo-excelexport-column>
<kendo-excelexport-column field="Rating" title="Rating">
</kendo-excelexport-column>
<kendo-excelexport-column field="Settlement" title="Settlement">
</kendo-excelexport-column>
<kendo-excelexport-column field="Lender" title="Lender">
</kendo-excelexport-column>
<kendo-excelexport-column field="LenderLoanNumber" title="Lender's Loan ID">
</kendo-excelexport-column>
<kendo-excelexport-column field="NumOfTrail" title="Number of Trails">
</kendo-excelexport-column>
<kendo-excelexport-column field="Trail" title="Total Trails Received">
</kendo-excelexport-column>
<kendo-excelexport-column field="PayOut" title="Paid to Beneficiary">
</kendo-excelexport-column>
<kendo-excelexport-column field="Balance" title="Balance">
</kendo-excelexport-column>
<kendo-excelexport-column field="OffsetBalance" title="Offset Balance">
</kendo-excelexport-column>
<kendo-excelexport-column field="Item" title="Loan Target">
</kendo-excelexport-column>
</kendo-grid-excel>

</kendo-grid>

+ 5
- 0
src/app/list-all-loans/list-all-loans.component.ts View File

@@ -3,6 +3,7 @@ import {DataStateChangeEvent, GridComponent, GridDataResult} from '@progress/ken
import {CompositeFilterDescriptor, SortDescriptor, toODataString} from '@progress/kendo-data-query';
import {LoanSummaryService} from '../service/loan_summary.service';
import {AuthService} from '../service/auth.service';
import {Observable} from 'rxjs';

@Component({
selector: 'app-list-all-loans',
@@ -63,4 +64,8 @@ export class ListAllLoansComponent implements OnInit {
return this.auth.allowEditLoan();
}

public allData = (): Observable<GridDataResult> => {
return this.service.queryAll({skip: 0, take: 999999, sort: this.sort, filter: this.filter});
}

}

+ 131
- 45
src/app/loan-add-new/loan-add-new.component.html View File

@@ -1,53 +1,139 @@

<div class="container outer">
<div class="container">
<bkp-divider-shadow-bottom></bkp-divider-shadow-bottom>

<div style="margin-top:20px;"></div>

<div class="row">
<div class="col-sm-12">
<kendo-stepper
[steps]="steps"
[stepType]="'label'"
[(currentStep)]="currentStep"
[style.width.px]="570">
</kendo-stepper>
</div>
</div>
<div class="row">
<div class="col-sm-9">
<div class="pane-content">
<form class="k-form" [formGroup]="form">
<app-loan-basic-info *ngIf="currentStep === 0" [basicInfo]="currentGroup"></app-loan-basic-info>
<app-loan-people-reward *ngIf="currentStep === 1" [peopleReward]="currentGroup"> </app-loan-people-reward>
<app-loan-trail-income *ngIf="currentStep === 2" [trailIncome]="currentGroup"> </app-loan-trail-income>

<span class="k-form-separator"></span>
<div class="k-form-buttons k-buttons-end">
<span class="page">Step {{ currentStep + 1 }} of 3</span>
<div>
<button class="k-button prev" *ngIf="currentStep !== 0" (click)="prev()">Previous</button>
<button class="k-button k-primary" (click)="next()" *ngIf="currentStep !== 2">Next</button>
<button class="k-button k-primary" (click)="submit()" *ngIf="currentStep === 2">Submit</button>
</div>
</div>
</form>
</div>
</div>
<div class="col-sm-3">
<app-loan-edit-hint-card> </app-loan-edit-hint-card>
</div>
<div class="example-wrapper" style="opacity:1;">
<kendo-dialog title="Transaction" *ngIf="dialogOpened" (close)="close('dialog')" [minWidth]="500" [width]="850"
[minHeight]="600">
<div class="example-wrapper">
<div class="row">
<div class="col-sm-12">
<div class="vertical-spacer"></div>
<div class="vertical-spacer"></div>
<hr>
Proudly presented by Supercredit.com
<div class="col-xs-12 col-sm-12 ">
<div class="pane-content">
<form class="k-form" [formGroup]="registerForm">
<fieldset class="k-form-fieldset">
<legend class="k-form-legend">Bank Transaction Details</legend>
<kendo-formfield>
<kendo-label [for]="transID" text="Transaction ID"></kendo-label>
<input formControlName="transID" kendoTextBox #transID required />

<kendo-formhint>Unique transaction
ID from bank </kendo-formhint>
<kendo-formerror>Error: the ID is required</kendo-formerror>
</kendo-formfield>

<kendo-formfield>
<kendo-label [for]="submissionDate" [optional]="false"
text="Submission Date"></kendo-label>
<kendo-datepicker #submissionDate formControlName="submissionDate"
[min]="min" [max]="max">
</kendo-datepicker>

<kendo-formhint>Date in bank</kendo-formhint>
</kendo-formfield>

<kendo-formfield>
<kendo-label [for]="clientNames" [optional]="false"
text="Client Names"></kendo-label>
<kendo-multiselect
#clientNames
formControlName="clientNames"
[textField]="'text'"
[valueField]="'value'"
[valuePrimitive]="true"
[data]="listClientNames"
>
</kendo-multiselect>
</kendo-formfield>

<kendo-formfield>
<kendo-label [for]="brokers" [optional]="false"
text="Brokers Names"></kendo-label>
<kendo-multiselect
#brokers
formControlName="brokers"
[textField]="'text'"
[valueField]="'value'"
[valuePrimitive]="true"
[data]="listClientNames"
>
</kendo-multiselect>
</kendo-formfield>

<kendo-formfield>
<kendo-label [for]="referals" [optional]="false"
text="Referals/BDM"></kendo-label>
<kendo-multiselect
#referals
formControlName="referals"
[textField]="'text'"
[valueField]="'value'"
[valuePrimitive]="true"
[data]="listClientNames"
>
</kendo-multiselect>
</kendo-formfield>

<kendo-formfield>
<kendo-label [for]="status" [text]="'Progress Status'"></kendo-label>
<kendo-dropdownlist
#status
formControlName="status"
[data]="listClientNames"
[defaultItem]="{ text: 'Select Status', value: null }"
[textField]="'text'"
[valueField]="'value'"
required
>
</kendo-dropdownlist>
<kendo-formerror>Error: status is required</kendo-formerror>
</kendo-formfield>

<kendo-formfield>
<kendo-label [for]="lender" text="Lender Organization">
</kendo-label>
<input formControlName="lender" kendoTextBox #lender required />

<kendo-formhint>E.g. NAB Bank</kendo-formhint>
<kendo-formerror>Error: Lender is required</kendo-formerror>
</kendo-formfield>

<kendo-formfield>
<kendo-label [for]="limit" text="Loan Limit">
</kendo-label>
<input formControlName="limit" kendoTextBox #limit required />

<kendo-formhint>E.g. 8000</kendo-formhint>
<kendo-formerror>Error: Limit is required</kendo-formerror>
</kendo-formfield>

<kendo-formfield>
<kendo-label [for]="settlementDate" [optional]="false"
text="Settlement Date"></kendo-label>
<kendo-datepicker #settlementDate formControlName="settlementDate"
[min]="min" [max]="max">
</kendo-datepicker>

<kendo-formhint>Date Settled</kendo-formhint>
</kendo-formfield>

<!-- <div class="k-form-buttons">
<button class="k-button k-primary"
(click)="submitForm()">Add New </button>
<button class="k-button" (click)="clearForm()">Clear</button>
</div> -->
</fieldset>
</form>
</div>
</div>
</div>
</div>
</div>

<kendo-dialog-actions>
<button kendoButton (click)="clearForm()">Clear</button>
<button kendoButton (click)="submitForm()" primary="true">Add New</button>
</kendo-dialog-actions>
</kendo-dialog>

<kendo-window [minWidth]="200" [minHeight]="125" title="About" *ngIf="windowOpened" (close)="close('window')">
<p style="text-align: center;">Additional info</p>
</kendo-window>
</div>



+ 1
- 4
src/app/loan-add-new/loan-add-new.component.scss View File

@@ -1,5 +1,2 @@
.pane-content { padding: 0 10px; }


div.vertical-spacer {
margin-bottom: 30px;
}

+ 48
- 51
src/app/loan-add-new/loan-add-new.component.ts View File

@@ -1,6 +1,6 @@
import {Component, OnInit, ViewChild} from '@angular/core';
import {FormControl, FormGroup, Validators} from '@angular/forms';
import {StepperComponent} from '@progress/kendo-angular-layout';
import { Component, OnInit, ViewChild } from '@angular/core';
import { FormControl, FormGroup, Validators } from '@angular/forms';

@Component({
selector: 'app-loan-add-new',
@@ -8,75 +8,72 @@ import {StepperComponent} from '@progress/kendo-angular-layout';
styleUrls: ['./loan-add-new.component.scss']
})
export class LoanAddNewComponent implements OnInit {
public submitted: boolean ;
public currentStep = 0;
@ViewChild('stepper', { static: true })
public stepper: StepperComponent;



public steps = [
{ label: 'Basic Info', isValid: true },
{ label: 'People Reward', isValid: false },
{ label: 'Trail Income', isValid: true },
{ label: 'Payable', isValid: true, optional: true }
];


//popup
public dialogOpened = false;
public windowOpened = false;

public registerForm: FormGroup = new FormGroup({
transID: new FormControl(),
submissionDate: new FormControl(new Date(2020, 0, 10)),
status: new FormControl(),
lender: new FormControl('SuperCredit', Validators.required),
amount: new FormControl(100, [Validators.required , Validators.min(100), Validators.max(1000000000)]),
settlementDate: new FormControl(new Date(2020, 0, 9)),
description: new FormControl( '', Validators.maxLength(2000)),
});
//test
public somedata : string = "opened";


//form access

public form = new FormGroup({
basicInfo: this.registerForm,
peopleReward: this.registerForm,
trailIncome :this.registerForm,
payable: this.registerForm
});
//@ViewChild('birthDate', {static: true}) birthDate: LoanEditComponent;

constructor() { }

public get currentGroup(): FormGroup {
return this.getGroupAt(this.currentStep);
ngOnInit(): void {
}

private getGroupAt(index: number): FormGroup {
const groups = Object.keys(this.form.controls).map((groupName) => this.form.get(groupName)) as FormGroup[];
return groups[index];
public close(component) {
this.somedata = "" + Math.random();
this[component + 'Opened'] = false;
}

public next(): void {
this.currentStep += 1;
public open(component) {
//this.somedata = "" + Math.random();
this[component + 'Opened'] = true;
}

public prev(): void {
this.currentStep -= 1;
public action(status) {
console.log(`Dialog result: ${status}`);
this.dialogOpened = false;
}

public submit(): void {
this.submitted = true;

if (!this.form.valid) {
this.form.markAllAsTouched();
this.stepper.validateSteps();
}

console.log('Submitted data', this.form.value);
}
public min: Date = new Date(2015, 0, 1);
public max: Date = new Date(2030, 4, 31);

public registerForm: FormGroup = new FormGroup({
transID: new FormControl(),
submissionDate: new FormControl(new Date(2020, 0, 10)),
clientNames : new FormControl([1]),
brokers : new FormControl([2]),
referals : new FormControl([3]),
status: new FormControl(),
lender: new FormControl(),
limit: new FormControl(),
settlementDate: new FormControl(new Date(2020, 0, 9)),
});

public submitForm(): void {
this.registerForm.markAllAsTouched();
//this.action('yes');
}

ngOnInit(): void {
public clearForm(): void {
this.registerForm.reset();
//this.action('no');
}

public listClientNames: Array<{ text: string, value: number }> = [
{ text: 'John', value: 1 },
{ text: 'Steven', value: 2 },
{ text: 'William', value: 3 }
];

public statis: { text: string, value: number } = { text: 'Female', value: 2 };


}

+ 6
- 0
src/app/loan-detail/loan-detail.component.html View File

@@ -0,0 +1,6 @@

<p>loan-detail works!</p>

<div style="background-color:yellow;"> {{dataItem.Id}}</div>

<div style="background-color:yellow;"> {{dataItem.Client}}</div>

+ 0
- 0
src/app/loan-detail/loan-detail.component.scss View File


+ 25
- 0
src/app/loan-detail/loan-detail.component.spec.ts View File

@@ -0,0 +1,25 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';

import { LoanDetailComponent } from './loan-detail.component';

describe('LoanDetailComponent', () => {
let component: LoanDetailComponent;
let fixture: ComponentFixture<LoanDetailComponent>;

beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ LoanDetailComponent ]
})
.compileComponents();
});

beforeEach(() => {
fixture = TestBed.createComponent(LoanDetailComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
});
});

+ 16
- 0
src/app/loan-detail/loan-detail.component.ts View File

@@ -0,0 +1,16 @@
import {Component, Input, OnInit} from '@angular/core';

@Component({
selector: 'app-loan-detail',
templateUrl: './loan-detail.component.html',
styleUrls: ['./loan-detail.component.scss']
})
export class LoanDetailComponent implements OnInit {

@Input() public dataItem :any;
constructor() { }

ngOnInit(): void {
}

}

+ 94
- 68
src/app/loan-edit/basicinfo/basicinfo.component.html View File

@@ -1,79 +1,105 @@
<ng-container [formGroup]="basicInfo">
<fieldset class="k-form-fieldset">
<legend class="k-form-legend"></legend>
<kendo-formfield>
<kendo-label [for]="transID" text="Transaction ID"></kendo-label>
<input formControlName="transID" kendoTextBox #transID disabled/>
<div class="row">
<div class="col-sm-9">
<form class="k-form" [formGroup]="basicInfo" (ngSubmit)="next()">
<ng-container >
<fieldset class="k-form-fieldset">
<legend class="k-form-legend"></legend>
<kendo-formfield>
<kendo-label [for]="LoanId" text="Loan ID"></kendo-label>
<input formControlName="LoanId" kendoTextBox #LoanId />

<kendo-formhint>Unique transaction
ID from SuperCredit (Auto generated when save, cannot be changed) </kendo-formhint>
<kendo-formerror>Error: the ID is required</kendo-formerror>
</kendo-formfield>
<bkp-divider-shadow-bottom></bkp-divider-shadow-bottom>
<div class="vertical-spacer"></div>
<kendo-formhint>Unique transaction
ID from SuperCredit (Auto generated when save, cannot be changed) </kendo-formhint>
<kendo-formerror>Error: the ID is required</kendo-formerror>
</kendo-formfield>
<bkp-divider-shadow-bottom></bkp-divider-shadow-bottom>
<div class="vertical-spacer"></div>


<kendo-formfield>
<kendo-label [for]="status" [text]="'Progress Status'"></kendo-label>
<kendo-dropdownlist
#status
formControlName="status"
[data]="listLoanStatus"
[defaultItem]="{ text: 'Select Status', value: null }"
[textField]="'text'"
[valueField]="'value'"
required
>
</kendo-dropdownlist>
<kendo-formerror>Error: status is required</kendo-formerror>
</kendo-formfield>
<bkp-divider-shadow-bottom></bkp-divider-shadow-bottom>
<div class="vertical-spacer"></div>
<kendo-formfield>
<kendo-label [for]="Status" [text]="'Progress Status'" ></kendo-label>
<kendo-dropdownlist
#Status
formControlName="Status"
[data]="listLoanStatus"
[defaultItem]="{ text: 'Select Status', value: null }"
[textField]="'text'"
[valueField]="'value'"
required
[valuePrimitive] = "true"
>
</kendo-dropdownlist>
<kendo-formhint>cannot be changed after settlement</kendo-formhint>
<kendo-formerror>Error: status is required</kendo-formerror>
</kendo-formfield>
<div class="vertical-spacer"></div>

<kendo-formfield>
<kendo-label [for]="lender" text="Lender Organization">
</kendo-label>
<kendo-textbox formControlName="lender" #lender [clearButton]="true"></kendo-textbox>
<kendo-formhint>E.g. NAB Bank</kendo-formhint>
<kendo-formerror>Error: Lender is required</kendo-formerror>
</kendo-formfield>
<bkp-divider-shadow-bottom></bkp-divider-shadow-bottom>
<div class="vertical-spacer"></div>
<kendo-formfield>
<kendo-label [for]="Lender" text="Lender Organization">
</kendo-label>
<kendo-textbox (valueChange)="onLenderNameChange($event)"
formControlName="Lender" #Lender
[clearButton]="true"
></kendo-textbox>
<kendo-formhint>E.g. NAB Bank, cannot be changed after settlement</kendo-formhint>
<kendo-formerror>Error: Lender is required</kendo-formerror>
</kendo-formfield>
<div class="vertical-spacer"></div>

<kendo-formfield>
<kendo-label [for]="Item" text="Loan Target">
</kendo-label>
<kendo-textbox formControlName="Item" #Item [clearButton]="true" ></kendo-textbox>
<kendo-formhint>E.g. 333 Opera House, Sydney Road, NSW 2000 , cannot be changed after settlement</kendo-formhint>
<kendo-formerror>Loan Target is required</kendo-formerror>
</kendo-formfield>
<div class="vertical-spacer"></div>

<kendo-formfield>
<kendo-label [for]="amount" text="Loan Limit"> </kendo-label>
<kendo-textbox formControlName="amount" #amount [clearButton]="true"></kendo-textbox>
<kendo-formhint>E.g. 8000</kendo-formhint>
<kendo-formerror>Error: Limit should be between 100 ~ 1,000,000,000</kendo-formerror>
</kendo-formfield>
<bkp-divider-shadow-bottom></bkp-divider-shadow-bottom>
<div class="vertical-spacer"></div>

<kendo-formfield>
<kendo-label [for]="settlementDate" [optional]="false" text="Settlement Date"></kendo-label>
<kendo-datepicker #settlementDate formControlName="settlementDate"
[min]="minSettlement" [max]="maxSettlement">
</kendo-datepicker>
<kendo-formfield>
<kendo-label [for]="Amount" text="Loan Limit"> </kendo-label>
<kendo-numerictextbox formControlName="Amount" #Amount [min]="100" [max]="1000000000" [format]="'c0'"></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 class="vertical-spacer"></div>

<kendo-formhint>Date Settled</kendo-formhint>
</kendo-formfield>
<bkp-divider-shadow-bottom></bkp-divider-shadow-bottom>
<div class="vertical-spacer"></div>
<kendo-formfield>
<kendo-label [for]="Settlement" [optional]="false" text="Settlement Date"></kendo-label>
<kendo-datepicker #Settlement formControlName="Settlement"
[min]="minSettlement" [max]="maxSettlement">
</kendo-datepicker>
<kendo-formhint>Date Settled</kendo-formhint>
</kendo-formfield>
<bkp-divider-shadow-bottom></bkp-divider-shadow-bottom>


<kendo-formfield>
<kendo-label [for]="description" [optional]="false"
text="Quick notes: ( < 1000 words ) "></kendo-label>
<kendo-editor #description formControlName="description" style="height: 500px;"></kendo-editor>
</kendo-formfield>
<bkp-divider-shadow-bottom></bkp-divider-shadow-bottom>
<div class="vertical-spacer"></div>
<kendo-formfield>
<kendo-label [for]="Description" [optional]="false"
text="Quick notes: ( < 1000 words ) " (click)="showDemoDescription($event)"></kendo-label>
<kendo-editor #Description formControlName="Description" style="height: 500px;" ></kendo-editor>
</kendo-formfield>
<bkp-divider-shadow-bottom></bkp-divider-shadow-bottom>
<div class="vertical-spacer"></div>

<!-- <div class="k-form-buttons">
<button class="k-button k-primary"
(click)="submitForm()">Add New </button>
<button class="k-button" (click)="clearForm()">Clear</button>
</div> -->
</fieldset>
</ng-container>
<kendo-formfield>
<kendo-label [for]="Rating" [optional]="false"
text="Rating: " (click)="showDemoDescription($event)"></kendo-label>
<app-rating-input #Rating formControlName="Rating" ></app-rating-input>
</kendo-formfield>

</fieldset>
</ng-container>
<div class="k-form-buttons k-buttons-end">
<div>
<button class="k-button k-primary" type="submit" >Next ▶ </button>
</div>
</div>
</form>

<span class="k-form-separator"></span>
</div>
<div class="col-sm-3">
<app-loan-edit-hint-card [currentStep]="'basicInfo'"> </app-loan-edit-hint-card>
</div>
</div>

+ 5
- 0
src/app/loan-edit/basicinfo/basicinfo.component.scss View File

@@ -0,0 +1,5 @@
.vertical-spacer{
height:1px;
margin-bottom:20px;
}


+ 84
- 13
src/app/loan-edit/basicinfo/basicinfo.component.ts View File

@@ -1,5 +1,8 @@
import {Component, Input, OnInit} from '@angular/core';
import {FormGroup} from '@angular/forms';
import {Component, Input, OnInit, Output, EventEmitter} from '@angular/core';
import {FormControl, FormGroup, Validators} from '@angular/forms';
import {LoanModel} from '../../models/loan.model';
import {LoanSingleService} from '../../service/loan.single.service';


@Component({
selector: 'app-loan-basic-info',
@@ -8,10 +11,18 @@ import {FormGroup} from '@angular/forms';
})
export class BasicinfoComponent implements OnInit {

constructor( private service: LoanSingleService) { }

@Input() Loan: LoanModel;
@Output() lenderNameChanged = new EventEmitter<string>();
@Output() NotifyNext = new EventEmitter<boolean>();

public minSettlement: Date = new Date(2015, 0, 1);
public maxSettlement: Date = new Date(2030, 4, 31);

public value = `
public basicInfo: FormGroup ;

public DemoDescription = `
<h1> Rich Text Editing </h1>
<table>
<tr> <td>
@@ -26,19 +37,10 @@ export class BasicinfoComponent implements OnInit {
<img src="https://edge.alluremedia.com.au/uploads/businessinsider/2015/05/P2P-to-date.jpg"
width=300">
</td>
</tr> <tr>
<td colspan="2">
<a href="https://google.com.au"> click for more details </a>
</td>
</tr>
</table>
`;

constructor() { }

ngOnInit(): void {
}

public listLoanStatus: Array<{text: string, value: string}> = [
{text: '1 - Processing:   Just received from Client', value: 'Processing'} ,
{text: '2 - Valuation :   Valuating From Bank', value: 'Valuation'},
@@ -48,5 +50,74 @@ export class BasicinfoComponent implements OnInit {
{text: '6 - Finished :   Fully paid, terminated, or switched)', value: 'Finished'},
];

@Input() public basicInfo: FormGroup;
ngOnInit(): void {
this.basicInfo = new FormGroup({
LoanId: new FormControl({value: this.Loan.Id, disabled: true}),
Status: new FormControl(),
Item: new FormControl(this.Loan.Item, Validators.required),
Lender : new FormControl({value: 'SuperCredit', disabled: false}, Validators.required),
Amount: new FormControl(100, [Validators.required , Validators.min(100), Validators.max(1000000000)]),
Settlement: new FormControl(new Date(2020, 0, 9)),
Description: new FormControl( '', Validators.maxLength(2000)),
Rating: new FormControl({value: this.Loan.Rating, disabled: false}),
});
this.LoadBasic();
}

onLenderNameChange(value: string): void {
console.log('emit lender change');
this.lenderNameChanged.emit(value);
}

public next(): void {
this.basicInfo.markAllAsTouched();
// console.log(this.basicInfo, this.Loan);
this.Loan.Lender = this.basicInfo.value.Lender;
this.Loan.Status = this.basicInfo.value.Status;
this.Loan.Item = this.basicInfo.value.Item;
this.Loan.Amount = this.basicInfo.value.Amount;
this.Loan.Settlement = this.basicInfo.value.Settlement;
this.Loan.Description = this.basicInfo.value.Description;
this.Loan.Rating = this.basicInfo.value.Rating;
this.service.updateBasicInfo(this.Loan).subscribe(
resp => {
// console.log(resp);
// move to next step
this.NotifyNext.emit(true);
}
);
}

public loanStatus(value: string): {text: string, value: string} {
this.listLoanStatus.forEach(( v) => {
if (v.value = value) {
return v;
}
});
return null;
}

public showDemoDescription($event): void{
this.basicInfo.get('Description').setValue(this.DemoDescription);
}
public LoadBasic(): void {
if (this.Loan === undefined) {
return ;
}
this.basicInfo.get('LoanId').setValue(this.Loan.Id);
this.basicInfo.get('Lender').setValue(this.Loan.Lender);
this.lenderNameChanged.emit(this.basicInfo.get('Lender').value);
this.basicInfo.get('Status').setValue(this.Loan.Status);
this.basicInfo.get('Item').setValue(this.Loan.Item);
this.basicInfo.get('Amount').setValue(this.Loan.Amount);
this.basicInfo.get('Settlement').setValue(this.Loan.Settlement);
this.basicInfo.get('Description').setValue(this.Loan.Description);
this.basicInfo.get('Rating').setValue(this.Loan.Rating);
return ;
if ( this.Loan.Status === 'Settled') {
this.basicInfo.get('Status').disable({onlySelf: true, emitEvent: false});
this.basicInfo.get('Item').disable({onlySelf: true, emitEvent: false});
this.basicInfo.get('Amount').disable({onlySelf: true, emitEvent: false});
}
}
}

+ 1
- 1
src/app/loan-edit/hint-card/hint-card.component.html View File

@@ -7,7 +7,7 @@
[shape]="'circle'"
></kendo-avatar>
<div>
<h1 kendoCardTitle>bg_tourism</h1>
<h1 kendoCardTitle>bg_tourism - {{currentStep}}</h1>
<p kendoCardSubtitle>Bulgaria, Europe</p>
</div>
</kendo-card-header>

+ 2
- 1
src/app/loan-edit/hint-card/hint-card.component.ts View File

@@ -1,4 +1,4 @@
import { Component, OnInit } from '@angular/core';
import {Component, Input, OnInit} from '@angular/core';

@Component({
selector: 'app-loan-edit-hint-card',
@@ -7,6 +7,7 @@ import { Component, OnInit } from '@angular/core';
})
export class HintCardComponent implements OnInit {

@Input() currentStep: string;
constructor() { }

ngOnInit(): void {

+ 55
- 132
src/app/loan-edit/loan-edit.component.html View File

@@ -1,136 +1,59 @@
<div class="example-wrapper" style="opacity:1;">
<kendo-dialog title="Transaction" *ngIf="dialogOpened" (close)="close('dialog')" [minWidth]="500" [width]="850"
[minHeight]="600">
<div class="example-wrapper">
<div class="row">
<div class="col-xs-12 col-sm-12 ">
<div class="pane-content">
<form class="k-form" [formGroup]="registerForm">
<fieldset class="k-form-fieldset">
<legend class="k-form-legend">Bank Transaction Details</legend>
<kendo-formfield>
<kendo-label [for]="transID" text="Transaction ID"></kendo-label>
<input formControlName="transID" kendoTextBox #transID required />

<kendo-formhint>Unique transaction
ID from bank </kendo-formhint>
<kendo-formerror>Error: the ID is required</kendo-formerror>
</kendo-formfield>

<kendo-formfield>
<kendo-label [for]="submissionDate" [optional]="false"
text="Submission Date"></kendo-label>
<kendo-datepicker #submissionDate formControlName="submissionDate"
[min]="min" [max]="max">
</kendo-datepicker>

<kendo-formhint>Date in bank</kendo-formhint>
</kendo-formfield>

<kendo-formfield>
<kendo-label [for]="clientNames" [optional]="false"
text="Client Names"></kendo-label>
<kendo-multiselect
#clientNames
formControlName="clientNames"
[textField]="'text'"
[valueField]="'value'"
[valuePrimitive]="true"
[data]="listClientNames"
>
</kendo-multiselect>
</kendo-formfield>

<kendo-formfield>
<kendo-label [for]="brokers" [optional]="false"
text="Brokers Names"></kendo-label>
<kendo-multiselect
#brokers
formControlName="brokers"
[textField]="'text'"
[valueField]="'value'"
[valuePrimitive]="true"
[data]="listClientNames"
>
</kendo-multiselect>
</kendo-formfield>

<kendo-formfield>
<kendo-label [for]="referals" [optional]="false"
text="Referals/BDM"></kendo-label>
<kendo-multiselect
#referals
formControlName="referals"
[textField]="'text'"
[valueField]="'value'"
[valuePrimitive]="true"
[data]="listClientNames"
>
</kendo-multiselect>
</kendo-formfield>

<kendo-formfield>
<kendo-label [for]="status" [text]="'Progress Status'"></kendo-label>
<kendo-dropdownlist
#status
formControlName="status"
[data]="listClientNames"
[defaultItem]="{ text: 'Select Status', value: null }"
[textField]="'text'"
[valueField]="'value'"
required
>
</kendo-dropdownlist>
<kendo-formerror>Error: status is required</kendo-formerror>
</kendo-formfield>

<kendo-formfield>
<kendo-label [for]="lender" text="Lender Organization">
</kendo-label>
<input formControlName="lender" kendoTextBox #lender required />

<kendo-formhint>E.g. NAB Bank</kendo-formhint>
<kendo-formerror>Error: Lender is required</kendo-formerror>
</kendo-formfield>

<kendo-formfield>
<kendo-label [for]="limit" text="Loan Limit">
</kendo-label>
<input formControlName="limit" kendoTextBox #limit required />

<kendo-formhint>E.g. 8000</kendo-formhint>
<kendo-formerror>Error: Limit is required</kendo-formerror>
</kendo-formfield>

<kendo-formfield>
<kendo-label [for]="settlementDate" [optional]="false"
text="Settlement Date"></kendo-label>
<kendo-datepicker #settlementDate formControlName="settlementDate"
[min]="min" [max]="max">
</kendo-datepicker>
<div class="container outer">
<div class="container">
<bkp-divider-shadow-bottom></bkp-divider-shadow-bottom>

<div style="margin-top:20px;"></div>

<div class="row">
<div class="col-sm-12" class="stepper">
<kendo-stepper
#stepper
[steps]="steps"
[stepType]="'label'"
[(currentStep)]="currentStep"
[style.width.px]="570">
</kendo-stepper>
</div>
</div>
<span class="k-form-separator"></span>
<app-loan-basic-info *ngIf="currentStep === 0"
#basicInfo
[Loan]="Loan"
(lenderNameChanged)="onLenderNameChange($event)"
(NotifyNext) ="next(0)"
></app-loan-basic-info>
<app-loan-people-reward *ngIf="currentStep === 1"
[Loan]="Loan"
(NotifyNext) ="next(1)"
(NotifyPrev) ="prev(1)"
> </app-loan-people-reward>
<app-loan-trail-income *ngIf="currentStep === 2"
[Loan]="Loan"
[LenderName]="LenderName"
(NotifyPrev) ="prev(2)"
> </app-loan-trail-income>

<div class="row">
<div class="col-sm-12 delete-button">
Delete this Loan <kendo-switch [(ngModel)]="showDelete">Allow Delete</kendo-switch>
</div>
<div class="col-sm-12 delete-button" *ngIf="showDelete">
<div class="k-form-buttons k-buttons-end delete-button">
<button kendoButton icon="delete" class="k-button k-primary" (click)="del()" >Delete </button>
</div>
</div>

<kendo-formhint>Date Settled</kendo-formhint>
</kendo-formfield>
</div>
<div class="row">
<div class="col-sm-12">
<div class="vertical-spacer"></div>
<div class="vertical-spacer"></div>
<hr>
Proudly presented by SuperCredit.com
</div>
</div>
</div>
</div>

<!-- <div class="k-form-buttons">
<button class="k-button k-primary"
(click)="submitForm()">Add New </button>
<button class="k-button" (click)="clearForm()">Clear</button>
</div> -->
</fieldset>
</form>
</div>
</div>
</div>
</div>

<kendo-dialog-actions>
<button kendoButton (click)="clearForm()">Clear</button>
<button kendoButton (click)="submitForm()" primary="true">Add New</button>
</kendo-dialog-actions>
</kendo-dialog>

<kendo-window [minWidth]="200" [minHeight]="125" title="About" *ngIf="windowOpened" (close)="close('window')">
<p style="text-align: center;">Additional info</p>
</kendo-window>
</div>

+ 9
- 1
src/app/loan-edit/loan-edit.component.scss View File

@@ -1,3 +1,11 @@
.pane-content { padding: 0 10px; }

div.vertical-spacer {
height: 10px;
margin-bottom: 30px;
}

.delete-button{
text-align: right;
margin-top: 10px;
}


+ 54
- 51
src/app/loan-edit/loan-edit.component.ts View File

@@ -1,5 +1,9 @@
import { Component, OnInit, ViewChild } from '@angular/core';
import { FormControl, FormGroup, Validators } from '@angular/forms';
import {Component, OnInit, ViewChild, EventEmitter, Output} from '@angular/core';
import {FormControl, FormGroup, Validators} from '@angular/forms';
import {StepperComponent} from '@progress/kendo-angular-layout';
import {LoanSingleService} from '../service/loan.single.service';
import {LoanModel} from '../models/loan.model';
import {BasicinfoComponent} from './basicinfo/basicinfo.component';


@Component({
@@ -8,72 +12,71 @@ import { FormControl, FormGroup, Validators } from '@angular/forms';
styleUrls: ['./loan-edit.component.scss']
})
export class LoanEditComponent implements OnInit {
//popup
public dialogOpened = false;
public windowOpened = false;
public submitted: boolean ;
public currentStep = 0;
@ViewChild('stepper', { static: true }) public stepper: StepperComponent;
@ViewChild('basicInfo') public basicInfo: BasicinfoComponent;
@Output() LoanUpdated = new EventEmitter<LoanModel>();

//test
public somedata : string = "opened";

public Loan: LoanModel = new LoanModel('');
public LenderName: string;
public curStepError = false;

//form access
//@ViewChild('birthDate', {static: true}) birthDate: LoanEditComponent;
public showDelete = false;

constructor() { }
public steps = [
{ label: 'Basic Info', isValid: true , errMsg: 'There are some errors'},
{ label: 'People Reward', isValid: true , errMsg: 'There are some errors'},
{ label: 'Trail Income', isValid: true, errMsg: 'There are some errors' }
];

ngOnInit(): void {
}
constructor( private lss: LoanSingleService) { }

public close(component) {
this.somedata = "" + Math.random();
this[component + 'Opened'] = false;
public get currentStepError(): boolean{
const ret = false; // TODO: set the value
this.curStepError = ret;
return ret;
}

public open(component) {
//this.somedata = "" + Math.random();
this[component + 'Opened'] = true;
}
public next(step: number): void {
if (! this.currentStepError && (this.currentStep !== this.steps.length)) {
this.currentStep += 1;

public action(status) {
console.log(`Dialog result: ${status}`);
this.dialogOpened = false;
return;
}
this.stepper.validateSteps();
}

public prev(step: number): void {
this.currentStep -= 1;
}

public onLenderNameChange(value: string): void{
this.LenderName = value;
}

public min: Date = new Date(2015, 0, 1);
public max: Date = new Date(2030, 4, 31);

public registerForm: FormGroup = new FormGroup({
transID: new FormControl(),
submissionDate: new FormControl(new Date(2020, 0, 10)),
clientNames : new FormControl([1]),
brokers : new FormControl([2]),
referals : new FormControl([3]),
status: new FormControl(),
lender: new FormControl(),
limit: new FormControl(),
settlementDate: new FormControl(new Date(2020, 0, 9)),
});

public submitForm(): void {
this.registerForm.markAllAsTouched();
//this.action('yes');
ngOnInit(): void {
const demoId = '02ad4e5a-fb5c-4f29-bc89-381a49d77bb7';
this.loadLoanById(demoId);
}

public clearForm(): void {
this.registerForm.reset();
//this.action('no');
public del(): void {
console.log('delete loan', this.Loan.Id);
}
public listClientNames: Array<{ text: string, value: number }> = [
{ text: 'John', value: 1 },
{ text: 'Steven', value: 2 },
{ text: 'William', value: 3 }
];

public statis: { text: string, value: number } = { text: 'Female', value: 2 };

public loadLoanById(id: string): void {
const self = this;
console.log('loading loan ', this.Loan.Id);
this.lss.getLoan(id).subscribe(
resp => {
this.Loan.Response = resp;
this.Loan.apiUrlFunc = self.lss.apiUrlFunc();
self.LoanUpdated.emit(this.Loan);
self.basicInfo.LoadBasic();
}
);
}

}

+ 59
- 1
src/app/loan-edit/people-reward/people-reward.component.html View File

@@ -1 +1,59 @@
<p>people-reward works!</p>
<ng-container>
<fieldset class="k-form-fieldset">
<legend class="k-form-legend"></legend>
<div>SuperCredit Loan Id: {{Loan.Id}}</div>
<div class="vertical-spacer"></div>
<bkp-divider-shadow-bottom></bkp-divider-shadow-bottom>

<kendo-grid [data]="gridData"
[height]="410"
(add)="addHandler($event)"
(cancel)="cancelHandler($event)"
(save)="saveHandler($event)"
(edit)="editHandler($event)"
(remove)="removeHandler($event)"
>
<ng-template kendoGridToolbarTemplate>
<button kendoGridAddCommand>Add new</button>
</ng-template>

<kendo-grid-command-column title="command" width="220">
<ng-template kendoGridCellTemplate let-isNew="isNew" let-dataItem>
<button kendoGridEditCommand [primary]="true" *ngIf="!dataItem.Paid">Edit</button>
<button kendoGridRemoveCommand *ngIf="!dataItem.Paid" >Remove</button>
<button kendoGridSaveCommand [disabled]="formGroup?.invalid">{{ isNew ? 'Add' : 'Update' }}</button>
<button kendoGridCancelCommand>{{ isNew ? 'Discard changes' : 'Cancel' }}</button>
</ng-template>
</kendo-grid-command-column>

<kendo-grid-column field="To" title="Name" width="300">
<ng-template kendoGridCellTemplate let-dataItem>
<div class="customer-photo" [ngStyle]="{'background-image' : photoURL(dataItem.To) }"></div>
<div class="customer-name"> {{ UserName(dataItem) }}</div>
</ng-template>
<ng-template
kendoGridEditTemplate let-fg="formGroup" let-column="column" let-dataItem="dataItem">
<app-people-select [formControl]="formGroup.get('To')" [translateId]="true" [width]="200"></app-people-select>
</ng-template>

</kendo-grid-column>

<kendo-grid-column field="Description" title="Description" width="200"></kendo-grid-column>

</kendo-grid>



<bkp-divider-shadow-bottom></bkp-divider-shadow-bottom>
<div class="vertical-spacer"></div>
</fieldset>
</ng-container>

<div class="k-form-buttons k-buttons-end">
<div>
<button class="k-button k-primary" (click)="prev()" > ◀ Prev</button>
<button kendoButton look="flat" [disabled]="true">&nbsp;</button>
<button class="k-button k-primary" (click)="next()"> Next ▶</button>

</div>
</div>

+ 20
- 0
src/app/loan-edit/people-reward/people-reward.component.scss View File

@@ -0,0 +1,20 @@
.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;
margin-bottom: 10px;
}

.customer-name {
display: inline-block;
vertical-align: middle;
line-height: 32px;
padding-left: 10px;
}

+ 224
- 5
src/app/loan-edit/people-reward/people-reward.component.ts View File

@@ -1,5 +1,24 @@
import {Component, Input, OnInit} from '@angular/core';
import {FormGroup} from '@angular/forms';
import {Component, Input, OnInit, Output, EventEmitter} from '@angular/core';
import {FormControl, FormGroup, Validators} from '@angular/forms';
import {LoanSummaryService} from '../../service/loan_summary.service';
import {AuthService} from '../../service/auth.service';
import {LoanModel} from '../../models/loan.model';
import {Observable} from 'rxjs';
import {RewardModel} from '../../models/reward.model';
import {PeopleModel} from '../../models/people.model';
import {debounce} from 'ts-debounce';



const createFormGroup = dataItem => new FormGroup({
Id: new FormControl(dataItem.Id),
To: new FormControl(dataItem.To, Validators.required),
From: new FormControl(dataItem.From),
Role: new FormControl(dataItem.Role),
Amount: new FormControl(dataItem.Amount, Validators.compose([Validators.required, Validators.pattern('^[0-9]{1,3}')])),
Description: new FormControl(dataItem.Description),
PayOutId: new FormControl({value: dataItem.PaidOutId, disabled: dataItem.PayOutId > 0 })
});

@Component({
selector: 'app-loan-people-reward',
@@ -8,9 +27,209 @@ import {FormGroup} from '@angular/forms';
})
export class PeopleRewardComponent implements OnInit {

constructor() { }
@Input() public Loan: LoanModel;
@Output() public NotifyNext = new EventEmitter<boolean>();
@Output() public NotifyPrev = new EventEmitter<boolean>();

public contacts: PeopleModel[] = [];
public total = 0;

public gridData: RewardModel[] = [];
public data = [

{
RewardId: 14,
UserName: 'Alina Cox',
PeopleId: 'df743325-810d-4d25-bb52-91a1a0c3ba22',
Role: 'broker',
RewardDescription: 'Trail',
RewardAmount: 100,
Paid: false,
},

{
RewardId: 13,
UserName: 'Alina Cox',
PeopleId: 'df743325-810d-4d25-bb52-91a1a0c3ba22',
Role: 'broker',
RewardDescription: 'Trail',
RewardAmount: 100,
Paid: false,
},

{
RewardId: 12,
UserName: 'Alina Cox',
PeopleId: 'df743325-810d-4d25-bb52-91a1a0c3ba22',
Role: 'broker',
RewardDescription: 'broker fee',
RewardAmount: 100,
Paid: true,
},
{
RewardId: 11,
UserName: 'Helen Morgan',
PeopleId: '92dd6e14-10da-47ae-89ac-3a52d6567e61',
Role: 'Referral',
RewardDescription: 'no fee',
RewardAmount: 500,
Paid: true,
},
{
RewardId: 10,
UserName: 'Oscar Coudors',
PeopleId: '09aa4151-7744-422e-9f2c-90b4871018f3',
Role: 'Upfront',
RewardDescription: 'no fee',
RewardAmount: 3000,
Paid: true,
}


];
public formGroup: FormGroup;
private editedRowIndex: number;

public existingRoles: string[] = [
'Broker',
'Client',
'Referral',
'Admin'
];

private debounceFilter: any ;

constructor(private ls: LoanSummaryService, private auth: AuthService) {
}

public ngOnInit(): void {
// this.gridData = this.service.products();
Object.assign(this.gridData, this.Loan.Reward);
console.log(this.Loan, this.gridData);

this.debounceFilter = debounce( (filter: string): void => {
this.auth.getPeopleList(filter).subscribe(
resp => {
this.contacts = resp.List;
this.total = resp.Count;
console.log(resp);
}
);
}, 500) ;
}


public addHandler({ sender }): void {
this.closeEditor(sender);
this.formGroup = createFormGroup({
Id: 0,
To: '',
From: '',
Role: '',
Amount: 0,
Description: '',
PayOutId: 0,
});

sender.addRow(this.formGroup);
}

public editHandler({ sender, rowIndex, dataItem }): void {
this.closeEditor(sender);

if ( dataItem.Paid ) {
alert( 'cannot edit');
}else{
this.formGroup = createFormGroup(dataItem);

this.editedRowIndex = rowIndex;

sender.editRow(rowIndex, this.formGroup);
}

}

public cancelHandler({ sender, rowIndex }): void{
console.log(sender);
this.closeEditor(sender, rowIndex);
}

public saveHandler({ sender, rowIndex, formGroup, isNew }): void {
const product = formGroup.value;

console.log('"saving', product, formGroup);
// this.service.save(product, isNew);

sender.closeRow(rowIndex);
}

public removeHandler({ dataItem }): void {
console.log(dataItem);
// this.service.remove(dataItem);
}

private closeEditor(grid, rowIndex = this.editedRowIndex): void {
grid.closeRow(rowIndex);
this.editedRowIndex = undefined;
this.formGroup = undefined;
}

public onUserNameChanged(event: any, dataItem: any): void {
console.log(event, dataItem);
dataItem.UserId = 'fuck this user id';
// debounce
// console.log(event);
}

private photoURL(peopleId: string): string {
const url = this.auth.getUrl('avatar/') + peopleId;
return 'url("' + url + '")';
}

private UserName(dataItem: RewardModel): string {
return dataItem.UserName;
}

public next(): void{
this.NotifyNext.emit(true);
}

public prev(): void {
this.NotifyPrev.emit(true);
}

filterChange(filter: string): void {
if (filter.length > 1 ) {
this.debounceFilter(filter);
}
}


public getContactImageUrl(contactId: string): string {
return this.auth.getUrl('avatar/' + contactId);
}

public valueChange(value: any): void {
console.log('valueChange', value);
}

public selectionChange(value: any): void {
console.log('selectionChange', value);
}

public open(): void {
console.log('open');
}

public close(): void {
console.log('close');
}

public focus(): void {
console.log('focus');
}

ngOnInit(): void {
public blur(): void {
console.log('blur');
}
@Input() public peopleReward: FormGroup;
}

+ 41
- 0
src/app/loan-edit/people-select/people-select.component.html View File

@@ -0,0 +1,41 @@
<kendo-multicolumncombobox
#list
[data]="searchResult"
[(ngModel)]="value"
[textField]="'Display'"
[valueField]="getEffectiveField()"
[valuePrimitive]="true"

[listHeight]="300"
placeholder="Type here to search"
[suggest]="true"
[filterable]="true"
[clearButton]="true"
[allowCustom]="false"


(filterChange)="filterChange($event)"
(valueChange)="valueChange($event)"
>
<kendo-combobox-column
[field]="'Display'"
[title]="'Contact Name'"
[width]="width"
>
<ng-template
kendoMultiColumnComboBoxColumnCellTemplate
let-dataItem
>
<img
class="contact-image"
[src]="getContactImageUrl(dataItem.Id)"
/>
<span>{{ dataItem.First +' ' + dataItem.Last}}</span>
</ng-template>
</kendo-combobox-column>
<ng-template kendoMultiColumnComboBoxFooterTemplate>
<strong>
{{ total }} records in total
</strong>
</ng-template>
</kendo-multicolumncombobox>

+ 9
- 0
src/app/loan-edit/people-select/people-select.component.scss View File

@@ -0,0 +1,9 @@
kendo-multicolumncombobox {
width: 100%;
}
.contact-image {
width: 20px;
height: 20px;
margin-right: 8px;
border-radius: 50%;
}

+ 25
- 0
src/app/loan-edit/people-select/people-select.component.spec.ts View File

@@ -0,0 +1,25 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';

import { PeopleSelectComponent } from './people-select.component';

describe('PeopleSelectComponent', () => {
let component: PeopleSelectComponent;
let fixture: ComponentFixture<PeopleSelectComponent>;

beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ PeopleSelectComponent ]
})
.compileComponents();
});

beforeEach(() => {
fixture = TestBed.createComponent(PeopleSelectComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
});
});

+ 186
- 0
src/app/loan-edit/people-select/people-select.component.ts View File

@@ -0,0 +1,186 @@
import {Component, forwardRef, Input, OnInit, ViewChild} from '@angular/core';
import {AuthService} from '../../service/auth.service';
import { debounce } from 'ts-debounce';
import {PeopleModel} from '../../models/people.model';
import {ControlValueAccessor, FormControl, FormGroup, NG_VALUE_ACCESSOR} from '@angular/forms';
import {MultiColumnComboBoxComponent} from '@progress/kendo-angular-dropdowns';
import {Observable, of} from 'rxjs';
import {PercentPipe} from '@angular/common';
import {map} from 'rxjs/operators';


@Component({
selector: 'app-people-select',
templateUrl: './people-select.component.html',
styleUrls: ['./people-select.component.scss'],
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => PeopleSelectComponent),
multi: true
}
]
})
export class PeopleSelectComponent implements OnInit, ControlValueAccessor {

@Input() disabled = false;
@Input() translateId: false; // true to out user Id, false output user name
@Input() width: number;
@Input() formControl: FormControl = new FormControl(); // this is a dummy place holder
@ViewChild('list', {static: true}) public text: MultiColumnComboBoxComponent;

public searchResult: PeopleModel[] = [];
public value = ''; // selecting the default and only empty contact element
public total = 0;

private debounceFilter: any ;

// Function to call when the rating changes.
private onChange = ( nameOrId: string) => {};
// Function to call when the input is touched (when a star is clicked).
private onTouched = () => {};


constructor(private auth: AuthService) { }

ngOnInit(): void {
this.prepareSearchPeople();
}

private prepareSearchPeople(): void{
this.debounceFilter = debounce( (filter: string): void => {
this.auth.getPeopleList(filter).subscribe(
resp => {
this.text.loading = false;
this.searchResult = resp.List;
this.total = resp.Count;
},
error => { this.text.loading = false; },
() => { this.text.loading = false; }
);
}, 500) ;
}

getEffectiveField(): string {
return this.translateId ? 'Id' : 'Display';
}

filterChange(filter: string): void {
if ( filter.length > 0 ) {
this.text.loading = true;
this.debounceFilter(filter); // conduct search even if filter is empty
}
}

public getContactImageUrl(contactId: string): string {
return this.auth.getUrl('avatar/' + contactId);
}

// ComboBox emit event on value change
public valueChange(str: string): void {
console.log('value change', str);
this.onChange(this.value);
}

// public selectionChange(value: PeopleModel): void {
// this.onTouched();
// console.log('selectionChange', value);
// this.value = this.translateId ? value.Id : value.FullName;
// this.onChange(this.value);
// }

// public open(): void {
// this.onTouched();
// // console.log('open', this.text);
// }
//
// public close(): void {
// this.onTouched();
// // console.log('close', this.text);
// }
//
// public focus(): void {
// this.onTouched();
// // console.log('focus', this.text);
// }
//
// public blur(): void {
// // console.log('blur', this.text);
// }

// Allows Angular to update the model (name or ID).
// Update the model and changes needed for the view here.
writeValue(nameOrId: string): void {
if ( nameOrId === undefined ){
console.log('who called me for write', this);
return;
}
const changed = nameOrId !== this.value;
if (this.needSearch() ){
this.text.loading = true;
console.log('searching ... ', nameOrId, this.translateId? 'by id' : 'by name');
this.searchUser(nameOrId, this.translateId).subscribe(
ppl => {
const person = new PeopleModel(
ppl.Id,
ppl.First,
ppl.Last,
ppl.Middle,
ppl.Title,
ppl.Display,
ppl.Nick
);
console.log('got search result ', person);
this.searchResult.push(person); // make sure it's available for selection, thus proper display
this.value = this.translateId ? person.Id : person.FullName;
console.log('before update', this.text.value);
this.text.value = this.value;
console.log('after update', this.text.value);
}, error => { console.error(error); this.text.loading = false; },
() => {this.text.loading = false; }
);
if ( changed ) {
this.onChange(nameOrId);
}
}
}

needSearch(): boolean {
this.searchResult.forEach((person) => {
if ( this.translateId) {
if ( person.Id === this.value ) {
return false; // found in cache
}
}else{
if (person.FullName.includes(this.value)){
return false;
}
}
});
return true;
}

// Search a user either based on partial name or a complete ID
searchUser(nameOrId: string, translateId: boolean): Observable<PeopleModel>{
if ( translateId ) {
return PeopleModel.searchPersonById( nameOrId) ;
}else{
return PeopleModel.searchPersonByName(nameOrId) ;
}
}

// Allows Angular to register a function to call when the model (rating) changes.
// Save the function as a property to call later here.
registerOnChange(fn: (nameOrId: string) => void): void {
this.onChange = fn;
}
// Allows Angular to register a function to call when the input has been touched.
// Save the function as a property to call later here.
registerOnTouched(fn: () => void): void {
this.onTouched = fn;
}
// Allows Angular to disable the input.
setDisabledState(isDisabled: boolean): void {
this.disabled = isDisabled;
}
}

+ 71
- 1
src/app/loan-edit/trail-income/trail-income.component.html View File

@@ -1 +1,71 @@
<p>trail-income works!</p>
<div class="row">
<div class="col-sm-12">
<form class="k-form">
<ng-container [formGroup]="trailIncome">
<bkp-divider><kendo-icon [name]="'file-pdf'"> </kendo-icon>&nbsp;Record from {{LenderName}} </bkp-divider>

<kendo-label [for]="LoanIdLabel" text="SuperCredit Loan ID"></kendo-label>
<p #LoanIdLabel> {{Loan.Id}} </p>
<div class="vertical-spacer"></div>

<kendo-formfield>
<kendo-label [for]="LenderLoanNumber" text="Fund Supplier's Loan Identification"></kendo-label>
<input #LenderLoanNumber formControlName="LenderLoanNumber" kendoTextBox />
<kendo-formhint>Unique transaction ID from Funds supplier </kendo-formhint>
<kendo-formerror>Error: the ID is required</kendo-formerror>
</kendo-formfield>
<div class="vertical-spacer"></div>


<bkp-divider><kendo-icon [name]="'table'"> </kendo-icon> &nbsp; Monthly Income </bkp-divider>

<kendo-grid [data]="gridData"
[height]="410"
(add)="addHandler($event)"
(cancel)="cancelHandler($event)"
(save)="saveHandler($event)"
(edit)="editHandler($event)"
(remove)="removeHandler($event)"
>
<ng-template kendoGridToolbarTemplate>
<button kendoGridAddCommand>Add new</button>
</ng-template>

<kendo-grid-command-column title="command" width="220">
<ng-template kendoGridCellTemplate let-isNew="isNew" let-dataItem>
<button kendoGridEditCommand [primary]="true" *ngIf="!dataItem.Paid">Edit</button>
<button kendoGridRemoveCommand *ngIf="!dataItem.Paid" >Remove</button>
<button kendoGridSaveCommand [disabled]="formGroup?.invalid">{{ isNew ? 'Add' : 'Update' }}</button>
<button kendoGridCancelCommand>{{ isNew ? 'Discard changes' : 'Cancel' }}</button>
</ng-template>
</kendo-grid-command-column>

<kendo-grid-column field="Amount" title="Trail Received" width="200" format="{0:c}" editor="numeric">
</kendo-grid-column>

<kendo-grid-column field="Ts" title="Trail Date" width="200" editor="date">
<ng-template kendoGridCellTemplate let-dataItem>
{{ dataItem.Ts | date: 'yyyy-MM-dd' }}
</ng-template>
</kendo-grid-column>

<kendo-grid-column field="Balance" title="Balance" width="200" editor="numeric">
</kendo-grid-column>

<kendo-grid-column field="OffsetBalance" title="Offset Balance" width="200" editor="numeric">
</kendo-grid-column>

</kendo-grid>

<bkp-divider-shadow-bottom></bkp-divider-shadow-bottom>
<div class="vertical-spacer"></div>

</ng-container>
</form>
<div class="k-form-buttons k-buttons-end">
<div>
<button class="k-button k-primary" (click)="prev()" >◀ Prev</button>
</div>
</div>
</div>
</div>

+ 4
- 0
src/app/loan-edit/trail-income/trail-income.component.scss View File

@@ -0,0 +1,4 @@
div.vertical-spacer {
height: 10px;
margin-bottom: 30px;
}

+ 84
- 4
src/app/loan-edit/trail-income/trail-income.component.ts View File

@@ -1,5 +1,14 @@
import {Component, Input, OnInit} from '@angular/core';
import {FormGroup} from '@angular/forms';
import {Component, Input, OnInit, Output, EventEmitter} from '@angular/core';
import {FormControl, FormGroup, Validators} from '@angular/forms';
import {LoanModel} from '../../models/loan.model';


const createFormGroup = dataItem => new FormGroup({
Amount : new FormControl(dataItem.Amount),
Ts: new FormControl(dataItem.Ts),
Balance: new FormControl(dataItem.Balance),
OffsetBalance: new FormControl(dataItem.OffsetBalance),
});

@Component({
selector: 'app-loan-trail-income',
@@ -7,10 +16,81 @@ import {FormGroup} from '@angular/forms';
styleUrls: ['./trail-income.component.scss']
})
export class TrailIncomeComponent implements OnInit {
@Input() public Loan: LoanModel;
@Input() public LenderName: string;
@Output() public NotifyNext = new EventEmitter<boolean>();
@Output() public NotifyPrev = new EventEmitter<boolean>();

public gridData: any[] = [];

public formGroup: FormGroup;
private editedRowIndex: number;

public trailIncome: FormGroup = new FormGroup({
LenderLoanNumber: new FormControl(),
});

constructor() { }
ngOnInit(): void { }

public addHandler({ sender }): void {
this.closeEditor(sender);

this.formGroup = createFormGroup({
Amount: 1000,
Ts: new Date('2020-05-20'),
Balance: 800000,
OffsetBalance: 600000
});

sender.addRow(this.formGroup);
}

public editHandler({ sender, rowIndex, dataItem }): void {
this.closeEditor(sender);

if ( dataItem.Paid ) {
alert( 'cannot edit');
}else{
this.formGroup = createFormGroup(dataItem);

this.editedRowIndex = rowIndex;

sender.editRow(rowIndex, this.formGroup);
}

}

public cancelHandler({ sender, rowIndex }): void {
console.log(sender);
this.closeEditor(sender, rowIndex);
}

public saveHandler({ sender, rowIndex, formGroup, isNew }): void {
const product = formGroup.value;

console.log('saving', product, formGroup);
// this.service.save(product, isNew);

sender.closeRow(rowIndex);
}

public removeHandler({ dataItem }): void {
console.log(dataItem);
// this.service.remove(dataItem);
}

private closeEditor(grid, rowIndex = this.editedRowIndex): void{
grid.closeRow(rowIndex);
this.editedRowIndex = undefined;
this.formGroup = undefined;
}

public next(): void{
this.NotifyNext.emit(true);
}

ngOnInit(): void {
public prev(): void {
this.NotifyPrev.emit(true);
}
@Input() public trailIncome: FormGroup;
}

+ 4
- 6
src/app/main-menu-items.ts View File

@@ -18,20 +18,18 @@ export const mainMenuItems: any[] = [
text: 'Loans',
icon: 'dollar',
items: [
{ text: 'Add+', icon: 'plus', popup: "loanEdit" },
{ text: 'Start New Loan', icon: 'plus', url: "./#start-a-new-loan" },
{ 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: 'Reward',
icon: 'percent',
items: [
{ text: 'List All', icon: 'table', url: '#' },
{ text: 'List All', icon: 'table', url: '#' },
{ text: 'By Broker', icon: 'table', url: '#' },
{ text: '--', separator: "true" },
{ text: 'Import From ...', icon : 'upload'}
{ text: 'PaidImport From ...', icon : 'upload'}
]
},
{

+ 19
- 0
src/app/models/broker.model.ts View File

@@ -0,0 +1,19 @@

export class BrokerModel{
Id: string;
First: string;
Last: string;
Middle: string;
Title: string;
Display: string;
Nick: string;

Login: string;
Enabled: boolean;

BSB: string;
ACC: string;
License: string;
Organization: string;

}

+ 121
- 0
src/app/models/loan.model.ts View File

@@ -0,0 +1,121 @@
import { PeopleModel } from "./people.model";
import {PeopleMapModel} from './people-map.model';
import {BrokerModel} from './broker.model';
import {PayInModel} from './pay-in.model';
import {RewardModel} from './reward.model';
import {ApiUrL} from '../service/auth.service';

export interface LoanModelCallBacks {
getUserName(userId: string): string;
getUserPhotoUrl(userId: string): string;
getUserRole(userId: string): string;
}


export class LoanModel {
constructor(
public Id: string,
public Amount?: number,
public Status?: string,
public Item?: string,
public Rating?: number,
public Settlement?: Date,
public Description?: string,

public Lender?: string,
public Client?: PeopleModel[],
public Broker?: BrokerModel[],
public OtherRewarder?: PeopleModel[],
public Reward?: RewardModel[],
public PayIn?: PayInModel[],
public PeopleMap?: PeopleMapModel[],

public apiUrlFunc?: ApiUrL
){}

public set Response(resp: LoanModel) {
this.Id = resp.Id;

this.Amount = resp.Amount;
this.Item = resp.Item;
this.Rating = resp.Rating;
this.Status = resp.Status;
this.Settlement = new Date(resp.Settlement);
this.Description = resp.Description;

this.Lender = resp.Lender;
this.Client = resp.Client;
this.Broker = resp.Broker;
this.OtherRewarder = resp.OtherRewarder;
this.setReward(resp.Reward);
this.PeopleMap = resp.PeopleMap;
this.PayIn = resp.PayIn;
}

private setReward(v: any[]): void{
this.Reward = [];
v.forEach((reward) => {
const r = new RewardModel(
reward.Amount,
reward.Description,
reward.Id,
reward.LoanId,
reward.PayOutId,
reward.To,
reward.From,
reward.Ts,
this.callBacks()
);
this.Reward.push(r);
});
return;
}

public emptyReward(): RewardModel {
return new RewardModel(
0, '', 0, this.Id,
0, '', '', new Date(), this.callBacks()
);
}

private callBacks(): LoanModelCallBacks {
return {
getUserName: this.getUserName.bind(this),
getUserPhotoUrl: this.getUserPhotoUrl.bind(this),
getUserRole: this.getUserRole.bind(this)
};
}

public getUserName(id: string): string {
// search client
this.Client.forEach(( c => {
if ( c.Id === id ) {
return c.First + ' ' + c.Last;
}
}));

this.Broker.forEach(( c => {
if ( c.Id === id ) {
return c.First + ' ' + c.Last;
}
}));

this.OtherRewarder.forEach(( c => {
if ( c.Id === id ) {
return c.First + ' ' + c.Last;
}
}));

return 'P:' + id;
}

public getUserPhotoUrl(id: string): string {
const url = this.apiUrlFunc.getUrl('avatar/') + id;
return 'url("' + url + '")';
}

public getUserRole(id: string): string {
return 'role' + id;
}

}

+ 4
- 0
src/app/models/pay-in.model.ts View File

@@ -0,0 +1,4 @@

export class PayInModel {
Id: number;
}

+ 18
- 0
src/app/models/payout-audit.model.ts View File

@@ -0,0 +1,18 @@
export class PayoutAudit{
id: string;

//parent
payOut: string;

//date
when : Date;

//by who, at least 2
who : string ;

//for what? edit? paid?
what: string;

//ip
ip: string;
}

+ 29
- 0
src/app/models/payout.model.ts View File

@@ -0,0 +1,29 @@
import { PayoutAudit } from "./payout-audit.model";

export class PayOutModel{
id: string;

//parent
loan: string

//parties
id_user: string
role: string;

//
amount: number;

//paid
paid: boolean;
paid_date: Date;
paid_to: string; //bank details;

//confirmed, by receiptient
confirmed: boolean;

//source
source?: string;

//audit
audits: PayoutAudit[];
}

+ 3
- 0
src/app/models/people-map.model.ts View File

@@ -0,0 +1,3 @@
export class PeopleMapModel {

}

+ 57
- 0
src/app/models/people.model.ts View File

@@ -0,0 +1,57 @@
import {Observable} from 'rxjs';

export class PeopleModel{
constructor(
public Id: string,
public First: string,
public Last: string,
public Middle: string,
public Title: string,
public Display: string,
public Nick: string,
){}

get FullName(): string {
if (this.Middle === '') {
return this.First + ' ' + this.Last;
}else{
return this.First + ' ' + this.Middle + ' ' + this.Last;
}
}

static searchPersonByName(name: string): Observable<PeopleModel>{
return new Observable ( observer => {
const dummy: PeopleModel = new PeopleModel(
'dummy-id',
'FSearch',
'LResult',
'',
'Mr.',
'Display Name',
'Nick Name'
);
setTimeout(() => {
observer.next(dummy);
observer.complete();
}, 1000);
});
}

static searchPersonById( id: string): Observable<PeopleModel> {
return new Observable ( observer => {
const dummy: PeopleModel = new PeopleModel(
id,
'FSearch',
'LResult',
'',
'Mr.',
'P:' + id,
'Nick Name'
);
setTimeout(() => {
observer.next(dummy);
observer.complete();
}, 1000);
});
}
}

+ 39
- 0
src/app/models/reward.model.ts View File

@@ -0,0 +1,39 @@
import {LoanModelCallBacks} from './loan.model';

export class RewardModel {
constructor(
public Amount: number,
public Description: string,
public Id: number,
public LoanId: string,
public PayOutId: number,
public To: string,
public From: string,
public Ts: Date,
private lc: LoanModelCallBacks
){}

public get Role(): string {
return this.lc.getUserRole(this.To);
}

public get UserId(): string {
return this.To;
}

public set UserId(v) {
this.To = v;
}

public get UserName(): string {
return this.lc.getUserName(this.To);
}

public get photoUrlTo(): string{
return this.lc.getUserPhotoUrl(this.To);
}

public get photoUrlFrom(): string{
return this.lc.getUserPhotoUrl(this.From);
}
}

+ 10
- 0
src/app/rating-input/rating-input.component.html View File

@@ -0,0 +1,10 @@
<span
*ngFor="let starred of stars; let i = index"
(click)="onTouched(); rate(i + (starred ? (value > i + 1 ? 1 : 0) : 1))">
<ng-container *ngIf="starred; else noStar">
<span ngClass='k-icon k-i-star yellow'></span>
</ng-container>
<ng-template #noStar>
<span ngClass="k-icon k-i-star-outline "></span>
</ng-template>
</span>

+ 11
- 0
src/app/rating-input/rating-input.component.scss View File

@@ -0,0 +1,11 @@
span {
display: inline-block;
width: 25px;
line-height: 25px;
text-align: center;
cursor: pointer;
}

.yellow {
color: #ffa600;
}

+ 25
- 0
src/app/rating-input/rating-input.component.spec.ts View File

@@ -0,0 +1,25 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';

import { RatingInputComponent } from './rating-input.component';

describe('RatingInputComponent', () => {
let component: RatingInputComponent;
let fixture: ComponentFixture<RatingInputComponent>;

beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ RatingInputComponent ]
})
.compileComponents();
});

beforeEach(() => {
fixture = TestBed.createComponent(RatingInputComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
});
});

+ 65
- 0
src/app/rating-input/rating-input.component.ts View File

@@ -0,0 +1,65 @@
import {Component, forwardRef, HostBinding, Input, OnInit} from '@angular/core';
import {ControlValueAccessor, NG_VALUE_ACCESSOR} from '@angular/forms';

@Component({
selector: 'app-rating-input',
templateUrl: './rating-input.component.html',
styleUrls: ['./rating-input.component.scss'],
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => RatingInputComponent),
multi: true
}
],
})
export class RatingInputComponent implements OnInit, ControlValueAccessor {
stars: boolean[] = Array(5).fill(false);

// Allow the input to be disabled, and when it is make it somewhat transparent.
@Input() disabled = false;
@HostBinding('style.opacity')
get opacity(): number {
return this.disabled ? 0.25 : 1;
}

constructor() { }

ngOnInit(): void {
}

// Function to call when the rating changes.
onChange = (rating: number) => {};
// Function to call when the input is touched (when a star is clicked).
onTouched = () => {};
get value(): number {
return this.stars.reduce((total, starred) => {
return total + (starred ? 1 : 0);
}, 0);
}
rate(rating: number) {
if (!this.disabled) {
this.writeValue(rating);
}
}
// Allows Angular to update the model (rating).
// Update the model and changes needed for the view here.
writeValue(rating: number): void {
this.stars = this.stars.map((_, i) => rating > i);
this.onChange(this.value)
}
// Allows Angular to register a function to call when the model (rating) changes.
// Save the function as a property to call later here.
registerOnChange(fn: (rating: number) => void): void {
this.onChange = fn;
}
// Allows Angular to register a function to call when the input has been touched.
// Save the function as a property to call later here.
registerOnTouched(fn: () => void): void {
this.onTouched = fn;
}
// Allows Angular to disable the input.
setDisabledState(isDisabled: boolean): void {
this.disabled = isDisabled;
}
}

src/app/transaction-list/rating.component.ts → src/app/rating-input/rating.component.ts View File

@@ -1,7 +1,7 @@
import { Component, OnInit, Input } from '@angular/core';

@Component({
selector: 'kendo-rating',
selector: 'app-biukop-rating',
template: `
<span *ngFor="let item of stars" [ngClass]="ratingIcon(item)"></span>
`,
@@ -24,4 +24,4 @@ export class RatingComponent implements OnInit {
public ratingIcon(item: number): string {
return (item <= this.value) ? 'k-icon k-i-star yellow' : 'k-icon k-i-star-outline';
}
}
}

+ 36
- 18
src/app/service/auth.service.ts View File

@@ -1,17 +1,24 @@
import {EventEmitter, Injectable, OnDestroy, OnInit} from '@angular/core';
import { NotificationService } from '@progress/kendo-angular-notification';
import {HttpClient, HttpEvent, HttpHandler, HttpInterceptor, HttpRequest} from '@angular/common/http';
import {HttpClient, HttpEvent, HttpHandler, HttpInterceptor, HttpParams, HttpRequest} from '@angular/common/http';
import {apiV1LoginResponse} from '../models/api-v1-login-response';
import {Observable} from 'rxjs';
import {AppComponent} from '../app.component';
import {Router} from '@angular/router';
import {PeopleModel} from '../models/people.model';

export interface ApiUrL {
getUrl(key: string): string;
};

@Injectable()
export class AuthService {

public apiUrl = 'https://svr2021.lawipac.com:8080/api/v1/';
public apiWsUrl = 'wss://svr2021.lawipac.com:8080/api/v1/ws';
public loggedIn = new apiV1LoginResponse(false, '', '',0 );
// public apiUrl = 'https://c5016.biukop.com.au:8080/api/v1/';
// public apiWsUrl = 'wss://c5016.biukop.com.au:8080/api/v1/ws';
public loggedIn = new apiV1LoginResponse(false, '', '', 0 );
loginSuccess = new EventEmitter <apiV1LoginResponse>();

constructor( private http: HttpClient ,
@@ -19,8 +26,7 @@ export class AuthService {
}


// tslint:disable-next-line:typedef
public AutoLogin() {
public AutoLogin(): void {
const sfm: apiV1LoginResponse = JSON.parse(localStorage.getItem('sfm'));
if (!sfm) {
console.log('no auto login');
@@ -33,11 +39,11 @@ export class AuthService {
sfm.sessionExpire
);
this.loginSuccess.emit(this.loggedIn);
//console.log ( 'auto login emit events', this.loggedIn);
// console.log ( 'auto login emit events', this.loggedIn);
}

// tslint:disable-next-line:typedef
isAuthenticated() {
isAuthenticated(): boolean {
return this.loggedIn.login;
}

@@ -45,8 +51,12 @@ export class AuthService {
return true;
}

// tslint:disable-next-line:typedef
login(email: string, password: string) {
saveSessionInfo(): void {
localStorage.setItem('sfm', JSON.stringify(this.loggedIn));
localStorage.setItem('mid', this.loggedIn.machineId);
}

login(email: string, password: string): void {

this.http.post<apiV1LoginResponse>(this.apiUrl + 'login', {u: email, p: password}).subscribe(
responseData => {
@@ -54,12 +64,11 @@ export class AuthService {
this.loggedIn.login = responseData.login;
this.loggedIn.machineId = responseData['Biukop-Mid'];
this.loggedIn.sessionExpire = responseData.sessionExpire;
localStorage.setItem('sfm', JSON.stringify(this.loggedIn));
localStorage.setItem('mid', this.loggedIn.machineId);
this.saveSessionInfo();
this.loginSuccess.emit(responseData);
},
error => {
const fail = new apiV1LoginResponse(false,'','',0);
const fail = new apiV1LoginResponse(false, '', '', 0);
this.loggedIn = fail;
console.log('login error', error);
this.loginSuccess.emit(this.loggedIn);
@@ -68,12 +77,11 @@ export class AuthService {
);
}

// tslint:disable-next-line:typedef
logout() {
this.loggedIn = new apiV1LoginResponse(false,'','',0);
logout(): void {
this.loggedIn = new apiV1LoginResponse(false, '', '', 0);
localStorage.removeItem('sfm');
this.loginSuccess.emit(this.loggedIn);
this.router.navigate(['/login']).then(r =>{
this.router.navigate(['/login']).then(r => {
console.log('prepare to log back in');
} );
this.http.post(`${this.apiUrl}logout`, '').subscribe(
@@ -87,7 +95,6 @@ export class AuthService {
}


// tslint:disable-next-line:variable-name
public getUrl(key: string): string{
const s = this.apiUrl + key;
const kvPair: {key: string, value: string}[] = [
@@ -103,4 +110,15 @@ export class AuthService {

// not found if arrive here
return s;
}}
}

public apiUrlFunc(): ApiUrL {
return {
getUrl: this.getUrl.bind(this)
};
}
public getPeopleList(filter: string): Observable<{Count: number, List: PeopleModel[]}> {
const params = new HttpParams().set('filter', filter);
return this.http.get<{Count:number, List: PeopleModel[]}>(this.apiUrl + 'people-list', { params});
}
}

+ 28
- 0
src/app/service/loan.single.service.ts View File

@@ -0,0 +1,28 @@
import {HttpClient} from '@angular/common/http';
import {ApiUrL, AuthService} from './auth.service';
import {Observable} from 'rxjs';
import {LoanModel} from '../models/loan.model';
import {Injectable} from '@angular/core';

@Injectable()
export class LoanSingleService {

constructor(private http: HttpClient, private auth: AuthService ){ }

getLoan(loanId: string): Observable<LoanModel> {
return this.http.get<LoanModel>(this.auth.getUrl('loan/' + loanId));
}

public updateBasicInfo(loan: LoanModel): Observable<any>{
return this.http.post(this.auth.getUrl('loan/basic/' + loan.Id), loan);
}

public photoUrl(peopleId: string): string{
const url = this.auth.getUrl('avatar/') + peopleId;
return 'url("' + url + '")';
}

public apiUrlFunc(): ApiUrL {
return this.auth.apiUrlFunc();
}
}

+ 3
- 4
src/app/service/loan_summary.service.ts View File

@@ -1,7 +1,6 @@
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';
@@ -11,7 +10,7 @@ export abstract class LoanQueryService extends BehaviorSubject<GridDataResult> {

private BASE_URL = '';

constructor(
protected constructor(
private http: HttpClient,
private auth: AuthService,
protected tableName: string
@@ -39,7 +38,7 @@ export abstract class LoanQueryService extends BehaviorSubject<GridDataResult> {
// console.log(index, response.data[index].Settlement , typeof response.data[index].Settlement );
// console.log(index, response.data[index].LastPayInDate , typeof response.data[index].LastPayInDate );
});
console.log(response);
// console.log(response);
return response;
}),
tap(() => this.loading = false)
@@ -48,7 +47,7 @@ export abstract class LoanQueryService extends BehaviorSubject<GridDataResult> {

public convertToDateTimeObject(str: string): Date{
if (str === '0001-01-01T00:00:00Z' || str === ''){
return null; //new Date('1900-12-31T13:00:00.000Z');
return null; // new Date('1900-12-31T13:00:00.000Z');
}else{
return new Date(str);
}

+ 10
- 10
src/app/transaction-list/transaction-list.component.html View File

@@ -10,7 +10,7 @@ kendoGridSelectBy="id"
[resizable]="true"
[height] = "700"
class="fullheight_grid"
[columnMenu]="{ filter: true }"
[columnMenu]="{ filter: true }"
>
<ng-template kendoGridToolbarTemplate>
<input placeholder="Search in all columns..." kendoTextBox (input)="onFilter($event.target.value)"/>
@@ -35,7 +35,7 @@ class="fullheight_grid"
<kendo-grid-column field="brokers" title="Brokers" [width]="220">
</kendo-grid-column>
<kendo-grid-column field="bdm" title="BDM/Referals" [width]="220">
</kendo-grid-column>
</kendo-grid-column>
<kendo-grid-column
field="country"
title="Country"
@@ -50,7 +50,7 @@ class="fullheight_grid"
</kendo-grid-column-group>
<kendo-grid-column-group title="Loan Information" [columnMenu]="false">
<kendo-grid-column field="status" title="Status" [width]="220">
</kendo-grid-column>
</kendo-grid-column>

<kendo-grid-column
field="status"
@@ -74,10 +74,10 @@ class="fullheight_grid"
<ng-template kendoGridCellTemplate let-dataItem>
<span [ngClass]="{'red text-bold': dataItem.loan_limit < 1000000}">{{ dataItem.loan_limit | currency }}</span>
</ng-template>
</kendo-grid-column>
</kendo-grid-column>

<kendo-grid-column field="lender" title="Lender" [width]="100">
</kendo-grid-column>
</kendo-grid-column>

<!-- <kendo-grid-column
field="is_online"
@@ -101,10 +101,10 @@ class="fullheight_grid"
filter="numeric"
>
<ng-template kendoGridCellTemplate let-dataItem>
<kendo-rating
<app-biukop-rating
[value]="dataItem.rating"
[max]="5"
></kendo-rating>
></app-biukop-rating>
</ng-template>
</kendo-grid-column>
<kendo-grid-column
@@ -147,13 +147,13 @@ class="fullheight_grid"
<ng-template kendoGridCellTemplate let-dataItem>
{{dataItem.submittsion_date | date: 'yyyy-MM-dd'}}
</ng-template>
</kendo-grid-column>
</kendo-grid-column>

<kendo-grid-column field="settlement_date" width="200" title="Settlement Date">
<ng-template kendoGridCellTemplate let-dataItem>
{{dataItem.settlement_date | date: 'yyyy-MM-dd'}}
</ng-template>
</kendo-grid-column>
</kendo-grid-column>
</kendo-grid-column-group>

<kendo-grid-pdf fileName="Transaction.pdf" [repeatHeaders]="true"></kendo-grid-pdf>
@@ -163,4 +163,4 @@ class="fullheight_grid"
some details {{dataItem.id}}
<trans-details [item]="dataItem"></trans-details>
</div>
</kendo-grid>
</kendo-grid>

Loading…
Cancel
Save