| { | { | ||||
| "name": "broker", | "name": "broker", | ||||
| "version": "0.0.0", | |||||
| "version": "2.0.1", | |||||
| "lockfileVersion": 1, | "lockfileVersion": 1, | ||||
| "requires": true, | "requires": true, | ||||
| "dependencies": { | "dependencies": { |
| { | { | ||||
| "name": "broker", | "name": "broker", | ||||
| "version": "0.0.0", | |||||
| "version": "2.0.1", | |||||
| "scripts": { | "scripts": { | ||||
| "ng": "ng", | "ng": "ng", | ||||
| "start": "ng serve --proxy-config proxy.conf.json", | "start": "ng serve --proxy-config proxy.conf.json", | ||||
| "prebuild": "npm --no-git-tag-version version patch", | |||||
| "build": "ng build ", | "build": "ng build ", | ||||
| "buildsfm": "ng build --prod --base-href=/broker/ --deploy-url=/broker/ ", | "buildsfm": "ng build --prod --base-href=/broker/ --deploy-url=/broker/ ", | ||||
| "test": "ng test", | "test": "ng test", |
| import {Title} from '@angular/platform-browser'; | import {Title} from '@angular/platform-browser'; | ||||
| import {WsLoginEventModel} from './models/websocket/ws.login.event.model'; | import {WsLoginEventModel} from './models/websocket/ws.login.event.model'; | ||||
| import {SessionService} from './service/session.service'; | import {SessionService} from './service/session.service'; | ||||
| import {AppConfig} from './app.config'; | |||||
| import {environment} from '../environments/environment'; | |||||
| @Component({ | @Component({ | ||||
| selector: 'app-root', | selector: 'app-root', | ||||
| encapsulation: ViewEncapsulation.None | encapsulation: ViewEncapsulation.None | ||||
| }) | }) | ||||
| export class AppComponent implements OnInit , OnDestroy { | export class AppComponent implements OnInit , OnDestroy { | ||||
| title = 'SFM Advanced Loan management'; | |||||
| title = 'SFM Web Office'; | |||||
| currentApplicationVersion = environment.appVersion; | |||||
| private menuItemSub: Subscription; | private menuItemSub: Subscription; | ||||
| @ViewChild('loanEditComponent', {static: true}) loanEdit: LoanEditComponent; | @ViewChild('loanEditComponent', {static: true}) loanEdit: LoanEditComponent; | ||||
| private ss: SessionService, | private ss: SessionService, | ||||
| private wsService: WebSocketService, | private wsService: WebSocketService, | ||||
| private titleService: Title){ | private titleService: Title){ | ||||
| this.title = 'SFM Web Office (' + this.currentApplicationVersion + ')'; | |||||
| this.webSocketSubscription = wsService.subscribe(m => { | this.webSocketSubscription = wsService.subscribe(m => { | ||||
| console.log('websocket server send this :', m); | |||||
| // console.log('websocket server send this :', m); | |||||
| }); | }); | ||||
| this.wsLoginSub = this.wsService.LoginEvent.subscribe( m => { | this.wsLoginSub = this.wsService.LoginEvent.subscribe( m => { |
| import {environment} from '../environments/environment'; | |||||
| export class AppConfigModel { | export class AppConfigModel { | ||||
| Server = 'https://c5016.biukop.com.au:8080/api/v1/'; | |||||
| Socket = 'ws://c5016.biukop.com.au:8080/api/v1/'; | |||||
| SessionStorageKey = 'sk'; | |||||
| Version = 2021; | |||||
| public Server = 'https://c5016.biukop.com.au:8080/api/v1/'; | |||||
| public Socket = 'ws://c5016.biukop.com.au:8080/api/v1/'; | |||||
| public SessionStorageKey = 'sk'; | |||||
| public Version ? = environment.appVersion; | |||||
| constructor(payload: Partial<AppConfigModel>) { | |||||
| this.Server = payload.Server || 'https://c5016.biukop.com.au:8080/api/v1/'; | |||||
| this.Socket = payload.Socket || 'ws://c5016.biukop.com.au:8080/api/v1/'; | |||||
| this.SessionStorageKey = payload.SessionStorageKey || 'sk'; | |||||
| this.Version = environment.appVersion; | |||||
| } | |||||
| } | } |
| import { Injectable } from '@angular/core'; | import { Injectable } from '@angular/core'; | ||||
| import { HttpClient } from '@angular/common/http'; | import { HttpClient } from '@angular/common/http'; | ||||
| import {AppConfigModel} from './app.config.model'; | import {AppConfigModel} from './app.config.model'; | ||||
| import {environment} from '../environments/environment'; | |||||
| @Injectable() | @Injectable() | ||||
| export class AppConfig { | export class AppConfig { | ||||
| static config: AppConfigModel; | |||||
| static config = new AppConfigModel({}); | |||||
| static currentApplicationVersion = environment.appVersion; | |||||
| static debugConfig: AppConfigModel = { | static debugConfig: AppConfigModel = { | ||||
| Server: 'https://svr2021.lawipac.com:8080/api/v1/', | Server: 'https://svr2021.lawipac.com:8080/api/v1/', | ||||
| Socket: 'wss://svr2021.lawipac.com:8080/api/v1/ws', | Socket: 'wss://svr2021.lawipac.com:8080/api/v1/ws', | ||||
| SessionStorageKey: 'sk', | SessionStorageKey: 'sk', | ||||
| Version: 2021 | |||||
| }; | }; | ||||
| static productionConfig: AppConfigModel = { | static productionConfig: AppConfigModel = { | ||||
| Server: 'https://c5016.biukop.com.au:8080/api/v1/', | Server: 'https://c5016.biukop.com.au:8080/api/v1/', | ||||
| Socket: 'wss://c5016.biukop.com.au:8080/api/v1/ws', | Socket: 'wss://c5016.biukop.com.au:8080/api/v1/ws', | ||||
| SessionStorageKey : 'sk', | SessionStorageKey : 'sk', | ||||
| Version: 2021 | |||||
| }; | }; | ||||
| constructor(private http: HttpClient) {} | constructor(private http: HttpClient) {} | ||||
| return new Promise<void>((resolve, reject) => { | return new Promise<void>((resolve, reject) => { | ||||
| const el: HTMLElement = document.getElementById('config'); | const el: HTMLElement = document.getElementById('config'); | ||||
| try { | try { | ||||
| AppConfig.config.Version = AppConfig.currentApplicationVersion; | |||||
| if ( location.href.includes('//localhost:4200/') ) { | if ( location.href.includes('//localhost:4200/') ) { | ||||
| AppConfig.config = AppConfig.debugConfig; | AppConfig.config = AppConfig.debugConfig; | ||||
| // AppConfig.config.Server = '/api/v1/'; | // AppConfig.config.Server = '/api/v1/'; | ||||
| console.log('Using Debug Config:', AppConfig.config); | |||||
| // console.log('Using Debug Config:', AppConfig.config); | |||||
| }else{ | }else{ | ||||
| const json = this.decode(el.innerText); | const json = this.decode(el.innerText); | ||||
| AppConfig.config = JSON.parse(json); | AppConfig.config = JSON.parse(json); | ||||
| // AppConfig.config.Server = '/api/v1/'; | // AppConfig.config.Server = '/api/v1/'; | ||||
| console.log('Using Production Config:', AppConfig.config); | |||||
| // console.log('Using Production Config:', AppConfig.config); | |||||
| } | } | ||||
| resolve(); | resolve(); | ||||
| }catch (e){ | }catch (e){ |
| import { SinglePayoutRewardsListComponent } from './single-payout-rewards-list/single-payout-rewards-list.component'; | import { SinglePayoutRewardsListComponent } from './single-payout-rewards-list/single-payout-rewards-list.component'; | ||||
| import {SessionService} from './service/session.service'; | import {SessionService} from './service/session.service'; | ||||
| import { NumberRangeFilterComponent } from './grid-filter/number-range-filter/number-range-filter.component'; | import { NumberRangeFilterComponent } from './grid-filter/number-range-filter/number-range-filter.component'; | ||||
| import { StringFilterComponent } from './grid-filter/string-filter/string-filter.component'; | |||||
| import { DateFilterComponent } from './grid-filter/date-filter/date-filter.component'; | |||||
| RewardsAllComponent, | RewardsAllComponent, | ||||
| SinglePayoutRewardsListComponent, | SinglePayoutRewardsListComponent, | ||||
| NumberRangeFilterComponent, | NumberRangeFilterComponent, | ||||
| StringFilterComponent, | |||||
| DateFilterComponent, | |||||
| ], | ], | ||||
| imports: [ | imports: [ | ||||
| BrowserModule, | BrowserModule, |
| <img src="../../assets/img/logo.png"> | <img src="../../assets/img/logo.png"> | ||||
| <form *ngIf='!loading' class="k-form " [formGroup]="userForm" (ngSubmit)="submitForm()"> | <form *ngIf='!loading' class="k-form " [formGroup]="userForm" (ngSubmit)="submitForm()"> | ||||
| <fieldset class="k-form-fieldset"> | <fieldset class="k-form-fieldset"> | ||||
| <legend class="k-form-legend">Login to Supercredit</legend> | |||||
| <legend class="k-form-legend">Login to Web Office | |||||
| <sup>{{currentApplicationVersion}}</sup></legend> | |||||
| <kendo-formfield [showErrors]="'initial'"> | <kendo-formfield [showErrors]="'initial'"> | ||||
| <kendo-label [for]="email" text="Email"></kendo-label> | <kendo-label [for]="email" text="Email"></kendo-label> | ||||
| <input formControlName="email" kendoTextBox #email required/> | <input formControlName="email" kendoTextBox #email required/> |
| import { AuthService } from '../service/auth.service'; | import { AuthService } from '../service/auth.service'; | ||||
| import {ApiV1LoginResponse} from '../models/api-v1-login-response'; | import {ApiV1LoginResponse} from '../models/api-v1-login-response'; | ||||
| import {SessionService} from '../service/session.service'; | import {SessionService} from '../service/session.service'; | ||||
| import {environment} from '../../environments/environment'; | |||||
| @Component({ | @Component({ | ||||
| selector: 'app-auth', | selector: 'app-auth', | ||||
| export class AuthComponent implements OnInit, OnDestroy{ | export class AuthComponent implements OnInit, OnDestroy{ | ||||
| loading: boolean ; // a state that user is currently loading loggin | loading: boolean ; // a state that user is currently loading loggin | ||||
| loginSub: Subscription; | loginSub: Subscription; | ||||
| currentApplicationVersion = environment.appVersion; | |||||
| public userForm: FormGroup = new FormGroup({ | public userForm: FormGroup = new FormGroup({ | ||||
| password: new FormControl('pass', [Validators.minLength(3), Validators.maxLength(20)]), | password: new FormControl('pass', [Validators.minLength(3), Validators.maxLength(20)]), |
| <kendo-dateinput [format]="'dd/MM/yyyy'" [placeholder]="'dd/mm/yyy'" | |||||
| [(ngModel)]="date" (valueChange)="onDateChange($event)"></kendo-dateinput> | |||||
| <img src="../../../assets/img/signs/plus-minus-sign-small-grey.png"> | |||||
| <kendo-dropdownlist [data]="rangeData" [(ngModel)]="range" (valueChange)="onRangeChange($event)"> | |||||
| </kendo-dropdownlist> |
| kendo-dropdownlist { | |||||
| max-width: 50px; | |||||
| } | |||||
| img{ | |||||
| width: 16px; | |||||
| height: 16px; | |||||
| margin: 7px 5px 5px; | |||||
| } |
| import { ComponentFixture, TestBed } from '@angular/core/testing'; | |||||
| import { DateFilterComponent } from './date-filter.component'; | |||||
| describe('DateFilterComponent', () => { | |||||
| let component: DateFilterComponent; | |||||
| let fixture: ComponentFixture<DateFilterComponent>; | |||||
| beforeEach(async () => { | |||||
| await TestBed.configureTestingModule({ | |||||
| declarations: [ DateFilterComponent ] | |||||
| }) | |||||
| .compileComponents(); | |||||
| }); | |||||
| beforeEach(() => { | |||||
| fixture = TestBed.createComponent(DateFilterComponent); | |||||
| component = fixture.componentInstance; | |||||
| fixture.detectChanges(); | |||||
| }); | |||||
| it('should create', () => { | |||||
| expect(component).toBeTruthy(); | |||||
| }); | |||||
| }); |
| import {Component, Input, OnInit} from '@angular/core'; | |||||
| import {BaseFilterCellComponent, FilterService} from '@progress/kendo-angular-grid'; | |||||
| import {CompositeFilterDescriptor, FilterDescriptor} from '@progress/kendo-data-query'; | |||||
| import {debounce} from 'ts-debounce'; | |||||
| @Component({ | |||||
| selector: 'app-date-filter', | |||||
| templateUrl: './date-filter.component.html', | |||||
| styleUrls: ['./date-filter.component.scss'] | |||||
| }) | |||||
| export class DateFilterComponent extends BaseFilterCellComponent implements OnInit { | |||||
| @Input() filter: CompositeFilterDescriptor; | |||||
| @Input() data: Date; | |||||
| @Input() fieldName = ''; | |||||
| @Input() start = 0; | |||||
| @Input() end = 0; | |||||
| public date: Date; | |||||
| @Input() public range = 0; | |||||
| public rangeData = []; | |||||
| public debouncedDoFilter = debounce(this.doFilter, 500); | |||||
| constructor(filterService: FilterService) { super(filterService); } | |||||
| ngOnInit(): void { | |||||
| this.rangeData = this.rangeBetween(this.start, this.end); | |||||
| if ( this.range < this.start){ | |||||
| this.range = this.start; | |||||
| } | |||||
| if ( this.range > this.end ){ | |||||
| this.range = this.end; | |||||
| } | |||||
| this.date = new Date(); | |||||
| } | |||||
| private rangeBetween(start: number, end: number): number[] { | |||||
| let ret = []; | |||||
| if (start > end) { | |||||
| ret = new Array(start - end + 1); | |||||
| for (let i = 0; i < ret.length; i++, start--) { | |||||
| ret[i] = start; | |||||
| } | |||||
| return ret; | |||||
| } else { | |||||
| ret = new Array(end - start + 1); | |||||
| for (let j = 0; j < ret.length; j++, start++){ | |||||
| ret[j] = start; | |||||
| } | |||||
| return ret; | |||||
| } | |||||
| } | |||||
| public onDateChange(d: Date): void { | |||||
| console.log(this.date); | |||||
| this.debouncedDoFilter().then(); | |||||
| } | |||||
| public onRangeChange(r: number): void { | |||||
| console.log(this.date, r); | |||||
| this.debouncedDoFilter().then(); | |||||
| } | |||||
| private doFilter(): void { | |||||
| if ( this.date === null || this.date.getFullYear() < 1900){ | |||||
| this.applyFilter(this.removeFilter(this.fieldName)); | |||||
| return; | |||||
| } | |||||
| if ( this.range === 0 ){ | |||||
| this.buildSingleFilter(); | |||||
| }else{ | |||||
| this.buildRangeFilter(); | |||||
| } | |||||
| } | |||||
| private buildSingleFilter(): void { | |||||
| if ( this.date < new Date('1900-01-01') ){ | |||||
| this.applyFilter(this.removeFilter(this.fieldName)); | |||||
| return; | |||||
| }else{ | |||||
| this.applyFilter(this.updateFilter({ | |||||
| field: this.fieldName, | |||||
| operator: 'eq', | |||||
| value: this.date | |||||
| })); | |||||
| } | |||||
| } | |||||
| private buildRangeFilter(): void { | |||||
| const fs: FilterDescriptor[] = []; | |||||
| const start: Date = new Date(this.date); start.setDate(this.date.getDate() - this.range); | |||||
| const end: Date = new Date(this.date); end.setDate(this.date.getDate() + this.range); | |||||
| console.log(new Date(start), new Date(end)); | |||||
| fs.push({ | |||||
| field: this.fieldName, | |||||
| operator: 'gte', | |||||
| value: start.getTime() | |||||
| }); | |||||
| fs.push({ | |||||
| field: this.fieldName, | |||||
| operator: 'lte', | |||||
| value: end.getTime() | |||||
| }); | |||||
| this.removeFilter(this.fieldName); | |||||
| const root: CompositeFilterDescriptor = this.filter || { logic: 'and', | |||||
| filters: fs, | |||||
| }; | |||||
| if (fs.length) { | |||||
| root.filters.push(...fs); | |||||
| } | |||||
| this.filterService.filter(root); | |||||
| } | |||||
| } |
| } | } | ||||
| ngOnInit(): void { | ngOnInit(): void { | ||||
| console.log(this); | |||||
| this.initAvailableOperators(); | this.initAvailableOperators(); | ||||
| this.showOperatorChoice = this.availableOperators.length > 1 || | this.showOperatorChoice = this.availableOperators.length > 1 || | ||||
| ( this.availableOperators[0].op !== '=' && this.availableOperators[0].op !== ' '); | ( this.availableOperators[0].op !== '=' && this.availableOperators[0].op !== ' '); | ||||
| private initAvailableOperators(): void { | private initAvailableOperators(): void { | ||||
| this.availableOperators = this.AllOperatorMap.filter( v => { | this.availableOperators = this.AllOperatorMap.filter( v => { | ||||
| console.log(v, this.options.indexOf(v.value), this.options); | |||||
| // console.log(v, this.options.indexOf(v.value), this.options); | |||||
| return this.options.indexOf(v.value) !== -1; | return this.options.indexOf(v.value) !== -1; | ||||
| } ); | } ); | ||||
| if ( this.availableOperators.length === 0) { | if ( this.availableOperators.length === 0) { | ||||
| return; | return; | ||||
| } | } | ||||
| if (this.isEmpty(this.valueFrom)){ | |||||
| this.applyFilter(this.removeFilter(this.fieldName)); | |||||
| return; | |||||
| } | |||||
| if (this.singleMode) { | if (this.singleMode) { | ||||
| this.buildSingleFilter(); | this.buildSingleFilter(); | ||||
| } else { | } else { |
| <kendo-textbox [(ngModel)]="data" (valueChange)="onValueChange($event)"> </kendo-textbox> |
| kendo-textbox { | |||||
| border-bottom: 1px solid darkgrey; | |||||
| } |
| import { ComponentFixture, TestBed } from '@angular/core/testing'; | |||||
| import { StringFilterComponent } from './string-filter.component'; | |||||
| describe('StringFilterComponent', () => { | |||||
| let component: StringFilterComponent; | |||||
| let fixture: ComponentFixture<StringFilterComponent>; | |||||
| beforeEach(async () => { | |||||
| await TestBed.configureTestingModule({ | |||||
| declarations: [ StringFilterComponent ] | |||||
| }) | |||||
| .compileComponents(); | |||||
| }); | |||||
| beforeEach(() => { | |||||
| fixture = TestBed.createComponent(StringFilterComponent); | |||||
| component = fixture.componentInstance; | |||||
| fixture.detectChanges(); | |||||
| }); | |||||
| it('should create', () => { | |||||
| expect(component).toBeTruthy(); | |||||
| }); | |||||
| }); |
| import {Component, Input, OnInit} from '@angular/core'; | |||||
| import {BaseFilterCellComponent, FilterService} from '@progress/kendo-angular-grid'; | |||||
| import {CompositeFilterDescriptor} from '@progress/kendo-data-query'; | |||||
| import {debounce} from 'ts-debounce'; | |||||
| @Component({ | |||||
| selector: 'app-string-filter', | |||||
| templateUrl: './string-filter.component.html', | |||||
| styleUrls: ['./string-filter.component.scss'] | |||||
| }) | |||||
| export class StringFilterComponent extends BaseFilterCellComponent implements OnInit { | |||||
| @Input() public filter: CompositeFilterDescriptor; | |||||
| @Input() data = ''; | |||||
| @Input() fieldName = ''; | |||||
| public debouncedFilter = debounce(this.doFilter, 500); | |||||
| constructor(filterService: FilterService) { super(filterService); } | |||||
| ngOnInit(): void { | |||||
| } | |||||
| public onValueChange(v: string): void { | |||||
| if ( this.fieldName !== '' ){ | |||||
| this.debouncedFilter(v).then(); | |||||
| } | |||||
| } | |||||
| public doFilter(v: string): void { | |||||
| this.applyFilter( | |||||
| v === '' || v === null ? | |||||
| this.removeFilter(this.fieldName) : | |||||
| this.updateFilter({ | |||||
| field: this.fieldName, | |||||
| operator: 'eq', | |||||
| value: v | |||||
| }) | |||||
| ); | |||||
| } | |||||
| } |
| [pageSize]="filter.Take" | [pageSize]="filter.Take" | ||||
| [skip]="filter.Skip" | [skip]="filter.Skip" | ||||
| [sortable]="sortable" | [sortable]="sortable" | ||||
| [filterable]="'row'" | |||||
| [filterable]="allowFilter" | |||||
| [loading]="loading" | [loading]="loading" | ||||
| [sort]="filter.Sort" | [sort]="filter.Sort" | ||||
| [filter]="state.filter" | [filter]="state.filter" | ||||
| [selectable]="true" | |||||
| [selectable]="selectable" | |||||
| kendoGridSelectBy | kendoGridSelectBy | ||||
| [selectedKeys]="gridSelection" | |||||
| [selectedKeys]="Selection" | |||||
| [rowClass]="rowClassCallbackBind" | [rowClass]="rowClassCallbackBind" | ||||
| <div [ngStyle]="{'width': allowAddNew? '70%': '100%'}" class="filter-panel-wrapper" > | <div [ngStyle]="{'width': allowAddNew? '70%': '100%'}" class="filter-panel-wrapper" > | ||||
| <span *ngIf="uploadMeta.Id > 0 " class="badge badge-pill badge-primary specific-upload"> {{uploadMeta.Id}} </span> | <span *ngIf="uploadMeta.Id > 0 " class="badge badge-pill badge-primary specific-upload"> {{uploadMeta.Id}} </span> | ||||
| <span *ngIf="uploadMeta.Id > 0 " class="badge badge-secondary specific-upload"> {{uploadMeta.FileName}} </span> | <span *ngIf="uploadMeta.Id > 0 " class="badge badge-secondary specific-upload"> {{uploadMeta.FileName}} </span> | ||||
| <button kendoButton icon="filter" (click)="showFilter()" >Filter</button> | |||||
| <button *ngIf="false" kendoButton icon="filter" (click)="showFilter()" >Filter</button> | |||||
| <kendo-switch [(ngModel)]="allowFilter" onLabel="🝖" | |||||
| offLabel="all"></kendo-switch> | |||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| </ng-template> | </ng-template> | ||||
| <kendo-grid-column field="Id" title="Id" width="100" editable="false"> | <kendo-grid-column field="Id" title="Id" width="100" editable="false"> | ||||
| <ng-template kendoGridFilterCellTemplate let-filter let-column="column"> | <ng-template kendoGridFilterCellTemplate let-filter let-column="column"> | ||||
| <app-number-range-filter [filter]="filter" [fieldName]="'Id'" | <app-number-range-filter [filter]="filter" [fieldName]="'Id'" | ||||
| [min]=1 | |||||
| [options]="['eq']" [min]=1 | |||||
| > | > | ||||
| </app-number-range-filter> | </app-number-range-filter> | ||||
| </ng-template> | </ng-template> | ||||
| [loading]="lenderNameService.loading"> | [loading]="lenderNameService.loading"> | ||||
| </kendo-combobox> | </kendo-combobox> | ||||
| </ng-template> | </ng-template> | ||||
| <ng-template kendoGridFilterCellTemplate let-filter let-column="column"> | |||||
| <app-string-filter [filter]="filter" [fieldName]="'Lender'"> | |||||
| </app-string-filter> | |||||
| </ng-template> | |||||
| </kendo-grid-column> | </kendo-grid-column> | ||||
| <kendo-grid-column field="LoanNumber" title="Lender Loan Id" width="150" editor="string"> | <kendo-grid-column field="LoanNumber" title="Lender Loan Id" width="150" editor="string"> | ||||
| <ng-template kendoGridFilterCellTemplate let-filter let-column="column"> | |||||
| <app-string-filter [filter]="filter" [fieldName]="'LoanNumber'"> | |||||
| </app-string-filter> | |||||
| </ng-template> | |||||
| </kendo-grid-column> | </kendo-grid-column> | ||||
| <kendo-grid-column field="IncomeAmount" title="Income" width="150" format="{0:c}" editor="numeric"> | <kendo-grid-column field="IncomeAmount" title="Income" width="150" format="{0:c}" editor="numeric"> | ||||
| <ng-template kendoGridFilterCellTemplate let-filter let-column="column"> | |||||
| <app-number-range-filter [filter]="filter" [fieldName]="'IncomeAmount'" | |||||
| [options]="['eq', 'lte', 'gte', 'range']" [min]=0 | |||||
| > | |||||
| </app-number-range-filter> | |||||
| </ng-template> | |||||
| </kendo-grid-column> | </kendo-grid-column> | ||||
| <kendo-grid-column field="IncomeType" title="Type" width="150" editor="string"> | <kendo-grid-column field="IncomeType" title="Type" width="150" editor="string"> | ||||
| <ng-template kendoGridFilterCellTemplate let-filter let-column="column"> | |||||
| <app-string-filter [filter]="filter" [fieldName]="'IncomeType'"> | |||||
| </app-string-filter> | |||||
| </ng-template> | |||||
| </kendo-grid-column> | </kendo-grid-column> | ||||
| <kendo-grid-column field="Ts" title="Trail Date" editor="date" width="100"> | |||||
| <kendo-grid-column field="Ts" title="Trail Date" editor="date" width="220"> | |||||
| <ng-template kendoGridCellTemplate let-dataItem> | <ng-template kendoGridCellTemplate let-dataItem> | ||||
| {{ dataItem.Ts | date: 'yyyy-MM-dd' }} | {{ dataItem.Ts | date: 'yyyy-MM-dd' }} | ||||
| </ng-template> | </ng-template> | ||||
| <ng-template kendoGridFilterCellTemplate let-filter let-column="column"> | |||||
| <app-date-filter [filter]="filter" [fieldName]="'Ts'" [start]=0 [end]="15" [range]=1 > | |||||
| </app-date-filter> | |||||
| </ng-template> | |||||
| </kendo-grid-column> | </kendo-grid-column> | ||||
| <kendo-grid-column field="Balance" title="Balance" width="150"> | <kendo-grid-column field="Balance" title="Balance" width="150"> | ||||
| </kendo-numerictextbox> | </kendo-numerictextbox> | ||||
| </ng-template> | </ng-template> | ||||
| <ng-template kendoGridFilterCellTemplate let-filter let-column="column"> | |||||
| <app-number-range-filter [filter]="filter" [fieldName]="'Balance'" | |||||
| [options]="['eq', 'lte', 'gte','range']" [min]=0 | |||||
| > | |||||
| </app-number-range-filter> | |||||
| </ng-template> | |||||
| </kendo-grid-column> | </kendo-grid-column> | ||||
| <kendo-grid-column field="OffsetBalance" title="Offset" width="150" > | <kendo-grid-column field="OffsetBalance" title="Offset" width="150" > | ||||
| [min]="-1" [max]="999999999" [autoCorrect]="true" class="balance"> | [min]="-1" [max]="999999999" [autoCorrect]="true" class="balance"> | ||||
| </kendo-numerictextbox> | </kendo-numerictextbox> | ||||
| </ng-template> | </ng-template> | ||||
| <ng-template kendoGridFilterCellTemplate let-filter let-column="column"> | |||||
| <app-number-range-filter [filter]="filter" [fieldName]="'OffsetBalance'" | |||||
| [options]="['eq', 'lte', 'gte', 'range']" [min]=0 | |||||
| > | |||||
| </app-number-range-filter> | |||||
| </ng-template> | |||||
| </kendo-grid-column> | </kendo-grid-column> | ||||
| <kendo-grid-column *ngIf="showUploadColumn" | <kendo-grid-column *ngIf="showUploadColumn" | ||||
| </button> | </button> | ||||
| <p *ngIf="dataItem.UploadId <=0" > - </p> | <p *ngIf="dataItem.UploadId <=0" > - </p> | ||||
| </ng-template> | </ng-template> | ||||
| <ng-template kendoGridFilterCellTemplate let-filter let-column="column"> | |||||
| <app-number-range-filter [filter]="filter" [fieldName]="'UploadId'" | |||||
| [options]="['eq']" [min]=0 | |||||
| > | |||||
| </app-number-range-filter> | |||||
| </ng-template> | |||||
| </kendo-grid-column> | </kendo-grid-column> | ||||
| <kendo-grid-column *ngIf="showLoanColumn" | <kendo-grid-column *ngIf="showLoanColumn" | ||||
| field="LoanId" title="Loan" width="210" | field="LoanId" title="Loan" width="210" | ||||
| [editable]="true " | |||||
| [editable]="true " [filterable]="false" | |||||
| [sortable]="false"> | [sortable]="false"> | ||||
| <ng-template kendoGridCellTemplate let-dataItem> | <ng-template kendoGridCellTemplate let-dataItem> | ||||
| <app-loan-card *ngIf="dataItem.LoanId !== '' " [Loan]="dataItem.Loan"></app-loan-card> | <app-loan-card *ngIf="dataItem.LoanId !== '' " [Loan]="dataItem.Loan"></app-loan-card> |
| import {PayInListResult} from '../models/pay-in-list-result.model'; | import {PayInListResult} from '../models/pay-in-list-result.model'; | ||||
| import {Router} from '@angular/router'; | import {Router} from '@angular/router'; | ||||
| import {PopupIncomeFilterComponent} from '../popup-income-filter/popup-income-filter.component'; | import {PopupIncomeFilterComponent} from '../popup-income-filter/popup-income-filter.component'; | ||||
| import {GridComponent, PageChangeEvent, RowClassArgs, SortSettings, DataStateChangeEvent} from '@progress/kendo-angular-grid'; | |||||
| import { | |||||
| GridComponent, | |||||
| PageChangeEvent, | |||||
| RowClassArgs, | |||||
| SortSettings, | |||||
| DataStateChangeEvent, | |||||
| SelectableSettings | |||||
| } from '@progress/kendo-angular-grid'; | |||||
| import {CompositeFilterDescriptor, FilterDescriptor, SortDescriptor} from '@progress/kendo-data-query'; | import {CompositeFilterDescriptor, FilterDescriptor, SortDescriptor} from '@progress/kendo-data-query'; | ||||
| import {UploadMetaModel} from '../models/uploadMetaModel'; | import {UploadMetaModel} from '../models/uploadMetaModel'; | ||||
| import {debounce} from 'ts-debounce'; | import {debounce} from 'ts-debounce'; | ||||
| export class PayInComponent implements OnInit { | export class PayInComponent implements OnInit { | ||||
| @Input() allowAddNew = true; | @Input() allowAddNew = true; | ||||
| @Input() allowEdit = true; | @Input() allowEdit = true; | ||||
| @Input() allowFilter = false; | |||||
| @Input() showLoanColumn = true; | @Input() showLoanColumn = true; | ||||
| @Input() showUploadColumn = true; | @Input() showUploadColumn = true; | ||||
| @Input() selectable: SelectableSettings | boolean; | |||||
| private filterUploadMeta: UploadMetaModel = new UploadMetaModel({}); | private filterUploadMeta: UploadMetaModel = new UploadMetaModel({}); | ||||
| public filterLoan = new LoanModel({}); | public filterLoan = new LoanModel({}); | ||||
| @Input() filter: PayInListFilterModel = new PayInListFilterModel({}); | @Input() filter: PayInListFilterModel = new PayInListFilterModel({}); | ||||
| @Input() public pageable = true; | @Input() public pageable = true; | ||||
| @Input() public pageSize = 15; | @Input() public pageSize = 15; | ||||
| public gridSelection: number[] = []; | |||||
| @Input() public Selection: number[] = []; | |||||
| public sortable: SortSettings = { | public sortable: SortSettings = { | ||||
| mode: 'single' | mode: 'single' | ||||
| }; | }; | ||||
| private ScrollTo(row: number): void { | private ScrollTo(row: number): void { | ||||
| this.grid.scrollTo({ row}); | this.grid.scrollTo({ row}); | ||||
| this.grid.focusCell(row + 1, 1 ); | this.grid.focusCell(row + 1, 1 ); | ||||
| this.gridSelection = [row]; | |||||
| this.Selection = [row]; | |||||
| } | } | ||||
| public selectOrAddPayIn(pi: PayInModel): void{ | public selectOrAddPayIn(pi: PayInModel): void{ | ||||
| if ( row >= 0 ) { // we found it | if ( row >= 0 ) { // we found it | ||||
| this.ScrollTo(row); | this.ScrollTo(row); | ||||
| } else{ | } else{ | ||||
| this.gridSelection = []; // select none | |||||
| this.Selection = []; // select none | |||||
| this.incomeFormGroup = this.createFormGroup(new PayInModelEx(pi)); | this.incomeFormGroup = this.createFormGroup(new PayInModelEx(pi)); | ||||
| this.grid.addRow(this.incomeFormGroup); | this.grid.addRow(this.incomeFormGroup); | ||||
| } | } |
| <div class="card-header bg-transparent header-elements-inline"> | <div class="card-header bg-transparent header-elements-inline"> | ||||
| <app-reward-select></app-reward-select> | <app-reward-select></app-reward-select> | ||||
| <div class="header-elements"> | <div class="header-elements"> | ||||
| <button> test </button> | |||||
| <kendo-chip | <kendo-chip | ||||
| [removable]="true" | [removable]="true" | ||||
| (remove)="onRemoveChip('somelabel', $event)" | (remove)="onRemoveChip('somelabel', $event)" | ||||
| <tbody> | <tbody> | ||||
| <tr> | <tr> | ||||
| <th class="text-left">Subtotal:</th> | <th class="text-left">Subtotal:</th> | ||||
| <td class="text-right">$1,090</td> | |||||
| <td class="text-right">{{amount | currency}}</td> | |||||
| </tr> | </tr> | ||||
| <tr> | <tr> | ||||
| <th class="text-left">Tax: <span class="font-weight-normal">(25%)</span></th> | <th class="text-left">Tax: <span class="font-weight-normal">(25%)</span></th> |
| export class PayOutDetailsComponent implements OnInit { | export class PayOutDetailsComponent implements OnInit { | ||||
| sales = []; | sales = []; | ||||
| amount = 3218; | |||||
| background = 'url(\'https://svr2021.lawipac.com:8080/api/v1/avatar/0\')'; | background = 'url(\'https://svr2021.lawipac.com:8080/api/v1/avatar/0\')'; | ||||
| constructor() { } | constructor() { } | ||||
| ngOnInit(): void { | ngOnInit(): void { | ||||
| setInterval(() => { | |||||
| this.amount += 1; | |||||
| }, 1000); | |||||
| } | } | ||||
| range(start: number, end: number): number[] { | range(start: number, end: number): number[] { | ||||
| console.log(s, e); | console.log(s, e); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| private startWebsocket(): void { | private startWebsocket(): void { | ||||
| console.log('starting websocket now..', this.url); | |||||
| // console.log('starting websocket now..', this.url); | |||||
| this.ws = new WebSocket(this.url); | this.ws = new WebSocket(this.url); | ||||
| this.ws.onopen = this.onOpen.bind(this); | this.ws.onopen = this.onOpen.bind(this); | ||||
| this.ws.onmessage = this.onMessage.bind(this); | this.ws.onmessage = this.onMessage.bind(this); |
| export const environment = { | export const environment = { | ||||
| appVersion: require('../../package.json').version + '-dev', | |||||
| production: true | production: true | ||||
| }; | }; |
| // The list of file replacements can be found in `angular.json`. | // The list of file replacements can be found in `angular.json`. | ||||
| export const environment = { | export const environment = { | ||||
| appVersion: require('../../package.json').version + '-dev', | |||||
| production: false | production: false | ||||
| }; | }; | ||||
| <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://sc5016.biukop.com.au:8080/" | |||||
| version="0.9.1" | |||||
| > | |||||
| <script id="config" type="text/biukop-config"> | |||||
| eyJTZXJ2ZXIiOiJodHRwczpcL1wvYzUwMTYuYml1a29wLmNvbS5hd | eyJTZXJ2ZXIiOiJodHRwczpcL1wvYzUwMTYuYml1a29wLmNvbS5hd | ||||
| To4MDgwXC9hcGlcL3YxXC8iLCJTb2NrZXQiOiJ3c3M6XC9cL2M1MD | To4MDgwXC9hcGlcL3YxXC8iLCJTb2NrZXQiOiJ3c3M6XC9cL2M1MD | ||||
| E2LmJpdWtvcC5jb20uYXU6ODA4MFwvYXBpXC92MVwvd3MiLCJTZXN | E2LmJpdWtvcC5jb20uYXU6ODA4MFwvYXBpXC92MVwvd3MiLCJTZXN |
| "extends": "./tsconfig.json", | "extends": "./tsconfig.json", | ||||
| "compilerOptions": { | "compilerOptions": { | ||||
| "outDir": "./out-tsc/app", | "outDir": "./out-tsc/app", | ||||
| "types": [] | |||||
| "types": [ | |||||
| "node" | |||||
| ] | |||||
| }, | }, | ||||
| "files": [ | "files": [ | ||||
| "src/main.ts", | "src/main.ts", |
| "compilerOptions": { | "compilerOptions": { | ||||
| "outDir": "./out-tsc/spec", | "outDir": "./out-tsc/spec", | ||||
| "types": [ | "types": [ | ||||
| "jasmine" | |||||
| "jasmine", | |||||
| "node" | |||||
| ] | ] | ||||
| }, | }, | ||||
| "files": [ | "files": [ |