| "scripts": { | "scripts": { | ||||
| "ng": "ng", | "ng": "ng", | ||||
| "start": "ng serve --proxy-config proxy.conf.json", | "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", | "test": "ng test", | ||||
| "lint": "ng lint", | "lint": "ng lint", | ||||
| "e2e": "ng e2e" | "e2e": "ng e2e" | ||||
| }, | }, | ||||
| "private": true, | "private": true, | ||||
| "dependencies": { | "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", | "@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", | "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": { | "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-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-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", | "protractor": "~7.0.0", | ||||
| "ts-node": "~8.3.0", | |||||
| "ts-node": "~9.1.1", | |||||
| "tslint": "~6.1.0", | "tslint": "~6.1.0", | ||||
| "typescript": "~4.0.2" | |||||
| "typescript": "^4.1.5" | |||||
| } | } | ||||
| } | } |
| import { TransactionComponent } from './transaction/transaction.component'; | import { TransactionComponent } from './transaction/transaction.component'; | ||||
| import {ListAllLoansComponent} from './list-all-loans/list-all-loans.component'; | import {ListAllLoansComponent} from './list-all-loans/list-all-loans.component'; | ||||
| import {LoanAddNewComponent} from './loan-add-new/loan-add-new.component'; | import {LoanAddNewComponent} from './loan-add-new/loan-add-new.component'; | ||||
| import {LoanEditComponent} from './loan-edit/loan-edit.component'; | |||||
| const routes: Routes = [ | const routes: Routes = [ | ||||
| {path : 'transaction', component: TransactionComponent, canActivate: [AuthGuard]}, | {path : 'transaction', component: TransactionComponent, canActivate: [AuthGuard]}, | ||||
| {path : 'transaction-list', component: TransactionListComponent, canActivate: [AuthGuard]}, | {path : 'transaction-list', component: TransactionListComponent, canActivate: [AuthGuard]}, | ||||
| {path : 'list-all-loans', component: ListAllLoansComponent, }, | {path : 'list-all-loans', component: ListAllLoansComponent, }, | ||||
| {path : 'start-a-new-loan', component: LoanAddNewComponent, }, | |||||
| {path : 'start-a-new-loan', component: LoanEditComponent, }, | |||||
| ]; | ]; | ||||
| @NgModule({ | @NgModule({ |
| <app-top-bar></app-top-bar> | <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> | <router-outlet></router-outlet> | ||||
| (item:any) =>{ | (item:any) =>{ | ||||
| // console.log("emit on select : " + item.text); | // console.log("emit on select : " + item.text); | ||||
| if ( item.popup === 'loanEdit'){ | if ( item.popup === 'loanEdit'){ | ||||
| this.loanEdit.somedata = '' + Math.random() + 'changed'; | |||||
| this.loanEdit.open('dialog'); | |||||
| // this.loanEdit.somedata = '' + Math.random() + 'changed'; | |||||
| // this.loanEdit.open('dialog'); | |||||
| } | } | ||||
| } | } | ||||
| ); | ); |
| import { TransactionComponent } from './transaction/transaction.component'; | import { TransactionComponent } from './transaction/transaction.component'; | ||||
| import { TransactionListComponent } from './transaction-list/transaction-list.component'; | import { TransactionListComponent } from './transaction-list/transaction-list.component'; | ||||
| import { ExcelExportModule } from '@progress/kendo-angular-excel-export'; | 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 { TransDetailsComponent } from './trans-details/trans-details.component'; | ||||
| import { TransTailsComponent } from './trans-details/trans-tails/trans-tails.component'; | import { TransTailsComponent } from './trans-details/trans-tails/trans-tails.component'; | ||||
| import {AuthHttpInterceptor} from './auth/auth-http-interceptor.service'; | import {AuthHttpInterceptor} from './auth/auth-http-interceptor.service'; | ||||
| import { PeopleRewardComponent } from './loan-edit/people-reward/people-reward.component'; | import { PeopleRewardComponent } from './loan-edit/people-reward/people-reward.component'; | ||||
| import { TrailIncomeComponent } from './loan-edit/trail-income/trail-income.component'; | import { TrailIncomeComponent } from './loan-edit/trail-income/trail-income.component'; | ||||
| import { HintCardComponent } from './loan-edit/hint-card/hint-card.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'; | |||||
| BasicinfoComponent, | BasicinfoComponent, | ||||
| PeopleRewardComponent, | PeopleRewardComponent, | ||||
| TrailIncomeComponent, | TrailIncomeComponent, | ||||
| HintCardComponent | |||||
| HintCardComponent, | |||||
| PeopleSelectComponent, | |||||
| LoanDetailComponent, | |||||
| RatingInputComponent | |||||
| ], | ], | ||||
| imports: [ | imports: [ | ||||
| BrowserModule, | BrowserModule, | ||||
| BrowserAnimationsModule, | |||||
| FormsModule, | FormsModule, | ||||
| CommonModule, | CommonModule, | ||||
| HttpClientModule, | HttpClientModule, | ||||
| AuthService, | AuthService, | ||||
| WebSocketService, | WebSocketService, | ||||
| LoanSummaryService, | LoanSummaryService, | ||||
| LoanSingleService, | |||||
| { | { | ||||
| provide: HTTP_INTERCEPTORS, | provide: HTTP_INTERCEPTORS, | ||||
| useClass: AuthHttpInterceptor, | useClass: AuthHttpInterceptor, |
| import {Injectable} from '@angular/core'; | 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 {Observable} from 'rxjs'; | ||||
| import {AuthService} from '../service/auth.service'; | import {AuthService} from '../service/auth.service'; | ||||
| import {tap} from 'rxjs/operators'; | import {tap} from 'rxjs/operators'; | ||||
| intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { | intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { | ||||
| let h = req.headers; | let h = req.headers; | ||||
| if (this.auth.loggedIn.hasValidSession()) { | if (this.auth.loggedIn.hasValidSession()) { | ||||
| h = h.set('Biukop-Session', this.auth.loggedIn.session); | h = h.set('Biukop-Session', this.auth.loggedIn.session); | ||||
| } | } | ||||
| }); | }); | ||||
| return next.handle(authReq).pipe( | return next.handle(authReq).pipe( | ||||
| tap(event => { | tap(event => { | ||||
| //console.log(event); | |||||
| // console.log(event); | |||||
| if (event.type === HttpEventType.Response){ | 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); | |||||
| } | |||||
| } | |||||
| } | } | ||||
| }) | }) | ||||
| ); | ); |
| constructor(private authService: AuthService, private router: Router, private notificationService: NotificationService) { } | constructor(private authService: AuthService, private router: Router, private notificationService: NotificationService) { } | ||||
| ngOnInit(): void { | ngOnInit(): void { | ||||
| this.authService.logout(); | |||||
| this.loginSub = this.authService.loginSuccess.subscribe( | this.loginSub = this.authService.loginSuccess.subscribe( | ||||
| responseData => { | responseData => { | ||||
| // console.log(responseData); | // console.log(responseData); |
| <div class="h-divider"> | <div class="h-divider"> | ||||
| <div class="shadow"></div> | |||||
| </div> | |||||
| <div class="biukop-shadow"></div> | |||||
| </div> |
| width: 100%; | width: 100%; | ||||
| position: relative; | position: relative; | ||||
| } | } | ||||
| .h-divider .shadow { | |||||
| .h-divider .biukop-shadow { | |||||
| overflow: hidden; | overflow: hidden; | ||||
| height: 20px; | height: 20px; | ||||
| } | } | ||||
| .h-divider .shadow:after { | |||||
| .h-divider .biukop-shadow:after { | |||||
| content: ''; | content: ''; | ||||
| display: block; | display: block; | ||||
| margin: -25px auto 0; | margin: -25px auto 0; | ||||
| border-radius: 125px/12px; | border-radius: 125px/12px; | ||||
| box-shadow: 0 0 8px black; | box-shadow: 0 0 8px black; | ||||
| } | } | ||||
| .h-divider .text { | .h-divider .text { | ||||
| width: 100px; | width: 100px; | ||||
| height: 45px; | height: 45px; | ||||
| box-shadow: 0 2px 4px #999; | box-shadow: 0 2px 4px #999; | ||||
| background: white; | background: white; | ||||
| } | } | ||||
| .h-divider .text i { | .h-divider .text i { | ||||
| position: absolute; | position: absolute; | ||||
| top: 4px; | top: 4px; | ||||
| font-style: normal; | font-style: normal; | ||||
| color: #999; | color: #999; | ||||
| } | } | ||||
| .h-divider .text2 { | .h-divider .text2 { | ||||
| width: 70px; | width: 70px; | ||||
| height: 70px; | height: 70px; | ||||
| box-shadow: 0 2px 4px #999; | box-shadow: 0 2px 4px #999; | ||||
| background: white; | background: white; | ||||
| } | } | ||||
| .h-divider img { | .h-divider img { | ||||
| position: absolute; | position: absolute; | ||||
| margin: 4px; | margin: 4px; | ||||
| border: 1px dashed #aaa; | border: 1px dashed #aaa; | ||||
| } | } | ||||
| /* end of horizontal dividor */ | |||||
| /* end of horizontal dividor */ |
| <kendo-icon [name]="'photo-camera'" [size]="'medium'"></kendo-icon> | <kendo-icon [name]="'photo-camera'" [size]="'medium'"></kendo-icon> | ||||
| <app-people-select></app-people-select> | |||||
| <button kendoButton (click)="onButtonClick()">Default</button> | <button kendoButton (click)="onButtonClick()">Default</button> | ||||
| <bkp-divider-text>some text</bkp-divider-text> | <bkp-divider-text>some text</bkp-divider-text> |
| </kendo-grid-column> | </kendo-grid-column> | ||||
| <kendo-grid-column field="Rating" title="Rating" width="110" [resizable]="false" filter="numeric"> | <kendo-grid-column field="Rating" title="Rating" width="110" [resizable]="false" filter="numeric"> | ||||
| <ng-template kendoGridCellTemplate let-dataItem> | <ng-template kendoGridCellTemplate let-dataItem> | ||||
| <kendo-rating | |||||
| <app-biukop-rating | |||||
| [value]="dataItem.Rating" | [value]="dataItem.Rating" | ||||
| [max]="5" | [max]="5" | ||||
| ></kendo-rating> | |||||
| ></app-biukop-rating> | |||||
| </ng-template> | </ng-template> | ||||
| </kendo-grid-column> | </kendo-grid-column> | ||||
| </kendo-grid-column> | </kendo-grid-column> | ||||
| <kendo-grid-column field="First" title="Broker Name" minResizableWidth="250" > | <kendo-grid-column field="First" title="Broker Name" minResizableWidth="250" > | ||||
| <ng-template kendoGridCellTemplate let-dataItem> | <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> | <div class="customer-name"> {{ dataItem.First }} , {{ dataItem.Last }} </div> | ||||
| </ng-template> | </ng-template> | ||||
| </kendo-grid-column> | </kendo-grid-column> |
| this.gridData = this.http.get<TopBrokerModel[]>(this.auth.getUrl('chart/top-broker')); | 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 + '")'; | |||||
| } | } | ||||
| } | } |
| (filterChange)="filterChange($event)" | (filterChange)="filterChange($event)" | ||||
| class="fullheight_grid" | 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"> | <kendo-grid-column field="Id" width="50" [class]="'topAlign'" [sortable]="false" [filterable]="false"> | ||||
| <ng-template kendoGridCellTemplate let-dataItem let-rowIndex="rowIndex" > | <ng-template kendoGridCellTemplate let-dataItem let-rowIndex="rowIndex" > | ||||
| <p title="{{dataItem.Id}}" > {{dataItem.Index}}</p> | <p title="{{dataItem.Id}}" > {{dataItem.Index}}</p> | ||||
| <kendo-grid-column-group title="Loan Details" [columnMenu]="false" [headerClass]="'colGroupLoanDetails'"> | <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'"> | <kendo-grid-column field="Rating" title="Rating" width="150" [resizable]="false" [filterable]="false" [headerClass]="'colRating'" [class]="'topAlign colRating'"> | ||||
| <ng-template kendoGridCellTemplate let-dataItem> | <ng-template kendoGridCellTemplate let-dataItem> | ||||
| <kendo-rating | |||||
| <app-biukop-rating | |||||
| [value]="dataItem.Rating" | [value]="dataItem.Rating" | ||||
| [max]="5" | [max]="5" | ||||
| ></kendo-rating> | |||||
| ></app-biukop-rating> | |||||
| </ng-template> | </ng-template> | ||||
| </kendo-grid-column> | </kendo-grid-column> | ||||
| </kendo-grid-column> | </kendo-grid-column> | ||||
| </kendo-grid-column-group> | </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>--> | <!-- <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> | </kendo-grid> |
| import {CompositeFilterDescriptor, SortDescriptor, toODataString} from '@progress/kendo-data-query'; | import {CompositeFilterDescriptor, SortDescriptor, toODataString} from '@progress/kendo-data-query'; | ||||
| import {LoanSummaryService} from '../service/loan_summary.service'; | import {LoanSummaryService} from '../service/loan_summary.service'; | ||||
| import {AuthService} from '../service/auth.service'; | import {AuthService} from '../service/auth.service'; | ||||
| import {Observable} from 'rxjs'; | |||||
| @Component({ | @Component({ | ||||
| selector: 'app-list-all-loans', | selector: 'app-list-all-loans', | ||||
| return this.auth.allowEditLoan(); | return this.auth.allowEditLoan(); | ||||
| } | } | ||||
| public allData = (): Observable<GridDataResult> => { | |||||
| return this.service.queryAll({skip: 0, take: 999999, sort: this.sort, filter: this.filter}); | |||||
| } | |||||
| } | } |
| <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="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> | ||||
| </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> | </div> | ||||
| .pane-content { padding: 0 10px; } | |||||
| div.vertical-spacer { | |||||
| margin-bottom: 30px; | |||||
| } |
| 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({ | @Component({ | ||||
| selector: 'app-loan-add-new', | selector: 'app-loan-add-new', | ||||
| styleUrls: ['./loan-add-new.component.scss'] | styleUrls: ['./loan-add-new.component.scss'] | ||||
| }) | }) | ||||
| export class LoanAddNewComponent implements OnInit { | 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() { } | 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 }; | |||||
| } | } |
| <p>loan-detail works!</p> | |||||
| <div style="background-color:yellow;"> {{dataItem.Id}}</div> | |||||
| <div style="background-color:yellow;"> {{dataItem.Client}}</div> |
| 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(); | |||||
| }); | |||||
| }); |
| 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 { | |||||
| } | |||||
| } |
| <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> |
| .vertical-spacer{ | |||||
| height:1px; | |||||
| margin-bottom:20px; | |||||
| } | |||||
| 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({ | @Component({ | ||||
| selector: 'app-loan-basic-info', | selector: 'app-loan-basic-info', | ||||
| }) | }) | ||||
| export class BasicinfoComponent implements OnInit { | 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 minSettlement: Date = new Date(2015, 0, 1); | ||||
| public maxSettlement: Date = new Date(2030, 4, 31); | public maxSettlement: Date = new Date(2030, 4, 31); | ||||
| public value = ` | |||||
| public basicInfo: FormGroup ; | |||||
| public DemoDescription = ` | |||||
| <h1> Rich Text Editing </h1> | <h1> Rich Text Editing </h1> | ||||
| <table> | <table> | ||||
| <tr> <td> | <tr> <td> | ||||
| <img src="https://edge.alluremedia.com.au/uploads/businessinsider/2015/05/P2P-to-date.jpg" | <img src="https://edge.alluremedia.com.au/uploads/businessinsider/2015/05/P2P-to-date.jpg" | ||||
| width=300"> | width=300"> | ||||
| </td> | </td> | ||||
| </tr> <tr> | |||||
| <td colspan="2"> | |||||
| <a href="https://google.com.au"> click for more details </a> | |||||
| </td> | |||||
| </tr> | </tr> | ||||
| </table> | </table> | ||||
| `; | `; | ||||
| constructor() { } | |||||
| ngOnInit(): void { | |||||
| } | |||||
| public listLoanStatus: Array<{text: string, value: string}> = [ | public listLoanStatus: Array<{text: string, value: string}> = [ | ||||
| {text: '1 - Processing: Just received from Client', value: 'Processing'} , | {text: '1 - Processing: Just received from Client', value: 'Processing'} , | ||||
| {text: '2 - Valuation : Valuating From Bank', value: 'Valuation'}, | {text: '2 - Valuation : Valuating From Bank', value: 'Valuation'}, | ||||
| {text: '6 - Finished : Fully paid, terminated, or switched)', value: 'Finished'}, | {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}); | |||||
| } | |||||
| } | |||||
| } | } |
| [shape]="'circle'" | [shape]="'circle'" | ||||
| ></kendo-avatar> | ></kendo-avatar> | ||||
| <div> | <div> | ||||
| <h1 kendoCardTitle>bg_tourism</h1> | |||||
| <h1 kendoCardTitle>bg_tourism - {{currentStep}}</h1> | |||||
| <p kendoCardSubtitle>Bulgaria, Europe</p> | <p kendoCardSubtitle>Bulgaria, Europe</p> | ||||
| </div> | </div> | ||||
| </kendo-card-header> | </kendo-card-header> |
| import { Component, OnInit } from '@angular/core'; | |||||
| import {Component, Input, OnInit} from '@angular/core'; | |||||
| @Component({ | @Component({ | ||||
| selector: 'app-loan-edit-hint-card', | selector: 'app-loan-edit-hint-card', | ||||
| }) | }) | ||||
| export class HintCardComponent implements OnInit { | export class HintCardComponent implements OnInit { | ||||
| @Input() currentStep: string; | |||||
| constructor() { } | constructor() { } | ||||
| ngOnInit(): void { | ngOnInit(): void { |
| <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> |
| .pane-content { padding: 0 10px; } | |||||
| div.vertical-spacer { | |||||
| height: 10px; | |||||
| margin-bottom: 30px; | |||||
| } | |||||
| .delete-button{ | |||||
| text-align: right; | |||||
| margin-top: 10px; | |||||
| } | |||||
| 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({ | @Component({ | ||||
| styleUrls: ['./loan-edit.component.scss'] | styleUrls: ['./loan-edit.component.scss'] | ||||
| }) | }) | ||||
| export class LoanEditComponent implements OnInit { | 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(); | |||||
| } | |||||
| ); | |||||
| } | |||||
| } | } |
| <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"> </button> | |||||
| <button class="k-button k-primary" (click)="next()"> Next ▶</button> | |||||
| </div> | |||||
| </div> |
| .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; | |||||
| } |
| 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({ | @Component({ | ||||
| selector: 'app-loan-people-reward', | selector: 'app-loan-people-reward', | ||||
| }) | }) | ||||
| export class PeopleRewardComponent implements OnInit { | 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; | |||||
| } | } |
| <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> |
| kendo-multicolumncombobox { | |||||
| width: 100%; | |||||
| } | |||||
| .contact-image { | |||||
| width: 20px; | |||||
| height: 20px; | |||||
| margin-right: 8px; | |||||
| border-radius: 50%; | |||||
| } |
| 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(); | |||||
| }); | |||||
| }); |
| 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; | |||||
| } | |||||
| } |
| <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> 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> 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> |
| div.vertical-spacer { | |||||
| height: 10px; | |||||
| margin-bottom: 30px; | |||||
| } |
| 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({ | @Component({ | ||||
| selector: 'app-loan-trail-income', | selector: 'app-loan-trail-income', | ||||
| styleUrls: ['./trail-income.component.scss'] | styleUrls: ['./trail-income.component.scss'] | ||||
| }) | }) | ||||
| export class TrailIncomeComponent implements OnInit { | 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() { } | 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; | |||||
| } | } |
| text: 'Loans', | text: 'Loans', | ||||
| icon: 'dollar', | icon: 'dollar', | ||||
| items: [ | items: [ | ||||
| { text: 'Add+', icon: 'plus', popup: "loanEdit" }, | |||||
| { text: 'Start New Loan', icon: 'plus', url: "./#start-a-new-loan" }, | { 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: 'List All New', icon: 'table' ,url: './#list-all-loans' }, | ||||
| ] | ] | ||||
| }, | }, | ||||
| { | { | ||||
| text: 'Trails', | |||||
| text: 'Reward', | |||||
| icon: 'percent', | icon: 'percent', | ||||
| items: [ | items: [ | ||||
| { text: 'List All', icon: 'table', url: '#' }, | |||||
| { text: 'List All', icon: 'table', url: '#' }, | |||||
| { text: 'By Broker', icon: 'table', url: '#' }, | |||||
| { text: '--', separator: "true" }, | { text: '--', separator: "true" }, | ||||
| { text: 'Import From ...', icon : 'upload'} | |||||
| { text: 'PaidImport From ...', icon : 'upload'} | |||||
| ] | ] | ||||
| }, | }, | ||||
| { | { |
| 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; | |||||
| } |
| 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; | |||||
| } | |||||
| } |
| export class PayInModel { | |||||
| Id: number; | |||||
| } |
| 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; | |||||
| } |
| 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[]; | |||||
| } |
| export class PeopleMapModel { | |||||
| } |
| 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); | |||||
| }); | |||||
| } | |||||
| } |
| 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); | |||||
| } | |||||
| } |
| <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> |
| span { | |||||
| display: inline-block; | |||||
| width: 25px; | |||||
| line-height: 25px; | |||||
| text-align: center; | |||||
| cursor: pointer; | |||||
| } | |||||
| .yellow { | |||||
| color: #ffa600; | |||||
| } |
| 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(); | |||||
| }); | |||||
| }); |
| 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; | |||||
| } | |||||
| } |
| import { Component, OnInit, Input } from '@angular/core'; | import { Component, OnInit, Input } from '@angular/core'; | ||||
| @Component({ | @Component({ | ||||
| selector: 'kendo-rating', | |||||
| selector: 'app-biukop-rating', | |||||
| template: ` | template: ` | ||||
| <span *ngFor="let item of stars" [ngClass]="ratingIcon(item)"></span> | <span *ngFor="let item of stars" [ngClass]="ratingIcon(item)"></span> | ||||
| `, | `, | ||||
| public ratingIcon(item: number): string { | public ratingIcon(item: number): string { | ||||
| return (item <= this.value) ? 'k-icon k-i-star yellow' : 'k-icon k-i-star-outline'; | return (item <= this.value) ? 'k-icon k-i-star yellow' : 'k-icon k-i-star-outline'; | ||||
| } | } | ||||
| } | |||||
| } |
| import {EventEmitter, Injectable, OnDestroy, OnInit} from '@angular/core'; | import {EventEmitter, Injectable, OnDestroy, OnInit} from '@angular/core'; | ||||
| import { NotificationService } from '@progress/kendo-angular-notification'; | 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 {apiV1LoginResponse} from '../models/api-v1-login-response'; | ||||
| import {Observable} from 'rxjs'; | import {Observable} from 'rxjs'; | ||||
| import {AppComponent} from '../app.component'; | import {AppComponent} from '../app.component'; | ||||
| import {Router} from '@angular/router'; | import {Router} from '@angular/router'; | ||||
| import {PeopleModel} from '../models/people.model'; | |||||
| export interface ApiUrL { | |||||
| getUrl(key: string): string; | |||||
| }; | |||||
| @Injectable() | @Injectable() | ||||
| export class AuthService { | export class AuthService { | ||||
| public apiUrl = 'https://svr2021.lawipac.com:8080/api/v1/'; | public apiUrl = 'https://svr2021.lawipac.com:8080/api/v1/'; | ||||
| public apiWsUrl = 'wss://svr2021.lawipac.com:8080/api/v1/ws'; | 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>(); | loginSuccess = new EventEmitter <apiV1LoginResponse>(); | ||||
| constructor( private http: HttpClient , | constructor( private http: HttpClient , | ||||
| } | } | ||||
| // tslint:disable-next-line:typedef | |||||
| public AutoLogin() { | |||||
| public AutoLogin(): void { | |||||
| const sfm: apiV1LoginResponse = JSON.parse(localStorage.getItem('sfm')); | const sfm: apiV1LoginResponse = JSON.parse(localStorage.getItem('sfm')); | ||||
| if (!sfm) { | if (!sfm) { | ||||
| console.log('no auto login'); | console.log('no auto login'); | ||||
| sfm.sessionExpire | sfm.sessionExpire | ||||
| ); | ); | ||||
| this.loginSuccess.emit(this.loggedIn); | 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; | return this.loggedIn.login; | ||||
| } | } | ||||
| return true; | 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( | this.http.post<apiV1LoginResponse>(this.apiUrl + 'login', {u: email, p: password}).subscribe( | ||||
| responseData => { | responseData => { | ||||
| this.loggedIn.login = responseData.login; | this.loggedIn.login = responseData.login; | ||||
| this.loggedIn.machineId = responseData['Biukop-Mid']; | this.loggedIn.machineId = responseData['Biukop-Mid']; | ||||
| this.loggedIn.sessionExpire = responseData.sessionExpire; | this.loggedIn.sessionExpire = responseData.sessionExpire; | ||||
| localStorage.setItem('sfm', JSON.stringify(this.loggedIn)); | |||||
| localStorage.setItem('mid', this.loggedIn.machineId); | |||||
| this.saveSessionInfo(); | |||||
| this.loginSuccess.emit(responseData); | this.loginSuccess.emit(responseData); | ||||
| }, | }, | ||||
| error => { | error => { | ||||
| const fail = new apiV1LoginResponse(false,'','',0); | |||||
| const fail = new apiV1LoginResponse(false, '', '', 0); | |||||
| this.loggedIn = fail; | this.loggedIn = fail; | ||||
| console.log('login error', error); | console.log('login error', error); | ||||
| this.loginSuccess.emit(this.loggedIn); | this.loginSuccess.emit(this.loggedIn); | ||||
| ); | ); | ||||
| } | } | ||||
| // tslint:disable-next-line:typedef | |||||
| logout() { | |||||
| this.loggedIn = new apiV1LoginResponse(false,'','',0); | |||||
| logout(): void { | |||||
| this.loggedIn = new apiV1LoginResponse(false, '', '', 0); | |||||
| localStorage.removeItem('sfm'); | localStorage.removeItem('sfm'); | ||||
| this.loginSuccess.emit(this.loggedIn); | this.loginSuccess.emit(this.loggedIn); | ||||
| this.router.navigate(['/login']).then(r =>{ | |||||
| this.router.navigate(['/login']).then(r => { | |||||
| console.log('prepare to log back in'); | console.log('prepare to log back in'); | ||||
| } ); | } ); | ||||
| this.http.post(`${this.apiUrl}logout`, '').subscribe( | this.http.post(`${this.apiUrl}logout`, '').subscribe( | ||||
| } | } | ||||
| // tslint:disable-next-line:variable-name | |||||
| public getUrl(key: string): string{ | public getUrl(key: string): string{ | ||||
| const s = this.apiUrl + key; | const s = this.apiUrl + key; | ||||
| const kvPair: {key: string, value: string}[] = [ | const kvPair: {key: string, value: string}[] = [ | ||||
| // not found if arrive here | // not found if arrive here | ||||
| return s; | 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}); | |||||
| } | |||||
| } |
| 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(); | |||||
| } | |||||
| } |
| import { Injectable } from '@angular/core'; | import { Injectable } from '@angular/core'; | ||||
| import { HttpClient } from '@angular/common/http'; | import { HttpClient } from '@angular/common/http'; | ||||
| import { GridDataResult } from '@progress/kendo-angular-grid'; | import { GridDataResult } from '@progress/kendo-angular-grid'; | ||||
| import { toODataString } from '@progress/kendo-data-query'; | |||||
| import { Observable, BehaviorSubject } from 'rxjs'; | import { Observable, BehaviorSubject } from 'rxjs'; | ||||
| import { map, tap } from 'rxjs/operators'; | import { map, tap } from 'rxjs/operators'; | ||||
| import {AuthService} from './auth.service'; | import {AuthService} from './auth.service'; | ||||
| private BASE_URL = ''; | private BASE_URL = ''; | ||||
| constructor( | |||||
| protected constructor( | |||||
| private http: HttpClient, | private http: HttpClient, | ||||
| private auth: AuthService, | private auth: AuthService, | ||||
| protected tableName: string | protected tableName: string | ||||
| // console.log(index, response.data[index].Settlement , typeof response.data[index].Settlement ); | // 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(index, response.data[index].LastPayInDate , typeof response.data[index].LastPayInDate ); | ||||
| }); | }); | ||||
| console.log(response); | |||||
| // console.log(response); | |||||
| return response; | return response; | ||||
| }), | }), | ||||
| tap(() => this.loading = false) | tap(() => this.loading = false) | ||||
| public convertToDateTimeObject(str: string): Date{ | public convertToDateTimeObject(str: string): Date{ | ||||
| if (str === '0001-01-01T00:00:00Z' || str === ''){ | 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{ | }else{ | ||||
| return new Date(str); | return new Date(str); | ||||
| } | } |
| [resizable]="true" | [resizable]="true" | ||||
| [height] = "700" | [height] = "700" | ||||
| class="fullheight_grid" | class="fullheight_grid" | ||||
| [columnMenu]="{ filter: true }" | |||||
| [columnMenu]="{ filter: true }" | |||||
| > | > | ||||
| <ng-template kendoGridToolbarTemplate> | <ng-template kendoGridToolbarTemplate> | ||||
| <input placeholder="Search in all columns..." kendoTextBox (input)="onFilter($event.target.value)"/> | <input placeholder="Search in all columns..." kendoTextBox (input)="onFilter($event.target.value)"/> | ||||
| <kendo-grid-column field="brokers" title="Brokers" [width]="220"> | <kendo-grid-column field="brokers" title="Brokers" [width]="220"> | ||||
| </kendo-grid-column> | </kendo-grid-column> | ||||
| <kendo-grid-column field="bdm" title="BDM/Referals" [width]="220"> | <kendo-grid-column field="bdm" title="BDM/Referals" [width]="220"> | ||||
| </kendo-grid-column> | |||||
| </kendo-grid-column> | |||||
| <kendo-grid-column | <kendo-grid-column | ||||
| field="country" | field="country" | ||||
| title="Country" | title="Country" | ||||
| </kendo-grid-column-group> | </kendo-grid-column-group> | ||||
| <kendo-grid-column-group title="Loan Information" [columnMenu]="false"> | <kendo-grid-column-group title="Loan Information" [columnMenu]="false"> | ||||
| <kendo-grid-column field="status" title="Status" [width]="220"> | <kendo-grid-column field="status" title="Status" [width]="220"> | ||||
| </kendo-grid-column> | |||||
| </kendo-grid-column> | |||||
| <kendo-grid-column | <kendo-grid-column | ||||
| field="status" | field="status" | ||||
| <ng-template kendoGridCellTemplate let-dataItem> | <ng-template kendoGridCellTemplate let-dataItem> | ||||
| <span [ngClass]="{'red text-bold': dataItem.loan_limit < 1000000}">{{ dataItem.loan_limit | currency }}</span> | <span [ngClass]="{'red text-bold': dataItem.loan_limit < 1000000}">{{ dataItem.loan_limit | currency }}</span> | ||||
| </ng-template> | </ng-template> | ||||
| </kendo-grid-column> | |||||
| </kendo-grid-column> | |||||
| <kendo-grid-column field="lender" title="Lender" [width]="100"> | <kendo-grid-column field="lender" title="Lender" [width]="100"> | ||||
| </kendo-grid-column> | |||||
| </kendo-grid-column> | |||||
| <!-- <kendo-grid-column | <!-- <kendo-grid-column | ||||
| field="is_online" | field="is_online" | ||||
| filter="numeric" | filter="numeric" | ||||
| > | > | ||||
| <ng-template kendoGridCellTemplate let-dataItem> | <ng-template kendoGridCellTemplate let-dataItem> | ||||
| <kendo-rating | |||||
| <app-biukop-rating | |||||
| [value]="dataItem.rating" | [value]="dataItem.rating" | ||||
| [max]="5" | [max]="5" | ||||
| ></kendo-rating> | |||||
| ></app-biukop-rating> | |||||
| </ng-template> | </ng-template> | ||||
| </kendo-grid-column> | </kendo-grid-column> | ||||
| <kendo-grid-column | <kendo-grid-column | ||||
| <ng-template kendoGridCellTemplate let-dataItem> | <ng-template kendoGridCellTemplate let-dataItem> | ||||
| {{dataItem.submittsion_date | date: 'yyyy-MM-dd'}} | {{dataItem.submittsion_date | date: 'yyyy-MM-dd'}} | ||||
| </ng-template> | </ng-template> | ||||
| </kendo-grid-column> | |||||
| </kendo-grid-column> | |||||
| <kendo-grid-column field="settlement_date" width="200" title="Settlement Date"> | <kendo-grid-column field="settlement_date" width="200" title="Settlement Date"> | ||||
| <ng-template kendoGridCellTemplate let-dataItem> | <ng-template kendoGridCellTemplate let-dataItem> | ||||
| {{dataItem.settlement_date | date: 'yyyy-MM-dd'}} | {{dataItem.settlement_date | date: 'yyyy-MM-dd'}} | ||||
| </ng-template> | </ng-template> | ||||
| </kendo-grid-column> | |||||
| </kendo-grid-column> | |||||
| </kendo-grid-column-group> | </kendo-grid-column-group> | ||||
| <kendo-grid-pdf fileName="Transaction.pdf" [repeatHeaders]="true"></kendo-grid-pdf> | <kendo-grid-pdf fileName="Transaction.pdf" [repeatHeaders]="true"></kendo-grid-pdf> | ||||
| some details {{dataItem.id}} | some details {{dataItem.id}} | ||||
| <trans-details [item]="dataItem"></trans-details> | <trans-details [item]="dataItem"></trans-details> | ||||
| </div> | </div> | ||||
| </kendo-grid> | |||||
| </kendo-grid> |