diff --git a/package-lock.json b/package-lock.json index 7492e3a..6653318 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "broker", - "version": "0.0.0", + "version": "2.0.1", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 32c9dc3..e2ba177 100644 --- a/package.json +++ b/package.json @@ -1,9 +1,10 @@ { "name": "broker", - "version": "0.0.0", + "version": "2.0.1", "scripts": { "ng": "ng", "start": "ng serve --proxy-config proxy.conf.json", + "prebuild": "npm --no-git-tag-version version patch", "build": "ng build ", "buildsfm": "ng build --prod --base-href=/broker/ --deploy-url=/broker/ ", "test": "ng test", diff --git a/src/app/app.component.ts b/src/app/app.component.ts index b50c8e0..96c52df 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -7,7 +7,7 @@ import {WebSocketService} from './websocket'; import {Title} from '@angular/platform-browser'; import {WsLoginEventModel} from './models/websocket/ws.login.event.model'; import {SessionService} from './service/session.service'; -import {AppConfig} from './app.config'; +import {environment} from '../environments/environment'; @Component({ selector: 'app-root', @@ -16,7 +16,8 @@ import {AppConfig} from './app.config'; encapsulation: ViewEncapsulation.None }) export class AppComponent implements OnInit , OnDestroy { - title = 'SFM Advanced Loan management'; + title = 'SFM Web Office'; + currentApplicationVersion = environment.appVersion; private menuItemSub: Subscription; @ViewChild('loanEditComponent', {static: true}) loanEdit: LoanEditComponent; @@ -29,8 +30,9 @@ export class AppComponent implements OnInit , OnDestroy { private ss: SessionService, private wsService: WebSocketService, private titleService: Title){ + this.title = 'SFM Web Office (' + this.currentApplicationVersion + ')'; 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 => { diff --git a/src/app/app.config.model.ts b/src/app/app.config.model.ts index fa9409a..bb92e6d 100644 --- a/src/app/app.config.model.ts +++ b/src/app/app.config.model.ts @@ -1,7 +1,14 @@ +import {environment} from '../environments/environment'; 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) { + 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; + } } diff --git a/src/app/app.config.ts b/src/app/app.config.ts index 726a079..59b20fe 100644 --- a/src/app/app.config.ts +++ b/src/app/app.config.ts @@ -1,24 +1,24 @@ import { Injectable } from '@angular/core'; import { HttpClient } from '@angular/common/http'; import {AppConfigModel} from './app.config.model'; +import {environment} from '../environments/environment'; @Injectable() export class AppConfig { - static config: AppConfigModel; + static config = new AppConfigModel({}); + static currentApplicationVersion = environment.appVersion; static debugConfig: AppConfigModel = { Server: 'https://svr2021.lawipac.com:8080/api/v1/', Socket: 'wss://svr2021.lawipac.com:8080/api/v1/ws', SessionStorageKey: 'sk', - Version: 2021 }; static productionConfig: AppConfigModel = { Server: 'https://c5016.biukop.com.au:8080/api/v1/', Socket: 'wss://c5016.biukop.com.au:8080/api/v1/ws', SessionStorageKey : 'sk', - Version: 2021 }; constructor(private http: HttpClient) {} @@ -27,15 +27,16 @@ export class AppConfig { return new Promise((resolve, reject) => { const el: HTMLElement = document.getElementById('config'); try { + AppConfig.config.Version = AppConfig.currentApplicationVersion; if ( location.href.includes('//localhost:4200/') ) { AppConfig.config = AppConfig.debugConfig; // AppConfig.config.Server = '/api/v1/'; - console.log('Using Debug Config:', AppConfig.config); + // console.log('Using Debug Config:', AppConfig.config); }else{ const json = this.decode(el.innerText); AppConfig.config = JSON.parse(json); // AppConfig.config.Server = '/api/v1/'; - console.log('Using Production Config:', AppConfig.config); + // console.log('Using Production Config:', AppConfig.config); } resolve(); }catch (e){ diff --git a/src/app/app.module.ts b/src/app/app.module.ts index e5f24cd..e47746c 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -113,6 +113,8 @@ import { RewardsAllComponent } from './rewards-all/rewards-all.component'; import { SinglePayoutRewardsListComponent } from './single-payout-rewards-list/single-payout-rewards-list.component'; import {SessionService} from './service/session.service'; 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'; @@ -194,6 +196,8 @@ export function initializeApp(appConfig: AppConfig): () => Promise { RewardsAllComponent, SinglePayoutRewardsListComponent, NumberRangeFilterComponent, + StringFilterComponent, + DateFilterComponent, ], imports: [ BrowserModule, diff --git a/src/app/auth/auth.component.html b/src/app/auth/auth.component.html index 070cf72..db4f15e 100644 --- a/src/app/auth/auth.component.html +++ b/src/app/auth/auth.component.html @@ -3,7 +3,8 @@
- Login to Supercredit + Login to Web Office + {{currentApplicationVersion}} diff --git a/src/app/auth/auth.component.ts b/src/app/auth/auth.component.ts index 0a69c9e..98111f4 100644 --- a/src/app/auth/auth.component.ts +++ b/src/app/auth/auth.component.ts @@ -6,6 +6,7 @@ import { Subscription } from 'rxjs'; import { AuthService } from '../service/auth.service'; import {ApiV1LoginResponse} from '../models/api-v1-login-response'; import {SessionService} from '../service/session.service'; +import {environment} from '../../environments/environment'; @Component({ selector: 'app-auth', @@ -15,6 +16,7 @@ import {SessionService} from '../service/session.service'; export class AuthComponent implements OnInit, OnDestroy{ loading: boolean ; // a state that user is currently loading loggin loginSub: Subscription; + currentApplicationVersion = environment.appVersion; public userForm: FormGroup = new FormGroup({ password: new FormControl('pass', [Validators.minLength(3), Validators.maxLength(20)]), diff --git a/src/app/grid-filter/date-filter/date-filter.component.html b/src/app/grid-filter/date-filter/date-filter.component.html new file mode 100644 index 0000000..5a0649a --- /dev/null +++ b/src/app/grid-filter/date-filter/date-filter.component.html @@ -0,0 +1,6 @@ + + + + + diff --git a/src/app/grid-filter/date-filter/date-filter.component.scss b/src/app/grid-filter/date-filter/date-filter.component.scss new file mode 100644 index 0000000..7249ea5 --- /dev/null +++ b/src/app/grid-filter/date-filter/date-filter.component.scss @@ -0,0 +1,9 @@ +kendo-dropdownlist { + max-width: 50px; +} + +img{ + width: 16px; + height: 16px; + margin: 7px 5px 5px; +} diff --git a/src/app/grid-filter/date-filter/date-filter.component.spec.ts b/src/app/grid-filter/date-filter/date-filter.component.spec.ts new file mode 100644 index 0000000..8e87935 --- /dev/null +++ b/src/app/grid-filter/date-filter/date-filter.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { DateFilterComponent } from './date-filter.component'; + +describe('DateFilterComponent', () => { + let component: DateFilterComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ DateFilterComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(DateFilterComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/grid-filter/date-filter/date-filter.component.ts b/src/app/grid-filter/date-filter/date-filter.component.ts new file mode 100644 index 0000000..b746175 --- /dev/null +++ b/src/app/grid-filter/date-filter/date-filter.component.ts @@ -0,0 +1,114 @@ +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); + } + +} diff --git a/src/app/grid-filter/number-range-filter/number-range-filter.component.ts b/src/app/grid-filter/number-range-filter/number-range-filter.component.ts index 59c24b5..0187ac1 100644 --- a/src/app/grid-filter/number-range-filter/number-range-filter.component.ts +++ b/src/app/grid-filter/number-range-filter/number-range-filter.component.ts @@ -72,7 +72,6 @@ export class NumberRangeFilterComponent extends BaseFilterCellComponent implemen } ngOnInit(): void { - console.log(this); this.initAvailableOperators(); this.showOperatorChoice = this.availableOperators.length > 1 || ( this.availableOperators[0].op !== '=' && this.availableOperators[0].op !== ' '); @@ -86,7 +85,7 @@ export class NumberRangeFilterComponent extends BaseFilterCellComponent implemen private initAvailableOperators(): void { 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; } ); if ( this.availableOperators.length === 0) { @@ -219,6 +218,11 @@ export class NumberRangeFilterComponent extends BaseFilterCellComponent implemen return; } + if (this.isEmpty(this.valueFrom)){ + this.applyFilter(this.removeFilter(this.fieldName)); + return; + } + if (this.singleMode) { this.buildSingleFilter(); } else { diff --git a/src/app/grid-filter/string-filter/string-filter.component.html b/src/app/grid-filter/string-filter/string-filter.component.html new file mode 100644 index 0000000..3775d70 --- /dev/null +++ b/src/app/grid-filter/string-filter/string-filter.component.html @@ -0,0 +1 @@ + diff --git a/src/app/grid-filter/string-filter/string-filter.component.scss b/src/app/grid-filter/string-filter/string-filter.component.scss new file mode 100644 index 0000000..dfa6d4f --- /dev/null +++ b/src/app/grid-filter/string-filter/string-filter.component.scss @@ -0,0 +1,3 @@ +kendo-textbox { + border-bottom: 1px solid darkgrey; +} diff --git a/src/app/grid-filter/string-filter/string-filter.component.spec.ts b/src/app/grid-filter/string-filter/string-filter.component.spec.ts new file mode 100644 index 0000000..59c7208 --- /dev/null +++ b/src/app/grid-filter/string-filter/string-filter.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { StringFilterComponent } from './string-filter.component'; + +describe('StringFilterComponent', () => { + let component: StringFilterComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ StringFilterComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(StringFilterComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/grid-filter/string-filter/string-filter.component.ts b/src/app/grid-filter/string-filter/string-filter.component.ts new file mode 100644 index 0000000..53cfe2f --- /dev/null +++ b/src/app/grid-filter/string-filter/string-filter.component.ts @@ -0,0 +1,38 @@ +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 + }) + ); + } +} diff --git a/src/app/pay-in/pay-in.component.html b/src/app/pay-in/pay-in.component.html index ab0544b..7d5fc7f 100644 --- a/src/app/pay-in/pay-in.component.html +++ b/src/app/pay-in/pay-in.component.html @@ -5,15 +5,15 @@ [pageSize]="filter.Take" [skip]="filter.Skip" [sortable]="sortable" - [filterable]="'row'" + [filterable]="allowFilter" [loading]="loading" [sort]="filter.Sort" [filter]="state.filter" - [selectable]="true" + [selectable]="selectable" kendoGridSelectBy - [selectedKeys]="gridSelection" + [selectedKeys]="Selection" [rowClass]="rowClassCallbackBind" @@ -38,7 +38,9 @@
{{uploadMeta.Id}} {{uploadMeta.FileName}} - + +
@@ -56,7 +58,7 @@ @@ -72,20 +74,44 @@ [loading]="lenderNameService.loading"> + + + + + + + + + + + + + + + + + - + {{ dataItem.Ts | date: 'yyyy-MM-dd' }} + + + + + @@ -112,6 +138,12 @@ + + + + @@ -137,6 +169,12 @@ [min]="-1" [max]="999999999" [autoCorrect]="true" class="balance"> + + + +

-

+ + + +
diff --git a/src/app/pay-in/pay-in.component.ts b/src/app/pay-in/pay-in.component.ts index 7d073f7..9fa1fae 100644 --- a/src/app/pay-in/pay-in.component.ts +++ b/src/app/pay-in/pay-in.component.ts @@ -6,7 +6,14 @@ import {PayInService} from '../service/pay-in.service'; import {PayInListResult} from '../models/pay-in-list-result.model'; import {Router} from '@angular/router'; 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 {UploadMetaModel} from '../models/uploadMetaModel'; import {debounce} from 'ts-debounce'; @@ -28,8 +35,10 @@ import {GridStateModel} from '../models/grid.state.model'; export class PayInComponent implements OnInit { @Input() allowAddNew = true; @Input() allowEdit = true; + @Input() allowFilter = false; @Input() showLoanColumn = true; @Input() showUploadColumn = true; + @Input() selectable: SelectableSettings | boolean; private filterUploadMeta: UploadMetaModel = new UploadMetaModel({}); public filterLoan = new LoanModel({}); @Input() filter: PayInListFilterModel = new PayInListFilterModel({}); @@ -51,7 +60,7 @@ export class PayInComponent implements OnInit { @Input() public pageable = true; @Input() public pageSize = 15; - public gridSelection: number[] = []; + @Input() public Selection: number[] = []; public sortable: SortSettings = { mode: 'single' }; @@ -369,7 +378,7 @@ export class PayInComponent implements OnInit { private ScrollTo(row: number): void { this.grid.scrollTo({ row}); this.grid.focusCell(row + 1, 1 ); - this.gridSelection = [row]; + this.Selection = [row]; } public selectOrAddPayIn(pi: PayInModel): void{ @@ -384,7 +393,7 @@ export class PayInComponent implements OnInit { if ( row >= 0 ) { // we found it this.ScrollTo(row); } else{ - this.gridSelection = []; // select none + this.Selection = []; // select none this.incomeFormGroup = this.createFormGroup(new PayInModelEx(pi)); this.grid.addRow(this.incomeFormGroup); } diff --git a/src/app/pay-out-details/pay-out-details.component.html b/src/app/pay-out-details/pay-out-details.component.html index d5226f7..47dc8bc 100644 --- a/src/app/pay-out-details/pay-out-details.component.html +++ b/src/app/pay-out-details/pay-out-details.component.html @@ -7,6 +7,7 @@
+ Subtotal: - $1,090 + {{amount | currency}} Tax: (25%) diff --git a/src/app/pay-out-details/pay-out-details.component.ts b/src/app/pay-out-details/pay-out-details.component.ts index 9da6622..d126a4c 100644 --- a/src/app/pay-out-details/pay-out-details.component.ts +++ b/src/app/pay-out-details/pay-out-details.component.ts @@ -9,12 +9,14 @@ import {ChipRemoveEvent} from '@progress/kendo-angular-buttons'; export class PayOutDetailsComponent implements OnInit { sales = []; + amount = 3218; background = 'url(\'https://svr2021.lawipac.com:8080/api/v1/avatar/0\')'; constructor() { } ngOnInit(): void { - - + setInterval(() => { + this.amount += 1; + }, 1000); } range(start: number, end: number): number[] { @@ -26,3 +28,4 @@ export class PayOutDetailsComponent implements OnInit { console.log(s, e); } } + diff --git a/src/app/websocket.ts b/src/app/websocket.ts index da3e805..0fbe8f1 100644 --- a/src/app/websocket.ts +++ b/src/app/websocket.ts @@ -26,7 +26,7 @@ export class WebSocketService extends Subject{ } 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.onopen = this.onOpen.bind(this); this.ws.onmessage = this.onMessage.bind(this); diff --git a/src/assets/img/signs/plus-and-minus-black.jpg b/src/assets/img/signs/plus-and-minus-black.jpg new file mode 100644 index 0000000..a51c831 Binary files /dev/null and b/src/assets/img/signs/plus-and-minus-black.jpg differ diff --git a/src/assets/img/signs/plus-and-minus-grey.png b/src/assets/img/signs/plus-and-minus-grey.png new file mode 100644 index 0000000..479aca9 Binary files /dev/null and b/src/assets/img/signs/plus-and-minus-grey.png differ diff --git a/src/assets/img/signs/plus-minus-color.png b/src/assets/img/signs/plus-minus-color.png new file mode 100644 index 0000000..a634090 Binary files /dev/null and b/src/assets/img/signs/plus-minus-color.png differ diff --git a/src/assets/img/signs/plus-minus-sign-small-grey.png b/src/assets/img/signs/plus-minus-sign-small-grey.png new file mode 100644 index 0000000..abfe9c7 Binary files /dev/null and b/src/assets/img/signs/plus-minus-sign-small-grey.png differ diff --git a/src/environments/environment.prod.ts b/src/environments/environment.prod.ts index 3612073..72f6a13 100644 --- a/src/environments/environment.prod.ts +++ b/src/environments/environment.prod.ts @@ -1,3 +1,4 @@ export const environment = { + appVersion: require('../../package.json').version + '-dev', production: true }; diff --git a/src/environments/environment.ts b/src/environments/environment.ts index 7b4f817..efb609e 100644 --- a/src/environments/environment.ts +++ b/src/environments/environment.ts @@ -3,6 +3,7 @@ // The list of file replacements can be found in `angular.json`. export const environment = { + appVersion: require('../../package.json').version + '-dev', production: false }; diff --git a/src/index.html b/src/index.html index 7164e21..932d08f 100644 --- a/src/index.html +++ b/src/index.html @@ -9,10 +9,7 @@ -