From 28f9bf21801aec6b3d46d2039968dd7bda3e8a9f Mon Sep 17 00:00:00 2001 From: Amritanshu Date: Fri, 15 Jul 2022 13:24:25 +0530 Subject: [PATCH] Chore: Moved from Untyped to Stongly Typed forms. --- overlord/.eslintrc.json | 6 +- overlord/package.json | 1 + .../account-detail.component.ts | 37 +++--- .../account-list/account-list-datasource.ts | 3 +- .../account-list/account-list.component.html | 2 +- .../account-list/account-list.component.ts | 31 +++-- .../src/app/account/account-routing.module.ts | 1 + .../app/attendance/attendance.component.html | 5 +- .../app/attendance/attendance.component.ts | 51 ++++---- .../src/app/attendance/attendance.service.ts | 2 +- .../src/app/auth/login/login.component.ts | 13 +- .../balance-sheet/balance-sheet.component.ts | 17 ++- .../src/app/cash-flow/cash-flow.component.ts | 20 +-- .../client-detail/client-detail.component.ts | 32 +++-- overlord/src/app/client/client.service.ts | 2 +- .../closing-stock/closing-stock.component.ts | 51 ++++---- .../closing-stock/closing-stock.service.ts | 1 - overlord/src/app/core/account.service.ts | 2 +- overlord/src/app/core/account.ts | 2 +- overlord/src/app/core/batch.ts | 1 - overlord/src/app/core/inventory.ts | 1 - overlord/src/app/core/voucher.service.ts | 2 +- .../cost-centre-detail.component.ts | 14 +- .../app/cost-centre/cost-centre.service.ts | 2 +- overlord/src/app/daybook/daybook.component.ts | 22 ++-- .../employee-attendance.component.html | 5 +- .../employee-attendance.component.ts | 69 +++++----- .../employee-attendance.service.ts | 2 +- .../employee-benefits.component.ts | 46 +++---- .../employee-functions.component.ts | 59 ++++----- .../employee-detail.component.ts | 54 ++++---- .../employee-list/employee-list.component.ts | 22 ++-- overlord/src/app/employee/employee.service.ts | 2 +- .../src/app/entries/entries.component.html | 6 +- overlord/src/app/entries/entries.component.ts | 55 ++++---- .../src/app/incentive/incentive.component.ts | 66 ++++------ .../src/app/issue/issue-dialog.component.ts | 24 ++-- overlord/src/app/issue/issue.component.ts | 64 ++++----- .../app/journal/journal-dialog.component.html | 4 +- .../app/journal/journal-dialog.component.ts | 31 +++-- .../src/app/journal/journal.component.html | 4 +- overlord/src/app/journal/journal.component.ts | 59 +++++---- overlord/src/app/ledger/ledger.component.ts | 26 ++-- .../net-transactions.component.ts | 20 +-- .../non-contract-purchase.module.ts | 1 - .../app/payment/payment-dialog.component.ts | 24 ++-- overlord/src/app/payment/payment.component.ts | 62 ++++----- .../product-group-detail.component.ts | 14 +- .../product-group/product-group.service.ts | 2 +- .../product-ledger.component.ts | 28 ++-- .../src/app/product-ledger/product-ledger.ts | 3 +- .../product-detail-dialog.component.ts | 41 +++--- .../product-detail.component.ts | 85 ++++++------ .../product-list/product-list.component.ts | 22 ++-- .../app/product/product-resolver.service.ts | 2 +- overlord/src/app/product/product.service.ts | 2 +- .../app/profit-loss/profit-loss.component.ts | 20 +-- .../purchase-entries.component.ts | 20 +-- .../purchase-return-dialog.component.ts | 24 ++-- .../purchase-return.component.ts | 63 +++++---- .../app/purchase/purchase-dialog.component.ts | 56 +++++--- .../src/app/purchase/purchase.component.ts | 108 +++++++-------- .../src/app/purchases/purchases.component.ts | 20 +-- .../rate-contract-detail.component.ts | 61 +++++---- .../app/rate-contract/rate-contract.module.ts | 7 +- .../raw-material-cost.component.ts | 21 ++- .../app/receipt/receipt-dialog.component.ts | 24 ++-- overlord/src/app/receipt/receipt.component.ts | 62 ++++----- .../recipe-detail/recipe-detail.component.ts | 92 ++++++------- .../recipe-list/recipe-list.component.ts | 23 ++-- .../role/role-detail/role-detail.component.ts | 45 ++++--- overlord/src/app/role/role.service.ts | 2 +- .../src/app/settings/settings.component.ts | 123 +++++++++--------- overlord/src/app/settings/settings.service.ts | 1 - overlord/src/app/shared/math.service.ts | 2 - .../stock-movement.component.ts | 20 +-- .../trial-balance/trial-balance.component.ts | 17 ++- .../user/user-detail/user-detail.component.ts | 59 ++++----- 78 files changed, 1091 insertions(+), 1004 deletions(-) diff --git a/overlord/.eslintrc.json b/overlord/.eslintrc.json index 2f71e5ac..6deda183 100644 --- a/overlord/.eslintrc.json +++ b/overlord/.eslintrc.json @@ -19,7 +19,8 @@ "plugin:@angular-eslint/template/process-inline-templates" ], "plugins": [ - "import" + "import", + "unused-imports" ], "rules": { "@angular-eslint/directive-selector": [ @@ -54,7 +55,8 @@ }, "newlines-between": "always" } - ] + ], + "unused-imports/no-unused-imports": "error" } }, { diff --git a/overlord/package.json b/overlord/package.json index 6b42094e..e225a884 100644 --- a/overlord/package.json +++ b/overlord/package.json @@ -53,6 +53,7 @@ "@typescript-eslint/parser": "^5.29.0", "eslint": "^8.18.0", "eslint-plugin-import": "2.26.0", + "eslint-plugin-unused-imports": "^2.0.0", "husky": "^8.0.1", "jasmine-core": "~3.8.0", "jasmine-spec-reporter": "7.0.0", diff --git a/overlord/src/app/account/account-detail/account-detail.component.ts b/overlord/src/app/account/account-detail/account-detail.component.ts index c4481ce7..be1229fa 100644 --- a/overlord/src/app/account/account-detail/account-detail.component.ts +++ b/overlord/src/app/account/account-detail/account-detail.component.ts @@ -1,5 +1,5 @@ import { AfterViewInit, Component, ElementRef, OnInit, ViewChild } from '@angular/core'; -import { UntypedFormBuilder, UntypedFormGroup } from '@angular/forms'; +import { FormControl, FormGroup } from '@angular/forms'; import { MatDialog } from '@angular/material/dialog'; import { ActivatedRoute, Router } from '@angular/router'; @@ -17,7 +17,15 @@ import { ConfirmDialogComponent } from '../../shared/confirm-dialog/confirm-dial }) export class AccountDetailComponent implements OnInit, AfterViewInit { @ViewChild('nameElement', { static: true }) nameElement?: ElementRef; - form: UntypedFormGroup; + form: FormGroup<{ + code: FormControl; + name: FormControl; + type: FormControl; + isActive: FormControl; + isReconcilable: FormControl; + costCentre: FormControl; + }>; + accountTypes: AccountType[] = []; costCentres: CostCentre[] = []; item: Account = new Account(); @@ -26,17 +34,16 @@ export class AccountDetailComponent implements OnInit, AfterViewInit { private route: ActivatedRoute, private router: Router, private dialog: MatDialog, - private fb: UntypedFormBuilder, private toaster: ToasterService, private ser: AccountService, ) { - this.form = this.fb.group({ - code: { value: '', disabled: true }, - name: '', - type: '', - isActive: '', - isReconcilable: '', - costCentre: '', + this.form = new FormGroup({ + code: new FormControl({ value: 0, disabled: true }, { nonNullable: true }), + name: new FormControl(null), + type: new FormControl(''), + isActive: new FormControl(true, { nonNullable: true }), + isReconcilable: new FormControl(false, { nonNullable: true }), + costCentre: new FormControl(null), }); } @@ -62,7 +69,7 @@ export class AccountDetailComponent implements OnInit, AfterViewInit { type: this.item.type, isActive: this.item.isActive, isReconcilable: this.item.isReconcilable, - costCentre: this.item.costCentre.id, + costCentre: this.item.costCentre.id!, }); } @@ -113,11 +120,11 @@ export class AccountDetailComponent implements OnInit, AfterViewInit { getItem(): Account { const formModel = this.form.value; - this.item.name = formModel.name; + this.item.name = formModel.name!; this.item.type = formModel.type; - this.item.isActive = formModel.isActive; - this.item.isReconcilable = formModel.isReconcilable; - this.item.costCentre.id = formModel.costCentre; + this.item.isActive = formModel.isActive!; + this.item.isReconcilable = formModel.isReconcilable!; + this.item.costCentre.id = formModel.costCentre!; return this.item; } } diff --git a/overlord/src/app/account/account-list/account-list-datasource.ts b/overlord/src/app/account/account-list/account-list-datasource.ts index 1452c104..cb426f94 100644 --- a/overlord/src/app/account/account-list/account-list-datasource.ts +++ b/overlord/src/app/account/account-list/account-list-datasource.ts @@ -6,6 +6,7 @@ import { merge, Observable, of as observableOf } from 'rxjs'; import { map, tap } from 'rxjs/operators'; import { Account } from '../../core/account'; +import { AccountType } from '../../core/account-type'; /** Simple sort comparator for example ID/Name columns (for client-side sorting). */ const compare = (a: string | number | boolean, b: string | number | boolean, isAsc: boolean) => @@ -91,7 +92,7 @@ export class AccountListDataSource extends DataSource { case 'name': return compare(a.name, b.name, isAsc); case 'type': - return compare(a.type.name, b.type.name, isAsc); + return compare((a.type as AccountType).name, (b.type as AccountType).name, isAsc); case 'isActive': return compare(a.isActive, b.isActive, isAsc); case 'isReconcilable': diff --git a/overlord/src/app/account/account-list/account-list.component.html b/overlord/src/app/account/account-list/account-list.component.html index a3954d5a..f84e3406 100644 --- a/overlord/src/app/account/account-list/account-list.component.html +++ b/overlord/src/app/account/account-list/account-list.component.html @@ -42,7 +42,7 @@ Type - {{ row.type }} + {{ row.type.name }} diff --git a/overlord/src/app/account/account-list/account-list.component.ts b/overlord/src/app/account/account-list/account-list.component.ts index 1926b888..6e0e7ea9 100644 --- a/overlord/src/app/account/account-list/account-list.component.ts +++ b/overlord/src/app/account/account-list/account-list.component.ts @@ -1,12 +1,13 @@ import { AfterViewInit, Component, ElementRef, OnInit, ViewChild } from '@angular/core'; -import { UntypedFormBuilder, UntypedFormControl, UntypedFormGroup } from '@angular/forms'; +import { FormControl, FormGroup } from '@angular/forms'; import { MatPaginator } from '@angular/material/paginator'; import { MatSort } from '@angular/material/sort'; import { ActivatedRoute } from '@angular/router'; import { Observable } from 'rxjs'; -import { debounceTime, distinctUntilChanged, startWith } from 'rxjs/operators'; +import { debounceTime, distinctUntilChanged } from 'rxjs/operators'; import { Account } from '../../core/account'; +import { AccountType } from '../../core/account-type'; import { AccountListDataSource } from './account-list-datasource'; @@ -21,29 +22,39 @@ export class AccountListComponent implements OnInit, AfterViewInit { @ViewChild(MatSort, { static: true }) sort?: MatSort; dataSource: AccountListDataSource; filter: Observable; - form: UntypedFormGroup; + form: FormGroup<{ + filter: FormControl; + }>; + list: Account[] = []; + accountTypes: AccountType[] = []; /** Columns displayed in the table. Columns IDs can be added, removed, or reordered. */ displayedColumns = ['name', 'type', 'isActive', 'isReconcilable', 'costCentre']; - constructor(private route: ActivatedRoute, private fb: UntypedFormBuilder) { - this.form = this.fb.group({ - filter: '', + constructor(private route: ActivatedRoute) { + this.form = new FormGroup({ + filter: new FormControl('', { nonNullable: true }), }); // Listen to Filter Change - this.filter = (this.form.get('filter') as UntypedFormControl).valueChanges.pipe( - startWith(''), + this.filter = this.form.controls.filter.valueChanges.pipe( debounceTime(150), distinctUntilChanged(), ); + this.dataSource = new AccountListDataSource(this.list, this.filter); } ngOnInit() { this.route.data.subscribe((value) => { - const data = value as { list: Account[] }; - + const data = value as { list: Account[]; accountTypes: AccountType[] }; + this.accountTypes = data.accountTypes; + data.list.forEach( + (x) => + (x.type = new AccountType({ + name: this.accountTypes.find((y) => y.id === x.type)?.name, + })), + ); this.list = data.list; }); this.dataSource = new AccountListDataSource(this.list, this.filter, this.paginator, this.sort); diff --git a/overlord/src/app/account/account-routing.module.ts b/overlord/src/app/account/account-routing.module.ts index 43badf2c..c6718f0c 100644 --- a/overlord/src/app/account/account-routing.module.ts +++ b/overlord/src/app/account/account-routing.module.ts @@ -21,6 +21,7 @@ const accountRoutes: Routes = [ }, resolve: { list: AccountListResolver, + accountTypes: AccountTypeResolver, }, }, { diff --git a/overlord/src/app/attendance/attendance.component.html b/overlord/src/app/attendance/attendance.component.html index f6240a59..04f12bc1 100644 --- a/overlord/src/app/attendance/attendance.component.html +++ b/overlord/src/app/attendance/attendance.component.html @@ -61,7 +61,10 @@ Prints {{ row.prints }} - new_releases + new_releases ([]); dataSource: AttendanceDataSource = new AttendanceDataSource(this.attendanceObservable); - form: UntypedFormGroup; + form: FormGroup<{ + date: FormControl; + attendances: FormArray< + FormGroup<{ + attendanceType: FormControl; + }> + >; + }>; info: Attendance = new Attendance(); attendanceTypes: AttendanceType[] = []; @@ -37,15 +39,14 @@ export class AttendanceComponent implements OnInit { constructor( private route: ActivatedRoute, private router: Router, - private fb: UntypedFormBuilder, private dialog: MatDialog, private toaster: ToasterService, private auth: AuthService, private ser: AttendanceService, ) { - this.form = this.fb.group({ - date: '', - attendances: this.fb.array([]), + this.form = new FormGroup({ + date: new FormControl(new Date(), { nonNullable: true }), + attendances: new FormArray }>>([]), }); } @@ -55,17 +56,13 @@ export class AttendanceComponent implements OnInit { this.info = data.info; this.attendanceTypes = data.attendanceTypes; - (this.form.get('date') as UntypedFormControl).setValue( - moment(this.info.date, 'DD-MMM-YYYY').toDate(), - ); - this.form.setControl( - 'attendances', - this.fb.array( - this.info.body.map((x) => - this.fb.group({ - attendanceType: x.attendanceType.id, - }), - ), + this.form.controls.date.setValue(moment(this.info.date, 'DD-MMM-YYYY').toDate()); + this.form.controls.attendances.reset(); + this.info.body.forEach((x) => + this.form.controls.attendances.push( + new FormGroup({ + attendanceType: new FormControl(x.attendanceType.id, { nonNullable: true }), + }), ), ); this.dataSource = new AttendanceDataSource(this.attendanceObservable); @@ -74,7 +71,7 @@ export class AttendanceComponent implements OnInit { } getClass(index: number) { - const array = this.form.get('attendances') as UntypedFormArray; + const array = this.form.controls.attendances; const id = array.controls[index].value.attendanceType; const { name } = this.attendanceTypes.filter((x) => x.id === id)[0]; return name.toLowerCase().replace(/(\s+\+\s+)|(\s+)/g, '-'); @@ -99,14 +96,10 @@ export class AttendanceComponent implements OnInit { getAttendance(): Attendance { const formModel = this.form.value; this.info.date = moment(formModel.date).format('DD-MMM-YYYY'); - const array = this.form.get('attendances') as UntypedFormArray; + const array = this.form.controls.attendances!; this.info.body.forEach((item, index) => { - item.attendanceType.id = array.controls[index].value.attendanceType; + item.attendanceType.id = array.controls[index].value.attendanceType!; }); return this.info; } - - get attendancesArray(): UntypedFormArray { - return this.form.get('attendances') as UntypedFormArray; - } } diff --git a/overlord/src/app/attendance/attendance.service.ts b/overlord/src/app/attendance/attendance.service.ts index ca34d6b6..74a54773 100644 --- a/overlord/src/app/attendance/attendance.service.ts +++ b/overlord/src/app/attendance/attendance.service.ts @@ -1,4 +1,4 @@ -import { HttpClient, HttpHeaders } from '@angular/common/http'; +import { HttpClient } from '@angular/common/http'; import { Injectable } from '@angular/core'; import { Observable } from 'rxjs/internal/Observable'; import { catchError } from 'rxjs/operators'; diff --git a/overlord/src/app/auth/login/login.component.ts b/overlord/src/app/auth/login/login.component.ts index 781c0b54..5b288ab5 100644 --- a/overlord/src/app/auth/login/login.component.ts +++ b/overlord/src/app/auth/login/login.component.ts @@ -1,5 +1,5 @@ import { AfterViewInit, Component, ElementRef, OnInit, ViewChild } from '@angular/core'; -import { UntypedFormBuilder, UntypedFormGroup } from '@angular/forms'; +import { FormControl, FormGroup, Validators } from '@angular/forms'; import { ActivatedRoute, Router } from '@angular/router'; import { ToasterService } from '../../core/toaster.service'; @@ -13,7 +13,7 @@ import { AuthService } from '../auth.service'; }) export class LoginComponent implements OnInit, AfterViewInit { @ViewChild('nameElement', { static: true }) nameElement?: ElementRef; - form: UntypedFormGroup; + form: FormGroup; hide: boolean; showOtp: boolean; clientId = ''; @@ -25,14 +25,13 @@ export class LoginComponent implements OnInit, AfterViewInit { private router: Router, private toaster: ToasterService, private cs: CookieService, - private fb: UntypedFormBuilder, ) { this.hide = true; this.showOtp = false; - this.form = this.fb.group({ - username: '', - password: '', - otp: '', + this.form = new FormGroup({ + username: new FormControl('', { validators: Validators.required, nonNullable: true }), + password: new FormControl('', { validators: Validators.required, nonNullable: true }), + otp: new FormControl(0), }); } diff --git a/overlord/src/app/balance-sheet/balance-sheet.component.ts b/overlord/src/app/balance-sheet/balance-sheet.component.ts index 96195739..0646a344 100644 --- a/overlord/src/app/balance-sheet/balance-sheet.component.ts +++ b/overlord/src/app/balance-sheet/balance-sheet.component.ts @@ -1,5 +1,5 @@ import { Component, OnInit, ViewChild } from '@angular/core'; -import { UntypedFormBuilder, UntypedFormGroup } from '@angular/forms'; +import { FormControl, FormGroup } from '@angular/forms'; import { MatPaginator } from '@angular/material/paginator'; import { MatSort } from '@angular/material/sort'; import { ActivatedRoute, Router } from '@angular/router'; @@ -18,17 +18,16 @@ export class BalanceSheetComponent implements OnInit { @ViewChild(MatSort, { static: true }) sort?: MatSort; info: BalanceSheet = new BalanceSheet(); dataSource: BalanceSheetDataSource = new BalanceSheetDataSource(this.info.body); - form: UntypedFormGroup; + form: FormGroup<{ + date: FormControl; + }>; + /** Columns displayed in the table. Columns IDs can be added, removed, or reordered. */ displayedColumns = ['group', 'name', 'subAmount', 'total']; - constructor( - private route: ActivatedRoute, - private router: Router, - private fb: UntypedFormBuilder, - ) { - this.form = this.fb.group({ - date: '', + constructor(private route: ActivatedRoute, private router: Router) { + this.form = new FormGroup({ + date: new FormControl(new Date(), { nonNullable: true }), }); } diff --git a/overlord/src/app/cash-flow/cash-flow.component.ts b/overlord/src/app/cash-flow/cash-flow.component.ts index fac54a70..c290c4fb 100644 --- a/overlord/src/app/cash-flow/cash-flow.component.ts +++ b/overlord/src/app/cash-flow/cash-flow.component.ts @@ -1,5 +1,5 @@ import { Component, OnInit } from '@angular/core'; -import { UntypedFormBuilder, UntypedFormGroup } from '@angular/forms'; +import { FormControl, FormGroup } from '@angular/forms'; import { ActivatedRoute, Router } from '@angular/router'; import * as moment from 'moment'; @@ -14,18 +14,18 @@ import { CashFlowDataSource } from './cash-flow-datasource'; export class CashFlowComponent implements OnInit { info: CashFlow = new CashFlow(); dataSource: CashFlowDataSource = new CashFlowDataSource(CashFlow.Data(this.info)); - form: UntypedFormGroup; + form: FormGroup<{ + startDate: FormControl; + finishDate: FormControl; + }>; + /** Columns displayed in the table. Columns IDs can be added, removed, or reordered. */ displayedColumns = ['name', 'amount']; - constructor( - private route: ActivatedRoute, - private router: Router, - private fb: UntypedFormBuilder, - ) { - this.form = this.fb.group({ - startDate: '', - finishDate: '', + constructor(private route: ActivatedRoute, private router: Router) { + this.form = new FormGroup({ + startDate: new FormControl(new Date(), { nonNullable: true }), + finishDate: new FormControl(new Date(), { nonNullable: true }), }); } diff --git a/overlord/src/app/client/client-detail/client-detail.component.ts b/overlord/src/app/client/client-detail/client-detail.component.ts index eb5c70d1..c2237cd6 100644 --- a/overlord/src/app/client/client-detail/client-detail.component.ts +++ b/overlord/src/app/client/client-detail/client-detail.component.ts @@ -1,5 +1,5 @@ import { AfterViewInit, Component, ElementRef, OnInit, ViewChild } from '@angular/core'; -import { UntypedFormBuilder, UntypedFormGroup } from '@angular/forms'; +import { FormControl, FormGroup } from '@angular/forms'; import { MatDialog } from '@angular/material/dialog'; import { ActivatedRoute, Router } from '@angular/router'; @@ -15,22 +15,30 @@ import { ClientService } from '../client.service'; }) export class ClientDetailComponent implements OnInit, AfterViewInit { @ViewChild('nameElement', { static: true }) nameElement?: ElementRef; - form: UntypedFormGroup; + form: FormGroup<{ + code: FormControl; + name: FormControl; + enabled: FormControl; + otp: FormControl; + }>; + item: Client = new Client(); constructor( private route: ActivatedRoute, private router: Router, private dialog: MatDialog, - private fb: UntypedFormBuilder, private toaster: ToasterService, private ser: ClientService, ) { - this.form = this.fb.group({ - code: { value: '', disabled: true }, - name: '', - enabled: false, - otp: '', + this.form = new FormGroup({ + code: new FormControl( + { value: '(Auto)', disabled: true }, + { nonNullable: true }, + ), + name: new FormControl(null), + enabled: new FormControl(false, { nonNullable: true }), + otp: new FormControl(null), }); } @@ -48,7 +56,7 @@ export class ClientDetailComponent implements OnInit, AfterViewInit { code: this.item.code || '(Auto)', name: this.item.name, enabled: this.item.enabled, - otp: this.item.otp, + otp: this.item.otp || null, }); } @@ -99,9 +107,9 @@ export class ClientDetailComponent implements OnInit, AfterViewInit { getItem(): Client { const formModel = this.form.value; - this.item.name = formModel.name; - this.item.enabled = formModel.enabled; - this.item.otp = formModel.otp; + this.item.name = formModel.name!; + this.item.enabled = formModel.enabled!; + this.item.otp = formModel.otp || undefined; return this.item; } } diff --git a/overlord/src/app/client/client.service.ts b/overlord/src/app/client/client.service.ts index 5359f59f..96c7de53 100644 --- a/overlord/src/app/client/client.service.ts +++ b/overlord/src/app/client/client.service.ts @@ -1,4 +1,4 @@ -import { HttpClient, HttpHeaders } from '@angular/common/http'; +import { HttpClient } from '@angular/common/http'; import { Injectable } from '@angular/core'; import { Observable } from 'rxjs/internal/Observable'; import { catchError } from 'rxjs/operators'; diff --git a/overlord/src/app/closing-stock/closing-stock.component.ts b/overlord/src/app/closing-stock/closing-stock.component.ts index 7ef46050..c407ffe3 100644 --- a/overlord/src/app/closing-stock/closing-stock.component.ts +++ b/overlord/src/app/closing-stock/closing-stock.component.ts @@ -1,10 +1,5 @@ import { Component, OnInit, ViewChild } from '@angular/core'; -import { - UntypedFormArray, - UntypedFormBuilder, - FormControl, - UntypedFormGroup, -} from '@angular/forms'; +import { FormGroup, FormArray, FormControl } from '@angular/forms'; import { MatDialog } from '@angular/material/dialog'; import { MatPaginator } from '@angular/material/paginator'; import { MatSelectChange } from '@angular/material/select'; @@ -34,8 +29,18 @@ export class ClosingStockComponent implements OnInit { @ViewChild(MatSort, { static: true }) sort?: MatSort; info: ClosingStock = new ClosingStock(); dataSource: ClosingStockDataSource = new ClosingStockDataSource(this.info.items); - form: UntypedFormGroup; + form: FormGroup<{ + date: FormControl; + costCentre: FormControl; + stocks: FormArray< + FormGroup<{ + physical: FormControl; + costCentre: FormControl; + }> + >; + }>; /** Columns displayed in the table. Columns IDs can be added, removed, or reordered. */ + displayedColumns = [ 'product', 'group', @@ -51,7 +56,6 @@ export class ClosingStockComponent implements OnInit { constructor( private route: ActivatedRoute, private router: Router, - private fb: UntypedFormBuilder, private toCsv: ToCsvService, private dialog: MatDialog, private toaster: ToasterService, @@ -59,10 +63,12 @@ export class ClosingStockComponent implements OnInit { private ser: ClosingStockService, ) { this.costCentres = []; - this.form = this.fb.group({ - date: '', - costCentre: '', - stocks: this.fb.array([]), + this.form = new FormGroup({ + date: new FormControl(new Date(), { nonNullable: true }), + costCentre: new FormControl(null), + stocks: new FormArray< + FormGroup<{ physical: FormControl; costCentre: FormControl }> + >([]), }); } @@ -75,15 +81,12 @@ export class ClosingStockComponent implements OnInit { date: moment(this.info.date, 'DD-MMM-YYYY').toDate(), costCentre: this.info.costCentre.id, }); - this.form.setControl( - 'stocks', - this.fb.array( - this.info.items.map((x) => - this.fb.group({ - physical: '' + x.physical, - costCentre: x.costCentre?.id, - }), - ), + this.info.items.forEach((x) => + this.form.controls.stocks.push( + new FormGroup({ + physical: new FormControl(x.physical, { nonNullable: true }), + costCentre: new FormControl(x.costCentre?.id, { nonNullable: true }), + }), ), ); this.dataSource = new ClosingStockDataSource(this.info.items, this.paginator, this.sort); @@ -113,9 +116,9 @@ export class ClosingStockComponent implements OnInit { getClosingStock(): ClosingStock { const formModel = this.form.value; this.info.date = moment(formModel.date).format('DD-MMM-YYYY'); - const array = this.form.get('stocks') as UntypedFormArray; + const array = this.form.controls.stocks; this.info.items.forEach((item, index) => { - item.physical = +array.controls[index].value.physical; + item.physical = +array.controls[index].value.physical!; item.costCentre = array.controls[index].value.costCentre == null ? undefined @@ -130,7 +133,7 @@ export class ClosingStockComponent implements OnInit { return new ClosingStock({ date: moment(formModel.date).format('DD-MMM-YYYY'), - costCentre: new CostCentre({ id: formModel.costCentre }), + costCentre: new CostCentre({ id: formModel.costCentre! }), }); } diff --git a/overlord/src/app/closing-stock/closing-stock.service.ts b/overlord/src/app/closing-stock/closing-stock.service.ts index dd76fd3a..4132db96 100644 --- a/overlord/src/app/closing-stock/closing-stock.service.ts +++ b/overlord/src/app/closing-stock/closing-stock.service.ts @@ -4,7 +4,6 @@ import { Observable } from 'rxjs/internal/Observable'; import { catchError } from 'rxjs/operators'; import { ErrorLoggerService } from '../core/error-logger.service'; -import { Voucher } from '../core/voucher'; import { ClosingStock } from './closing-stock'; diff --git a/overlord/src/app/core/account.service.ts b/overlord/src/app/core/account.service.ts index 4f97ef10..4aa098c9 100644 --- a/overlord/src/app/core/account.service.ts +++ b/overlord/src/app/core/account.service.ts @@ -1,4 +1,4 @@ -import { HttpClient, HttpHeaders, HttpParams } from '@angular/common/http'; +import { HttpClient, HttpParams } from '@angular/common/http'; import { Injectable } from '@angular/core'; import { Observable } from 'rxjs/internal/Observable'; import { catchError } from 'rxjs/operators'; diff --git a/overlord/src/app/core/account.ts b/overlord/src/app/core/account.ts index d513a0c9..81a26283 100644 --- a/overlord/src/app/core/account.ts +++ b/overlord/src/app/core/account.ts @@ -5,7 +5,7 @@ export class Account { id: string | undefined; code: number; name: string; - type: AccountType; + type: AccountType | number; isActive: boolean; isReconcilable: boolean; isStarred: boolean; diff --git a/overlord/src/app/core/batch.ts b/overlord/src/app/core/batch.ts index 3aaf0c0b..0fd8c8d7 100644 --- a/overlord/src/app/core/batch.ts +++ b/overlord/src/app/core/batch.ts @@ -1,4 +1,3 @@ -import { Product } from './product'; import { ProductSku } from './product-sku'; export class Batch { diff --git a/overlord/src/app/core/inventory.ts b/overlord/src/app/core/inventory.ts index 10269572..7d880a1e 100644 --- a/overlord/src/app/core/inventory.ts +++ b/overlord/src/app/core/inventory.ts @@ -1,5 +1,4 @@ import { Batch } from './batch'; -import { Product } from './product'; export class Inventory { id: string | undefined; diff --git a/overlord/src/app/core/voucher.service.ts b/overlord/src/app/core/voucher.service.ts index 724d4f85..4fcd8bdb 100644 --- a/overlord/src/app/core/voucher.service.ts +++ b/overlord/src/app/core/voucher.service.ts @@ -1,4 +1,4 @@ -import { HttpClient, HttpHeaders, HttpParams } from '@angular/common/http'; +import { HttpClient, HttpParams } from '@angular/common/http'; import { Injectable } from '@angular/core'; import { Observable } from 'rxjs/internal/Observable'; import { catchError } from 'rxjs/operators'; diff --git a/overlord/src/app/cost-centre/cost-centre-detail/cost-centre-detail.component.ts b/overlord/src/app/cost-centre/cost-centre-detail/cost-centre-detail.component.ts index 13e09913..59536631 100644 --- a/overlord/src/app/cost-centre/cost-centre-detail/cost-centre-detail.component.ts +++ b/overlord/src/app/cost-centre/cost-centre-detail/cost-centre-detail.component.ts @@ -1,5 +1,5 @@ import { AfterViewInit, Component, ElementRef, OnInit, ViewChild } from '@angular/core'; -import { UntypedFormBuilder, UntypedFormGroup } from '@angular/forms'; +import { FormControl, FormGroup } from '@angular/forms'; import { ActivatedRoute, Router } from '@angular/router'; import { CostCentre } from '../../core/cost-centre'; @@ -13,18 +13,20 @@ import { CostCentreService } from '../cost-centre.service'; }) export class CostCentreDetailComponent implements OnInit, AfterViewInit { @ViewChild('nameElement', { static: true }) nameElement?: ElementRef; - form: UntypedFormGroup; + form: FormGroup<{ + name: FormControl; + }>; + item: CostCentre = new CostCentre(); constructor( private route: ActivatedRoute, private router: Router, - private fb: UntypedFormBuilder, private toaster: ToasterService, private ser: CostCentreService, ) { - this.form = this.fb.group({ - name: '', + this.form = new FormGroup({ + name: new FormControl(null), }); } @@ -65,7 +67,7 @@ export class CostCentreDetailComponent implements OnInit, AfterViewInit { getItem(): CostCentre { const formModel = this.form.value; - this.item.name = formModel.name; + this.item.name = formModel.name!; return this.item; } } diff --git a/overlord/src/app/cost-centre/cost-centre.service.ts b/overlord/src/app/cost-centre/cost-centre.service.ts index 75f905c2..756e8fe1 100644 --- a/overlord/src/app/cost-centre/cost-centre.service.ts +++ b/overlord/src/app/cost-centre/cost-centre.service.ts @@ -1,4 +1,4 @@ -import { HttpClient, HttpHeaders } from '@angular/common/http'; +import { HttpClient } from '@angular/common/http'; import { Injectable } from '@angular/core'; import { Observable } from 'rxjs/internal/Observable'; import { catchError } from 'rxjs/operators'; diff --git a/overlord/src/app/daybook/daybook.component.ts b/overlord/src/app/daybook/daybook.component.ts index 1cfacd40..a344994c 100644 --- a/overlord/src/app/daybook/daybook.component.ts +++ b/overlord/src/app/daybook/daybook.component.ts @@ -1,5 +1,5 @@ import { Component, OnInit, ViewChild } from '@angular/core'; -import { UntypedFormBuilder, UntypedFormGroup } from '@angular/forms'; +import { FormControl, FormGroup } from '@angular/forms'; import { MatPaginator } from '@angular/material/paginator'; import { MatSort } from '@angular/material/sort'; import { ActivatedRoute, Router } from '@angular/router'; @@ -7,7 +7,6 @@ import * as moment from 'moment'; import { Daybook } from './daybook'; import { DaybookDataSource } from './daybook-datasource'; -import { DaybookService } from './daybook.service'; @Component({ selector: 'app-daybook', @@ -19,7 +18,11 @@ export class DaybookComponent implements OnInit { @ViewChild(MatSort, { static: true }) sort?: MatSort; info: Daybook = new Daybook(); dataSource: DaybookDataSource = new DaybookDataSource(this.info.body); - form: UntypedFormGroup; + form: FormGroup<{ + startDate: FormControl; + finishDate: FormControl; + }>; + selectedRowId = ''; /** Columns displayed in the table. Columns IDs can be added, removed, or reordered. */ displayedColumns = [ @@ -32,15 +35,10 @@ export class DaybookComponent implements OnInit { 'creditAmount', ]; - constructor( - private route: ActivatedRoute, - private router: Router, - private fb: UntypedFormBuilder, - private ser: DaybookService, - ) { - this.form = this.fb.group({ - startDate: '', - finishDate: '', + constructor(private route: ActivatedRoute, private router: Router) { + this.form = new FormGroup({ + startDate: new FormControl(new Date(), { nonNullable: true }), + finishDate: new FormControl(new Date(), { nonNullable: true }), }); } diff --git a/overlord/src/app/employee-attendance/employee-attendance.component.html b/overlord/src/app/employee-attendance/employee-attendance.component.html index 5c1b3c0c..34ee3c38 100644 --- a/overlord/src/app/employee-attendance/employee-attendance.component.html +++ b/overlord/src/app/employee-attendance/employee-attendance.component.html @@ -90,7 +90,10 @@ Prints {{ row.prints }} - new_releases + new_releases ; + finishDate: FormControl; + employee: FormControl; + attendances: FormArray< + FormGroup<{ + attendanceType: FormControl; + }> + >; + }>; info: EmployeeAttendance = new EmployeeAttendance(); attendanceTypes: AttendanceType[] = []; @@ -47,22 +51,21 @@ export class EmployeeAttendanceComponent implements OnInit, AfterViewInit { constructor( private route: ActivatedRoute, private router: Router, - private fb: UntypedFormBuilder, private dialog: MatDialog, private toaster: ToasterService, private auth: AuthService, private ser: EmployeeAttendanceService, private employeeSer: EmployeeService, ) { - this.form = this.fb.group({ - startDate: '', - finishDate: '', - employee: '', - attendances: this.fb.array([]), + this.form = new FormGroup({ + startDate: new FormControl(new Date(), { nonNullable: true }), + finishDate: new FormControl(new Date(), { nonNullable: true }), + employee: new FormControl(null), + attendances: new FormArray }>>([]), }); // Listen to Employee Value Changes - this.employees = (this.form.get('employee') as UntypedFormControl).valueChanges.pipe( - startWith(null), + this.employees = this.form.controls.employee.valueChanges.pipe( + map((x) => (x instanceof Employee ? x.name : x)), map((x) => (x !== null && x.length >= 1 ? x : null)), debounceTime(150), distinctUntilChanged(), @@ -76,21 +79,15 @@ export class EmployeeAttendanceComponent implements OnInit, AfterViewInit { this.info = data.info; this.attendanceTypes = data.attendanceTypes; - (this.form.get('startDate') as UntypedFormControl).setValue( - moment(this.info.startDate, 'DD-MMM-YYYY').toDate(), - ); - (this.form.get('finishDate') as UntypedFormControl).setValue( - moment(this.info.finishDate, 'DD-MMM-YYYY').toDate(), - ); - (this.form.get('employee') as UntypedFormControl).setValue(this.info.employee); - this.form.setControl( - 'attendances', - this.fb.array( - this.info.body.map((x) => - this.fb.group({ - attendanceType: x.attendanceType.id, - }), - ), + this.form.controls.startDate.setValue(moment(this.info.startDate, 'DD-MMM-YYYY').toDate()); + this.form.controls.finishDate.setValue(moment(this.info.finishDate, 'DD-MMM-YYYY').toDate()); + this.form.controls.employee.setValue(this.info.employee); + this.form.controls.attendances.reset(); + this.info.body.forEach((x) => + this.form.controls.attendances.push( + new FormGroup({ + attendanceType: new FormControl(x.attendanceType.id, { nonNullable: true }), + }), ), ); this.dataSource = new EmployeeAttendanceDataSource(this.employeeAttendanceObservable); @@ -115,7 +112,7 @@ export class EmployeeAttendanceComponent implements OnInit, AfterViewInit { } getClass(index: number) { - const array = this.form.get('attendances') as UntypedFormArray; + const array = this.form.controls.attendances; const id = array.controls[index].value.attendanceType; const { name } = this.attendanceTypes.filter((x) => x.id === id)[0]; return name.toLowerCase().replace(/(\s+\+\s+)|(\s+)/g, '-'); @@ -148,14 +145,10 @@ export class EmployeeAttendanceComponent implements OnInit, AfterViewInit { const formValue = this.form.value; this.info.startDate = moment(formValue.startDate).format('DD-MMM-YYYY'); this.info.finishDate = moment(formValue.finishDate).format('DD-MMM-YYYY'); - const array = this.form.get('attendances') as UntypedFormArray; + const array = this.form.value.attendances!; this.info.body.forEach((item, index) => { - item.attendanceType.id = array.controls[index].value.attendanceType; + item.attendanceType.id = array[index].attendanceType!; }); return this.info; } - - get attendancesArray(): UntypedFormArray { - return this.form.get('attendances') as UntypedFormArray; - } } diff --git a/overlord/src/app/employee-attendance/employee-attendance.service.ts b/overlord/src/app/employee-attendance/employee-attendance.service.ts index 303e5dff..46f0b350 100644 --- a/overlord/src/app/employee-attendance/employee-attendance.service.ts +++ b/overlord/src/app/employee-attendance/employee-attendance.service.ts @@ -1,4 +1,4 @@ -import { HttpClient, HttpHeaders, HttpParams } from '@angular/common/http'; +import { HttpClient, HttpParams } from '@angular/common/http'; import { Injectable } from '@angular/core'; import { Observable } from 'rxjs/internal/Observable'; import { catchError } from 'rxjs/operators'; diff --git a/overlord/src/app/employee-benefits/employee-benefits.component.ts b/overlord/src/app/employee-benefits/employee-benefits.component.ts index 6888722f..15b027d7 100644 --- a/overlord/src/app/employee-benefits/employee-benefits.component.ts +++ b/overlord/src/app/employee-benefits/employee-benefits.component.ts @@ -1,11 +1,11 @@ import { AfterViewInit, Component, ElementRef, OnInit, ViewChild } from '@angular/core'; -import { UntypedFormBuilder, UntypedFormControl, UntypedFormGroup } from '@angular/forms'; +import { FormControl, FormGroup } from '@angular/forms'; import { MatAutocompleteSelectedEvent } from '@angular/material/autocomplete'; import { MatDialog } from '@angular/material/dialog'; import { ActivatedRoute, Router } from '@angular/router'; import * as moment from 'moment'; import { BehaviorSubject, Observable, of as observableOf } from 'rxjs'; -import { debounceTime, distinctUntilChanged, map, startWith, switchMap } from 'rxjs/operators'; +import { debounceTime, distinctUntilChanged, map, switchMap } from 'rxjs/operators'; import { AuthService } from '../auth/auth.service'; import { AccountBalance } from '../core/account-balance'; @@ -29,7 +29,15 @@ export class EmployeeBenefitsComponent implements OnInit, AfterViewInit { @ViewChild('employeeElement', { static: true }) employeeElement?: ElementRef; public benefitsObservable = new BehaviorSubject([]); dataSource: EmployeeBenefitsDataSource = new EmployeeBenefitsDataSource(this.benefitsObservable); - form: UntypedFormGroup; + form: FormGroup<{ + date: FormControl; + addRow: FormGroup<{ + employee: FormControl; + grossSalary: FormControl; + daysWorked: FormControl; + }>; + }>; + voucher: Voucher = new Voucher(); employee: Employee | null = null; accBal: AccountBalance | null = null; @@ -51,26 +59,22 @@ export class EmployeeBenefitsComponent implements OnInit, AfterViewInit { constructor( private route: ActivatedRoute, private router: Router, - private fb: UntypedFormBuilder, private dialog: MatDialog, private toaster: ToasterService, public auth: AuthService, private ser: VoucherService, private employeeSer: EmployeeService, ) { - this.form = this.fb.group({ - date: '', - addRow: this.fb.group({ - employee: '', - grossSalary: '', - daysWorked: '', + this.form = new FormGroup({ + date: new FormControl(new Date(), { nonNullable: true }), + addRow: new FormGroup({ + employee: new FormControl(''), + grossSalary: new FormControl(''), + daysWorked: new FormControl(''), }), }); // Setup Employee Autocomplete - this.employees = ( - (this.form.get('addRow') as UntypedFormControl).get('employee') as UntypedFormControl - ).valueChanges.pipe( - startWith(null), + this.employees = this.form.controls.addRow.controls.employee.valueChanges.pipe( map((x) => (x !== null && x.length >= 1 ? x : null)), debounceTime(150), distinctUntilChanged(), @@ -147,10 +151,10 @@ export class EmployeeBenefitsComponent implements OnInit, AfterViewInit { return; } - const formValue = (this.form.get('addRow') as UntypedFormControl).value; - const grossSalary = +formValue.grossSalary; - const daysWorked = +formValue.daysWorked; - const date = (this.form.get('date') as UntypedFormControl).value; + const formValue = this.form.value.addRow!; + const grossSalary = +formValue.grossSalary!; + const daysWorked = +formValue.daysWorked!; + const date = this.form.value.date!; const daysInMonth = moment(date).daysInMonth(); const esi = EmployeeBenefitsComponent.getEsi(grossSalary, daysWorked, daysInMonth); const pf = EmployeeBenefitsComponent.getPf(grossSalary, daysWorked, daysInMonth); @@ -171,11 +175,7 @@ export class EmployeeBenefitsComponent implements OnInit, AfterViewInit { } resetAddRow() { - (this.form.get('addRow') as UntypedFormControl).reset({ - employee: '', - grossSalary: null, - daysWorked: null, - }); + this.form.controls.addRow.reset(); this.employee = null; setTimeout(() => { if (this.employeeElement) { diff --git a/overlord/src/app/employee-functions/employee-functions.component.ts b/overlord/src/app/employee-functions/employee-functions.component.ts index dad610b0..d7357b88 100644 --- a/overlord/src/app/employee-functions/employee-functions.component.ts +++ b/overlord/src/app/employee-functions/employee-functions.component.ts @@ -1,5 +1,5 @@ import { Component } from '@angular/core'; -import { UntypedFormBuilder, UntypedFormControl, UntypedFormGroup } from '@angular/forms'; +import { FormControl, FormGroup } from '@angular/forms'; import { MatDatepicker } from '@angular/material/datepicker'; import { MatDialog } from '@angular/material/dialog'; import { ActivatedRoute, Router } from '@angular/router'; @@ -17,15 +17,21 @@ import { EmployeeFunctionsService } from './employee-functions.service'; styleUrls: ['./employee-functions.component.css'], }) export class EmployeeFunctionsComponent { - creditSalaryForm: UntypedFormGroup; - attendanceRecordForm: UntypedFormGroup; - fingerprintForm: UntypedFormGroup; + creditSalaryForm: FormGroup<{ + date: FormControl; + }>; + + attendanceRecordForm: FormGroup<{ + startDate: FormControl; + finishDate: FormControl; + }>; + + fingerprintForm: FormGroup<{}>; fingerprintFile: File | null = null; constructor( private route: ActivatedRoute, private router: Router, - private fb: UntypedFormBuilder, private dialog: MatDialog, private toaster: ToasterService, private auth: AuthService, @@ -33,37 +39,33 @@ export class EmployeeFunctionsComponent { ) { const startDate = moment().date(1); const finishDate = moment().date(startDate.daysInMonth()); - this.creditSalaryForm = this.fb.group({ - date: finishDate, + this.creditSalaryForm = new FormGroup({ + date: new FormControl(finishDate, { nonNullable: true }), }); - this.attendanceRecordForm = this.fb.group({ - startDate, - finishDate, + this.attendanceRecordForm = new FormGroup({ + startDate: new FormControl(moment(), { nonNullable: true }), + finishDate: new FormControl(moment(), { nonNullable: true }), }); - this.fingerprintForm = this.fb.group({}); + this.fingerprintForm = new FormGroup({}); } chosenYearHandler(normalizedYear: Moment) { - const dateControl = this.creditSalaryForm.get('date') as UntypedFormControl; - const ctrlValue = dateControl.value; + const ctrlValue = this.creditSalaryForm.value.date!; ctrlValue.year(normalizedYear.year()); ctrlValue.date(ctrlValue.daysInMonth()); - dateControl.setValue(ctrlValue); + this.creditSalaryForm.setValue({ date: ctrlValue }); } chosenMonthHandler(normlizedMonth: Moment, datepicker: MatDatepicker) { - const dateControl = this.creditSalaryForm.get('date') as UntypedFormControl; - const ctrlValue = dateControl.value; + const ctrlValue = this.creditSalaryForm.value.date!; ctrlValue.month(normlizedMonth.month()); ctrlValue.date(ctrlValue.daysInMonth()); - dateControl.setValue(ctrlValue); + this.creditSalaryForm.setValue({ date: ctrlValue }); datepicker.close(); } creditSalary() { - const date = moment((this.creditSalaryForm.get('date') as UntypedFormControl).value).format( - 'DD-MMM-YYYY', - ); + const date = this.creditSalaryForm.value.date!.format('DD-MMM-YYYY'); if (!date) { this.toaster.show('Danger', 'Please choose a valid date.'); return; @@ -79,12 +81,8 @@ export class EmployeeFunctionsComponent { } attendanceRecordUrl() { - const startDate = moment( - (this.attendanceRecordForm.get('startDate') as UntypedFormControl).value, - ).format('DD-MMM-YYYY'); - const finishDate = moment( - (this.attendanceRecordForm.get('finishDate') as UntypedFormControl).value, - ).format('DD-MMM-YYYY'); + const startDate = this.attendanceRecordForm.value.startDate!.format('DD-MMM-YYYY'); + const finishDate = this.attendanceRecordForm.value.finishDate!.format('DD-MMM-YYYY'); if (!startDate || !finishDate) { // this.toaster.show('Danger', 'Please choose a start and finish date.'); return ''; @@ -93,12 +91,8 @@ export class EmployeeFunctionsComponent { } fingerPrintUrl() { - const startDate = moment( - (this.attendanceRecordForm.get('startDate') as UntypedFormControl).value, - ).format('DD-MMM-YYYY'); - const finishDate = moment( - (this.attendanceRecordForm.get('finishDate') as UntypedFormControl).value, - ).format('DD-MMM-YYYY'); + const startDate = this.attendanceRecordForm.value.startDate!.format('DD-MMM-YYYY'); + const finishDate = this.attendanceRecordForm.value.finishDate!.format('DD-MMM-YYYY'); if (!startDate || !finishDate) { // this.toaster.show('Danger', 'Please choose a start and finish date.'); return ''; @@ -107,7 +101,6 @@ export class EmployeeFunctionsComponent { } detectFiles(event: Event) { - // eslint-disable-next-line prefer-destructuring this.fingerprintFile = ((event.target as HTMLInputElement).files as FileList)[0]; } diff --git a/overlord/src/app/employee/employee-detail/employee-detail.component.ts b/overlord/src/app/employee/employee-detail/employee-detail.component.ts index ad37e92e..17a2ed50 100644 --- a/overlord/src/app/employee/employee-detail/employee-detail.component.ts +++ b/overlord/src/app/employee/employee-detail/employee-detail.component.ts @@ -1,5 +1,5 @@ import { AfterViewInit, Component, ElementRef, OnInit, ViewChild } from '@angular/core'; -import { UntypedFormBuilder, UntypedFormControl, UntypedFormGroup } from '@angular/forms'; +import { FormControl, FormGroup } from '@angular/forms'; import { MatDialog } from '@angular/material/dialog'; import { ActivatedRoute, Router } from '@angular/router'; import * as moment from 'moment'; @@ -17,7 +17,18 @@ import { EmployeeService } from '../employee.service'; }) export class EmployeeDetailComponent implements OnInit, AfterViewInit { @ViewChild('nameElement', { static: true }) nameElement?: ElementRef; - form: UntypedFormGroup; + form: FormGroup<{ + code: FormControl; + name: FormControl; + designation: FormControl; + salary: FormControl; + points: FormControl; + isActive: FormControl; + costCentre: FormControl; + joiningDate: FormControl; + leavingDate: FormControl; + }>; + costCentres: CostCentre[] = []; item: Employee = new Employee(); @@ -25,23 +36,22 @@ export class EmployeeDetailComponent implements OnInit, AfterViewInit { private route: ActivatedRoute, private router: Router, private dialog: MatDialog, - private fb: UntypedFormBuilder, private toaster: ToasterService, private ser: EmployeeService, ) { - this.form = this.fb.group({ - code: { value: '', disabled: true }, - name: '', - designation: '', - salary: '', - points: '', - isActive: '', - costCentre: '', - joiningDate: '', - leavingDate: '', + this.form = new FormGroup({ + code: new FormControl({ value: 0, disabled: true }, { nonNullable: true }), + name: new FormControl(null), + designation: new FormControl(null), + salary: new FormControl(null), + points: new FormControl(null), + isActive: new FormControl(true, { nonNullable: true }), + costCentre: new FormControl(null), + joiningDate: new FormControl(new Date(), { nonNullable: true }), + leavingDate: new FormControl(null), }); // Listen to IsActive Changes - (this.form.get('isActive') as UntypedFormControl).valueChanges.subscribe((x) => { + this.form.controls.isActive.valueChanges.subscribe((x) => { this.item.isActive = x; }); } @@ -64,10 +74,10 @@ export class EmployeeDetailComponent implements OnInit, AfterViewInit { salary: this.item.salary || '', points: this.item.points || '', isActive: this.item.isActive, - costCentre: this.item.costCentre.id, + costCentre: this.item.costCentre.id!, joiningDate: this.item.joiningDate ? moment(this.item.joiningDate, 'DD-MMM-YYYY').toDate() - : '', + : new Date(), leavingDate: this.item.isActive ? null : moment(this.item.leavingDate, 'DD-MMM-YYYY').toDate(), @@ -121,12 +131,12 @@ export class EmployeeDetailComponent implements OnInit, AfterViewInit { getItem(): Employee { const formModel = this.form.value; - this.item.name = formModel.name; - this.item.designation = formModel.designation; - this.item.salary = +formModel.salary; - this.item.points = +formModel.points; - this.item.isActive = formModel.isActive; - this.item.costCentre.id = formModel.costCentre; + this.item.name = formModel.name!; + this.item.designation = formModel.designation!; + this.item.salary = +formModel.salary!; + this.item.points = +formModel.points!; + this.item.isActive = formModel.isActive!; + this.item.costCentre.id = formModel.costCentre!; this.item.joiningDate = moment(formModel.joiningDate).format('DD-MMM-YYYY'); this.item.leavingDate = this.item.isActive ? null diff --git a/overlord/src/app/employee/employee-list/employee-list.component.ts b/overlord/src/app/employee/employee-list/employee-list.component.ts index c66e9be2..bd522e0f 100644 --- a/overlord/src/app/employee/employee-list/employee-list.component.ts +++ b/overlord/src/app/employee/employee-list/employee-list.component.ts @@ -1,10 +1,10 @@ import { AfterViewInit, Component, ElementRef, OnInit, ViewChild } from '@angular/core'; -import { UntypedFormBuilder, UntypedFormControl, UntypedFormGroup } from '@angular/forms'; +import { FormControl, FormGroup } from '@angular/forms'; import { MatPaginator } from '@angular/material/paginator'; import { MatSort } from '@angular/material/sort'; import { ActivatedRoute } from '@angular/router'; import { Observable } from 'rxjs'; -import { debounceTime, distinctUntilChanged, startWith } from 'rxjs/operators'; +import { debounceTime, distinctUntilChanged } from 'rxjs/operators'; import { ToCsvService } from '../../shared/to-csv.service'; import { Employee } from '../employee'; @@ -22,7 +22,10 @@ export class EmployeeListComponent implements OnInit, AfterViewInit { @ViewChild(MatSort, { static: true }) sort?: MatSort; dataSource: EmployeeListDataSource; filter: Observable; - form: UntypedFormGroup; + form: FormGroup<{ + filter: FormControl; + }>; + list: Employee[] = []; /** Columns displayed in the table. Columns IDs can be added, removed, or reordered. */ @@ -37,16 +40,11 @@ export class EmployeeListComponent implements OnInit, AfterViewInit { 'leavingDate', ]; - constructor( - private route: ActivatedRoute, - private fb: UntypedFormBuilder, - private toCsv: ToCsvService, - ) { - this.form = this.fb.group({ - filter: '', + constructor(private route: ActivatedRoute, private toCsv: ToCsvService) { + this.form = new FormGroup({ + filter: new FormControl('', { nonNullable: true }), }); - this.filter = (this.form.get('filter') as UntypedFormControl).valueChanges.pipe( - startWith(''), + this.filter = this.form.controls.filter.valueChanges.pipe( debounceTime(150), distinctUntilChanged(), ); diff --git a/overlord/src/app/employee/employee.service.ts b/overlord/src/app/employee/employee.service.ts index 35a3ac4d..ca2d9072 100644 --- a/overlord/src/app/employee/employee.service.ts +++ b/overlord/src/app/employee/employee.service.ts @@ -1,4 +1,4 @@ -import { HttpClient, HttpHeaders, HttpParams } from '@angular/common/http'; +import { HttpClient, HttpParams } from '@angular/common/http'; import { Injectable } from '@angular/core'; import { Observable } from 'rxjs/internal/Observable'; import { catchError } from 'rxjs/operators'; diff --git a/overlord/src/app/entries/entries.component.html b/overlord/src/app/entries/entries.component.html index 1453f9db..f7a4896d 100644 --- a/overlord/src/app/entries/entries.component.html +++ b/overlord/src/app/entries/entries.component.html @@ -44,9 +44,9 @@ fxLayoutAlign="space-around start" > - Posted - Not Posted - All + Posted + Not Posted + All ; + finishDate: FormControl; + posted: FormControl; + issue: FormControl; + }>; + displayedColumns = [ 'date', 'voucherType', @@ -32,16 +38,12 @@ export class EntriesComponent implements OnInit { posted: boolean | null = null; issue: boolean = false; - constructor( - private route: ActivatedRoute, - private router: Router, - private fb: UntypedFormBuilder, - ) { - this.form = this.fb.group({ - startDate: '', - finishDate: '', - posted: '', - issue: '', + constructor(private route: ActivatedRoute, private router: Router) { + this.form = new FormGroup({ + startDate: new FormControl(new Date(), { nonNullable: true }), + finishDate: new FormControl(new Date(), { nonNullable: true }), + posted: new FormControl(null), + issue: new FormControl(false, { nonNullable: true }), }); } @@ -50,10 +52,8 @@ export class EntriesComponent implements OnInit { const data = value as { info: Report }; this.info = data.info; const queryMap = this.route.snapshot.queryParamMap; - const startDateO = queryMap.get('s'); - const finishDateO = queryMap.get('f'); - const startDate = startDateO !== null ? moment(startDateO, 'DD-MMM-YYYY').toDate() : ''; - const finishDate = finishDateO !== null ? moment(finishDateO, 'DD-MMM-YYYY').toDate() : ''; + const startDate = moment(queryMap.get('s') || undefined, 'DD-MMM-YYYY').toDate(); + const finishDate = moment(queryMap.get('f') || undefined, 'DD-MMM-YYYY').toDate(); const postedO = queryMap.get('p'); this.posted = postedO !== null ? postedO === 'true' : null; const pageSizeO = queryMap.get('ps'); @@ -69,13 +69,13 @@ export class EntriesComponent implements OnInit { this.form.setValue({ startDate: startDate, finishDate: finishDate, - posted: postedO ?? 'null', + posted: this.posted, issue: this.issue, }); if (this.posted === null || this.posted) { - (this.form.get('issue') as UntypedFormControl).enable(); + this.form.controls.issue.enable(); } else { - (this.form.get('issue') as UntypedFormControl).disable(); + this.form.controls.issue.disable(); } this.dataSource = new EntriesDatasource( this.info.report, @@ -106,12 +106,8 @@ export class EntriesComponent implements OnInit { refresh() { const formModel = this.form.value; - const startDate = formModel.startDate - ? moment(formModel.startDate).format('DD-MMM-YYYY') - : null; - const finishDate = formModel.finishDate - ? moment(formModel.finishDate).format('DD-MMM-YYYY') - : null; + const startDate = moment(formModel.startDate).format('DD-MMM-YYYY'); + const finishDate = moment(formModel.finishDate).format('DD-MMM-YYYY'); this.router.navigate([], { relativeTo: this.route, queryParams: { s: startDate, f: finishDate }, @@ -120,13 +116,10 @@ export class EntriesComponent implements OnInit { } togglePosted($event: MatRadioChange) { - if ($event.value === 'true') { - this.posted = true; - } else if ($event.value === 'false') { - this.posted = false; + console.log($event.value); + this.posted = $event.value; + if (this.posted === false) { this.issue = false; - } else { - this.posted = null; } this.router.navigate([], { relativeTo: this.route, diff --git a/overlord/src/app/incentive/incentive.component.ts b/overlord/src/app/incentive/incentive.component.ts index 20831ca6..21319f93 100644 --- a/overlord/src/app/incentive/incentive.component.ts +++ b/overlord/src/app/incentive/incentive.component.ts @@ -1,10 +1,5 @@ import { Component, OnInit } from '@angular/core'; -import { - UntypedFormArray, - UntypedFormBuilder, - UntypedFormControl, - UntypedFormGroup, -} from '@angular/forms'; +import { FormArray, FormControl, FormGroup } from '@angular/forms'; import { MatDialog } from '@angular/material/dialog'; import { ActivatedRoute, Router } from '@angular/router'; import * as moment from 'moment'; @@ -31,7 +26,15 @@ import { IncentiveDataSource } from './incentive-datasource'; export class IncentiveComponent implements OnInit { public incentiveObservable = new BehaviorSubject([]); dataSource: IncentiveDataSource = new IncentiveDataSource(this.incentiveObservable); - form: UntypedFormGroup; + form: FormGroup<{ + date: FormControl; + incentives: FormArray< + FormGroup<{ + points: FormControl; + }> + >; + }>; + voucher: Voucher = new Voucher(); account: Account = new Account(); accBal: AccountBalance | null = null; @@ -41,18 +44,17 @@ export class IncentiveComponent implements OnInit { constructor( private route: ActivatedRoute, private router: Router, - private fb: UntypedFormBuilder, private dialog: MatDialog, private toaster: ToasterService, public auth: AuthService, private ser: VoucherService, ) { - this.form = this.fb.group({ - date: '', - incentives: this.fb.array([]), + this.form = new FormGroup({ + date: new FormControl(new Date(), { nonNullable: true }), + incentives: new FormArray }>>([]), }); // Listen to Date Change - (this.form.get('date') as UntypedFormControl).valueChanges + this.form.controls.date.valueChanges .pipe(map((x) => moment(x).format('DD-MMM-YYYY'))) .subscribe((x) => { if (x !== this.voucher.date && !this.voucher.id) { @@ -74,17 +76,12 @@ export class IncentiveComponent implements OnInit { loadVoucher(voucher: Voucher) { this.voucher = voucher; - (this.form.get('date') as UntypedFormControl).setValue( - moment(this.voucher.date, 'DD-MMM-YYYY').toDate(), - ); - this.form.setControl( - 'incentives', - this.fb.array( - this.voucher.incentives.map((x) => - this.fb.group({ - points: x.points, - }), - ), + this.form.controls.date.setValue(moment(this.voucher.date, 'DD-MMM-YYYY').toDate()); + this.voucher.incentives.forEach((x) => + this.form.controls.incentives.push( + new FormGroup({ + points: new FormControl(x.points, { nonNullable: true }), + }), ), ); this.dataSource = new IncentiveDataSource(this.incentiveObservable); @@ -104,28 +101,20 @@ export class IncentiveComponent implements OnInit { less(row: Incentive, i: number) { if (row.points >= 1) { row.points -= 1; - ((this.form.get('incentives') as UntypedFormArray).get(`${i}`) as UntypedFormGroup).setValue({ - points: `${row.points}`, + this.form.controls.incentives.controls[i].setValue({ + points: row.points, }); } } change(row: Incentive, i: number) { - row.points = +( - ((this.form.get('incentives') as UntypedFormArray).get(`${i}`) as UntypedFormGroup).get( - 'points', - ) as UntypedFormControl - ).value; - ((this.form.get('incentives') as UntypedFormArray).get(`${i}`) as UntypedFormGroup).setValue({ - points: `${row.points}`, - }); + row.points = this.form.controls.incentives.controls[i].value.points!; + this.form.controls.incentives.controls[i].setValue({ points: row.points }); } more(row: Incentive, i: number) { row.points += 1; - ((this.form.get('incentives') as UntypedFormArray).get(`${i}`) as UntypedFormGroup).setValue({ - points: `${row.points}`, - }); + this.form.controls.incentives.controls[i].setValue({ points: row.points }); } amount(row: Incentive) { @@ -176,9 +165,10 @@ export class IncentiveComponent implements OnInit { getVoucher(): Voucher { const formModel = this.form.value; this.voucher.date = moment(formModel.date).format('DD-MMM-YYYY'); - const array = this.form.get('incentives') as UntypedFormArray; + const array = this.form.controls.incentives; + this.voucher.incentives.forEach((item, index) => { - item.points = array.controls[index].value.points; + item.points = array.controls[index].value.points!; }); return this.voucher; } diff --git a/overlord/src/app/issue/issue-dialog.component.ts b/overlord/src/app/issue/issue-dialog.component.ts index 2433006c..cd9d27c9 100644 --- a/overlord/src/app/issue/issue-dialog.component.ts +++ b/overlord/src/app/issue/issue-dialog.component.ts @@ -1,9 +1,9 @@ import { Component, Inject, OnInit } from '@angular/core'; -import { UntypedFormBuilder, UntypedFormControl, UntypedFormGroup } from '@angular/forms'; +import { FormControl, FormGroup } from '@angular/forms'; import { MatAutocompleteSelectedEvent } from '@angular/material/autocomplete'; import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; import { Observable } from 'rxjs'; -import { debounceTime, distinctUntilChanged, startWith, switchMap } from 'rxjs/operators'; +import { debounceTime, distinctUntilChanged, map, switchMap } from 'rxjs/operators'; import { Batch } from '../core/batch'; import { BatchService } from '../core/batch.service'; @@ -17,23 +17,27 @@ import { MathService } from '../shared/math.service'; }) export class IssueDialogComponent implements OnInit { batches: Observable; - form: UntypedFormGroup; + form: FormGroup<{ + batch: FormControl; + quantity: FormControl; + }>; + batch: Batch = new Batch(); constructor( public dialogRef: MatDialogRef, @Inject(MAT_DIALOG_DATA) public data: { inventory: Inventory; date: string }, - private fb: UntypedFormBuilder, private math: MathService, private batchSer: BatchService, ) { - this.form = this.fb.group({ - batch: '', - quantity: '', + this.form = new FormGroup({ + batch: new FormControl(null), + quantity: new FormControl('', { nonNullable: true }), }); // Listen to Batch Autocomplete Change - this.batches = (this.form.get('batch') as UntypedFormControl).valueChanges.pipe( - startWith(''), + this.batches = this.form.controls.batch.valueChanges.pipe( + map((x) => (x instanceof Batch ? x.name : x)), + map((x) => (x !== null && x.length >= 1 ? x : '')), debounceTime(150), distinctUntilChanged(), switchMap((x) => this.batchSer.autocomplete(this.data.date, x)), @@ -43,7 +47,7 @@ export class IssueDialogComponent implements OnInit { ngOnInit() { this.form.setValue({ batch: this.data.inventory.batch, - quantity: this.data.inventory.quantity, + quantity: `${this.data.inventory.quantity}`, }); this.batch = this.data.inventory.batch as Batch; } diff --git a/overlord/src/app/issue/issue.component.ts b/overlord/src/app/issue/issue.component.ts index 964c06b0..b896a471 100644 --- a/overlord/src/app/issue/issue.component.ts +++ b/overlord/src/app/issue/issue.component.ts @@ -1,5 +1,5 @@ import { AfterViewInit, Component, ElementRef, OnInit, OnDestroy, ViewChild } from '@angular/core'; -import { UntypedFormBuilder, UntypedFormControl, UntypedFormGroup } from '@angular/forms'; +import { FormControl, FormGroup } from '@angular/forms'; import { MatAutocompleteSelectedEvent } from '@angular/material/autocomplete'; import { MatDialog } from '@angular/material/dialog'; import { ActivatedRoute, Router } from '@angular/router'; @@ -7,7 +7,7 @@ import { Hotkey, HotkeysService } from 'angular2-hotkeys'; import { round } from 'mathjs'; import * as moment from 'moment'; import { BehaviorSubject, Observable } from 'rxjs'; -import { debounceTime, distinctUntilChanged, map, startWith, switchMap } from 'rxjs/operators'; +import { debounceTime, distinctUntilChanged, map, switchMap } from 'rxjs/operators'; import { AuthService } from '../auth/auth.service'; import { Batch } from '../core/batch'; @@ -39,7 +39,18 @@ export class IssueComponent implements OnInit, AfterViewInit, OnDestroy { public gridObservable = new BehaviorSubject([]); dataSource: IssueDataSource = new IssueDataSource(this.inventoryObservable); gridDataSource: IssueGridDataSource = new IssueGridDataSource(this.gridObservable); - form: UntypedFormGroup; + form: FormGroup<{ + date: FormControl; + source: FormControl; + destination: FormControl; + amount: FormControl; + addRow: FormGroup<{ + batch: FormControl; + quantity: FormControl; + }>; + narration: FormControl; + }>; + voucher: Voucher = new Voucher(); costCentres: CostCentre[] = []; batch: Batch | null = null; @@ -52,7 +63,6 @@ export class IssueComponent implements OnInit, AfterViewInit, OnDestroy { constructor( private route: ActivatedRoute, private router: Router, - private fb: UntypedFormBuilder, private dialog: MatDialog, private hotkeys: HotkeysService, private toaster: ToasterService, @@ -62,22 +72,21 @@ export class IssueComponent implements OnInit, AfterViewInit, OnDestroy { private batchSer: BatchService, private issueGridSer: IssueGridService, ) { - this.form = this.fb.group({ - date: '', - source: '', - destination: '', - amount: { value: '', disabled: true }, - addRow: this.fb.group({ - batch: '', - quantity: '', + this.form = new FormGroup({ + date: new FormControl(new Date(), { nonNullable: true }), + source: new FormControl(null), + destination: new FormControl(null), + amount: new FormControl({ value: 0, disabled: true }, { nonNullable: true }), + addRow: new FormGroup({ + batch: new FormControl(null), + quantity: new FormControl('', { nonNullable: true }), }), - narration: '', + narration: new FormControl('', { nonNullable: true }), }); // Listen to Batch Autocomplete Change - this.batches = ( - (this.form.get('addRow') as UntypedFormControl).get('batch') as UntypedFormControl - ).valueChanges.pipe( - startWith('null'), + this.batches = this.form.controls.addRow.controls.batch.valueChanges.pipe( + map((x) => (x instanceof Batch ? x.name : x)), + map((x) => (x !== null && x.length >= 1 ? x : '')), debounceTime(150), distinctUntilChanged(), switchMap((x) => @@ -85,7 +94,7 @@ export class IssueComponent implements OnInit, AfterViewInit, OnDestroy { ), ); // Listen to Date Change - (this.form.get('date') as UntypedFormControl).valueChanges + this.form.controls.date.valueChanges .pipe(map((x) => moment(x).format('DD-MMM-YYYY'))) .subscribe((x) => this.showGrid(x)); } @@ -138,8 +147,8 @@ export class IssueComponent implements OnInit, AfterViewInit, OnDestroy { this.voucher = voucher; this.form.setValue({ date: moment(this.voucher.date, 'DD-MMM-YYYY').toDate(), - source: (this.voucher.source as CostCentre).id, - destination: (this.voucher.destination as CostCentre).id, + source: (this.voucher.source as CostCentre).id!, + destination: (this.voucher.destination as CostCentre).id!, amount: Math.abs(this.voucher.inventories.map((x) => x.amount).reduce((p, c) => p + c, 0)), addRow: { batch: '', @@ -160,7 +169,7 @@ export class IssueComponent implements OnInit, AfterViewInit, OnDestroy { } addRow() { - const formValue = (this.form.get('addRow') as UntypedFormControl).value; + const formValue = this.form.value.addRow!; const quantity = this.math.parseAmount(formValue.quantity, 2); const isConsumption = this.form.value.source === '7b845f95-dfef-fa4a-897c-f0baf15284a3'; if (this.batch === null || quantity <= 0) { @@ -194,10 +203,7 @@ export class IssueComponent implements OnInit, AfterViewInit, OnDestroy { } resetAddRow() { - (this.form.get('addRow') as UntypedFormControl).reset({ - batch: null, - quantity: '', - }); + this.form.controls.addRow.reset(); this.batch = null; setTimeout(() => { if (this.batchElement) { @@ -212,7 +218,7 @@ export class IssueComponent implements OnInit, AfterViewInit, OnDestroy { Math.abs(this.voucher.inventories.map((x) => x.amount).reduce((p, c) => p + c, 0)), 2, ); - (this.form.get('amount') as UntypedFormControl).setValue(amount); + this.form.controls.amount.setValue(amount); } editRow(row: Inventory) { @@ -282,9 +288,9 @@ export class IssueComponent implements OnInit, AfterViewInit, OnDestroy { getVoucher(): Voucher { const formModel = this.form.value; this.voucher.date = moment(formModel.date).format('DD-MMM-YYYY'); - (this.voucher.source as CostCentre).id = formModel.source; - (this.voucher.destination as CostCentre).id = formModel.destination; - this.voucher.narration = formModel.narration; + (this.voucher.source as CostCentre).id = formModel.source!; + (this.voucher.destination as CostCentre).id = formModel.destination!; + this.voucher.narration = formModel.narration!; return this.voucher; } diff --git a/overlord/src/app/journal/journal-dialog.component.html b/overlord/src/app/journal/journal-dialog.component.html index 96225faf..9cab2573 100644 --- a/overlord/src/app/journal/journal-dialog.component.html +++ b/overlord/src/app/journal/journal-dialog.component.html @@ -10,8 +10,8 @@ > - Dr - Cr + Dr + Cr diff --git a/overlord/src/app/journal/journal-dialog.component.ts b/overlord/src/app/journal/journal-dialog.component.ts index 62aaef23..6080314b 100644 --- a/overlord/src/app/journal/journal-dialog.component.ts +++ b/overlord/src/app/journal/journal-dialog.component.ts @@ -1,9 +1,9 @@ import { Component, Inject, OnInit } from '@angular/core'; -import { UntypedFormBuilder, UntypedFormControl, UntypedFormGroup } from '@angular/forms'; +import { FormControl, FormGroup } from '@angular/forms'; import { MatAutocompleteSelectedEvent } from '@angular/material/autocomplete'; import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; import { Observable, of as observableOf } from 'rxjs'; -import { debounceTime, distinctUntilChanged, map, startWith, switchMap } from 'rxjs/operators'; +import { debounceTime, distinctUntilChanged, map, switchMap } from 'rxjs/operators'; import { Account } from '../core/account'; import { AccountBalance } from '../core/account-balance'; @@ -18,26 +18,29 @@ import { MathService } from '../shared/math.service'; }) export class JournalDialogComponent implements OnInit { accounts: Observable; - form: UntypedFormGroup; + form: FormGroup<{ + debit: FormControl; + account: FormControl; + amount: FormControl; + }>; + account: Account = new Account(); accBal: AccountBalance | null = null; constructor( public dialogRef: MatDialogRef, @Inject(MAT_DIALOG_DATA) public data: { journal: Journal; date: string }, - private fb: UntypedFormBuilder, private math: MathService, private accountSer: AccountService, ) { - this.form = this.fb.group({ - debit: '1', - account: '', - amount: '', + this.form = new FormGroup({ + debit: new FormControl(1, { nonNullable: true }), + account: new FormControl(''), + amount: new FormControl('', { nonNullable: true }), }); this.accBal = null; // Setup Account Autocomplete - this.accounts = (this.form.get('account') as UntypedFormControl).valueChanges.pipe( - startWith(null), + this.accounts = this.form.controls.account.valueChanges.pipe( map((x) => (x !== null && x.length >= 1 ? x : null)), debounceTime(150), distinctUntilChanged(), @@ -47,9 +50,9 @@ export class JournalDialogComponent implements OnInit { ngOnInit() { this.form.setValue({ - debit: `${this.data.journal.debit}`, - account: this.data.journal.account, - amount: this.data.journal.amount, + debit: this.data.journal.debit, + account: this.data.journal.account.name, + amount: `${this.data.journal.amount}`, }); this.account = this.data.journal.account; } @@ -68,7 +71,7 @@ export class JournalDialogComponent implements OnInit { accept(): void { const formValue = this.form.value; - const amount = this.math.journalAmount(formValue.amount, +formValue.debit); + const amount = this.math.journalAmount(formValue.amount, formValue.debit!); this.data.journal.debit = amount.debit; this.data.journal.account = this.account; this.data.journal.amount = amount.amount; diff --git a/overlord/src/app/journal/journal.component.html b/overlord/src/app/journal/journal.component.html index 755b9489..0d0dd418 100644 --- a/overlord/src/app/journal/journal.component.html +++ b/overlord/src/app/journal/journal.component.html @@ -37,8 +37,8 @@ > - Dr - Cr + Dr + Cr diff --git a/overlord/src/app/journal/journal.component.ts b/overlord/src/app/journal/journal.component.ts index 155fc365..b1bb8859 100644 --- a/overlord/src/app/journal/journal.component.ts +++ b/overlord/src/app/journal/journal.component.ts @@ -1,5 +1,5 @@ import { AfterViewInit, Component, ElementRef, OnInit, OnDestroy, ViewChild } from '@angular/core'; -import { UntypedFormBuilder, UntypedFormControl, UntypedFormGroup } from '@angular/forms'; +import { FormControl, FormGroup } from '@angular/forms'; import { MatAutocompleteSelectedEvent } from '@angular/material/autocomplete'; import { MatDialog } from '@angular/material/dialog'; import { ActivatedRoute, Router } from '@angular/router'; @@ -7,7 +7,7 @@ import { Hotkey, HotkeysService } from 'angular2-hotkeys'; import { round } from 'mathjs'; import * as moment from 'moment'; import { BehaviorSubject, Observable, of as observableOf } from 'rxjs'; -import { debounceTime, distinctUntilChanged, map, startWith, switchMap } from 'rxjs/operators'; +import { debounceTime, distinctUntilChanged, map, switchMap } from 'rxjs/operators'; import { AuthService } from '../auth/auth.service'; import { Account } from '../core/account'; @@ -37,7 +37,16 @@ export class JournalComponent implements OnInit, AfterViewInit, OnDestroy { @ViewChild('dateElement', { static: true }) dateElement?: ElementRef; public journalObservable = new BehaviorSubject([]); dataSource: JournalDataSource = new JournalDataSource(this.journalObservable); - form: UntypedFormGroup; + form: FormGroup<{ + date: FormControl; + addRow: FormGroup<{ + debit: FormControl; + account: FormControl; + amount: FormControl; + }>; + narration: FormControl; + }>; + voucher: Voucher = new Voucher(); account: Account | null; accBal: AccountBalance | null = null; @@ -49,7 +58,6 @@ export class JournalComponent implements OnInit, AfterViewInit, OnDestroy { constructor( private route: ActivatedRoute, private router: Router, - private fb: UntypedFormBuilder, private dialog: MatDialog, private hotkeys: HotkeysService, private toaster: ToasterService, @@ -60,21 +68,18 @@ export class JournalComponent implements OnInit, AfterViewInit, OnDestroy { private accountSer: AccountService, ) { this.account = null; - this.form = this.fb.group({ - date: '', - addRow: this.fb.group({ - debit: '1', - account: '', - amount: '', + this.form = new FormGroup({ + date: new FormControl(new Date(), { nonNullable: true }), + addRow: new FormGroup({ + debit: new FormControl(1, { nonNullable: true }), + account: new FormControl(''), + amount: new FormControl('', { nonNullable: true }), }), - narration: '', + narration: new FormControl('', { nonNullable: true }), }); this.accBal = null; // Setup Account Autocomplete - this.accounts = ( - (this.form.get('addRow') as UntypedFormControl).get('account') as UntypedFormControl - ).valueChanges.pipe( - startWith(null), + this.accounts = this.form.controls.addRow.controls.account.valueChanges.pipe( map((x) => (x !== null && x.length >= 1 ? x : null)), debounceTime(150), distinctUntilChanged(), @@ -141,9 +146,9 @@ export class JournalComponent implements OnInit, AfterViewInit, OnDestroy { this.form.setValue({ date: moment(this.voucher.date, 'DD-MMM-YYYY').toDate(), addRow: { - debit: '1', - account: '', - amount: 0, + debit: 1, + account: null, + amount: '', }, narration: this.voucher.narration, }); @@ -160,8 +165,8 @@ export class JournalComponent implements OnInit, AfterViewInit, OnDestroy { } addRow() { - const formValue = (this.form.get('addRow') as UntypedFormControl).value; - const amount = this.math.journalAmount(formValue.amount, +formValue.debit); + const formValue = this.form.value.addRow!; + const amount = this.math.journalAmount(formValue.amount!, formValue.debit!); if (this.account === null || amount.amount === 0) { return; } @@ -192,9 +197,7 @@ export class JournalComponent implements OnInit, AfterViewInit, OnDestroy { Math.abs(this.voucher.journals.map((x) => x.debit * x.amount).reduce((p, c) => p + c)), 2, ); - const { debit } = (this.form.get('addRow') as UntypedFormControl).value; - (this.form.get('addRow') as UntypedFormControl).reset({ - debit, + this.form.controls.addRow.reset({ account: null, amount: `${amount}`, }); @@ -212,7 +215,7 @@ export class JournalComponent implements OnInit, AfterViewInit, OnDestroy { width: '750px', data: { journal: { ...row }, - date: moment((this.form.get('date') as UntypedFormControl).value).format('DD-MMM-YYYY'), + date: moment(this.form.value.date).format('DD-MMM-YYYY'), }, }); @@ -239,8 +242,8 @@ export class JournalComponent implements OnInit, AfterViewInit, OnDestroy { const amount = Math.abs( this.voucher.journals.map((x) => x.debit * x.amount).reduce((p, c) => p + c, 0), ); - (this.form.get('addRow') as UntypedFormControl).patchValue({ - amount, + this.form.controls.addRow.patchValue({ + amount: `${amount}`, }); } @@ -289,7 +292,7 @@ export class JournalComponent implements OnInit, AfterViewInit, OnDestroy { getVoucher(): Voucher { const formModel = this.form.value; this.voucher.date = moment(formModel.date).format('DD-MMM-YYYY'); - this.voucher.narration = formModel.narration; + this.voucher.narration = formModel.narration!; return this.voucher; } @@ -325,7 +328,7 @@ export class JournalComponent implements OnInit, AfterViewInit, OnDestroy { accountSelected(event: MatAutocompleteSelectedEvent): void { const account = event.option.value; this.account = account; - const date = moment((this.form.get('date') as UntypedFormControl).value).format('DD-MMM-YYYY'); + const date = moment(this.form.value.date).format('DD-MMM-YYYY'); this.accountSer.balance(account.id as string, date).subscribe((v) => { this.accBal = v; }); diff --git a/overlord/src/app/ledger/ledger.component.ts b/overlord/src/app/ledger/ledger.component.ts index 5502d92f..08c9d5b1 100644 --- a/overlord/src/app/ledger/ledger.component.ts +++ b/overlord/src/app/ledger/ledger.component.ts @@ -1,12 +1,12 @@ import { AfterViewInit, Component, ElementRef, OnInit, ViewChild } from '@angular/core'; -import { UntypedFormBuilder, UntypedFormControl, UntypedFormGroup } from '@angular/forms'; +import { FormControl, FormGroup } from '@angular/forms'; import { MatAutocompleteSelectedEvent } from '@angular/material/autocomplete'; import { MatPaginator } from '@angular/material/paginator'; import { MatSort } from '@angular/material/sort'; import { ActivatedRoute, Router } from '@angular/router'; import * as moment from 'moment'; import { Observable, of as observableOf } from 'rxjs'; -import { debounceTime, distinctUntilChanged, map, startWith, switchMap } from 'rxjs/operators'; +import { debounceTime, distinctUntilChanged, map, switchMap } from 'rxjs/operators'; import { Account } from '../core/account'; import { AccountService } from '../core/account.service'; @@ -27,7 +27,12 @@ export class LedgerComponent implements OnInit, AfterViewInit { @ViewChild(MatSort, { static: true }) sort?: MatSort; info: Ledger = new Ledger(); dataSource: LedgerDataSource = new LedgerDataSource(this.info.body); - form: UntypedFormGroup; + form: FormGroup<{ + startDate: FormControl; + finishDate: FormControl; + account: FormControl; + }>; + selectedRowId = ''; debit = 0; credit = 0; @@ -40,19 +45,18 @@ export class LedgerComponent implements OnInit, AfterViewInit { constructor( private route: ActivatedRoute, private router: Router, - private fb: UntypedFormBuilder, private toCsv: ToCsvService, private ser: LedgerService, private accountSer: AccountService, ) { - this.form = this.fb.group({ - startDate: '', - finishDate: '', - account: '', + this.form = new FormGroup({ + startDate: new FormControl(new Date(), { nonNullable: true }), + finishDate: new FormControl(new Date(), { nonNullable: true }), + account: new FormControl(null), }); - this.accounts = (this.form.get('account') as UntypedFormControl).valueChanges.pipe( - startWith(null), + this.accounts = this.form.controls.account.valueChanges.pipe( + map((x) => (x instanceof Account ? x.name : x)), map((x) => (x !== null && x.length >= 1 ? x : null)), debounceTime(150), distinctUntilChanged(), @@ -127,7 +131,7 @@ export class LedgerComponent implements OnInit, AfterViewInit { const formModel = this.form.value; return new Ledger({ - account: formModel.account, + account: formModel.account as Account, startDate: moment(formModel.startDate).format('DD-MMM-YYYY'), finishDate: moment(formModel.finishDate).format('DD-MMM-YYYY'), }); diff --git a/overlord/src/app/net-transactions/net-transactions.component.ts b/overlord/src/app/net-transactions/net-transactions.component.ts index ab09ab4a..1dad0ee2 100644 --- a/overlord/src/app/net-transactions/net-transactions.component.ts +++ b/overlord/src/app/net-transactions/net-transactions.component.ts @@ -1,5 +1,5 @@ import { Component, OnInit, ViewChild } from '@angular/core'; -import { UntypedFormBuilder, UntypedFormGroup } from '@angular/forms'; +import { FormControl, FormGroup } from '@angular/forms'; import { MatPaginator } from '@angular/material/paginator'; import { MatSort } from '@angular/material/sort'; import { ActivatedRoute, Router } from '@angular/router'; @@ -18,19 +18,19 @@ export class NetTransactionsComponent implements OnInit { @ViewChild(MatSort, { static: true }) sort?: MatSort; info: NetTransactions = new NetTransactions(); dataSource: NetTransactionsDataSource = new NetTransactionsDataSource(this.info.body); - form: UntypedFormGroup; + form: FormGroup<{ + startDate: FormControl; + finishDate: FormControl; + }>; + selectedRowId = ''; /** Columns displayed in the table. Columns IDs can be added, removed, or reordered. */ displayedColumns = ['type', 'name', 'debit', 'credit']; - constructor( - private route: ActivatedRoute, - private router: Router, - private fb: UntypedFormBuilder, - ) { - this.form = this.fb.group({ - startDate: '', - finishDate: '', + constructor(private route: ActivatedRoute, private router: Router) { + this.form = new FormGroup({ + startDate: new FormControl(new Date(), { nonNullable: true }), + finishDate: new FormControl(new Date(), { nonNullable: true }), }); } diff --git a/overlord/src/app/non-contact-purchase/non-contract-purchase.module.ts b/overlord/src/app/non-contact-purchase/non-contract-purchase.module.ts index fead1839..5068776e 100644 --- a/overlord/src/app/non-contact-purchase/non-contract-purchase.module.ts +++ b/overlord/src/app/non-contact-purchase/non-contract-purchase.module.ts @@ -4,7 +4,6 @@ import { CommonModule } from '@angular/common'; import { NgModule } from '@angular/core'; import { FlexLayoutModule } from '@angular/flex-layout'; import { ReactiveFormsModule } from '@angular/forms'; -import { MomentDateAdapter } from '@angular/material-moment-adapter'; import { MatButtonModule } from '@angular/material/button'; import { MatCardModule } from '@angular/material/card'; import { MatCheckboxModule } from '@angular/material/checkbox'; diff --git a/overlord/src/app/payment/payment-dialog.component.ts b/overlord/src/app/payment/payment-dialog.component.ts index 5e38fb80..fa5784a9 100644 --- a/overlord/src/app/payment/payment-dialog.component.ts +++ b/overlord/src/app/payment/payment-dialog.component.ts @@ -1,9 +1,9 @@ import { Component, Inject, OnInit } from '@angular/core'; -import { UntypedFormBuilder, UntypedFormControl, UntypedFormGroup } from '@angular/forms'; +import { FormControl, FormGroup } from '@angular/forms'; import { MatAutocompleteSelectedEvent } from '@angular/material/autocomplete'; import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; import { Observable, of as observableOf } from 'rxjs'; -import { debounceTime, distinctUntilChanged, map, startWith, switchMap } from 'rxjs/operators'; +import { debounceTime, distinctUntilChanged, map, switchMap } from 'rxjs/operators'; import { Account } from '../core/account'; import { AccountBalance } from '../core/account-balance'; @@ -18,25 +18,27 @@ import { MathService } from '../shared/math.service'; }) export class PaymentDialogComponent implements OnInit { accounts: Observable; - form: UntypedFormGroup; + form: FormGroup<{ + account: FormControl; + amount: FormControl; + }>; + account: Account = new Account(); accBal: AccountBalance | null = null; constructor( public dialogRef: MatDialogRef, @Inject(MAT_DIALOG_DATA) public data: { journal: Journal; date: string }, - private fb: UntypedFormBuilder, private math: MathService, private accountSer: AccountService, ) { - this.form = this.fb.group({ - account: '', - amount: '', + this.form = new FormGroup({ + account: new FormControl(''), + amount: new FormControl('', { nonNullable: true }), }); this.accBal = null; // Setup Account Autocomplete - this.accounts = (this.form.get('account') as UntypedFormControl).valueChanges.pipe( - startWith(null), + this.accounts = this.form.controls.account.valueChanges.pipe( map((x) => (x !== null && x.length >= 1 ? x : null)), debounceTime(150), distinctUntilChanged(), @@ -46,8 +48,8 @@ export class PaymentDialogComponent implements OnInit { ngOnInit() { this.form.setValue({ - account: this.data.journal.account, - amount: this.data.journal.amount, + account: this.data.journal.account.name, + amount: `${this.data.journal.amount}`, }); this.account = this.data.journal.account; } diff --git a/overlord/src/app/payment/payment.component.ts b/overlord/src/app/payment/payment.component.ts index 28d3f279..bef887cf 100644 --- a/overlord/src/app/payment/payment.component.ts +++ b/overlord/src/app/payment/payment.component.ts @@ -1,5 +1,5 @@ import { AfterViewInit, Component, ElementRef, OnInit, OnDestroy, ViewChild } from '@angular/core'; -import { UntypedFormBuilder, UntypedFormControl, UntypedFormGroup } from '@angular/forms'; +import { FormControl, FormGroup } from '@angular/forms'; import { MatAutocompleteSelectedEvent } from '@angular/material/autocomplete'; import { MatDialog } from '@angular/material/dialog'; import { ActivatedRoute, Router } from '@angular/router'; @@ -7,7 +7,7 @@ import { Hotkey, HotkeysService } from 'angular2-hotkeys'; import { round } from 'mathjs'; import * as moment from 'moment'; import { BehaviorSubject, Observable, of as observableOf } from 'rxjs'; -import { debounceTime, distinctUntilChanged, map, startWith, switchMap } from 'rxjs/operators'; +import { debounceTime, distinctUntilChanged, map, switchMap } from 'rxjs/operators'; import { AuthService } from '../auth/auth.service'; import { Account } from '../core/account'; @@ -37,7 +37,17 @@ export class PaymentComponent implements OnInit, AfterViewInit, OnDestroy { @ViewChild('dateElement', { static: true }) dateElement?: ElementRef; public journalObservable = new BehaviorSubject([]); dataSource: PaymentDataSource = new PaymentDataSource(this.journalObservable); - form: UntypedFormGroup; + form: FormGroup<{ + date: FormControl; + paymentAccount: FormControl; + paymentAmount: FormControl; + addRow: FormGroup<{ + account: FormControl; + amount: FormControl; + }>; + narration: FormControl; + }>; + paymentAccounts: Account[] = []; paymentJournal: Journal = new Journal(); voucher: Voucher = new Voucher(); @@ -51,7 +61,6 @@ export class PaymentComponent implements OnInit, AfterViewInit, OnDestroy { constructor( private route: ActivatedRoute, private router: Router, - private fb: UntypedFormBuilder, private dialog: MatDialog, private hotkeys: HotkeysService, private toaster: ToasterService, @@ -62,29 +71,26 @@ export class PaymentComponent implements OnInit, AfterViewInit, OnDestroy { private accountSer: AccountService, ) { this.account = null; - this.form = this.fb.group({ - date: '', - paymentAccount: '', - paymentAmount: { value: '', disabled: true }, - addRow: this.fb.group({ - account: '', - amount: '', + this.form = new FormGroup({ + date: new FormControl(new Date(), { nonNullable: true }), + paymentAccount: new FormControl('', { nonNullable: true }), + paymentAmount: new FormControl({ value: 0, disabled: true }, { nonNullable: true }), + addRow: new FormGroup({ + account: new FormControl(''), + amount: new FormControl('', { nonNullable: true }), }), - narration: '', + narration: new FormControl('', { nonNullable: true }), }); this.accBal = null; // Listen to Account Autocomplete Change - this.accounts = ( - (this.form.get('addRow') as UntypedFormControl).get('account') as UntypedFormControl - ).valueChanges.pipe( - startWith(null), + this.accounts = this.form.controls.addRow.controls.account.valueChanges.pipe( map((x) => (x !== null && x.length >= 1 ? x : null)), debounceTime(150), distinctUntilChanged(), switchMap((x) => (x === null ? observableOf([]) : this.accountSer.autocomplete(x))), ); // Listen to Payment Account Change - (this.form.get('paymentAccount') as UntypedFormControl).valueChanges.subscribe((x) => + this.form.controls.paymentAccount.valueChanges.subscribe((x) => this.router.navigate([], { relativeTo: this.route, queryParams: { a: x }, @@ -153,11 +159,11 @@ export class PaymentComponent implements OnInit, AfterViewInit, OnDestroy { [this.paymentJournal] = this.voucher.journals.filter((x) => x.debit === -1); this.form.setValue({ date: moment(this.voucher.date, 'DD-MMM-YYYY').toDate(), - paymentAccount: this.paymentJournal.account.id, + paymentAccount: this.paymentJournal.account.id!, paymentAmount: this.paymentJournal.amount, addRow: { account: '', - amount: 0, + amount: '', }, narration: this.voucher.narration, }); @@ -174,10 +180,7 @@ export class PaymentComponent implements OnInit, AfterViewInit, OnDestroy { } addRow() { - const amount = this.math.parseAmount( - (this.form.get('addRow') as UntypedFormControl).value.amount, - 2, - ); + const amount = this.math.parseAmount(this.form.value.addRow?.amount!, 2); const debit = 1; if (this.account === null || amount <= 0) { return; @@ -206,10 +209,7 @@ export class PaymentComponent implements OnInit, AfterViewInit, OnDestroy { } resetAddRow() { - (this.form.get('addRow') as UntypedFormControl).reset({ - account: null, - amount: null, - }); + this.form.controls.addRow.reset({ account: null, amount: '' }); this.account = null; this.accBal = null; setTimeout(() => { @@ -226,7 +226,7 @@ export class PaymentComponent implements OnInit, AfterViewInit, OnDestroy { Math.abs(journals.map((x) => x.amount).reduce((p, c) => p + c, 0)), 2, ); - (this.form.get('paymentAmount') as UntypedFormControl).setValue(this.paymentJournal.amount); + this.form.controls.paymentAmount.setValue(this.paymentJournal.amount); } editRow(row: Journal) { @@ -234,7 +234,7 @@ export class PaymentComponent implements OnInit, AfterViewInit, OnDestroy { width: '750px', data: { journal: { ...row }, - date: moment((this.form.get('date') as UntypedFormControl).value).format('DD-MMM-YYYY'), + date: moment(this.form.value.date).format('DD-MMM-YYYY'), }, }); @@ -305,7 +305,7 @@ export class PaymentComponent implements OnInit, AfterViewInit, OnDestroy { const formModel = this.form.value; this.voucher.date = moment(formModel.date).format('DD-MMM-YYYY'); this.paymentJournal.account.id = formModel.paymentAccount; - this.voucher.narration = formModel.narration; + this.voucher.narration = formModel.narration!; return this.voucher; } @@ -341,7 +341,7 @@ export class PaymentComponent implements OnInit, AfterViewInit, OnDestroy { accountSelected(event: MatAutocompleteSelectedEvent): void { const account = event.option.value; this.account = account; - const date = moment((this.form.get('date') as UntypedFormControl).value).format('DD-MMM-YYYY'); + const date = moment(this.form.value.date).format('DD-MMM-YYYY'); this.accountSer.balance(account.id as string, date).subscribe((v) => { this.accBal = v; }); diff --git a/overlord/src/app/product-group/product-group-detail/product-group-detail.component.ts b/overlord/src/app/product-group/product-group-detail/product-group-detail.component.ts index 28c06f40..ad1fab08 100644 --- a/overlord/src/app/product-group/product-group-detail/product-group-detail.component.ts +++ b/overlord/src/app/product-group/product-group-detail/product-group-detail.component.ts @@ -1,5 +1,5 @@ import { AfterViewInit, Component, ElementRef, OnInit, ViewChild } from '@angular/core'; -import { UntypedFormBuilder, UntypedFormGroup } from '@angular/forms'; +import { FormControl, FormGroup } from '@angular/forms'; import { ActivatedRoute, Router } from '@angular/router'; import { ProductGroup } from '../../core/product-group'; @@ -13,18 +13,20 @@ import { ProductGroupService } from '../product-group.service'; }) export class ProductGroupDetailComponent implements OnInit, AfterViewInit { @ViewChild('nameElement', { static: true }) nameElement?: ElementRef; - form: UntypedFormGroup; + form: FormGroup<{ + name: FormControl; + }>; + item: ProductGroup = new ProductGroup(); constructor( private route: ActivatedRoute, private router: Router, - private fb: UntypedFormBuilder, private toaster: ToasterService, private ser: ProductGroupService, ) { - this.form = this.fb.group({ - name: '', + this.form = new FormGroup({ + name: new FormControl(null), }); } @@ -65,7 +67,7 @@ export class ProductGroupDetailComponent implements OnInit, AfterViewInit { getItem(): ProductGroup { const formModel = this.form.value; - this.item.name = formModel.name; + this.item.name = formModel.name!; return this.item; } } diff --git a/overlord/src/app/product-group/product-group.service.ts b/overlord/src/app/product-group/product-group.service.ts index 0e8633bf..e2adac76 100644 --- a/overlord/src/app/product-group/product-group.service.ts +++ b/overlord/src/app/product-group/product-group.service.ts @@ -1,4 +1,4 @@ -import { HttpClient, HttpHeaders } from '@angular/common/http'; +import { HttpClient } from '@angular/common/http'; import { Injectable } from '@angular/core'; import { Observable } from 'rxjs/internal/Observable'; import { catchError } from 'rxjs/operators'; diff --git a/overlord/src/app/product-ledger/product-ledger.component.ts b/overlord/src/app/product-ledger/product-ledger.component.ts index 89818745..378443d7 100644 --- a/overlord/src/app/product-ledger/product-ledger.component.ts +++ b/overlord/src/app/product-ledger/product-ledger.component.ts @@ -1,12 +1,12 @@ import { AfterViewInit, Component, ElementRef, OnInit, ViewChild } from '@angular/core'; -import { UntypedFormBuilder, UntypedFormControl, UntypedFormGroup } from '@angular/forms'; +import { FormControl, FormGroup } from '@angular/forms'; import { MatAutocompleteSelectedEvent } from '@angular/material/autocomplete'; import { MatPaginator } from '@angular/material/paginator'; import { MatSort } from '@angular/material/sort'; import { ActivatedRoute, Router } from '@angular/router'; import * as moment from 'moment'; import { Observable, of as observableOf } from 'rxjs'; -import { debounceTime, distinctUntilChanged, map, startWith, switchMap } from 'rxjs/operators'; +import { debounceTime, distinctUntilChanged, map, switchMap } from 'rxjs/operators'; import { Product } from '../core/product'; import { ProductSku } from '../core/product-sku'; @@ -28,7 +28,12 @@ export class ProductLedgerComponent implements OnInit, AfterViewInit { @ViewChild(MatSort, { static: true }) sort?: MatSort; info: ProductLedger = new ProductLedger(); dataSource: ProductLedgerDataSource = new ProductLedgerDataSource(this.info.body); - form: UntypedFormGroup; + form: FormGroup<{ + startDate: FormControl; + finishDate: FormControl; + product: FormControl; + }>; + selectedRowId = ''; debitQuantity = 0; debitAmount = 0; @@ -55,19 +60,18 @@ export class ProductLedgerComponent implements OnInit, AfterViewInit { constructor( private route: ActivatedRoute, private router: Router, - private fb: UntypedFormBuilder, private toCsv: ToCsvService, private ser: ProductLedgerService, private productSer: ProductService, ) { - this.form = this.fb.group({ - startDate: '', - finishDate: '', - product: '', + this.form = new FormGroup({ + startDate: new FormControl(new Date(), { nonNullable: true }), + finishDate: new FormControl(new Date(), { nonNullable: true }), + product: new FormControl(null), }); - this.products = (this.form.get('product') as UntypedFormControl).valueChanges.pipe( - startWith(null), + this.products = this.form.controls.product.valueChanges.pipe( + map((x) => (x instanceof Product ? x.name : x)), map((x) => (x !== null && x.length >= 1 ? x : null)), debounceTime(150), distinctUntilChanged(), @@ -134,7 +138,7 @@ export class ProductLedgerComponent implements OnInit, AfterViewInit { show() { const info = this.getInfo(); - this.router.navigate(['product-ledger', (info.product as Product).id], { + this.router.navigate(['product-ledger', info.product.id], { queryParams: { startDate: info.startDate, finishDate: info.finishDate, @@ -146,7 +150,7 @@ export class ProductLedgerComponent implements OnInit, AfterViewInit { const formModel = this.form.value; return new ProductLedger({ - product: formModel.product, + product: formModel.product as Product, startDate: moment(formModel.startDate).format('DD-MMM-YYYY'), finishDate: moment(formModel.finishDate).format('DD-MMM-YYYY'), }); diff --git a/overlord/src/app/product-ledger/product-ledger.ts b/overlord/src/app/product-ledger/product-ledger.ts index 6e6f31f2..a2f68a61 100644 --- a/overlord/src/app/product-ledger/product-ledger.ts +++ b/overlord/src/app/product-ledger/product-ledger.ts @@ -5,12 +5,13 @@ import { ProductLedgerItem } from './product-ledger-item'; export class ProductLedger { startDate: string; finishDate: string; - product?: Product; + product: Product; body: ProductLedgerItem[]; public constructor(init?: Partial) { this.startDate = ''; this.finishDate = ''; + this.product = new Product(); this.body = []; Object.assign(this, init); } diff --git a/overlord/src/app/product/product-detail/product-detail-dialog.component.ts b/overlord/src/app/product/product-detail/product-detail-dialog.component.ts index 9e24b620..3786648e 100644 --- a/overlord/src/app/product/product-detail/product-detail-dialog.component.ts +++ b/overlord/src/app/product/product-detail/product-detail-dialog.component.ts @@ -1,5 +1,5 @@ import { Component, Inject, OnInit } from '@angular/core'; -import { UntypedFormBuilder, UntypedFormGroup } from '@angular/forms'; +import { FormControl, FormGroup } from '@angular/forms'; import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; import { StockKeepingUnit } from '../../core/product'; @@ -10,52 +10,57 @@ import { StockKeepingUnit } from '../../core/product'; styleUrls: ['./product-detail-dialog.component.css'], }) export class ProductDetailDialogComponent implements OnInit { - form: UntypedFormGroup; + form: FormGroup<{ + units: FormControl; + fraction: FormControl; + productYield: FormControl; + costPrice: FormControl; + salePrice: FormControl; + }>; constructor( public dialogRef: MatDialogRef, @Inject(MAT_DIALOG_DATA) public data: { item: StockKeepingUnit; isSold: boolean; isPurchased: boolean }, - private fb: UntypedFormBuilder, ) { - this.form = this.fb.group({ - units: '', - fraction: '', - productYield: '', - costPrice: '', - salePrice: '', + this.form = new FormGroup({ + units: new FormControl('', { nonNullable: true }), + fraction: new FormControl(1, { nonNullable: true }), + productYield: new FormControl(1, { nonNullable: true }), + costPrice: new FormControl(0, { nonNullable: true }), + salePrice: new FormControl(0, { nonNullable: true }), }); } ngOnInit() { this.form.setValue({ units: this.data.item.units, - fraction: '' + this.data.item.fraction, - productYield: '' + this.data.item.productYield, - costPrice: '' + this.data.item.costPrice, - salePrice: '' + this.data.item.salePrice, + fraction: this.data.item.fraction, + productYield: this.data.item.productYield, + costPrice: this.data.item.costPrice, + salePrice: this.data.item.salePrice, }); } accept(): void { const formValue = this.form.value; - const fraction = +formValue.fraction; + const fraction = formValue.fraction!; if (fraction < 1) { return; } - const productYield = +formValue.productYield; + const productYield = formValue.productYield!; if (productYield < 0 || productYield > 1) { return; } - const costPrice = +formValue.costPrice; + const costPrice = formValue.costPrice!; if (costPrice < 0) { return; } - const salePrice = +formValue.salePrice; + const salePrice = formValue.salePrice!; if (salePrice < 0) { return; } - this.data.item.units = formValue.units; + this.data.item.units = formValue.units!; this.data.item.fraction = fraction; this.data.item.productYield = productYield; this.data.item.costPrice = costPrice; diff --git a/overlord/src/app/product/product-detail/product-detail.component.ts b/overlord/src/app/product/product-detail/product-detail.component.ts index d8a553c9..71a3bf55 100644 --- a/overlord/src/app/product/product-detail/product-detail.component.ts +++ b/overlord/src/app/product/product-detail/product-detail.component.ts @@ -1,5 +1,5 @@ import { AfterViewInit, Component, ElementRef, OnInit, ViewChild } from '@angular/core'; -import { UntypedFormBuilder, UntypedFormControl, UntypedFormGroup } from '@angular/forms'; +import { FormControl, FormGroup } from '@angular/forms'; import { MatDialog } from '@angular/material/dialog'; import { ActivatedRoute, Router } from '@angular/router'; import { BehaviorSubject } from 'rxjs'; @@ -20,7 +20,23 @@ import { ProductDetailDialogComponent } from './product-detail-dialog.component' }) export class ProductDetailComponent implements OnInit, AfterViewInit { @ViewChild('nameElement', { static: true }) nameElement?: ElementRef; - form: UntypedFormGroup; + form: FormGroup<{ + code: FormControl; + name: FormControl; + fractionUnits: FormControl; + addRow: FormGroup<{ + units: FormControl; + fraction: FormControl; + productYield: FormControl; + costPrice: FormControl; + salePrice: FormControl; + }>; + isPurchased: FormControl; + isSold: FormControl; + isActive: FormControl; + productGroup: FormControl; + }>; + productGroups: ProductGroup[] = []; public skus = new BehaviorSubject([]); dataSource: ProductDetailDatasource = new ProductDetailDatasource(this.skus); @@ -32,25 +48,24 @@ export class ProductDetailComponent implements OnInit, AfterViewInit { private route: ActivatedRoute, private router: Router, private dialog: MatDialog, - private fb: UntypedFormBuilder, private toaster: ToasterService, private ser: ProductService, ) { - this.form = this.fb.group({ - code: { value: '', disabled: true }, - name: '', - fractionUnits: '', - addRow: this.fb.group({ - units: '', - fraction: '', - productYield: '', - costPrice: '', - salePrice: '', + this.form = new FormGroup({ + code: new FormControl({ value: 0, disabled: true }, { nonNullable: true }), + name: new FormControl(null), + fractionUnits: new FormControl(null), + addRow: new FormGroup({ + units: new FormControl(null), + fraction: new FormControl(null), + productYield: new FormControl(null), + costPrice: new FormControl(null), + salePrice: new FormControl(null), }), - isPurchased: '', - isSold: '', - isActive: '', - productGroup: '', + isPurchased: new FormControl(true, { nonNullable: true }), + isSold: new FormControl(true, { nonNullable: true }), + isActive: new FormControl(true, { nonNullable: true }), + productGroup: new FormControl(null), }); } @@ -70,7 +85,7 @@ export class ProductDetailComponent implements OnInit, AfterViewInit { this.form.setValue({ code: this.item.code || '(Auto)', name: this.item.name, - fractionUnits: this.item.fractionUnits, + fractionUnits: this.item.fractionUnits!, addRow: { units: '', fraction: '', @@ -81,7 +96,7 @@ export class ProductDetailComponent implements OnInit, AfterViewInit { isPurchased: this.item.isPurchased, isSold: this.item.isSold, isActive: this.item.isActive, - productGroup: this.item.productGroup ? this.item.productGroup.id : '', + productGroup: this.item.productGroup ? this.item.productGroup.id! : '', }); } @@ -94,30 +109,30 @@ export class ProductDetailComponent implements OnInit, AfterViewInit { } addRow() { - const formValue = (this.form.get('addRow') as UntypedFormControl).value; - const fraction = +formValue.fraction; + const formValue = this.form.value.addRow!; + const fraction = +formValue.fraction!; if (fraction < 1) { this.toaster.show('Danger', 'Fraction has to be >= 1'); return; } - const productYield = +formValue.productYield; + const productYield = +formValue.productYield!; if (productYield < 0 || productYield > 1) { this.toaster.show('Danger', 'Product Yield has to be > 0 and <= 1'); return; } - const costPrice = +formValue.costPrice; + const costPrice = +formValue.costPrice!; if (costPrice < 0) { this.toaster.show('Danger', 'Price has to be >= 0'); return; } - const salePrice = +formValue.salePrice; + const salePrice = +formValue.salePrice!; if (salePrice < 0) { this.toaster.show('Danger', 'Sale Price has to be >= 0'); return; } this.item.skus.push( new StockKeepingUnit({ - units: formValue.units, + units: formValue.units!, fraction, productYield, costPrice, @@ -129,13 +144,7 @@ export class ProductDetailComponent implements OnInit, AfterViewInit { } resetAddRow() { - (this.form.get('addRow') as UntypedFormControl).reset({ - units: '', - fraction: '', - productYield: '', - costPrice: '', - salePrice: '', - }); + this.form.controls.addRow.reset(); } editRow(row: StockKeepingUnit) { @@ -203,15 +212,15 @@ export class ProductDetailComponent implements OnInit, AfterViewInit { getItem(): Product { const formModel = this.form.value; - this.item.name = formModel.name; - this.item.fractionUnits = formModel.fractionUnits; - this.item.isPurchased = formModel.isPurchased; - this.item.isSold = formModel.isSold; - this.item.isActive = formModel.isActive; + this.item.name = formModel.name!; + this.item.fractionUnits = formModel.fractionUnits!; + this.item.isPurchased = formModel.isPurchased!; + this.item.isSold = formModel.isSold!; + this.item.isActive = formModel.isActive!; if (this.item.productGroup === null || this.item.productGroup === undefined) { this.item.productGroup = new ProductGroup(); } - this.item.productGroup.id = formModel.productGroup; + this.item.productGroup.id = formModel.productGroup!; return this.item; } } diff --git a/overlord/src/app/product/product-list/product-list.component.ts b/overlord/src/app/product/product-list/product-list.component.ts index d3c84778..53ee7194 100644 --- a/overlord/src/app/product/product-list/product-list.component.ts +++ b/overlord/src/app/product/product-list/product-list.component.ts @@ -1,10 +1,10 @@ import { AfterViewInit, Component, ElementRef, OnInit, ViewChild } from '@angular/core'; -import { UntypedFormBuilder, UntypedFormControl, UntypedFormGroup } from '@angular/forms'; +import { FormControl, FormGroup } from '@angular/forms'; import { MatPaginator } from '@angular/material/paginator'; import { MatSort } from '@angular/material/sort'; import { ActivatedRoute } from '@angular/router'; import { Observable } from 'rxjs'; -import { debounceTime, distinctUntilChanged, startWith } from 'rxjs/operators'; +import { debounceTime, distinctUntilChanged } from 'rxjs/operators'; import { Product } from '../../core/product'; import { ToCsvService } from '../../shared/to-csv.service'; @@ -23,23 +23,21 @@ export class ProductListComponent implements OnInit, AfterViewInit { list: Product[] = []; filter: Observable; dataSource: ProductListDataSource; - form: UntypedFormGroup; + form: FormGroup<{ + filter: FormControl; + }>; + /** Columns displayed in the table. Columns IDs can be added, removed, or reordered. */ displayedColumns: string[] = []; private _showExtended = true; - constructor( - private route: ActivatedRoute, - private fb: UntypedFormBuilder, - private toCsv: ToCsvService, - ) { + constructor(private route: ActivatedRoute, private toCsv: ToCsvService) { this.showExtended = true; - this.form = this.fb.group({ - filter: '', + this.form = new FormGroup({ + filter: new FormControl('', { nonNullable: true }), }); - this.filter = (this.form.get('filter') as UntypedFormControl).valueChanges.pipe( - startWith(''), + this.filter = this.form.controls.filter.valueChanges.pipe( debounceTime(150), distinctUntilChanged(), ); diff --git a/overlord/src/app/product/product-resolver.service.ts b/overlord/src/app/product/product-resolver.service.ts index 2d7916d2..4c74b9fd 100644 --- a/overlord/src/app/product/product-resolver.service.ts +++ b/overlord/src/app/product/product-resolver.service.ts @@ -1,5 +1,5 @@ import { Injectable } from '@angular/core'; -import { ActivatedRouteSnapshot, Resolve, Router } from '@angular/router'; +import { ActivatedRouteSnapshot, Resolve } from '@angular/router'; import { Observable } from 'rxjs/internal/Observable'; import { Product } from '../core/product'; diff --git a/overlord/src/app/product/product.service.ts b/overlord/src/app/product/product.service.ts index c75c9977..d1c306dd 100644 --- a/overlord/src/app/product/product.service.ts +++ b/overlord/src/app/product/product.service.ts @@ -1,4 +1,4 @@ -import { HttpClient, HttpHeaders, HttpParams } from '@angular/common/http'; +import { HttpClient, HttpParams } from '@angular/common/http'; import { Injectable } from '@angular/core'; import { Observable } from 'rxjs/internal/Observable'; import { catchError } from 'rxjs/operators'; diff --git a/overlord/src/app/profit-loss/profit-loss.component.ts b/overlord/src/app/profit-loss/profit-loss.component.ts index bf2d81e5..e93bfdc4 100644 --- a/overlord/src/app/profit-loss/profit-loss.component.ts +++ b/overlord/src/app/profit-loss/profit-loss.component.ts @@ -1,5 +1,5 @@ import { Component, OnInit, ViewChild } from '@angular/core'; -import { UntypedFormBuilder, UntypedFormGroup } from '@angular/forms'; +import { FormControl, FormGroup } from '@angular/forms'; import { MatPaginator } from '@angular/material/paginator'; import { MatSort } from '@angular/material/sort'; import { ActivatedRoute, Router } from '@angular/router'; @@ -18,19 +18,19 @@ export class ProfitLossComponent implements OnInit { @ViewChild(MatSort, { static: true }) sort?: MatSort; info: ProfitLoss = new ProfitLoss(); dataSource: ProfitLossDataSource = new ProfitLossDataSource(this.info.body); - form: UntypedFormGroup; + form: FormGroup<{ + startDate: FormControl; + finishDate: FormControl; + }>; + selectedRowId = ''; /** Columns displayed in the table. Columns IDs can be added, removed, or reordered. */ displayedColumns = ['group', 'name', 'amount', 'total']; - constructor( - private route: ActivatedRoute, - private router: Router, - private fb: UntypedFormBuilder, - ) { - this.form = this.fb.group({ - startDate: '', - finishDate: '', + constructor(private route: ActivatedRoute, private router: Router) { + this.form = new FormGroup({ + startDate: new FormControl(new Date(), { nonNullable: true }), + finishDate: new FormControl(new Date(), { nonNullable: true }), }); } diff --git a/overlord/src/app/purchase-entries/purchase-entries.component.ts b/overlord/src/app/purchase-entries/purchase-entries.component.ts index f02aae55..351bd1f5 100644 --- a/overlord/src/app/purchase-entries/purchase-entries.component.ts +++ b/overlord/src/app/purchase-entries/purchase-entries.component.ts @@ -1,5 +1,5 @@ import { Component, OnInit, ViewChild } from '@angular/core'; -import { UntypedFormBuilder, UntypedFormGroup } from '@angular/forms'; +import { FormControl, FormGroup } from '@angular/forms'; import { MatPaginator } from '@angular/material/paginator'; import { MatSort } from '@angular/material/sort'; import { ActivatedRoute, Router } from '@angular/router'; @@ -18,7 +18,11 @@ export class PurchaseEntriesComponent implements OnInit { @ViewChild(MatSort, { static: true }) sort?: MatSort; info: PurchaseEntries = new PurchaseEntries(); dataSource: PurchaseEntriesDataSource = new PurchaseEntriesDataSource(this.info.body); - form: UntypedFormGroup; + form: FormGroup<{ + startDate: FormControl; + finishDate: FormControl; + }>; + selectedRowId = ''; /** Columns displayed in the table. Columns IDs can be added, removed, or reordered. */ displayedColumns = [ @@ -32,14 +36,10 @@ export class PurchaseEntriesComponent implements OnInit { 'amount', ]; - constructor( - private route: ActivatedRoute, - private router: Router, - private fb: UntypedFormBuilder, - ) { - this.form = this.fb.group({ - startDate: '', - finishDate: '', + constructor(private route: ActivatedRoute, private router: Router) { + this.form = new FormGroup({ + startDate: new FormControl(new Date(), { nonNullable: true }), + finishDate: new FormControl(new Date(), { nonNullable: true }), }); } diff --git a/overlord/src/app/purchase-return/purchase-return-dialog.component.ts b/overlord/src/app/purchase-return/purchase-return-dialog.component.ts index e9355fb9..5c8a4b73 100644 --- a/overlord/src/app/purchase-return/purchase-return-dialog.component.ts +++ b/overlord/src/app/purchase-return/purchase-return-dialog.component.ts @@ -1,9 +1,9 @@ import { Component, Inject, OnInit } from '@angular/core'; -import { UntypedFormBuilder, UntypedFormControl, UntypedFormGroup } from '@angular/forms'; +import { FormControl, FormGroup } from '@angular/forms'; import { MatAutocompleteSelectedEvent } from '@angular/material/autocomplete'; import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; import { Observable } from 'rxjs'; -import { debounceTime, distinctUntilChanged, startWith, switchMap } from 'rxjs/operators'; +import { debounceTime, distinctUntilChanged, map, switchMap } from 'rxjs/operators'; import { Batch } from '../core/batch'; import { BatchService } from '../core/batch.service'; @@ -17,23 +17,27 @@ import { MathService } from '../shared/math.service'; }) export class PurchaseReturnDialogComponent implements OnInit { batches: Observable; - form: UntypedFormGroup; + form: FormGroup<{ + batch: FormControl; + quantity: FormControl; + }>; + batch: Batch = new Batch(); constructor( public dialogRef: MatDialogRef, @Inject(MAT_DIALOG_DATA) public data: { inventory: Inventory; date: string }, - private fb: UntypedFormBuilder, private math: MathService, private batchSer: BatchService, ) { - this.form = this.fb.group({ - batch: '', - quantity: '', + this.form = new FormGroup({ + batch: new FormControl(null), + quantity: new FormControl('', { nonNullable: true }), }); // Listen to Batch Autocomplete Change - this.batches = (this.form.get('batch') as UntypedFormControl).valueChanges.pipe( - startWith('null'), + this.batches = this.form.controls.batch.valueChanges.pipe( + map((x) => (x instanceof Batch ? x.name : x)), + map((x) => (x !== null && x.length >= 1 ? x : '')), debounceTime(150), distinctUntilChanged(), switchMap((x) => this.batchSer.autocomplete(this.data.date, x)), @@ -43,7 +47,7 @@ export class PurchaseReturnDialogComponent implements OnInit { ngOnInit() { this.form.setValue({ batch: this.data.inventory.batch, - quantity: this.data.inventory.quantity, + quantity: `${this.data.inventory.quantity}`, }); this.batch = this.data.inventory.batch as Batch; } diff --git a/overlord/src/app/purchase-return/purchase-return.component.ts b/overlord/src/app/purchase-return/purchase-return.component.ts index 11b616e4..4fd9d0ac 100644 --- a/overlord/src/app/purchase-return/purchase-return.component.ts +++ b/overlord/src/app/purchase-return/purchase-return.component.ts @@ -1,5 +1,5 @@ import { AfterViewInit, Component, ElementRef, OnInit, OnDestroy, ViewChild } from '@angular/core'; -import { UntypedFormBuilder, UntypedFormControl, UntypedFormGroup } from '@angular/forms'; +import { FormControl, FormGroup } from '@angular/forms'; import { MatAutocompleteSelectedEvent } from '@angular/material/autocomplete'; import { MatDialog } from '@angular/material/dialog'; import { ActivatedRoute, Router } from '@angular/router'; @@ -7,7 +7,7 @@ import { Hotkey, HotkeysService } from 'angular2-hotkeys'; import { round } from 'mathjs'; import * as moment from 'moment'; import { BehaviorSubject, Observable, of as observableOf } from 'rxjs'; -import { debounceTime, distinctUntilChanged, map, startWith, switchMap } from 'rxjs/operators'; +import { debounceTime, distinctUntilChanged, map, switchMap } from 'rxjs/operators'; import { AuthService } from '../auth/auth.service'; import { Account } from '../core/account'; @@ -40,7 +40,17 @@ export class PurchaseReturnComponent implements OnInit, AfterViewInit, OnDestroy @ViewChild('dateElement', { static: true }) dateElement?: ElementRef; public inventoryObservable = new BehaviorSubject([]); dataSource: PurchaseReturnDataSource = new PurchaseReturnDataSource(this.inventoryObservable); - form: UntypedFormGroup; + form: FormGroup<{ + date: FormControl; + account: FormControl; + amount: FormControl; + addRow: FormGroup<{ + batch: FormControl; + quantity: FormControl; + }>; + narration: FormControl; + }>; + voucher: Voucher = new Voucher(); batch: Batch | null = null; accBal: AccountBalance | null = null; @@ -53,7 +63,6 @@ export class PurchaseReturnComponent implements OnInit, AfterViewInit, OnDestroy constructor( private route: ActivatedRoute, private router: Router, - private fb: UntypedFormBuilder, private dialog: MatDialog, private hotkeys: HotkeysService, private toaster: ToasterService, @@ -64,29 +73,28 @@ export class PurchaseReturnComponent implements OnInit, AfterViewInit, OnDestroy private batchSer: BatchService, private accountSer: AccountService, ) { - this.form = this.fb.group({ - date: '', - account: '', - amount: { value: '', disabled: true }, - addRow: this.fb.group({ - batch: '', - quantity: '', + this.form = new FormGroup({ + date: new FormControl(new Date(), { nonNullable: true }), + account: new FormControl(null), + amount: new FormControl({ value: 0, disabled: true }, { nonNullable: true }), + addRow: new FormGroup({ + batch: new FormControl(null), + quantity: new FormControl('', { nonNullable: true }), }), - narration: '', + narration: new FormControl('', { nonNullable: true }), }); // Listen to Account Autocomplete Change - this.accounts = (this.form.get('account') as UntypedFormControl).valueChanges.pipe( - startWith(null), + this.accounts = this.form.controls.account.valueChanges.pipe( + map((x) => (x instanceof Account ? x.name : x)), map((x) => (x !== null && x.length >= 1 ? x : null)), debounceTime(150), distinctUntilChanged(), switchMap((x) => (x === null ? observableOf([]) : this.accountSer.autocomplete(x))), ); // Listen to Batch Autocomplete Change - this.batches = ( - (this.form.get('addRow') as UntypedFormControl).get('batch') as UntypedFormControl - ).valueChanges.pipe( - startWith(''), + this.batches = this.form.controls.addRow.controls.batch.valueChanges.pipe( + map((x) => (x instanceof Batch ? x.name : x)), + map((x) => (x !== null && x.length >= 1 ? x : '')), debounceTime(150), distinctUntilChanged(), switchMap((x) => @@ -153,7 +161,7 @@ export class PurchaseReturnComponent implements OnInit, AfterViewInit, OnDestroy this.voucher = voucher; this.form.setValue({ date: moment(this.voucher.date, 'DD-MMM-YYYY').toDate(), - account: this.voucher.vendor, + account: this.voucher.vendor || null, amount: Math.abs(this.voucher.inventories.map((x) => x.amount).reduce((p, c) => p + c, 0)), addRow: { batch: '', @@ -174,7 +182,7 @@ export class PurchaseReturnComponent implements OnInit, AfterViewInit, OnDestroy } addRow() { - const formValue = (this.form.get('addRow') as UntypedFormControl).value; + const formValue = this.form.value.addRow!; const quantity = this.math.parseAmount(formValue.quantity, 2); if (this.batch === null || quantity <= 0 || this.batch.quantityRemaining < quantity) { return; @@ -199,10 +207,7 @@ export class PurchaseReturnComponent implements OnInit, AfterViewInit, OnDestroy } resetAddRow() { - (this.form.get('addRow') as UntypedFormControl).reset({ - batch: null, - quantity: '', - }); + this.form.controls.addRow.reset(); this.batch = null; setTimeout(() => { if (this.batchElement) { @@ -213,7 +218,7 @@ export class PurchaseReturnComponent implements OnInit, AfterViewInit, OnDestroy updateView() { this.inventoryObservable.next(this.voucher.inventories); - (this.form.get('amount') as UntypedFormControl).setValue( + this.form.controls.amount.setValue( round(Math.abs(this.voucher.inventories.map((x) => x.amount).reduce((p, c) => p + c, 0)), 2), ); } @@ -293,8 +298,10 @@ export class PurchaseReturnComponent implements OnInit, AfterViewInit, OnDestroy getVoucher(): Voucher { const formModel = this.form.value; this.voucher.date = moment(formModel.date).format('DD-MMM-YYYY'); - this.voucher.vendor = formModel.account; - this.voucher.narration = formModel.narration; + if (formModel.account instanceof Account) { + this.voucher.vendor = formModel.account; + } + this.voucher.narration = formModel.narration!; return this.voucher; } @@ -328,7 +335,7 @@ export class PurchaseReturnComponent implements OnInit, AfterViewInit, OnDestroy } accountSelected(event: MatAutocompleteSelectedEvent): void { - (this.form.get('account') as UntypedFormControl).setValue(event.option.value); + this.form.controls.account.setValue(event.option.value); } batchSelected(event: MatAutocompleteSelectedEvent): void { diff --git a/overlord/src/app/purchase/purchase-dialog.component.ts b/overlord/src/app/purchase/purchase-dialog.component.ts index 8634e2b1..542bf1e5 100644 --- a/overlord/src/app/purchase/purchase-dialog.component.ts +++ b/overlord/src/app/purchase/purchase-dialog.component.ts @@ -1,10 +1,10 @@ import { Component, Inject, OnInit } from '@angular/core'; -import { UntypedFormBuilder, UntypedFormControl, UntypedFormGroup } from '@angular/forms'; +import { FormControl, FormGroup } from '@angular/forms'; import { MatAutocompleteSelectedEvent } from '@angular/material/autocomplete'; import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; import { round } from 'mathjs'; import { Observable, of as observableOf } from 'rxjs'; -import { debounceTime, distinctUntilChanged, map, startWith, switchMap } from 'rxjs/operators'; +import { debounceTime, distinctUntilChanged, map, switchMap } from 'rxjs/operators'; import { Batch } from '../core/batch'; import { Inventory } from '../core/inventory'; @@ -20,26 +20,32 @@ import { MathService } from '../shared/math.service'; }) export class PurchaseDialogComponent implements OnInit { products: Observable; - form: UntypedFormGroup; + form: FormGroup<{ + product: FormControl; + quantity: FormControl; + price: FormControl; + tax: FormControl; + discount: FormControl; + }>; + product: ProductSku = new ProductSku(); constructor( public dialogRef: MatDialogRef, @Inject(MAT_DIALOG_DATA) public data: { inventory: Inventory }, - private fb: UntypedFormBuilder, private math: MathService, private productSer: ProductService, ) { - this.form = this.fb.group({ - product: '', - quantity: '', - price: '', - tax: '', - discount: '', + this.form = new FormGroup({ + product: new FormControl(null), + quantity: new FormControl('', { nonNullable: true }), + price: new FormControl('', { nonNullable: true }), + tax: new FormControl('', { nonNullable: true }), + discount: new FormControl('', { nonNullable: true }), }); // Listen to Product Autocomplete Change - this.products = (this.form.get('product') as UntypedFormControl).valueChanges.pipe( - startWith(null), + this.products = this.form.controls.product.valueChanges.pipe( + map((x) => (x instanceof ProductSku ? x.name : x)), map((x) => (x !== null && x.length >= 1 ? x : null)), debounceTime(150), distinctUntilChanged(), @@ -50,10 +56,10 @@ export class PurchaseDialogComponent implements OnInit { ngOnInit() { this.form.setValue({ product: this.data.inventory.batch?.sku, - quantity: this.data.inventory.quantity, - price: this.data.inventory.rate, - tax: this.data.inventory.tax, - discount: this.data.inventory.discount, + quantity: `${this.data.inventory.quantity}`, + price: `${this.data.inventory.rate}`, + tax: `${this.data.inventory.tax}`, + discount: `${this.data.inventory.discount}`, }); this.product = this.data.inventory.batch?.sku; } @@ -63,8 +69,22 @@ export class PurchaseDialogComponent implements OnInit { } productSelected(event: MatAutocompleteSelectedEvent): void { - this.product = event.option.value; - (this.form.get('price') as UntypedFormControl).setValue(this.product.costPrice); + const product: ProductSku = event.option.value; + this.product = product; + this.form.controls.price.setValue(`${product.costPrice}`); + if (product.isRateContracted) { + this.form.controls.price.disable(); + this.form.controls.tax.disable(); + this.form.controls.discount.disable(); + this.form.controls.tax.setValue('RC'); + this.form.controls.discount.setValue('RC'); + } else { + this.form.controls.price.enable(); + this.form.controls.tax.enable(); + this.form.controls.discount.enable(); + this.form.controls.tax.setValue(''); + this.form.controls.discount.setValue(''); + } } accept(): void { diff --git a/overlord/src/app/purchase/purchase.component.ts b/overlord/src/app/purchase/purchase.component.ts index 0ba573cc..b5996e97 100644 --- a/overlord/src/app/purchase/purchase.component.ts +++ b/overlord/src/app/purchase/purchase.component.ts @@ -1,5 +1,5 @@ import { AfterViewInit, Component, ElementRef, OnInit, OnDestroy, ViewChild } from '@angular/core'; -import { UntypedFormBuilder, UntypedFormControl, UntypedFormGroup } from '@angular/forms'; +import { FormControl, FormGroup } from '@angular/forms'; import { MatAutocompleteSelectedEvent } from '@angular/material/autocomplete'; import { MatDialog } from '@angular/material/dialog'; import { ActivatedRoute, Router } from '@angular/router'; @@ -7,7 +7,7 @@ import { Hotkey, HotkeysService } from 'angular2-hotkeys'; import { round } from 'mathjs'; import * as moment from 'moment'; import { BehaviorSubject, Observable, of as observableOf } from 'rxjs'; -import { debounceTime, distinctUntilChanged, map, startWith, switchMap } from 'rxjs/operators'; +import { debounceTime, distinctUntilChanged, map, switchMap } from 'rxjs/operators'; import { AuthService } from '../auth/auth.service'; import { Account } from '../core/account'; @@ -42,7 +42,20 @@ export class PurchaseComponent implements OnInit, AfterViewInit, OnDestroy { @ViewChild('dateElement', { static: true }) dateElement?: ElementRef; public inventoryObservable = new BehaviorSubject([]); dataSource: PurchaseDataSource = new PurchaseDataSource(this.inventoryObservable); - form: UntypedFormGroup; + form: FormGroup<{ + date: FormControl; + account: FormControl; + amount: FormControl; + addRow: FormGroup<{ + product: FormControl; + quantity: FormControl; + price: FormControl; + tax: FormControl; + discount: FormControl; + }>; + narration: FormControl; + }>; + voucher: Voucher = new Voucher(); product: ProductSku | null = null; accBal: AccountBalance | null = null; @@ -55,7 +68,6 @@ export class PurchaseComponent implements OnInit, AfterViewInit, OnDestroy { constructor( private route: ActivatedRoute, private router: Router, - private fb: UntypedFormBuilder, private dialog: MatDialog, private hotkeys: HotkeysService, private toaster: ToasterService, @@ -66,33 +78,30 @@ export class PurchaseComponent implements OnInit, AfterViewInit, OnDestroy { private productSer: ProductService, private accountSer: AccountService, ) { - this.form = this.fb.group({ - date: '', - account: '', - amount: { value: '', disabled: true }, - addRow: this.fb.group({ - product: '', - quantity: '', - price: '', - tax: '', - discount: '', + this.form = new FormGroup({ + date: new FormControl(new Date(), { nonNullable: true }), + account: new FormControl(null), + amount: new FormControl({ value: 0, disabled: true }, { nonNullable: true }), + addRow: new FormGroup({ + product: new FormControl(''), + quantity: new FormControl('', { nonNullable: true }), + price: new FormControl('', { nonNullable: true }), + tax: new FormControl('', { nonNullable: true }), + discount: new FormControl('', { nonNullable: true }), }), - narration: '', + narration: new FormControl('', { nonNullable: true }), }); this.accBal = null; // Listen to Account Autocomplete Change - this.accounts = (this.form.get('account') as UntypedFormControl).valueChanges.pipe( - startWith(null), + this.accounts = this.form.controls.account.valueChanges.pipe( + map((x) => (x instanceof Account ? x.name : x)), map((x) => (x !== null && x.length >= 1 ? x : null)), debounceTime(150), distinctUntilChanged(), switchMap((x) => (x === null ? observableOf([]) : this.accountSer.autocomplete(x))), ); // Listen to Product Autocomplete Change - this.products = ( - (this.form.get('addRow') as UntypedFormControl).get('product') as UntypedFormControl - ).valueChanges.pipe( - startWith(null), + this.products = this.form.controls.addRow.controls.product.valueChanges.pipe( map((x) => (x !== null && x.length >= 1 ? x : null)), debounceTime(150), distinctUntilChanged(), @@ -103,7 +112,8 @@ export class PurchaseComponent implements OnInit, AfterViewInit, OnDestroy { x, true, moment(this.form.value.date).format('DD-MMM-YYYY'), - this.form.value.account.id, + // this.form.value.account?.id, + '', ), ), ); @@ -167,7 +177,7 @@ export class PurchaseComponent implements OnInit, AfterViewInit, OnDestroy { this.voucher = voucher; this.form.setValue({ date: moment(this.voucher.date, 'DD-MMM-YYYY').toDate(), - account: this.voucher.vendor, + account: this.voucher.vendor || null, amount: Math.abs(this.voucher.inventories.map((x) => x.amount).reduce((p, c) => p + c, 0)), addRow: { product: '', @@ -191,7 +201,7 @@ export class PurchaseComponent implements OnInit, AfterViewInit, OnDestroy { } addRow() { - const formValue = (this.form.get('addRow') as UntypedFormControl).value; + const formValue = this.form.value.addRow!; const quantity = this.math.parseAmount(formValue.quantity, 2); if (this.product === null || quantity <= 0) { return; @@ -228,19 +238,11 @@ export class PurchaseComponent implements OnInit, AfterViewInit, OnDestroy { } resetAddRow() { - (this.form.get('addRow') as UntypedFormControl).reset({ - product: null, - quantity: '', - price: '', - tax: '', - discount: '', - }); + this.form.controls.addRow.reset(); this.product = null; - ((this.form.get('addRow') as UntypedFormControl).get('price') as UntypedFormControl).enable(); - ((this.form.get('addRow') as UntypedFormControl).get('tax') as UntypedFormControl).enable(); - ( - (this.form.get('addRow') as UntypedFormControl).get('discount') as UntypedFormControl - ).enable(); + this.form.controls.addRow.controls.price.enable(); + this.form.controls.addRow.controls.tax.enable(); + this.form.controls.addRow.controls.discount.enable(); setTimeout(() => { if (this.productElement) { this.productElement.nativeElement.focus(); @@ -250,7 +252,7 @@ export class PurchaseComponent implements OnInit, AfterViewInit, OnDestroy { updateView() { this.inventoryObservable.next(this.voucher.inventories); - (this.form.get('amount') as UntypedFormControl).setValue( + this.form.controls.amount.setValue( round(Math.abs(this.voucher.inventories.map((x) => x.amount).reduce((p, c) => p + c, 0)), 2), ); } @@ -327,8 +329,10 @@ export class PurchaseComponent implements OnInit, AfterViewInit, OnDestroy { getVoucher(): Voucher { const formModel = this.form.value; this.voucher.date = moment(formModel.date).format('DD-MMM-YYYY'); - this.voucher.vendor = formModel.account; - this.voucher.narration = formModel.narration; + if (formModel.account instanceof Account) { + this.voucher.vendor = formModel.account; + } + this.voucher.narration = formModel.narration!; return this.voucher; } @@ -362,26 +366,26 @@ export class PurchaseComponent implements OnInit, AfterViewInit, OnDestroy { } accountSelected(event: MatAutocompleteSelectedEvent): void { - (this.form.get('account') as UntypedFormControl).setValue(event.option.value); + this.form.controls.account.setValue(event.option.value); } productSelected(event: MatAutocompleteSelectedEvent): void { const product: ProductSku = event.option.value; - const addRowForm: UntypedFormControl = this.form.get('addRow') as UntypedFormControl; + const addRowForm = this.form.controls.addRow; this.product = product; - (addRowForm.get('price') as UntypedFormControl).setValue(product.costPrice); + addRowForm.controls.price.setValue(`${product.costPrice}`); if (product.isRateContracted) { - (addRowForm.get('price') as UntypedFormControl).disable(); - (addRowForm.get('tax') as UntypedFormControl).disable(); - (addRowForm.get('discount') as UntypedFormControl).disable(); - (addRowForm.get('tax') as UntypedFormControl).setValue('RC'); - (addRowForm.get('discount') as UntypedFormControl).setValue('RC'); + addRowForm.controls.price.disable(); + addRowForm.controls.tax.disable(); + addRowForm.controls.discount.disable(); + addRowForm.controls.tax.setValue('RC'); + addRowForm.controls.discount.setValue('RC'); } else { - (addRowForm.get('price') as UntypedFormControl).enable(); - (addRowForm.get('tax') as UntypedFormControl).enable(); - (addRowForm.get('discount') as UntypedFormControl).enable(); - (addRowForm.get('tax') as UntypedFormControl).setValue(''); - (addRowForm.get('discount') as UntypedFormControl).setValue(''); + addRowForm.controls.price.enable(); + addRowForm.controls.tax.enable(); + addRowForm.controls.discount.enable(); + addRowForm.controls.tax.setValue(''); + addRowForm.controls.discount.setValue(''); } } diff --git a/overlord/src/app/purchases/purchases.component.ts b/overlord/src/app/purchases/purchases.component.ts index 8d8dc8c6..f565d231 100644 --- a/overlord/src/app/purchases/purchases.component.ts +++ b/overlord/src/app/purchases/purchases.component.ts @@ -1,5 +1,5 @@ import { Component, OnInit, ViewChild } from '@angular/core'; -import { UntypedFormBuilder, UntypedFormGroup } from '@angular/forms'; +import { FormControl, FormGroup } from '@angular/forms'; import { MatPaginator } from '@angular/material/paginator'; import { MatSort } from '@angular/material/sort'; import { ActivatedRoute, Router } from '@angular/router'; @@ -19,19 +19,19 @@ export class PurchasesComponent implements OnInit { @ViewChild(MatSort, { static: true }) sort?: MatSort; info: Purchases = new Purchases(); dataSource: PurchasesDataSource = new PurchasesDataSource(this.info.body); - form: UntypedFormGroup; + form: FormGroup<{ + startDate: FormControl; + finishDate: FormControl; + }>; + selectedRowId = ''; /** Columns displayed in the table. Columns IDs can be added, removed, or reordered. */ displayedColumns = ['product', 'quantity', 'rate', 'amount']; - constructor( - private route: ActivatedRoute, - private router: Router, - private fb: UntypedFormBuilder, - ) { - this.form = this.fb.group({ - startDate: '', - finishDate: '', + constructor(private route: ActivatedRoute, private router: Router) { + this.form = new FormGroup({ + startDate: new FormControl(new Date(), { nonNullable: true }), + finishDate: new FormControl(new Date(), { nonNullable: true }), }); } diff --git a/overlord/src/app/rate-contract/rate-contract-detail/rate-contract-detail.component.ts b/overlord/src/app/rate-contract/rate-contract-detail/rate-contract-detail.component.ts index 94e6d467..00f742bc 100644 --- a/overlord/src/app/rate-contract/rate-contract-detail/rate-contract-detail.component.ts +++ b/overlord/src/app/rate-contract/rate-contract-detail/rate-contract-detail.component.ts @@ -1,11 +1,11 @@ import { AfterViewInit, Component, ElementRef, OnInit, ViewChild } from '@angular/core'; -import { UntypedFormBuilder, UntypedFormControl, UntypedFormGroup } from '@angular/forms'; +import { FormControl, FormGroup } from '@angular/forms'; import { MatAutocompleteSelectedEvent } from '@angular/material/autocomplete'; import { MatDialog } from '@angular/material/dialog'; import { ActivatedRoute, Router } from '@angular/router'; import * as moment from 'moment'; import { BehaviorSubject, Observable, of as observableOf } from 'rxjs'; -import { debounceTime, distinctUntilChanged, map, startWith, switchMap } from 'rxjs/operators'; +import { debounceTime, distinctUntilChanged, map, switchMap } from 'rxjs/operators'; import { Account } from '../../core/account'; import { AccountService } from '../../core/account.service'; @@ -31,7 +31,18 @@ export class RateContractDetailComponent implements OnInit, AfterViewInit { @ViewChild('productElement', { static: true }) productElement?: ElementRef; public itemsObservable = new BehaviorSubject([]); dataSource: RateContractDetailDatasource = new RateContractDetailDatasource(this.itemsObservable); - form: UntypedFormGroup; + form: FormGroup<{ + date: FormControl; + account: FormControl; + validFrom: FormControl; + validTill: FormControl; + addRow: FormGroup<{ + product: FormControl; + price: FormControl; + }>; + narration: FormControl; + }>; + item: RateContract = new RateContract(); product: Product | null = null; @@ -44,7 +55,6 @@ export class RateContractDetailComponent implements OnInit, AfterViewInit { constructor( private route: ActivatedRoute, private router: Router, - private fb: UntypedFormBuilder, private toaster: ToasterService, private dialog: MatDialog, private math: MathService, @@ -52,29 +62,27 @@ export class RateContractDetailComponent implements OnInit, AfterViewInit { private productSer: ProductService, private accountSer: AccountService, ) { - this.form = this.fb.group({ - date: '', - account: '', - validFrom: '', - validTill: '', - addRow: this.fb.group({ - product: '', - price: '', + this.form = new FormGroup({ + date: new FormControl(new Date(), { nonNullable: true }), + account: new FormControl(null), + validFrom: new FormControl(new Date(), { nonNullable: true }), + validTill: new FormControl(new Date(), { nonNullable: true }), + addRow: new FormGroup({ + product: new FormControl(''), + price: new FormControl('', { nonNullable: true }), }), - narration: '', + narration: new FormControl('', { nonNullable: true }), }); - this.accounts = (this.form.get('account') as UntypedFormControl).valueChanges.pipe( - startWith(null), + this.accounts = this.form.controls.account.valueChanges.pipe( + map((x) => (x instanceof Account ? x.name : x)), + map((x) => (x !== null && x.length >= 1 ? x : null)), map((x) => (x !== null && x.length >= 1 ? x : null)), debounceTime(150), distinctUntilChanged(), switchMap((x) => (x === null ? observableOf([]) : this.accountSer.autocomplete(x))), ); // Listen to Product Autocomplete Change - this.products = ( - (this.form.get('addRow') as UntypedFormControl).get('product') as UntypedFormControl - ).valueChanges.pipe( - startWith(null), + this.products = this.form.controls.addRow.controls.product.valueChanges.pipe( map((x) => (x !== null && x.length >= 1 ? x : null)), debounceTime(150), distinctUntilChanged(), @@ -115,7 +123,7 @@ export class RateContractDetailComponent implements OnInit, AfterViewInit { } addRow() { - const formValue = (this.form.get('addRow') as UntypedFormControl).value; + const formValue = this.form.value.addRow!; const price = this.math.parseAmount(formValue.price, 2); if (this.product === null || price <= 0) { return; @@ -136,10 +144,7 @@ export class RateContractDetailComponent implements OnInit, AfterViewInit { } resetAddRow() { - (this.form.get('addRow') as UntypedFormControl).reset({ - product: null, - price: '', - }); + this.form.controls.addRow.reset(); this.product = null; setTimeout(() => { if (this.productElement) { @@ -157,7 +162,7 @@ export class RateContractDetailComponent implements OnInit, AfterViewInit { } accountSelected(event: MatAutocompleteSelectedEvent): void { - (this.form.get('account') as UntypedFormControl).setValue(event.option.value); + this.form.controls.account.setValue(event.option.value); } productSelected(event: MatAutocompleteSelectedEvent): void { @@ -211,8 +216,10 @@ export class RateContractDetailComponent implements OnInit, AfterViewInit { this.item.date = moment(formModel.date).format('DD-MMM-YYYY'); this.item.validFrom = moment(formModel.validFrom).format('DD-MMM-YYYY'); this.item.validTill = moment(formModel.validTill).format('DD-MMM-YYYY'); - this.item.vendor = formModel.account; - this.item.narration = formModel.narration; + if (formModel.account instanceof Account) { + this.item.vendor = formModel.account; + } + this.item.narration = formModel.narration!; return this.item; } } diff --git a/overlord/src/app/rate-contract/rate-contract.module.ts b/overlord/src/app/rate-contract/rate-contract.module.ts index cc5e2468..1b4e8cd8 100644 --- a/overlord/src/app/rate-contract/rate-contract.module.ts +++ b/overlord/src/app/rate-contract/rate-contract.module.ts @@ -8,12 +8,7 @@ import { MatAutocompleteModule } from '@angular/material/autocomplete'; import { MatButtonModule } from '@angular/material/button'; import { MatCardModule } from '@angular/material/card'; import { MatCheckboxModule } from '@angular/material/checkbox'; -import { - DateAdapter, - MAT_DATE_FORMATS, - MAT_DATE_LOCALE, - MatNativeDateModule, -} from '@angular/material/core'; +import { DateAdapter, MAT_DATE_FORMATS, MAT_DATE_LOCALE } from '@angular/material/core'; import { MatDatepickerModule } from '@angular/material/datepicker'; import { MatDividerModule } from '@angular/material/divider'; import { MatIconModule } from '@angular/material/icon'; diff --git a/overlord/src/app/raw-material-cost/raw-material-cost.component.ts b/overlord/src/app/raw-material-cost/raw-material-cost.component.ts index aed94593..decd3c8a 100644 --- a/overlord/src/app/raw-material-cost/raw-material-cost.component.ts +++ b/overlord/src/app/raw-material-cost/raw-material-cost.component.ts @@ -1,5 +1,5 @@ import { Component, OnInit, ViewChild } from '@angular/core'; -import { UntypedFormBuilder, UntypedFormGroup } from '@angular/forms'; +import { FormControl, FormGroup } from '@angular/forms'; import { MatPaginator } from '@angular/material/paginator'; import { MatSort } from '@angular/material/sort'; import { ActivatedRoute, Router } from '@angular/router'; @@ -20,7 +20,11 @@ export class RawMaterialCostComponent implements OnInit { @ViewChild(MatSort, { static: true }) sort?: MatSort; info: RawMaterialCost = new RawMaterialCost(); dataSource: RawMaterialCostDataSource = new RawMaterialCostDataSource(this.info.body); - form: UntypedFormGroup; + form: FormGroup<{ + startDate: FormControl; + finishDate: FormControl; + }>; + debitQuantity = 0; debitAmount = 0; creditQuantity = 0; @@ -32,15 +36,10 @@ export class RawMaterialCostComponent implements OnInit { columnsNoId = ['name', 'issue', 'sale', 'rmc']; columnsId = ['name', 'group', 'quantity', 'net', 'gross']; - constructor( - private route: ActivatedRoute, - private router: Router, - private fb: UntypedFormBuilder, - private toCsv: ToCsvService, - ) { - this.form = this.fb.group({ - startDate: '', - finishDate: '', + constructor(private route: ActivatedRoute, private router: Router, private toCsv: ToCsvService) { + this.form = new FormGroup({ + startDate: new FormControl(new Date(), { nonNullable: true }), + finishDate: new FormControl(new Date(), { nonNullable: true }), }); } diff --git a/overlord/src/app/receipt/receipt-dialog.component.ts b/overlord/src/app/receipt/receipt-dialog.component.ts index 8ea25f80..2423fc43 100644 --- a/overlord/src/app/receipt/receipt-dialog.component.ts +++ b/overlord/src/app/receipt/receipt-dialog.component.ts @@ -1,9 +1,9 @@ import { Component, Inject, OnInit } from '@angular/core'; -import { UntypedFormBuilder, UntypedFormControl, UntypedFormGroup } from '@angular/forms'; +import { FormControl, FormGroup } from '@angular/forms'; import { MatAutocompleteSelectedEvent } from '@angular/material/autocomplete'; import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; import { Observable, of as observableOf } from 'rxjs'; -import { debounceTime, distinctUntilChanged, map, startWith, switchMap } from 'rxjs/operators'; +import { debounceTime, distinctUntilChanged, map, switchMap } from 'rxjs/operators'; import { Account } from '../core/account'; import { AccountBalance } from '../core/account-balance'; @@ -18,25 +18,27 @@ import { MathService } from '../shared/math.service'; }) export class ReceiptDialogComponent implements OnInit { accounts: Observable; - form: UntypedFormGroup; + form: FormGroup<{ + account: FormControl; + amount: FormControl; + }>; + account: Account = new Account(); accBal: AccountBalance | null = null; constructor( public dialogRef: MatDialogRef, @Inject(MAT_DIALOG_DATA) public data: { journal: Journal; date: string }, - private fb: UntypedFormBuilder, private math: MathService, private accountSer: AccountService, ) { - this.form = this.fb.group({ - account: '', - amount: '', + this.form = new FormGroup({ + account: new FormControl(''), + amount: new FormControl('', { nonNullable: true }), }); this.accBal = null; // Setup Account Autocomplete - this.accounts = (this.form.get('account') as UntypedFormControl).valueChanges.pipe( - startWith(null), + this.accounts = this.form.controls.account.valueChanges.pipe( map((x) => (x !== null && x.length >= 1 ? x : null)), debounceTime(150), distinctUntilChanged(), @@ -46,8 +48,8 @@ export class ReceiptDialogComponent implements OnInit { ngOnInit() { this.form.setValue({ - account: this.data.journal.account, - amount: this.data.journal.amount, + account: this.data.journal.account.name, + amount: `${this.data.journal.amount}`, }); this.account = this.data.journal.account; } diff --git a/overlord/src/app/receipt/receipt.component.ts b/overlord/src/app/receipt/receipt.component.ts index 261e7101..464f9666 100644 --- a/overlord/src/app/receipt/receipt.component.ts +++ b/overlord/src/app/receipt/receipt.component.ts @@ -1,5 +1,5 @@ import { AfterViewInit, Component, ElementRef, OnInit, OnDestroy, ViewChild } from '@angular/core'; -import { UntypedFormBuilder, UntypedFormControl, UntypedFormGroup } from '@angular/forms'; +import { FormControl, FormGroup } from '@angular/forms'; import { MatAutocompleteSelectedEvent } from '@angular/material/autocomplete'; import { MatDialog } from '@angular/material/dialog'; import { ActivatedRoute, Router } from '@angular/router'; @@ -7,7 +7,7 @@ import { Hotkey, HotkeysService } from 'angular2-hotkeys'; import { round } from 'mathjs'; import * as moment from 'moment'; import { BehaviorSubject, Observable, of as observableOf } from 'rxjs'; -import { debounceTime, distinctUntilChanged, map, startWith, switchMap } from 'rxjs/operators'; +import { debounceTime, distinctUntilChanged, map, switchMap } from 'rxjs/operators'; import { AuthService } from '../auth/auth.service'; import { Account } from '../core/account'; @@ -37,7 +37,17 @@ export class ReceiptComponent implements OnInit, AfterViewInit, OnDestroy { @ViewChild('dateElement', { static: true }) dateElement?: ElementRef; public journalObservable = new BehaviorSubject([]); dataSource: ReceiptDataSource = new ReceiptDataSource(this.journalObservable); - form: UntypedFormGroup; + form: FormGroup<{ + date: FormControl; + receiptAccount: FormControl; + receiptAmount: FormControl; + addRow: FormGroup<{ + account: FormControl; + amount: FormControl; + }>; + narration: FormControl; + }>; + receiptAccounts: Account[] = []; receiptJournal: Journal = new Journal(); voucher: Voucher = new Voucher(); @@ -51,7 +61,6 @@ export class ReceiptComponent implements OnInit, AfterViewInit, OnDestroy { constructor( private route: ActivatedRoute, private router: Router, - private fb: UntypedFormBuilder, private dialog: MatDialog, private hotkeys: HotkeysService, private toaster: ToasterService, @@ -61,29 +70,26 @@ export class ReceiptComponent implements OnInit, AfterViewInit, OnDestroy { private ser: VoucherService, private accountSer: AccountService, ) { - this.form = this.fb.group({ - date: '', - receiptAccount: '', - receiptAmount: { value: '', disabled: true }, - addRow: this.fb.group({ - account: '', - amount: '', + this.form = new FormGroup({ + date: new FormControl(new Date(), { nonNullable: true }), + receiptAccount: new FormControl('', { nonNullable: true }), + receiptAmount: new FormControl({ value: 0, disabled: true }, { nonNullable: true }), + addRow: new FormGroup({ + account: new FormControl(''), + amount: new FormControl('', { nonNullable: true }), }), - narration: '', + narration: new FormControl('', { nonNullable: true }), }); this.accBal = null; // Listen to Account Autocomplete Change - this.accounts = ( - (this.form.get('addRow') as UntypedFormControl).get('account') as UntypedFormControl - ).valueChanges.pipe( - startWith(null), + this.accounts = this.form.controls.addRow.controls.account.valueChanges.pipe( map((x) => (x !== null && x.length >= 1 ? x : null)), debounceTime(150), distinctUntilChanged(), switchMap((x) => (x === null ? observableOf([]) : this.accountSer.autocomplete(x))), ); // Listen to Receipt Account Change - (this.form.get('receiptAccount') as UntypedFormControl).valueChanges.subscribe((x) => + this.form.controls.receiptAccount.valueChanges.subscribe((x) => this.router.navigate([], { relativeTo: this.route, queryParams: { a: x }, @@ -152,11 +158,11 @@ export class ReceiptComponent implements OnInit, AfterViewInit, OnDestroy { [this.receiptJournal] = this.voucher.journals.filter((x) => x.debit === 1); this.form.setValue({ date: moment(this.voucher.date, 'DD-MMM-YYYY').toDate(), - receiptAccount: this.receiptJournal.account.id, + receiptAccount: this.receiptJournal.account.id!, receiptAmount: this.receiptJournal.amount, addRow: { account: '', - amount: 0, + amount: '', }, narration: this.voucher.narration, }); @@ -173,10 +179,7 @@ export class ReceiptComponent implements OnInit, AfterViewInit, OnDestroy { } addRow() { - const amount = this.math.parseAmount( - (this.form.get('addRow') as UntypedFormControl).value.amount, - 2, - ); + const amount = this.math.parseAmount(this.form.value.addRow?.amount!, 2); const debit = -1; if (this.account === null || amount <= 0) { return; @@ -205,10 +208,7 @@ export class ReceiptComponent implements OnInit, AfterViewInit, OnDestroy { } resetAddRow() { - (this.form.get('addRow') as UntypedFormControl).reset({ - account: null, - amount: null, - }); + this.form.controls.addRow.reset({ account: null, amount: '' }); this.account = null; this.accBal = null; setTimeout(() => { @@ -225,7 +225,7 @@ export class ReceiptComponent implements OnInit, AfterViewInit, OnDestroy { Math.abs(journals.map((x) => x.amount).reduce((p, c) => p + c, 0)), 2, ); - (this.form.get('receiptAmount') as UntypedFormControl).setValue(this.receiptJournal.amount); + this.form.controls.receiptAmount.setValue(this.receiptJournal.amount); } editRow(row: Journal) { @@ -233,7 +233,7 @@ export class ReceiptComponent implements OnInit, AfterViewInit, OnDestroy { width: '750px', data: { journal: { ...row }, - date: moment((this.form.get('date') as UntypedFormControl).value).format('DD-MMM-YYYY'), + date: moment(this.form.value.date).format('DD-MMM-YYYY'), }, }); @@ -304,7 +304,7 @@ export class ReceiptComponent implements OnInit, AfterViewInit, OnDestroy { const formModel = this.form.value; this.voucher.date = moment(formModel.date).format('DD-MMM-YYYY'); this.receiptJournal.account.id = formModel.receiptAccount; - this.voucher.narration = formModel.narration; + this.voucher.narration = formModel.narration!; return this.voucher; } @@ -340,7 +340,7 @@ export class ReceiptComponent implements OnInit, AfterViewInit, OnDestroy { accountSelected(event: MatAutocompleteSelectedEvent): void { const account = event.option.value; this.account = account; - const date = moment((this.form.get('date') as UntypedFormControl).value).format('DD-MMM-YYYY'); + const date = moment(this.form.value.date).format('DD-MMM-YYYY'); this.accountSer.balance(account.id as string, date).subscribe((v) => { this.accBal = v; }); diff --git a/overlord/src/app/recipe/recipe-detail/recipe-detail.component.ts b/overlord/src/app/recipe/recipe-detail/recipe-detail.component.ts index 0432edc9..3de0e27b 100644 --- a/overlord/src/app/recipe/recipe-detail/recipe-detail.component.ts +++ b/overlord/src/app/recipe/recipe-detail/recipe-detail.component.ts @@ -1,12 +1,12 @@ import { AfterViewInit, Component, ElementRef, OnInit, ViewChild } from '@angular/core'; -import { UntypedFormBuilder, UntypedFormControl, UntypedFormGroup } from '@angular/forms'; +import { FormControl, FormGroup } from '@angular/forms'; import { MatAutocompleteSelectedEvent } from '@angular/material/autocomplete'; import { MatDialog } from '@angular/material/dialog'; import { ActivatedRoute, Router } from '@angular/router'; import { round } from 'mathjs'; import * as moment from 'moment'; import { BehaviorSubject, Observable, of as observableOf } from 'rxjs'; -import { debounceTime, distinctUntilChanged, map, startWith, switchMap } from 'rxjs/operators'; +import { debounceTime, distinctUntilChanged, map, switchMap } from 'rxjs/operators'; import { Product } from '../../core/product'; import { ProductSku } from '../../core/product-sku'; @@ -30,7 +30,21 @@ export class RecipeDetailComponent implements OnInit, AfterViewInit { @ViewChild('ingredientElement', { static: true }) ingredientElement?: ElementRef; public itemsObservable = new BehaviorSubject([]); dataSource: RecipeDetailDatasource = new RecipeDetailDatasource(this.itemsObservable); - form: UntypedFormGroup; + form: FormGroup<{ + validFrom: FormControl; + validTill: FormControl; + recipeYield: FormControl; + costPrice: FormControl; + salePrice: FormControl; + costPercentage: FormControl; + product: FormControl; + addRow: FormGroup<{ + ingredient: FormControl; + quantity: FormControl; + rate: FormControl; + }>; + }>; + product: ProductSku | null; products: Observable; ingredient: ProductSku | null; @@ -42,7 +56,6 @@ export class RecipeDetailComponent implements OnInit, AfterViewInit { constructor( private route: ActivatedRoute, private router: Router, - private fb: UntypedFormBuilder, private dialog: MatDialog, private toaster: ToasterService, private math: MathService, @@ -51,33 +64,30 @@ export class RecipeDetailComponent implements OnInit, AfterViewInit { ) { this.product = null; this.ingredient = null; - this.form = this.fb.group({ - validFrom: '', - validTill: '', - recipeYield: '', - salePrice: '', - costPrice: '', - costPercentage: '', - product: new Product(), - addRow: this.fb.group({ - ingredient: '', - quantity: '', - rate: '', + this.form = new FormGroup({ + validFrom: new FormControl(new Date(), { nonNullable: true }), + validTill: new FormControl(new Date(), { nonNullable: true }), + recipeYield: new FormControl(null), + costPrice: new FormControl(null), + salePrice: new FormControl(null), + costPercentage: new FormControl(null), + product: new FormControl(new ProductSku()), + addRow: new FormGroup({ + ingredient: new FormControl(''), + quantity: new FormControl('', { nonNullable: true }), + rate: new FormControl('', { nonNullable: true }), }), }); // Setup Product Autocomplete - this.products = (this.form.get('product') as UntypedFormControl).valueChanges.pipe( - startWith(null), + this.products = this.form.controls.product.valueChanges.pipe( + map((x) => (x instanceof ProductSku ? x.name : x)), map((x) => (x !== null && x.length >= 1 ? x : null)), debounceTime(150), distinctUntilChanged(), switchMap((x) => (x === null ? observableOf([]) : this.productSer.autocompleteSku(x, false))), ); // Setup Product Autocomplete - this.ingredients = ( - (this.form.get('addRow') as UntypedFormControl).get('ingredient') as UntypedFormControl - ).valueChanges.pipe( - startWith(null), + this.ingredients = this.form.controls.addRow.controls.ingredient.valueChanges.pipe( map((x) => (x !== null && x.length >= 1 ? x : null)), debounceTime(150), distinctUntilChanged(), @@ -100,10 +110,10 @@ export class RecipeDetailComponent implements OnInit, AfterViewInit { this.form.setValue({ validFrom: moment(item.validFrom, 'DD-MMM-YYYY').toDate(), validTill: moment(item.validTill, 'DD-MMM-YYYY').toDate(), - recipeYield: '' + item.recipeYield, - salePrice: '' + item.salePrice, - costPrice: '' + item.costPrice, - costPercentage: '', + recipeYield: `${item.recipeYield}`, + salePrice: `${item.salePrice}`, + costPrice: `${item.costPrice}`, + costPercentage: null, product: item.sku, addRow: { ingredient: null, @@ -133,8 +143,8 @@ export class RecipeDetailComponent implements OnInit, AfterViewInit { productSelected(event: MatAutocompleteSelectedEvent): void { const product: ProductSku = event.option.value; this.item.sku = product; - (this.form.get('product') as UntypedFormControl).setValue(product); - (this.form.get('salePrice') as UntypedFormControl).setValue('' + (product.salePrice ?? 0)); + this.form.controls.product.setValue(product); + this.form.controls.salePrice.setValue('' + (product.salePrice ?? 0)); } ingredientSelected(event: MatAutocompleteSelectedEvent): void { @@ -143,15 +153,11 @@ export class RecipeDetailComponent implements OnInit, AfterViewInit { const item = this.getItem(); this.ser .getIngredientDetails(ingredient.id, item.validFrom, item.validTill) - .subscribe((x) => - ( - (this.form.get('addRow') as UntypedFormControl).get('rate') as UntypedFormControl - ).setValue('' + x.costPrice), - ); + .subscribe((x) => this.form.controls.addRow.controls.rate.setValue('' + x.costPrice)); } addRow() { - const formValue = (this.form.get('addRow') as UntypedFormControl).value; + const formValue = this.form.value.addRow!; const quantity = this.math.parseAmount(formValue.quantity, 2); const rate = this.math.parseAmount(formValue.rate, 2); if (this.ingredient === null || quantity <= 0 || rate <= 0) { @@ -176,11 +182,7 @@ export class RecipeDetailComponent implements OnInit, AfterViewInit { } resetAddRow() { - (this.form.get('addRow') as UntypedFormControl).reset({ - ingredient: null, - quantity: '', - rate: '', - }); + this.form.controls.addRow.reset(); this.ingredient = null; setTimeout(() => { if (this.ingredientElement) { @@ -195,13 +197,13 @@ export class RecipeDetailComponent implements OnInit, AfterViewInit { this.item.items.map((x) => x.quantity * x.price).reduce((p, c) => p + c, 0), 2, ); - (this.form.get('costPrice') as UntypedFormControl).setValue(costPrice); - const salePrice = this.math.parseAmount(this.form.value.salePrice, 2); + this.form.controls.costPrice.setValue(`${costPrice}`); + const salePrice = this.math.parseAmount(this.form.value.salePrice!, 2); if (salePrice < 0) { return; } const costPercentage = round((100 * costPrice) / salePrice, 2); - (this.form.get('costPercentage') as UntypedFormControl).setValue(costPercentage); + this.form.controls.costPercentage.setValue(costPercentage); } deleteRow(row: RecipeItem) { @@ -250,9 +252,9 @@ export class RecipeDetailComponent implements OnInit, AfterViewInit { const formModel = this.form.value; this.item.validFrom = moment(formModel.validFrom).format('DD-MMM-YYYY'); this.item.validTill = moment(formModel.validTill).format('DD-MMM-YYYY'); - this.item.recipeYield = this.math.parseAmount(formModel.recipeYield, 2); - this.item.salePrice = this.math.parseAmount(formModel.salePrice, 2); - this.item.costPrice = this.math.parseAmount(formModel.costPrice, 2); + this.item.recipeYield = this.math.parseAmount(formModel.recipeYield!, 2); + this.item.salePrice = this.math.parseAmount(formModel.salePrice!, 2); + this.item.costPrice = this.math.parseAmount(formModel.costPrice!, 2); return this.item; } } diff --git a/overlord/src/app/recipe/recipe-list/recipe-list.component.ts b/overlord/src/app/recipe/recipe-list/recipe-list.component.ts index 28da3494..3c44a5ca 100644 --- a/overlord/src/app/recipe/recipe-list/recipe-list.component.ts +++ b/overlord/src/app/recipe/recipe-list/recipe-list.component.ts @@ -1,5 +1,5 @@ import { Component, OnInit, ViewChild } from '@angular/core'; -import { UntypedFormBuilder, UntypedFormGroup } from '@angular/forms'; +import { FormControl, FormGroup } from '@angular/forms'; import { MatPaginator } from '@angular/material/paginator'; import { MatSort } from '@angular/material/sort'; import { ActivatedRoute } from '@angular/router'; @@ -19,7 +19,12 @@ import { RecipeListDatasource } from './recipe-list-datasource'; export class RecipeListComponent implements OnInit { @ViewChild(MatPaginator, { static: true }) paginator?: MatPaginator; @ViewChild(MatSort, { static: true }) sort?: MatSort; - form: UntypedFormGroup; + form: FormGroup<{ + validFrom: FormControl; + validTill: FormControl; + productGroup: FormControl; + }>; + productGroups: ProductGroup[] = []; validFromFilter: BehaviorSubject = new BehaviorSubject(null); validTillFilter: BehaviorSubject = new BehaviorSubject(null); @@ -36,11 +41,11 @@ export class RecipeListComponent implements OnInit { /** Columns displayed in the table. Columns IDs can be added, removed, or reordered. */ displayedColumns = ['name', 'validity', 'salePrice', 'costPrice', 'costPercentage']; - constructor(private route: ActivatedRoute, private fb: UntypedFormBuilder) { - this.form = this.fb.group({ - validFrom: '', - validTill: '', - productGroup: '', + constructor(private route: ActivatedRoute) { + this.form = new FormGroup({ + validFrom: new FormControl(new Date(), { nonNullable: true }), + validTill: new FormControl(new Date(), { nonNullable: true }), + productGroup: new FormControl(null), }); } @@ -72,8 +77,8 @@ export class RecipeListComponent implements OnInit { }); this.productGroups = data.productGroups; this.form.setValue({ - validFrom: vf === null ? '' : moment(vf, 'DD-MMM-YYYY').toDate(), - validTill: vt === null ? '' : moment(vt, 'DD-MMM-YYYY').toDate(), + validFrom: vf === null ? new Date() : moment(vf, 'DD-MMM-YYYY').toDate(), + validTill: vt === null ? new Date() : moment(vt, 'DD-MMM-YYYY').toDate(), productGroup: '', }); this.data.next(data.list); diff --git a/overlord/src/app/role/role-detail/role-detail.component.ts b/overlord/src/app/role/role-detail/role-detail.component.ts index 696d6513..8c8f0fb6 100644 --- a/overlord/src/app/role/role-detail/role-detail.component.ts +++ b/overlord/src/app/role/role-detail/role-detail.component.ts @@ -1,10 +1,5 @@ import { AfterViewInit, Component, ElementRef, OnInit, ViewChild } from '@angular/core'; -import { - UntypedFormArray, - UntypedFormBuilder, - UntypedFormControl, - UntypedFormGroup, -} from '@angular/forms'; +import { FormArray, FormControl, FormGroup } from '@angular/forms'; import { MatDialog } from '@angular/material/dialog'; import { ActivatedRoute, Router } from '@angular/router'; @@ -20,20 +15,27 @@ import { RoleService } from '../role.service'; }) export class RoleDetailComponent implements OnInit, AfterViewInit { @ViewChild('nameElement', { static: true }) nameElement?: ElementRef; - form: UntypedFormGroup; + form: FormGroup<{ + name: FormControl; + permissions: FormArray< + FormGroup<{ + permission: FormControl; + }> + >; + }>; + item: Role = new Role(); constructor( private route: ActivatedRoute, private router: Router, - private fb: UntypedFormBuilder, private toaster: ToasterService, private dialog: MatDialog, private ser: RoleService, ) { - this.form = this.fb.group({ - name: '', - permissions: this.fb.array([]), + this.form = new FormGroup({ + name: new FormControl(null), + permissions: new FormArray }>>([]), }); } @@ -42,15 +44,12 @@ export class RoleDetailComponent implements OnInit, AfterViewInit { const data = value as { item: Role }; this.item = data.item; - (this.form.get('name') as UntypedFormControl).setValue(this.item.name); - this.form.setControl( - 'permissions', - this.fb.array( - this.item.permissions.map((x) => - this.fb.group({ - permission: x.enabled, - }), - ), + this.form.controls.name.setValue(this.item.name); + this.item.permissions.forEach((x) => + this.form.controls.permissions.push( + new FormGroup({ + permission: new FormControl(x.enabled, { nonNullable: true }), + }), ), ); }); @@ -103,10 +102,10 @@ export class RoleDetailComponent implements OnInit, AfterViewInit { getItem(): Role { const formModel = this.form.value; - this.item.name = formModel.name; - const array = this.form.get('permissions') as UntypedFormArray; + this.item.name = formModel.name!; + const array = this.form.controls.permissions; this.item.permissions.forEach((item, index) => { - item.enabled = array.controls[index].value.permission; + item.enabled = array.controls[index].value.permission!; }); return this.item; } diff --git a/overlord/src/app/role/role.service.ts b/overlord/src/app/role/role.service.ts index 0f9b1995..4eb28bcd 100644 --- a/overlord/src/app/role/role.service.ts +++ b/overlord/src/app/role/role.service.ts @@ -1,4 +1,4 @@ -import { HttpClient, HttpHeaders } from '@angular/common/http'; +import { HttpClient } from '@angular/common/http'; import { Injectable } from '@angular/core'; import { Observable } from 'rxjs/internal/Observable'; import { catchError } from 'rxjs/operators'; diff --git a/overlord/src/app/settings/settings.component.ts b/overlord/src/app/settings/settings.component.ts index c5770dd4..92aea03b 100644 --- a/overlord/src/app/settings/settings.component.ts +++ b/overlord/src/app/settings/settings.component.ts @@ -1,10 +1,5 @@ import { Component, OnInit } from '@angular/core'; -import { - UntypedFormArray, - UntypedFormBuilder, - UntypedFormControl, - UntypedFormGroup, -} from '@angular/forms'; +import { FormArray, FormControl, FormGroup } from '@angular/forms'; import { MatDialog } from '@angular/material/dialog'; import { ActivatedRoute, Router } from '@angular/router'; import * as moment from 'moment'; @@ -32,14 +27,31 @@ export class SettingsComponent implements OnInit { accountTypes: AccountType[] = []; voucherTypes: AccountType[] = []; - lockInfoForm: UntypedFormGroup; + lockInfoForm: FormGroup<{ + validFrom: FormControl; + validTill: FormControl; + index: FormControl; + lockOlder: FormControl; + olderRolling: FormControl; + olderDate: FormControl; + olderDays: FormControl; + lockNewer: FormControl; + newerRolling: FormControl; + newerDate: FormControl; + newerDays: FormControl; + accountTypes: FormArray }>>; + voucherTypes: FormArray }>>; + }>; + lockInformation: LockInfo[]; lockOlder: boolean = false; olderRolling: boolean = false; lockNewer: boolean = false; newerRolling: boolean = false; - rebaseDataForm: UntypedFormGroup; + rebaseDataForm: FormGroup<{ + date: FormControl; + }>; maintenance: { enabled: boolean; user: string }; @@ -50,7 +62,6 @@ export class SettingsComponent implements OnInit { constructor( private route: ActivatedRoute, private router: Router, - private fb: UntypedFormBuilder, private dialog: MatDialog, private toaster: ToasterService, public auth: AuthService, @@ -58,24 +69,24 @@ export class SettingsComponent implements OnInit { ) { const startDate = moment().date(1); const finishDate = moment().date(startDate.daysInMonth()); - this.lockInfoForm = this.fb.group({ - validFrom: '', - validTill: '', - index: 0, - lockOlder: '', - olderRolling: '', - olderDate: finishDate, - olderDays: 0, - lockNewer: '', - newerRolling: '', - newerDate: finishDate, - newerDays: 0, - accountTypes: this.fb.array([]), - voucherTypes: this.fb.array([]), + this.lockInfoForm = new FormGroup({ + validFrom: new FormControl(null), + validTill: new FormControl(null), + index: new FormControl(0, { nonNullable: true }), + lockOlder: new FormControl(false, { nonNullable: true }), + olderRolling: new FormControl(false, { nonNullable: true }), + olderDate: new FormControl(finishDate), + olderDays: new FormControl(0), + lockNewer: new FormControl(false, { nonNullable: true }), + newerRolling: new FormControl(false, { nonNullable: true }), + newerDate: new FormControl(finishDate), + newerDays: new FormControl(0), + accountTypes: new FormArray }>>([]), + voucherTypes: new FormArray }>>([]), }); this.lockInformation = []; - this.rebaseDataForm = this.fb.group({ - date: moment(), + this.rebaseDataForm = new FormGroup({ + date: new FormControl(moment(), { nonNullable: true }), }); this.listenToLockForm(); @@ -100,24 +111,20 @@ export class SettingsComponent implements OnInit { showLockInformation(info: LockInfo[]) { this.lockInformation = info; - this.lockInfoForm.setControl( - 'accountTypes', - this.fb.array( - this.accountTypes.map((x) => - this.fb.group({ - accountType: false, - }), - ), + this.lockInfoForm.controls.accountTypes.reset(); + this.accountTypes.forEach((x) => + this.lockInfoForm.controls.accountTypes.push( + new FormGroup({ + accountType: new FormControl(false, { nonNullable: true }), + }), ), ); - this.lockInfoForm.setControl( - 'voucherTypes', - this.fb.array( - this.voucherTypes.map((x) => - this.fb.group({ - voucherType: false, - }), - ), + this.lockInfoForm.controls.voucherTypes.reset(); + this.voucherTypes.forEach((x) => + this.lockInfoForm.controls.voucherTypes.push( + new FormGroup({ + voucherType: new FormControl(false, { nonNullable: true }), + }), ), ); this.dataSource = new LockDataSource(this.lockObservable); @@ -125,16 +132,16 @@ export class SettingsComponent implements OnInit { } listenToLockForm() { - (this.lockInfoForm.get('lockOlder') as UntypedFormControl).valueChanges.subscribe((x) => { + this.lockInfoForm.controls.lockOlder.valueChanges.subscribe((x) => { this.lockOlder = x; }); - (this.lockInfoForm.get('lockNewer') as UntypedFormControl).valueChanges.subscribe((x) => { + this.lockInfoForm.controls.lockNewer.valueChanges.subscribe((x) => { this.lockNewer = x; }); - (this.lockInfoForm.get('olderRolling') as UntypedFormControl).valueChanges.subscribe((x) => { + this.lockInfoForm.controls.olderRolling.valueChanges.subscribe((x) => { this.olderRolling = x; }); - (this.lockInfoForm.get('newerRolling') as UntypedFormControl).valueChanges.subscribe((x) => { + this.lockInfoForm.controls.newerRolling.valueChanges.subscribe((x) => { this.newerRolling = x; }); } @@ -142,44 +149,40 @@ export class SettingsComponent implements OnInit { saveLock() { const item = new LockInfo(); if (this.lockOlder && this.olderRolling) { - item.start.days = +(this.lockInfoForm.get('olderDays') as UntypedFormControl).value; + item.start.days = +this.lockInfoForm.value.olderDays!; } else if (this.lockOlder && !this.olderRolling) { - item.start.date = moment( - (this.lockInfoForm.get('olderDate') as UntypedFormControl).value, - ).format('DD-MMM-YYYY'); + item.start.date = this.lockInfoForm.value.olderDate!.format('DD-MMM-YYYY'); } if (this.lockNewer && this.newerRolling) { - item.finish.days = +(this.lockInfoForm.get('newerDays') as UntypedFormControl).value; + item.finish.days = +this.lockInfoForm.value.newerDays!; } if (this.lockNewer && !this.newerRolling) { - item.finish.date = moment( - (this.lockInfoForm.get('newerDate') as UntypedFormControl).value, - ).format('DD-MMM-YYYY'); + item.finish.date = this.lockInfoForm.value.newerDate!.format('DD-MMM-YYYY'); } - const atArray = this.lockInfoForm.get('accountTypes') as UntypedFormArray; + const atArray = this.lockInfoForm.controls.accountTypes; this.accountTypes.forEach((at, index) => { if (atArray.controls[index].value.accountType) { item.accountTypes.push({ id: at.id, name: at.name }); } }); - const vtArray = this.lockInfoForm.get('voucherTypes') as UntypedFormArray; + const vtArray = this.lockInfoForm.controls.voucherTypes; this.voucherTypes.forEach((vt, index) => { if (vtArray.controls[index].value.voucherType) { item.voucherTypes.push({ id: vt.id, name: vt.name }); } }); - const validFrom = (this.lockInfoForm.get('validFrom') as UntypedFormControl).value; + const validFrom = this.lockInfoForm.value.validFrom; if (validFrom) { item.validFrom = moment(validFrom).format('DD-MMM-YYYY'); } - const validTill = (this.lockInfoForm.get('validTill') as UntypedFormControl).value; + const validTill = this.lockInfoForm.value.validTill; if (validTill) { item.validTill = moment(validTill).format('DD-MMM-YYYY'); } - item.index = +(this.lockInfoForm.get('index') as UntypedFormControl).value; + item.index = +this.lockInfoForm.value.index!; this.ser.setLockInformation(item).subscribe( (result) => { @@ -199,9 +202,7 @@ export class SettingsComponent implements OnInit { } confirmRebase(): void { - const rebaseDate = moment((this.rebaseDataForm.get('date') as UntypedFormControl).value).format( - 'DD-MMM-YYYY', - ); + const rebaseDate = this.rebaseDataForm.value.date!.format('DD-MMM-YYYY'); const dialogRef = this.dialog.open(ConfirmDialogComponent, { width: '250px', data: { diff --git a/overlord/src/app/settings/settings.service.ts b/overlord/src/app/settings/settings.service.ts index 863f74ab..e3844784 100644 --- a/overlord/src/app/settings/settings.service.ts +++ b/overlord/src/app/settings/settings.service.ts @@ -4,7 +4,6 @@ import { Observable } from 'rxjs/internal/Observable'; import { catchError } from 'rxjs/operators'; import { ErrorLoggerService } from '../core/error-logger.service'; -import { Product } from '../core/product'; import { LockInfo } from './lock-info'; diff --git a/overlord/src/app/shared/math.service.ts b/overlord/src/app/shared/math.service.ts index ab3e154a..4e80a3a0 100644 --- a/overlord/src/app/shared/math.service.ts +++ b/overlord/src/app/shared/math.service.ts @@ -5,7 +5,6 @@ import { evaluate, round } from 'mathjs'; providedIn: 'root', }) export class MathService { - // eslint-disable-next-line class-methods-use-this journalAmount(amount: string = '', debit: number): { debit: number; amount: number } { const val = this.parseAmount(amount, 2); let newDebit = debit; @@ -15,7 +14,6 @@ export class MathService { return { debit: newDebit, amount: Math.abs(val) }; } - // eslint-disable-next-line class-methods-use-this parseAmount(amount: string = '', rounding: number = 2): number { const cleaned = `${amount}`.replace(new RegExp('(₹[s]*)|(,)|(s)', 'g'), ''); if (cleaned === '') { diff --git a/overlord/src/app/stock-movement/stock-movement.component.ts b/overlord/src/app/stock-movement/stock-movement.component.ts index a9c6f425..979a3ced 100644 --- a/overlord/src/app/stock-movement/stock-movement.component.ts +++ b/overlord/src/app/stock-movement/stock-movement.component.ts @@ -1,5 +1,5 @@ import { Component, OnInit, ViewChild } from '@angular/core'; -import { UntypedFormBuilder, UntypedFormGroup } from '@angular/forms'; +import { FormControl, FormGroup } from '@angular/forms'; import { MatPaginator } from '@angular/material/paginator'; import { MatSort } from '@angular/material/sort'; import { ActivatedRoute, Router } from '@angular/router'; @@ -18,19 +18,19 @@ export class StockMovementComponent implements OnInit { @ViewChild(MatSort, { static: true }) sort?: MatSort; info: StockMovement = new StockMovement(); dataSource: StockMovementDataSource = new StockMovementDataSource(this.info.body); - form: UntypedFormGroup; + form: FormGroup<{ + startDate: FormControl; + finishDate: FormControl; + }>; + selectedRowId = ''; /** Columns displayed in the table. Columns IDs can be added, removed, or reordered. */ displayedColumns = ['group', 'name', 'opening', 'purchase', 'issue', 'closing']; - constructor( - private route: ActivatedRoute, - private router: Router, - private fb: UntypedFormBuilder, - ) { - this.form = this.fb.group({ - startDate: '', - finishDate: '', + constructor(private route: ActivatedRoute, private router: Router) { + this.form = new FormGroup({ + startDate: new FormControl(new Date(), { nonNullable: true }), + finishDate: new FormControl(new Date(), { nonNullable: true }), }); } diff --git a/overlord/src/app/trial-balance/trial-balance.component.ts b/overlord/src/app/trial-balance/trial-balance.component.ts index c19bf5e9..70f336d4 100644 --- a/overlord/src/app/trial-balance/trial-balance.component.ts +++ b/overlord/src/app/trial-balance/trial-balance.component.ts @@ -1,5 +1,5 @@ import { Component, OnInit, ViewChild } from '@angular/core'; -import { UntypedFormBuilder, UntypedFormGroup } from '@angular/forms'; +import { FormControl, FormGroup } from '@angular/forms'; import { MatPaginator } from '@angular/material/paginator'; import { MatSort } from '@angular/material/sort'; import { ActivatedRoute, Router } from '@angular/router'; @@ -18,17 +18,16 @@ export class TrialBalanceComponent implements OnInit { @ViewChild(MatSort, { static: true }) sort?: MatSort; info: TrialBalance = new TrialBalance(); dataSource: TrialBalanceDataSource = new TrialBalanceDataSource(this.info.body); - form: UntypedFormGroup; + form: FormGroup<{ + date: FormControl; + }>; + /** Columns displayed in the table. Columns IDs can be added, removed, or reordered. */ displayedColumns = ['type', 'name', 'debit', 'credit']; - constructor( - private route: ActivatedRoute, - private router: Router, - private fb: UntypedFormBuilder, - ) { - this.form = this.fb.group({ - date: '', + constructor(private route: ActivatedRoute, private router: Router) { + this.form = new FormGroup({ + date: new FormControl(new Date(), { nonNullable: true }), }); } diff --git a/overlord/src/app/user/user-detail/user-detail.component.ts b/overlord/src/app/user/user-detail/user-detail.component.ts index 1b4c3c83..acfd4679 100644 --- a/overlord/src/app/user/user-detail/user-detail.component.ts +++ b/overlord/src/app/user/user-detail/user-detail.component.ts @@ -1,10 +1,5 @@ import { AfterViewInit, Component, ElementRef, OnInit, ViewChild } from '@angular/core'; -import { - UntypedFormArray, - UntypedFormBuilder, - UntypedFormControl, - UntypedFormGroup, -} from '@angular/forms'; +import { FormArray, FormControl, FormGroup } from '@angular/forms'; import { MatDialog } from '@angular/material/dialog'; import { ActivatedRoute, Router } from '@angular/router'; @@ -20,24 +15,33 @@ import { UserService } from '../user.service'; }) export class UserDetailComponent implements OnInit, AfterViewInit { @ViewChild('nameElement', { static: true }) nameElement?: ElementRef; - form: UntypedFormGroup; + form: FormGroup<{ + name: FormControl; + password: FormControl; + lockedOut: FormControl; + roles: FormArray< + FormGroup<{ + role: FormControl; + }> + >; + }>; + item: User = new User(); hide: boolean; constructor( private route: ActivatedRoute, private router: Router, - private fb: UntypedFormBuilder, private toaster: ToasterService, private dialog: MatDialog, private ser: UserService, ) { this.hide = true; - this.form = this.fb.group({ - name: '', - password: '', - lockedOut: '', - roles: this.fb.array([]), + this.form = new FormGroup({ + name: new FormControl(null), + password: new FormControl(null), + lockedOut: new FormControl(false, { nonNullable: true }), + roles: new FormArray }>>([]), }); } @@ -51,17 +55,14 @@ export class UserDetailComponent implements OnInit, AfterViewInit { showItem(item: User) { this.item = item; - (this.form.get('name') as UntypedFormControl).setValue(item.name); - (this.form.get('password') as UntypedFormControl).setValue(''); - (this.form.get('lockedOut') as UntypedFormControl).setValue(item.lockedOut); - this.form.setControl( - 'roles', - this.fb.array( - item.roles.map((x) => - this.fb.group({ - role: x.enabled, - }), - ), + this.form.controls.name.setValue(item.name); + this.form.controls.password.setValue(null); + this.form.controls.lockedOut.setValue(item.lockedOut); + this.item.roles.forEach((x) => + this.form.controls.roles.push( + new FormGroup({ + role: new FormControl(x.enabled, { nonNullable: true }), + }), ), ); } @@ -125,12 +126,12 @@ export class UserDetailComponent implements OnInit, AfterViewInit { getItem(): User { const formModel = this.form.value; - this.item.name = formModel.name; - this.item.password = formModel.password; - this.item.lockedOut = formModel.lockedOut; - const array = this.form.get('roles') as UntypedFormArray; + this.item.name = formModel.name!; + this.item.password = formModel.password!; + this.item.lockedOut = formModel.lockedOut!; + const array = this.form.controls.roles; this.item.roles.forEach((item, index) => { - item.enabled = array.controls[index].value.role; + item.enabled = array.controls[index].value.role!; }); return this.item; }