| this.listenToMenuEvent(); | this.listenToMenuEvent(); | ||||
| // must be the last, as it may emit events | // must be the last, as it may emit events | ||||
| this.authService.AutoLogin(); | this.authService.AutoLogin(); | ||||
| } | } | ||||
| listenToMenuEvent(): void { | listenToMenuEvent(): void { |
| export class AppConfigModel { | |||||
| Server = 'https://c5016.biukop.com.au:8080/api/v1/'; | |||||
| Socket = 'ws://c5016.biukop.com.au:8080/api/v1/'; | |||||
| } |
| 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; | |||||
| } | |||||
| } |
| //Angular | //Angular | ||||
| import { NgModule } from '@angular/core'; | |||||
| import {APP_INITIALIZER, NgModule} from '@angular/core'; | |||||
| import { CommonModule } from '@angular/common'; | import { CommonModule } from '@angular/common'; | ||||
| import { BrowserModule } from '@angular/platform-browser'; | import { BrowserModule } from '@angular/platform-browser'; | ||||
| import { FormsModule, ReactiveFormsModule } from '@angular/forms'; | import { FormsModule, ReactiveFormsModule } from '@angular/forms'; | ||||
| import {SafeUrlPipe} from './pipe/safe.url.pipe'; | import {SafeUrlPipe} from './pipe/safe.url.pipe'; | ||||
| import { ImagePopupDialogComponent } from './image-popup-dialog/image-popup-dialog.component'; | import { ImagePopupDialogComponent } from './image-popup-dialog/image-popup-dialog.component'; | ||||
| import { PopupIncomeFilterComponent } from './popup-income-filter/popup-income-filter.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(); | |||||
| } | |||||
| UploadDetailComponent, | UploadDetailComponent, | ||||
| SafeUrlPipe, | SafeUrlPipe, | ||||
| ImagePopupDialogComponent, | ImagePopupDialogComponent, | ||||
| PopupIncomeFilterComponent | |||||
| PopupIncomeFilterComponent, | |||||
| LoanCardComponent | |||||
| ], | ], | ||||
| imports: [ | imports: [ | ||||
| BrowserModule, | BrowserModule, | ||||
| provide: HTTP_INTERCEPTORS, | provide: HTTP_INTERCEPTORS, | ||||
| useClass: UploadInterceptor, | useClass: UploadInterceptor, | ||||
| multi: true | multi: true | ||||
| } | |||||
| }, | |||||
| AppConfig, | |||||
| { provide: APP_INITIALIZER, | |||||
| useFactory: initializeApp, | |||||
| deps: [AppConfig], multi: true } | |||||
| ], | ], | ||||
| bootstrap: [AppComponent] | bootstrap: [AppComponent] | ||||
| }) | }) |
| resp => { | resp => { | ||||
| this.Loans = []; | this.Loans = []; | ||||
| resp.forEach( v => { | resp.forEach( v => { | ||||
| const l = new LoanModel(v.Id); | |||||
| const l = new LoanModel(v); | |||||
| l.Response = v; | l.Response = v; | ||||
| this.Loans.push(l); | this.Loans.push(l); | ||||
| }); | }); |
| <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> | |||||
| 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; | |||||
| } |
| 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(); | |||||
| }); | |||||
| }); |
| 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]); | |||||
| } | |||||
| } |
| @Output() LoanUpdated = new EventEmitter<LoanModel>(); | @Output() LoanUpdated = new EventEmitter<LoanModel>(); | ||||
| public Loan: LoanModel = new LoanModel(''); | |||||
| public Loan: LoanModel = new LoanModel({}); | |||||
| public curStepSuccess = false; | public curStepSuccess = false; | ||||
| public showDelete = false; | public showDelete = false; |
| export class LoanModel { | 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 { | 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 | auth, lss | ||||
| ); | |||||
| }); | |||||
| return nLoan; | return nLoan; | ||||
| } | } | ||||
| // remove auth serivce and lss service for Json.stringify | // remove auth serivce and lss service for Json.stringify | ||||
| public cloneForJson(): LoanModel { | 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 | |||||
| }); | |||||
| } | } | ||||
| } | } |
| </ng-template> | </ng-template> | ||||
| </kendo-grid-column> | </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> | <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> | </ng-template> | ||||
| </kendo-grid-column> | </kendo-grid-column> | ||||
| public showUpload(id: number): void { | public showUpload(id: number): void { | ||||
| this.router.navigate(['/upload-details', id]); | this.router.navigate(['/upload-details', id]); | ||||
| } | } | ||||
| public gotoLoan(id: string): void { | |||||
| this.router.navigate(['/edit-loan', id]); | |||||
| } | |||||
| public setBalance(): void{ | public setBalance(): void{ | ||||
| if ( this.showBalance ){ | if ( this.showBalance ){ |
| import {PeopleModel} from '../models/people.model'; | import {PeopleModel} from '../models/people.model'; | ||||
| import {UserExtraModel} from '../models/user-extra.model'; | import {UserExtraModel} from '../models/user-extra.model'; | ||||
| import {Observable} from 'rxjs'; | import {Observable} from 'rxjs'; | ||||
| import {AppConfig} from '../app.config'; | |||||
| @Injectable() | @Injectable() | ||||
| export class AuthService { | export class AuthService { | ||||
| loginSuccess = new EventEmitter <ApiV1LoginResponse>(); | loginSuccess = new EventEmitter <ApiV1LoginResponse>(); | ||||
| constructor( private http: HttpClient , | constructor( private http: HttpClient , | ||||
| private router: Router) { | |||||
| private router: Router, | |||||
| private config: AppConfig) { | |||||
| this.apiUrl = config.apiUrl; | |||||
| this.apiWsUrl = config.apiWsUrl; | |||||
| } | } | ||||
| public AutoLogin(): void { | public AutoLogin(): void { | ||||
| const sfm: ApiV1LoginResponse = JSON.parse(localStorage.getItem('sfm')); | const sfm: ApiV1LoginResponse = JSON.parse(localStorage.getItem('sfm')); | ||||
| if (!sfm) { | if (!sfm) { |
| <meta name="viewport" content="width=device-width, initial-scale=1"> | <meta name="viewport" content="width=device-width, initial-scale=1"> | ||||
| <link rel="icon" type="image/x-icon" href="favicon.ico"> | <link rel="icon" type="image/x-icon" href="favicon.ico"> | ||||
| </head> | </head> | ||||
| <body> | <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> | <app-root></app-root> | ||||
| </body> | </body> | ||||
| </html> | |||||
| </html> |