| @@ -30,7 +30,6 @@ export class AppComponent implements OnInit , OnDestroy { | |||
| this.listenToMenuEvent(); | |||
| // must be the last, as it may emit events | |||
| this.authService.AutoLogin(); | |||
| } | |||
| listenToMenuEvent(): void { | |||
| @@ -0,0 +1,5 @@ | |||
| export class AppConfigModel { | |||
| Server = 'https://c5016.biukop.com.au:8080/api/v1/'; | |||
| Socket = 'ws://c5016.biukop.com.au:8080/api/v1/'; | |||
| } | |||
| @@ -1 +1,58 @@ | |||
| import { Injectable } from '@angular/core'; | |||
| import { HttpClient } from '@angular/common/http'; | |||
| import {AppConfigModel} from './app.config.model'; | |||
| @Injectable() | |||
| export class AppConfig { | |||
| static config: AppConfigModel; | |||
| static debugConfig: AppConfigModel = { | |||
| Server: 'https://svr2021.lawipac.com:8080/api/v1/', | |||
| Socket: 'wss://svr2021.lawipac.com:8080/api/v1/ws' | |||
| }; | |||
| static productionConfig: AppConfigModel = { | |||
| Server: 'https://c5016.biukop.com.au:8080/api/v1/', | |||
| Socket: 'wss://c5016.biukop.com.au:8080/api/v1/ws' | |||
| }; | |||
| constructor(private http: HttpClient) {} | |||
| load(): Promise<void> { | |||
| return new Promise<void>((resolve, reject) => { | |||
| const el: HTMLElement = document.getElementById('config'); | |||
| try { | |||
| if ( location.href.includes('//localhost:4200/') ) { | |||
| AppConfig.config = AppConfig.debugConfig; | |||
| console.log('Using Debug Config:', AppConfig.config); | |||
| }else{ | |||
| const json = this.decode(el.innerText); | |||
| AppConfig.config = JSON.parse(json); | |||
| console.log('Using Production Config:', AppConfig.config); | |||
| } | |||
| resolve(); | |||
| }catch (e){ | |||
| console.log('cannot load config'); | |||
| alert('Failed to load configuration, please contact administrator'); | |||
| AppConfig.config = AppConfig.productionConfig; // fallback to hardcoded config | |||
| console.log('fall back to built-in config', AppConfig.config); | |||
| resolve(); | |||
| // reject(); | |||
| } | |||
| }); | |||
| } | |||
| decode(strIn: string): string { | |||
| return atob(strIn); | |||
| } | |||
| public get apiUrl(): string { | |||
| return AppConfig.config.Server; | |||
| } | |||
| public get apiWsUrl(): string { | |||
| return AppConfig.config.Socket; | |||
| } | |||
| } | |||
| @@ -1,6 +1,6 @@ | |||
| //Angular | |||
| import { NgModule } from '@angular/core'; | |||
| import {APP_INITIALIZER, NgModule} from '@angular/core'; | |||
| import { CommonModule } from '@angular/common'; | |||
| import { BrowserModule } from '@angular/platform-browser'; | |||
| import { FormsModule, ReactiveFormsModule } from '@angular/forms'; | |||
| @@ -94,10 +94,14 @@ import { UploadDetailComponent } from './upload-detail/upload-detail.component'; | |||
| import {SafeUrlPipe} from './pipe/safe.url.pipe'; | |||
| import { ImagePopupDialogComponent } from './image-popup-dialog/image-popup-dialog.component'; | |||
| import { PopupIncomeFilterComponent } from './popup-income-filter/popup-income-filter.component'; | |||
| import { LoanCardComponent } from './loan-card/loan-card.component'; | |||
| import {AppConfig} from './app.config'; | |||
| export function initializeApp(appConfig: AppConfig): () => Promise<void> { | |||
| return () => appConfig.load(); | |||
| } | |||
| @@ -157,7 +161,8 @@ import { PopupIncomeFilterComponent } from './popup-income-filter/popup-income-f | |||
| UploadDetailComponent, | |||
| SafeUrlPipe, | |||
| ImagePopupDialogComponent, | |||
| PopupIncomeFilterComponent | |||
| PopupIncomeFilterComponent, | |||
| LoanCardComponent | |||
| ], | |||
| imports: [ | |||
| BrowserModule, | |||
| @@ -210,7 +215,11 @@ import { PopupIncomeFilterComponent } from './popup-income-filter/popup-income-f | |||
| provide: HTTP_INTERCEPTORS, | |||
| useClass: UploadInterceptor, | |||
| multi: true | |||
| } | |||
| }, | |||
| AppConfig, | |||
| { provide: APP_INITIALIZER, | |||
| useFactory: initializeApp, | |||
| deps: [AppConfig], multi: true } | |||
| ], | |||
| bootstrap: [AppComponent] | |||
| }) | |||
| @@ -19,7 +19,7 @@ export class ClientLoanListComponent implements OnInit { | |||
| resp => { | |||
| this.Loans = []; | |||
| resp.forEach( v => { | |||
| const l = new LoanModel(v.Id); | |||
| const l = new LoanModel(v); | |||
| l.Response = v; | |||
| this.Loans.push(l); | |||
| }); | |||
| @@ -0,0 +1,6 @@ | |||
| <div class="card loan" (click)="gotoLoan(LoanId)"> | |||
| <span class="badge badge-success">{{Loan.Item}}</span> | |||
| <span> Amount: {{Loan.Amount | currency }}</span> | |||
| <span> Settlement: {{Loan.Settlement | date:'yyyy-mm-dd' }}</span> | |||
| </div> | |||
| @@ -0,0 +1,17 @@ | |||
| div.loan.card { | |||
| display: -webkit-box; | |||
| display: -ms-flexbox; | |||
| display: flex; | |||
| -webkit-box-orient: vertical; | |||
| -webkit-box-direction: normal; | |||
| -ms-flex-direction: column; | |||
| flex-direction: column; | |||
| position: relative; | |||
| -webkit-transition: all 0.4s cubic-bezier(0.645, 0.045, 0.355, 1); | |||
| -o-transition: all 0.4s cubic-bezier(0.645, 0.045, 0.355, 1); | |||
| transition: all 0.4s cubic-bezier(0.645, 0.045, 0.355, 1); | |||
| border-radius: 10px; | |||
| overflow: hidden; | |||
| -webkit-box-shadow: 15px 15px 27px #e1e1e3, -15px -15px 27px #ffffff; | |||
| box-shadow: 15px 15px 27px #e1e1e3, -15px -15px 27px #ffffff; | |||
| } | |||
| @@ -0,0 +1,25 @@ | |||
| import { ComponentFixture, TestBed } from '@angular/core/testing'; | |||
| import { LoanCardComponent } from './loan-card.component'; | |||
| describe('LoanCardComponent', () => { | |||
| let component: LoanCardComponent; | |||
| let fixture: ComponentFixture<LoanCardComponent>; | |||
| beforeEach(async () => { | |||
| await TestBed.configureTestingModule({ | |||
| declarations: [ LoanCardComponent ] | |||
| }) | |||
| .compileComponents(); | |||
| }); | |||
| beforeEach(() => { | |||
| fixture = TestBed.createComponent(LoanCardComponent); | |||
| component = fixture.componentInstance; | |||
| fixture.detectChanges(); | |||
| }); | |||
| it('should create', () => { | |||
| expect(component).toBeTruthy(); | |||
| }); | |||
| }); | |||
| @@ -0,0 +1,26 @@ | |||
| import {Component, Input, OnInit} from '@angular/core'; | |||
| import {LoanModel} from '../models/loan.model'; | |||
| import {LoanSingleService} from '../service/loan.single.service'; | |||
| import {Router} from '@angular/router'; | |||
| @Component({ | |||
| selector: 'app-loan-card', | |||
| templateUrl: './loan-card.component.html', | |||
| styleUrls: ['./loan-card.component.scss'] | |||
| }) | |||
| export class LoanCardComponent implements OnInit { | |||
| @Input() LoanId = ''; | |||
| public Loan: LoanModel = new LoanModel({}); | |||
| constructor(private lss: LoanSingleService, private router: Router) { } | |||
| ngOnInit(): void { | |||
| this.lss.getLoan(this.LoanId).subscribe( resp => { | |||
| this.Loan.Response = resp; | |||
| }); | |||
| } | |||
| public gotoLoan(id: string): void { | |||
| this.router.navigate(['/edit-loan', id]); | |||
| } | |||
| } | |||
| @@ -21,7 +21,7 @@ export class LoanEditComponent implements OnInit { | |||
| @Output() LoanUpdated = new EventEmitter<LoanModel>(); | |||
| public Loan: LoanModel = new LoanModel(''); | |||
| public Loan: LoanModel = new LoanModel({}); | |||
| public curStepSuccess = false; | |||
| public showDelete = false; | |||
| @@ -14,35 +14,102 @@ export interface LoanModelCallBacks { | |||
| 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 LenderLoanNumber?: string, | |||
| public Client?: PeopleModel[], | |||
| public Broker?: BrokerModel[], | |||
| public OtherRewarder?: PeopleModel[], | |||
| public Reward?: RewardModel[], | |||
| public RewardPeople?: PeopleModel[], | |||
| public PayIn?: PayInModel[], | |||
| public PeopleMap?: PeopleMapModel[], | |||
| public auth?: AuthService, | |||
| public lss?: LoanSingleService | |||
| ){} | |||
| 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 LenderLoanNumber?: string; | |||
| public Client?: PeopleModel[]; | |||
| public Broker?: BrokerModel[]; | |||
| public OtherRewarder?: PeopleModel[]; | |||
| public Reward?: RewardModel[]; | |||
| public RewardPeople?: PeopleModel[]; | |||
| public PayIn?: PayInModel[]; | |||
| public PeopleMap?: PeopleMapModel[]; | |||
| public auth?: AuthService; | |||
| public lss?: LoanSingleService; | |||
| constructor(payload: Partial<LoanModel>) { | |||
| this.Id = payload.Id || ''; | |||
| this.Amount = payload.Amount || 0; | |||
| this.Status = payload.Status || ''; | |||
| this.Item = payload.Item || ''; | |||
| this.Rating = payload.Rating || 0; | |||
| this.Settlement = payload.Settlement ? new Date(payload.Settlement) : new Date('1900-01-01') ; | |||
| this.Description = payload.Description || ''; | |||
| this.Lender = payload.Lender || ''; | |||
| this.LenderLoanNumber = payload.LenderLoanNumber || ''; | |||
| if ( payload.Client && payload.Client.length > 0 ){ | |||
| this.setClient(payload.Client); | |||
| } else{ | |||
| this.Client = []; | |||
| } | |||
| if (payload.Broker && payload.Broker.length > 0 ) { | |||
| this.setBroker(payload.Broker); | |||
| }else{ | |||
| this.Broker = []; | |||
| } | |||
| if (payload.OtherRewarder && payload.OtherRewarder.length > 0 ) { | |||
| this.setOtherRewarder(payload.OtherRewarder); | |||
| }else{ | |||
| this.OtherRewarder = []; | |||
| } | |||
| if (payload.Reward && payload.Reward.length > 0 ) { | |||
| this.setReward(payload.Reward); | |||
| }else{ | |||
| this.Reward = []; | |||
| } | |||
| if (payload.RewardPeople && payload.RewardPeople.length > 0 ) { | |||
| this.setRewardPeople(payload.RewardPeople); | |||
| }else{ | |||
| this.RewardPeople = []; | |||
| } | |||
| if (payload.PayIn && payload.PayIn.length > 0 ) { | |||
| this.setPayIn(payload.PayIn); | |||
| }else{ | |||
| this.PayIn = []; | |||
| } | |||
| if (payload.PeopleMap && payload.PeopleMap.length > 0) { | |||
| this.PeopleMap = payload.PeopleMap; | |||
| }else{ | |||
| this.PeopleMap = []; | |||
| } | |||
| this.auth = payload.auth || null; | |||
| this.lss = payload.lss || null; | |||
| } | |||
| public static EmptyNew(lss: LoanSingleService, auth: AuthService): LoanModel { | |||
| const nLoan = new LoanModel( | |||
| '', 0 , '', '', 0, new Date(), '', | |||
| '', '', [], [], [], [], [], [], [], | |||
| const nLoan = new LoanModel({ | |||
| Id: '', | |||
| Amount: 0, | |||
| Status: '', | |||
| Item: '', | |||
| Rating: 0, | |||
| Settlement: new Date(), | |||
| Description: '', | |||
| Lender: '', | |||
| LenderLoanNumber: '', | |||
| Client: [], | |||
| Broker: [], | |||
| OtherRewarder: [], | |||
| Reward: [], | |||
| RewardPeople: [], | |||
| PayIn: [], | |||
| PeopleMap: [], | |||
| auth, lss | |||
| ); | |||
| }); | |||
| return nLoan; | |||
| } | |||
| @@ -287,25 +354,25 @@ export class LoanModel { | |||
| // remove auth serivce and lss service for Json.stringify | |||
| public cloneForJson(): LoanModel { | |||
| return new LoanModel( | |||
| this.Id, | |||
| this.Amount, | |||
| this.Status, | |||
| this.Item, | |||
| this.Rating, | |||
| this.Settlement, | |||
| this.Description, | |||
| this.Lender, | |||
| this.LenderLoanNumber, | |||
| this.Client, | |||
| this.Broker, | |||
| this.OtherRewarder, | |||
| this.Reward, | |||
| this.RewardPeople, | |||
| this.PayIn, | |||
| this.PeopleMap, | |||
| undefined, | |||
| undefined | |||
| ); | |||
| return new LoanModel({ | |||
| Id: this.Id, | |||
| Amount: this.Amount, | |||
| Status: this.Status, | |||
| Item: this.Item, | |||
| Rating: this.Rating, | |||
| Settlement: this.Settlement, | |||
| Description: this.Description, | |||
| Lender: this.Lender, | |||
| LenderLoanNumber: this.LenderLoanNumber, | |||
| Client: this.Client, | |||
| Broker: this.Broker, | |||
| OtherRewarder: this.OtherRewarder, | |||
| Reward: this.Reward, | |||
| RewardPeople: this.RewardPeople, | |||
| PayIn: this.PayIn, | |||
| PeopleMap: this.PeopleMap, | |||
| auth: undefined, | |||
| lss: undefined | |||
| }); | |||
| } | |||
| } | |||
| @@ -119,9 +119,10 @@ | |||
| </ng-template> | |||
| </kendo-grid-column> | |||
| <kendo-grid-column field="LoanId" title="Loan" width="80" [editable]="false" [sortable]="false"> | |||
| <kendo-grid-column field="LoanId" title="Loan" width="210" [editable]="false" [sortable]="false"> | |||
| <ng-template kendoGridCellTemplate let-dataItem> | |||
| <button *ngIf="dataItem.LoanId != '' && dataItem.LoanId != undefined " kendoButton [icon]="'page-properties'" (click)="gotoLoan(dataItem.LoanId)" > </button> | |||
| <app-loan-card [LoanId]="dataItem.LoanId"></app-loan-card> | |||
| </ng-template> | |||
| </kendo-grid-column> | |||
| @@ -155,9 +155,7 @@ export class PayInComponent implements OnInit { | |||
| public showUpload(id: number): void { | |||
| this.router.navigate(['/upload-details', id]); | |||
| } | |||
| public gotoLoan(id: string): void { | |||
| this.router.navigate(['/edit-loan', id]); | |||
| } | |||
| public setBalance(): void{ | |||
| if ( this.showBalance ){ | |||
| @@ -5,6 +5,7 @@ import {Router} from '@angular/router'; | |||
| import {PeopleModel} from '../models/people.model'; | |||
| import {UserExtraModel} from '../models/user-extra.model'; | |||
| import {Observable} from 'rxjs'; | |||
| import {AppConfig} from '../app.config'; | |||
| @Injectable() | |||
| export class AuthService { | |||
| @@ -17,10 +18,12 @@ export class AuthService { | |||
| loginSuccess = new EventEmitter <ApiV1LoginResponse>(); | |||
| constructor( private http: HttpClient , | |||
| private router: Router) { | |||
| private router: Router, | |||
| private config: AppConfig) { | |||
| this.apiUrl = config.apiUrl; | |||
| this.apiWsUrl = config.apiWsUrl; | |||
| } | |||
| public AutoLogin(): void { | |||
| const sfm: ApiV1LoginResponse = JSON.parse(localStorage.getItem('sfm')); | |||
| if (!sfm) { | |||
| @@ -8,10 +8,15 @@ | |||
| <meta name="viewport" content="width=device-width, initial-scale=1"> | |||
| <link rel="icon" type="image/x-icon" href="favicon.ico"> | |||
| </head> | |||
| <body> | |||
| <script id="config" type="text/biukop-config" | |||
| server="https://svr2021.lawipac.com:8080/api/v1/" | |||
| version="0.9.1" | |||
| > | |||
| ICB7CiAgICAgICJTZXJ2ZXIiOiAiaHR0cHM6Ly9zdnIyMDIxLmxhd2lwYWMuY29tOjgwODAvYXBpL3YxLyIsCiAgICAgICJTb2NrZXQiOiAid3NzOi8vc3ZyMjAyMS5sYXdpcGFjLmNvbTo4MDgwL2FwaS92MS93cyIKICB9 | |||
| </script> | |||
| <app-root></app-root> | |||
| </body> | |||
| </html> | |||
| </html> | |||