Chore: Eslint v9

Chore: Angular Zoneless
Chore: Removed Angular-Hotkeys dependency
Fix: Localization works properly now
Chore: Using Material 3 theme now
Chore: Removed toaster service to use snackbar directly
Fix: F2 Date working on all components now
This commit is contained in:
tanshu committed 2024-07-25 10:16:48 +05:30
1 parent c07c79ffda
commit 336a8f59c5
94 files changed
+846 -1030

No files matched your search

@@ -22,7 +22,7 @@ import { Account } from '../../core/account';
import { AccountType } from '../../core/account-type';
import { AccountService } from '../../core/account.service';
import { CostCentre } from '../../core/cost-centre';
import { ToasterService } from '../../core/toaster.service';
import { MatSnackBar } from '@angular/material/snack-bar';
import { ConfirmDialogComponent } from '../../shared/confirm-dialog/confirm-dialog.component';
@Component({
@@ -50,7 +50,7 @@ import { ConfirmDialogComponent } from '../../shared/confirm-dialog/confirm-dial
],
})
export class AccountDetailComponent implements OnInit, AfterViewInit {
@ViewChild('nameElement', { static: true }) nameElement?: ElementRef;
@ViewChild('nameElement', { static: true }) nameElement!: ElementRef<HTMLInputElement>;
form: FormGroup<{
code: FormControl<number | string>;
name: FormControl<string | null>;
@@ -68,7 +68,7 @@ export class AccountDetailComponent implements OnInit, AfterViewInit {
private route: ActivatedRoute,
private router: Router,
private dialog: MatDialog,
private toaster: ToasterService,
private snackBar: MatSnackBar,
private ser: AccountService,
) {
this.form = new FormGroup({
@@ -109,20 +109,18 @@ export class AccountDetailComponent implements OnInit, AfterViewInit {
ngAfterViewInit() {
setTimeout(() => {
if (this.nameElement) {
this.nameElement.nativeElement.focus();
}
this.nameElement.nativeElement.focus();
}, 0);
}
save() {
this.ser.saveOrUpdate(this.getItem()).subscribe({
next: () => {
this.toaster.show('Success', '');
this.snackBar.open('', 'Success');
this.router.navigateByUrl('/accounts');
},
error: (error) => {
this.toaster.show('Danger', error);
this.snackBar.open(error, 'Danger');
},
});
}
@@ -130,11 +128,11 @@ export class AccountDetailComponent implements OnInit, AfterViewInit {
delete() {
this.ser.delete(this.item.id as string).subscribe({
next: () => {
this.toaster.show('Success', '');
this.snackBar.open('', 'Success');
this.router.navigateByUrl('/accounts');
},
error: (error) => {
this.toaster.show('Danger', error);
this.snackBar.open(error, 'Danger');
},
});
}
@@ -63,9 +63,9 @@ import { AccountListDataSource } from './account-list-datasource';
],
})
export class AccountListComponent implements OnInit, AfterViewInit {
@ViewChild('filterElement', { static: true }) filterElement?: ElementRef;
@ViewChild(MatPaginator, { static: true }) paginator?: MatPaginator;
@ViewChild(MatSort, { static: true }) sort?: MatSort;
@ViewChild('filterElement', { static: true }) filterElement!: ElementRef<HTMLInputElement>;
@ViewChild(MatPaginator, { static: true }) paginator!: MatPaginator;
@ViewChild(MatSort, { static: true }) sort!: MatSort;
dataSource: AccountListDataSource;
filter: Observable<string>;
form: FormGroup<{
@@ -85,7 +85,7 @@ export class AccountListComponent implements OnInit, AfterViewInit {
// Listen to Filter Change
this.filter = this.form.controls.filter.valueChanges.pipe(debounceTime(150), distinctUntilChanged());
this.dataSource = new AccountListDataSource(this.list, this.filter);
this.dataSource = new AccountListDataSource(this.list, this.filter, this.paginator, this.sort);
}
ngOnInit() {
@@ -100,9 +100,7 @@ export class AccountListComponent implements OnInit, AfterViewInit {
ngAfterViewInit() {
setTimeout(() => {
if (this.filterElement) {
this.filterElement.nativeElement.focus();
}
this.filterElement.nativeElement.focus();
}, 0);
}
}
+9 -4
View File
@@ -1,6 +1,11 @@
import { LayoutModule } from '@angular/cdk/layout';
import { provideHttpClient, withInterceptors } from '@angular/common/http';
import { LOCALE_ID, importProvidersFrom, ApplicationConfig } from '@angular/core';
import {
LOCALE_ID,
importProvidersFrom,
ApplicationConfig,
provideExperimentalZonelessChangeDetection,
} from '@angular/core';
import { ReactiveFormsModule } from '@angular/forms';
import { MatButtonModule } from '@angular/material/button';
import { MatCardModule } from '@angular/material/card';
@@ -13,7 +18,7 @@ import { MatMenuModule } from '@angular/material/menu';
import { MatPaginatorModule } from '@angular/material/paginator';
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
import { MatSidenavModule } from '@angular/material/sidenav';
import { MatSnackBarModule } from '@angular/material/snack-bar';
import { MAT_SNACK_BAR_DEFAULT_OPTIONS, MatSnackBarModule } from '@angular/material/snack-bar';
import { MatSortModule } from '@angular/material/sort';
import { MatTableModule } from '@angular/material/table';
import { MatToolbarModule } from '@angular/material/toolbar';
@@ -21,7 +26,6 @@ import { MomentDateAdapter } from '@angular/material-moment-adapter';
import { BrowserModule } from '@angular/platform-browser';
import { provideAnimations } from '@angular/platform-browser/animations';
import { provideRouter, withRouterConfig } from '@angular/router';
import { HotkeyModule } from 'angular2-hotkeys';
import { dateFormat } from './app.environment';
import { routes } from './app.routes';
@@ -34,7 +38,6 @@ export const appConfig: ApplicationConfig = {
providers: [
importProvidersFrom(
BrowserModule,
HotkeyModule.forRoot(),
LayoutModule,
MatButtonModule,
MatCardModule,
@@ -64,5 +67,7 @@ export const appConfig: ApplicationConfig = {
),
{ provide: DateAdapter, useClass: MomentDateAdapter, deps: [MAT_DATE_LOCALE] },
{ provide: MAT_DATE_FORMATS, useValue: dateFormat },
{ provide: MAT_SNACK_BAR_DEFAULT_OPTIONS, useValue: { duration: 3000 } },
provideExperimentalZonelessChangeDetection(),
],
};
-1
View File
@@ -1,5 +1,4 @@
export const environment = {
// eslint-disable-next-line @typescript-eslint/naming-convention
ACCESS_TOKEN_REFRESH_MINUTES: 10, // refresh token 10 minutes before expiry
version: '13.0.0',
title: 'HnG / TGB',
@@ -7,7 +7,14 @@
<div class="flex flex-row justify-around content-start items-start sm:max-lg:flex-col">
<mat-form-field class="flex-auto basis-4/5 mr-5">
<mat-label>Date</mat-label>
<input matInput [matDatepicker]="date" (focus)="date.open()" formControlName="date" autocomplete="off" />
<input
matInput
#dateElement
[matDatepicker]="date"
(focus)="dateElement.select()"
formControlName="date"
autocomplete="off"
/>
<mat-datepicker-toggle matSuffix [for]="date"></mat-datepicker-toggle>
<mat-datepicker #date></mat-datepicker>
</mat-form-field>
@@ -27,13 +27,16 @@ import moment from 'moment';
import { BehaviorSubject } from 'rxjs';
import { AuthService } from '../auth/auth.service';
import { ToasterService } from '../core/toaster.service';
import { MatSnackBar } from '@angular/material/snack-bar';
import { Attendance } from './attendance';
import { AttendanceDataSource } from './attendance-datasource';
import { AttendanceItem } from './attendance-item';
import { AttendanceType } from './attendance-type';
import { AttendanceService } from './attendance.service';
import { ViewChild } from '@angular/core';
import { ElementRef } from '@angular/core';
import { HostListener } from '@angular/core';
@Component({
selector: 'app-attendance',
@@ -73,6 +76,7 @@ import { AttendanceService } from './attendance.service';
],
})
export class AttendanceComponent implements OnInit {
@ViewChild('dateElement', { static: false }) dateElement!: ElementRef<HTMLInputElement>;
public attendanceObservable = new BehaviorSubject<AttendanceItem[]>([]);
dataSource: AttendanceDataSource = new AttendanceDataSource(this.attendanceObservable);
form: FormGroup<{
@@ -89,11 +93,18 @@ export class AttendanceComponent implements OnInit {
displayedColumns = ['code', 'name', 'designation', 'department', 'status', 'prints'];
@HostListener('window:keydown.f2', ['$event'])
focusDate(event: KeyboardEvent) {
event.preventDefault();
this.dateElement.nativeElement.focus();
this.dateElement.nativeElement.select();
}
constructor(
private route: ActivatedRoute,
private router: Router,
private dialog: MatDialog,
private toaster: ToasterService,
private snackBar: MatSnackBar,
private auth: AuthService,
private ser: AttendanceService,
) {
@@ -138,10 +149,10 @@ export class AttendanceComponent implements OnInit {
save() {
this.ser.save(this.getAttendance()).subscribe({
next: () => {
this.toaster.show('Success', '');
this.snackBar.open('', 'Success');
},
error: (error) => {
this.toaster.show('Danger', error);
this.snackBar.open(error, 'Danger');
},
});
}
+2 -2
View File
@@ -2,7 +2,7 @@ import { inject } from '@angular/core';
import { CanActivateFn } from '@angular/router';
import { Router } from '@angular/router';
import { ToasterService } from '../core/toaster.service';
import { MatSnackBar } from '@angular/material/snack-bar';
import { AuthService } from './auth.service';
@@ -18,7 +18,7 @@ export const authGuard: CanActivateFn = (route, state) => {
return false;
}
if (permission !== undefined && user.perms.indexOf(permission) === -1) {
inject(ToasterService).show('Danger', 'You do not have the permission to access this area.');
inject(MatSnackBar).open('You do not have the permission to access this area.', 'Danger');
return false;
}
// logged in so return true
@@ -8,7 +8,7 @@ import { MatIcon } from '@angular/material/icon';
import { MatInput } from '@angular/material/input';
import { ActivatedRoute, Router } from '@angular/router';
import { ToasterService } from '../../core/toaster.service';
import { MatSnackBar } from '@angular/material/snack-bar';
import { CookieService } from '../../shared/cookie.service';
import { AuthService } from '../auth.service';
@@ -34,7 +34,7 @@ import { AuthService } from '../auth.service';
],
})
export class LoginComponent implements OnInit, AfterViewInit {
@ViewChild('nameElement', { static: true }) nameElement?: ElementRef;
@ViewChild('nameElement', { static: true }) nameElement!: ElementRef<HTMLInputElement>;
form: FormGroup<{
username: FormControl<string>;
password: FormControl<string>;
@@ -50,7 +50,7 @@ export class LoginComponent implements OnInit, AfterViewInit {
private route: ActivatedRoute,
private auth: AuthService,
private router: Router,
private toaster: ToasterService,
private snackBar: MatSnackBar,
private cs: CookieService,
) {
this.hide = true;
@@ -68,9 +68,7 @@ export class LoginComponent implements OnInit, AfterViewInit {
ngAfterViewInit() {
setTimeout(() => {
if (this.nameElement) {
this.nameElement.nativeElement.focus();
}
this.nameElement.nativeElement.focus();
}, 0);
}
@@ -91,7 +89,7 @@ export class LoginComponent implements OnInit, AfterViewInit {
this.showOtp = true;
this.clientId = this.cs.getCookie('client_id');
}
this.toaster.show('Danger', error.error.details);
this.snackBar.open(error.error.details, 'Danger');
},
});
}
@@ -1,7 +1,7 @@
import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { ToasterService } from '../../core/toaster.service';
import { MatSnackBar } from '@angular/material/snack-bar';
import { AuthService } from '../auth.service';
@Component({
@@ -13,7 +13,7 @@ export class LogoutComponent implements OnInit {
constructor(
private auth: AuthService,
private router: Router,
private toaster: ToasterService,
private snackBar: MatSnackBar,
) {}
ngOnInit() {
@@ -7,13 +7,7 @@
<div class="flex flex-row justify-around content-start items-start sm:max-lg:flex-col">
<mat-form-field class="flex-auto mr-5">
<mat-label>Date</mat-label>
<input
matInput
[matDatepicker]="dateInput"
(focus)="dateInput.open()"
formControlName="date"
autocomplete="off"
/>
<input matInput #dateElement [matDatepicker]="dateInput" formControlName="date" autocomplete="off" />
<mat-datepicker-toggle matSuffix [for]="dateInput"></mat-datepicker-toggle>
<mat-datepicker #dateInput></mat-datepicker>
</mat-form-field>
@@ -1,5 +1,5 @@
import { CurrencyPipe } from '@angular/common';
import { Component, OnInit, ViewChild } from '@angular/core';
import { Component, ElementRef, HostListener, OnInit, ViewChild } from '@angular/core';
import { FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms';
import { MatButton } from '@angular/material/button';
import { MatCard, MatCardHeader, MatCardTitle, MatCardContent } from '@angular/material/card';
@@ -73,10 +73,11 @@ import { BalanceSheetDataSource } from './balance-sheet-datasource';
],
})
export class BalanceSheetComponent implements OnInit {
@ViewChild(MatPaginator, { static: true }) paginator?: MatPaginator;
@ViewChild(MatSort, { static: true }) sort?: MatSort;
@ViewChild(MatPaginator, { static: true }) paginator!: MatPaginator;
@ViewChild(MatSort, { static: true }) sort!: MatSort;
@ViewChild('dateElement', { static: true }) dateElement!: ElementRef<HTMLInputElement>;
info: BalanceSheet = new BalanceSheet();
dataSource: BalanceSheetDataSource = new BalanceSheetDataSource(this.info.body);
dataSource: BalanceSheetDataSource = new BalanceSheetDataSource(this.info.body, this.paginator, this.sort);
form: FormGroup<{
date: FormControl<Date>;
}>;
@@ -84,6 +85,13 @@ export class BalanceSheetComponent implements OnInit {
/** Columns displayed in the table. Columns IDs can be added, removed, or reordered. */
displayedColumns = ['group', 'name', 'subAmount', 'total'];
@HostListener('window:keydown.f2', ['$event'])
focusDate(event: KeyboardEvent) {
event.preventDefault();
this.dateElement.nativeElement.focus();
this.dateElement.nativeElement.select();
}
constructor(
private route: ActivatedRoute,
private router: Router,
@@ -9,8 +9,8 @@
<mat-label>Start Date</mat-label>
<input
matInput
#startDateElement
[matDatepicker]="startDate"
(focus)="startDate.open()"
formControlName="startDate"
autocomplete="off"
/>
@@ -19,13 +19,7 @@
</mat-form-field>
<mat-form-field class="flex-auto basis-2/5 mr-5">
<mat-label>Finish Date</mat-label>
<input
matInput
[matDatepicker]="finishDate"
(focus)="finishDate.open()"
formControlName="finishDate"
autocomplete="off"
/>
<input matInput [matDatepicker]="finishDate" formControlName="finishDate" autocomplete="off" />
<mat-datepicker-toggle matSuffix [for]="finishDate"></mat-datepicker-toggle>
<mat-datepicker #finishDate></mat-datepicker>
</mat-form-field>
@@ -1,5 +1,5 @@
import { CurrencyPipe } from '@angular/common';
import { Component, OnInit } from '@angular/core';
import { Component, ElementRef, HostListener, OnInit, ViewChild } from '@angular/core';
import { FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms';
import { MatButton } from '@angular/material/button';
import { MatCard, MatCardHeader, MatCardTitle, MatCardContent } from '@angular/material/card';
@@ -64,6 +64,7 @@ import { CashFlowDataSource } from './cash-flow-datasource';
],
})
export class CashFlowComponent implements OnInit {
@ViewChild('startDateElement', { static: true }) startDate!: ElementRef<HTMLInputElement>;
info: CashFlow = new CashFlow();
dataSource: CashFlowDataSource = new CashFlowDataSource(CashFlow.Data(this.info));
form: FormGroup<{
@@ -74,6 +75,13 @@ export class CashFlowComponent implements OnInit {
/** Columns displayed in the table. Columns IDs can be added, removed, or reordered. */
displayedColumns = ['name', 'amount'];
@HostListener('window:keydown.f2', ['$event'])
focusDate(event: KeyboardEvent) {
event.preventDefault();
this.startDate.nativeElement.focus();
this.startDate.nativeElement.select();
}
constructor(
private route: ActivatedRoute,
private router: Router,
@@ -8,7 +8,7 @@ import { MatFormField, MatLabel } from '@angular/material/form-field';
import { MatInput } from '@angular/material/input';
import { ActivatedRoute, Router } from '@angular/router';
import { ToasterService } from '../../core/toaster.service';
import { MatSnackBar } from '@angular/material/snack-bar';
import { ConfirmDialogComponent } from '../../shared/confirm-dialog/confirm-dialog.component';
import { Client } from '../client';
import { ClientService } from '../client.service';
@@ -33,7 +33,7 @@ import { ClientService } from '../client.service';
],
})
export class ClientDetailComponent implements OnInit, AfterViewInit {
@ViewChild('nameElement', { static: true }) nameElement?: ElementRef;
@ViewChild('nameElement', { static: true }) nameElement!: ElementRef<HTMLInputElement>;
form: FormGroup<{
code: FormControl<number | string>;
name: FormControl<string | null>;
@@ -47,7 +47,7 @@ export class ClientDetailComponent implements OnInit, AfterViewInit {
private route: ActivatedRoute,
private router: Router,
private dialog: MatDialog,
private toaster: ToasterService,
private snackBar: MatSnackBar,
private ser: ClientService,
) {
this.form = new FormGroup({
@@ -78,20 +78,18 @@ export class ClientDetailComponent implements OnInit, AfterViewInit {
ngAfterViewInit() {
setTimeout(() => {
if (this.nameElement) {
this.nameElement.nativeElement.focus();
}
this.nameElement.nativeElement.focus();
}, 0);
}
save() {
this.ser.update(this.getItem()).subscribe({
next: () => {
this.toaster.show('Success', '');
this.snackBar.open('', 'Success');
this.router.navigateByUrl('/clients');
},
error: (error) => {
this.toaster.show('Danger', error);
this.snackBar.open(error, 'Danger');
},
});
}
@@ -99,11 +97,11 @@ export class ClientDetailComponent implements OnInit, AfterViewInit {
delete() {
this.ser.delete(this.item.id).subscribe({
next: () => {
this.toaster.show('Success', '');
this.snackBar.open('', 'Success');
this.router.navigateByUrl('/clients');
},
error: (error) => {
this.toaster.show('Danger', error);
this.snackBar.open(error, 'Danger');
},
});
}
@@ -49,10 +49,10 @@ import { ClientListDataSource } from './client-list-datasource';
],
})
export class ClientListComponent implements OnInit {
@ViewChild(MatPaginator, { static: true }) paginator?: MatPaginator;
@ViewChild(MatSort, { static: true }) sort?: MatSort;
@ViewChild(MatPaginator, { static: true }) paginator!: MatPaginator;
@ViewChild(MatSort, { static: true }) sort!: MatSort;
list: Client[] = [];
dataSource: ClientListDataSource = new ClientListDataSource(this.list);
dataSource: ClientListDataSource = new ClientListDataSource(this.list, this.paginator, this.sort);
/** Columns displayed in the table. Columns IDs can be added, removed, or reordered. */
displayedColumns = ['code', 'name', 'enabled', 'otp', 'created', 'last'];
@@ -24,13 +24,7 @@
</mat-form-field>
<mat-form-field class="flex-auto basis-2/5 mr-5">
<mat-label>Date</mat-label>
<input
matInput
[matDatepicker]="dateInput"
(focus)="dateInput.open()"
formControlName="date"
autocomplete="off"
/>
<input matInput #dateElement [matDatepicker]="dateInput" formControlName="date" autocomplete="off" />
<mat-datepicker-toggle matSuffix [for]="dateInput"></mat-datepicker-toggle>
<mat-datepicker #dateInput></mat-datepicker>
</mat-form-field>
@@ -1,5 +1,5 @@
import { DecimalPipe, CurrencyPipe } from '@angular/common';
import { Component, OnInit, ViewChild } from '@angular/core';
import { Component, ElementRef, HostListener, OnInit, ViewChild } from '@angular/core';
import { FormGroup, FormArray, FormControl, ReactiveFormsModule } from '@angular/forms';
import { MatIconButton, MatButton } from '@angular/material/button';
import {
@@ -36,7 +36,7 @@ import moment from 'moment';
import { AuthService } from '../auth/auth.service';
import { CostCentre } from '../core/cost-centre';
import { ToasterService } from '../core/toaster.service';
import { MatSnackBar } from '@angular/material/snack-bar';
import { User } from '../core/user';
import { ConfirmDialogComponent } from '../shared/confirm-dialog/confirm-dialog.component';
import { ToCsvService } from '../shared/to-csv.service';
@@ -89,10 +89,11 @@ import { ClosingStockService } from './closing-stock.service';
],
})
export class ClosingStockComponent implements OnInit {
@ViewChild(MatPaginator, { static: true }) paginator?: MatPaginator;
@ViewChild(MatSort, { static: true }) sort?: MatSort;
@ViewChild(MatPaginator, { static: true }) paginator!: MatPaginator;
@ViewChild(MatSort, { static: true }) sort!: MatSort;
@ViewChild('dateElement', { static: true }) dateElement!: ElementRef<HTMLInputElement>;
info: ClosingStock = new ClosingStock();
dataSource: ClosingStockDataSource = new ClosingStockDataSource(this.info.items);
dataSource: ClosingStockDataSource = new ClosingStockDataSource(this.info.items, this.paginator, this.sort);
form: FormGroup<{
date: FormControl<Date>;
costCentre: FormControl<string | null>;
@@ -109,12 +110,19 @@ export class ClosingStockComponent implements OnInit {
costCentres: CostCentre[];
@HostListener('window:keydown.f2', ['$event'])
focusDate(event: KeyboardEvent) {
event.preventDefault();
this.dateElement.nativeElement.focus();
this.dateElement.nativeElement.select();
}
constructor(
private route: ActivatedRoute,
private router: Router,
private toCsv: ToCsvService,
private dialog: MatDialog,
private toaster: ToasterService,
private snackBar: MatSnackBar,
public auth: AuthService,
private ser: ClosingStockService,
) {
@@ -162,10 +170,10 @@ export class ClosingStockComponent implements OnInit {
save() {
this.ser.save(this.getClosingStock()).subscribe({
next: () => {
this.toaster.show('Success', '');
this.snackBar.open('', 'Success');
},
error: (error) => {
this.toaster.show('Danger', error);
this.snackBar.open(error, 'Danger');
},
});
}
@@ -243,10 +251,10 @@ export class ClosingStockComponent implements OnInit {
post() {
this.ser.post(this.info.date, this.info.costCentre.id as string).subscribe({
next: () => {
this.toaster.show('Success', 'Voucher Posted');
this.snackBar.open('Voucher Posted', 'Success');
},
error: (error) => {
this.toaster.show('Danger', error);
this.snackBar.open(error, 'Danger');
},
});
}
@@ -254,11 +262,11 @@ export class ClosingStockComponent implements OnInit {
delete() {
this.ser.delete(this.info.date, this.info.costCentre.id as string).subscribe({
next: () => {
this.toaster.show('Success', '');
this.snackBar.open('', 'Success');
this.router.navigate(['/closing-stock'], { replaceUrl: true });
},
error: (error) => {
this.toaster.show('Danger', error);
this.snackBar.open(error, 'Danger');
},
});
}
+2 -2
View File
@@ -8,7 +8,7 @@ import { catchError } from 'rxjs/operators';
import { AuthService } from '../auth/auth.service';
import { ConfirmDialogComponent } from '../shared/confirm-dialog/confirm-dialog.component';
import { ToasterService } from './toaster.service';
import { MatSnackBar } from '@angular/material/snack-bar';
export const authInterceptor: HttpInterceptorFn = (req, next) => {
return next(req).pipe(
@@ -31,7 +31,7 @@ export const authInterceptor: HttpInterceptorFn = (req, next) => {
}
// auto logout if 401 response returned from api
inject(AuthService).logout();
inject(ToasterService).show('Danger', 'User has been logged out');
inject(MatSnackBar).open('User has been logged out', 'Danger');
const dialogRef = inject(MatDialog).open(ConfirmDialogComponent, {
width: '250px',
data: {
@@ -1,15 +0,0 @@
import { inject, TestBed } from '@angular/core/testing';
import { ToasterService } from './toaster.service';
describe('ToasterService', () => {
beforeEach(() => {
TestBed.configureTestingModule({
providers: [ToasterService],
});
});
it('should be created', inject([ToasterService], (service: ToasterService) => {
expect(service).toBeTruthy();
}));
});
-15
View File
@@ -1,15 +0,0 @@
import { Injectable } from '@angular/core';
import { MatSnackBar } from '@angular/material/snack-bar';
@Injectable({
providedIn: 'root',
})
export class ToasterService {
constructor(private snackBar: MatSnackBar) {}
show(type: string, msg: string) {
this.snackBar.open(msg, type, {
duration: 3000,
});
}
}
@@ -7,7 +7,7 @@ import { MatInput } from '@angular/material/input';
import { ActivatedRoute, Router } from '@angular/router';
import { CostCentre } from '../../core/cost-centre';
import { ToasterService } from '../../core/toaster.service';
import { MatSnackBar } from '@angular/material/snack-bar';
import { CostCentreService } from '../cost-centre.service';
@Component({
@@ -29,7 +29,7 @@ import { CostCentreService } from '../cost-centre.service';
],
})
export class CostCentreDetailComponent implements OnInit, AfterViewInit {
@ViewChild('nameElement', { static: true }) nameElement?: ElementRef;
@ViewChild('nameElement', { static: true }) nameElement!: ElementRef<HTMLInputElement>;
form: FormGroup<{
name: FormControl<string | null>;
}>;
@@ -39,7 +39,7 @@ export class CostCentreDetailComponent implements OnInit, AfterViewInit {
constructor(
private route: ActivatedRoute,
private router: Router,
private toaster: ToasterService,
private snackBar: MatSnackBar,
private ser: CostCentreService,
) {
this.form = new FormGroup({
@@ -64,20 +64,18 @@ export class CostCentreDetailComponent implements OnInit, AfterViewInit {
ngAfterViewInit() {
setTimeout(() => {
if (this.nameElement) {
this.nameElement.nativeElement.focus();
}
this.nameElement.nativeElement.focus();
}, 0);
}
save() {
this.ser.saveOrUpdate(this.getItem()).subscribe({
next: () => {
this.toaster.show('Success', '');
this.snackBar.open('', 'Success');
this.router.navigateByUrl('/cost-centres');
},
error: (error) => {
this.toaster.show('Danger', error);
this.snackBar.open(error, 'Danger');
},
});
}
@@ -52,10 +52,10 @@ import { CostCentreListDataSource } from './cost-centre-list-datasource';
],
})
export class CostCentreListComponent implements OnInit {
@ViewChild(MatPaginator, { static: true }) paginator?: MatPaginator;
@ViewChild(MatSort, { static: true }) sort?: MatSort;
@ViewChild(MatPaginator, { static: true }) paginator!: MatPaginator;
@ViewChild(MatSort, { static: true }) sort!: MatSort;
list: CostCentre[] = [];
dataSource: CostCentreListDataSource = new CostCentreListDataSource(this.list);
dataSource: CostCentreListDataSource = new CostCentreListDataSource(this.list, this.paginator, this.sort);
/** Columns displayed in the table. Columns IDs can be added, removed, or reordered. */
displayedColumns = ['name', 'isFixture'];
@@ -9,8 +9,8 @@
<mat-label>Start Date</mat-label>
<input
matInput
#startDateElement
[matDatepicker]="startDate"
(focus)="startDate.open()"
formControlName="startDate"
autocomplete="off"
/>
@@ -19,13 +19,7 @@
</mat-form-field>
<mat-form-field class="flex-auto basis-2/5 mr-5">
<mat-label>Finish Date</mat-label>
<input
matInput
[matDatepicker]="finishDate"
(focus)="finishDate.open()"
formControlName="finishDate"
autocomplete="off"
/>
<input matInput [matDatepicker]="finishDate" formControlName="finishDate" autocomplete="off" />
<mat-datepicker-toggle matSuffix [for]="finishDate"></mat-datepicker-toggle>
<mat-datepicker #finishDate></mat-datepicker>
</mat-form-field>
+12 -4
View File
@@ -1,5 +1,5 @@
import { CurrencyPipe } from '@angular/common';
import { Component, OnInit, ViewChild } from '@angular/core';
import { Component, ElementRef, HostListener, OnInit, ViewChild } from '@angular/core';
import { FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms';
import { MatButton } from '@angular/material/button';
import { MatCard, MatCardHeader, MatCardTitle, MatCardContent } from '@angular/material/card';
@@ -63,10 +63,11 @@ import { DaybookDataSource } from './daybook-datasource';
],
})
export class DaybookComponent implements OnInit {
@ViewChild(MatPaginator, { static: true }) paginator?: MatPaginator;
@ViewChild(MatSort, { static: true }) sort?: MatSort;
@ViewChild(MatPaginator, { static: true }) paginator!: MatPaginator;
@ViewChild(MatSort, { static: true }) sort!: MatSort;
@ViewChild('startDateElement', { static: true }) startDate!: ElementRef<HTMLInputElement>;
info: Daybook = new Daybook();
dataSource: DaybookDataSource = new DaybookDataSource(this.info.body);
dataSource: DaybookDataSource = new DaybookDataSource(this.info.body, this.paginator, this.sort);
form: FormGroup<{
startDate: FormControl<Date>;
finishDate: FormControl<Date>;
@@ -76,6 +77,13 @@ export class DaybookComponent implements OnInit {
/** Columns displayed in the table. Columns IDs can be added, removed, or reordered. */
displayedColumns = ['date', 'type', 'narration', 'debitText', 'debitAmount', 'creditText', 'creditAmount'];
@HostListener('window:keydown.f2', ['$event'])
focusDate(event: KeyboardEvent) {
event.preventDefault();
this.startDate.nativeElement.focus();
this.startDate.nativeElement.select();
}
constructor(
private route: ActivatedRoute,
private router: Router,
@@ -9,8 +9,8 @@
<mat-label>Start Date</mat-label>
<input
matInput
#startDateElement
[matDatepicker]="startDate"
(focus)="startDate.open()"
formControlName="startDate"
autocomplete="off"
/>
@@ -19,13 +19,7 @@
</mat-form-field>
<mat-form-field class="flex-auto">
<mat-label>Finish Date</mat-label>
<input
matInput
[matDatepicker]="finishDate"
(focus)="finishDate.open()"
formControlName="finishDate"
autocomplete="off"
/>
<input matInput [matDatepicker]="finishDate" formControlName="finishDate" autocomplete="off" />
<mat-datepicker-toggle matSuffix [for]="finishDate"></mat-datepicker-toggle>
<mat-datepicker #finishDate></mat-datepicker>
</mat-form-field>
@@ -1,5 +1,5 @@
import { AsyncPipe } from '@angular/common';
import { AfterViewInit, Component, ElementRef, OnInit, ViewChild } from '@angular/core';
import { AfterViewInit, Component, ElementRef, HostListener, OnInit, ViewChild } from '@angular/core';
import { FormArray, FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms';
import { MatAutocompleteSelectedEvent, MatAutocompleteTrigger, MatAutocomplete } from '@angular/material/autocomplete';
import { MatButton } from '@angular/material/button';
@@ -31,7 +31,7 @@ import { debounceTime, distinctUntilChanged, switchMap } from 'rxjs/operators';
import { AttendanceType } from '../attendance/attendance-type';
import { AuthService } from '../auth/auth.service';
import { ToasterService } from '../core/toaster.service';
import { MatSnackBar } from '@angular/material/snack-bar';
import { Employee } from '../employee/employee';
import { EmployeeService } from '../employee/employee.service';
@@ -81,7 +81,8 @@ import { EmployeeAttendanceService } from './employee-attendance.service';
],
})
export class EmployeeAttendanceComponent implements OnInit, AfterViewInit {
@ViewChild('employeeElement', { static: true }) employeeElement?: ElementRef;
@ViewChild('employeeElement', { static: true }) employeeElement!: ElementRef<HTMLInputElement>;
@ViewChild('startDateElement', { static: true }) startDate!: ElementRef<HTMLInputElement>;
public employeeAttendanceObservable = new BehaviorSubject<EmployeeAttendanceItem[]>([]);
dataSource: EmployeeAttendanceDataSource = new EmployeeAttendanceDataSource(this.employeeAttendanceObservable);
@@ -103,11 +104,18 @@ export class EmployeeAttendanceComponent implements OnInit, AfterViewInit {
employees: Observable<Employee[]>;
@HostListener('window:keydown.f2', ['$event'])
focusDate(event: KeyboardEvent) {
event.preventDefault();
this.startDate.nativeElement.focus();
this.startDate.nativeElement.select();
}
constructor(
private route: ActivatedRoute,
private router: Router,
private dialog: MatDialog,
private toaster: ToasterService,
private snackBar: MatSnackBar,
private auth: AuthService,
private ser: EmployeeAttendanceService,
private employeeSer: EmployeeService,
@@ -150,9 +158,7 @@ export class EmployeeAttendanceComponent implements OnInit, AfterViewInit {
ngAfterViewInit() {
setTimeout(() => {
if (this.employeeElement) {
this.employeeElement.nativeElement.focus();
}
this.employeeElement.nativeElement.focus();
}, 0);
}
@@ -188,10 +194,10 @@ export class EmployeeAttendanceComponent implements OnInit, AfterViewInit {
save() {
this.ser.save(this.getEmployeeAttendance()).subscribe({
next: () => {
this.toaster.show('Success', '');
this.snackBar.open('', 'Success');
},
error: (error) => {
this.toaster.show('Danger', error);
this.snackBar.open(error, 'Danger');
},
});
}
@@ -7,7 +7,14 @@
<div class="flex flex-row justify-around content-start items-start">
<mat-form-field class="flex-auto">
<mat-label>Date</mat-label>
<input matInput [matDatepicker]="date" (focus)="date.open()" formControlName="date" autocomplete="off" />
<input
matInput
#dateElement
[matDatepicker]="date"
(focus)="dateElement.select()"
formControlName="date"
autocomplete="off"
/>
<mat-datepicker-toggle matSuffix [for]="date"></mat-datepicker-toggle>
<mat-datepicker #date></mat-datepicker>
</mat-form-field>
@@ -37,7 +37,7 @@ import { debounceTime, distinctUntilChanged, switchMap } from 'rxjs/operators';
import { AuthService } from '../auth/auth.service';
import { AccountBalance } from '../core/account-balance';
import { EmployeeBenefit } from '../core/employee-benefit';
import { ToasterService } from '../core/toaster.service';
import { MatSnackBar } from '@angular/material/snack-bar';
import { User } from '../core/user';
import { Voucher } from '../core/voucher';
import { VoucherService } from '../core/voucher.service';
@@ -47,6 +47,7 @@ import { ConfirmDialogComponent } from '../shared/confirm-dialog/confirm-dialog.
import { LocalTimePipe } from '../shared/local-time.pipe';
import { EmployeeBenefitsDataSource } from './employee-benefits-datasource';
import { HostListener } from '@angular/core';
@Component({
selector: 'app-employee-benefits',
@@ -91,7 +92,8 @@ import { EmployeeBenefitsDataSource } from './employee-benefits-datasource';
],
})
export class EmployeeBenefitsComponent implements OnInit, AfterViewInit {
@ViewChild('employeeElement', { static: true }) employeeElement?: ElementRef;
@ViewChild('employeeElement', { static: true }) employeeElement!: ElementRef<HTMLInputElement>;
@ViewChild('dateElement', { static: true }) dateElement!: ElementRef<HTMLInputElement>;
public benefitsObservable = new BehaviorSubject<EmployeeBenefit[]>([]);
dataSource: EmployeeBenefitsDataSource = new EmployeeBenefitsDataSource(this.benefitsObservable);
form: FormGroup<{
@@ -121,11 +123,18 @@ export class EmployeeBenefitsComponent implements OnInit, AfterViewInit {
employees: Observable<Employee[]>;
@HostListener('window:keydown.f2', ['$event'])
focusDate(event: KeyboardEvent) {
event.preventDefault();
this.dateElement.nativeElement.focus();
this.dateElement.nativeElement.select();
}
constructor(
private route: ActivatedRoute,
private router: Router,
private dialog: MatDialog,
private toaster: ToasterService,
private snackBar: MatSnackBar,
public auth: AuthService,
private ser: VoucherService,
private employeeSer: EmployeeService,
@@ -174,9 +183,7 @@ export class EmployeeBenefitsComponent implements OnInit, AfterViewInit {
ngAfterViewInit() {
setTimeout(() => {
if (this.employeeElement) {
this.employeeElement.nativeElement.focus();
}
this.employeeElement.nativeElement.focus();
}, 0);
}
@@ -205,7 +212,7 @@ export class EmployeeBenefitsComponent implements OnInit, AfterViewInit {
addRow() {
const oldFiltered = this.voucher.employeeBenefits.filter((x) => x.employee.id === (this.employee as Employee).id);
if (oldFiltered.length) {
this.toaster.show('Danger', 'Employee has already been added');
this.snackBar.open('Employee has already been added', 'Danger');
return;
}
@@ -239,9 +246,7 @@ export class EmployeeBenefitsComponent implements OnInit, AfterViewInit {
this.form.controls.addRow.reset();
this.employee = null;
setTimeout(() => {
if (this.employeeElement) {
this.employeeElement.nativeElement.focus();
}
this.employeeElement.nativeElement.focus();
}, 0);
}
@@ -264,10 +269,10 @@ export class EmployeeBenefitsComponent implements OnInit, AfterViewInit {
this.ser.post(this.voucher.id as string).subscribe({
next: (result) => {
this.loadVoucher(result);
this.toaster.show('Success', 'Voucher Posted');
this.snackBar.open('Voucher Posted', 'Success');
},
error: (error) => {
this.toaster.show('Danger', error);
this.snackBar.open(error, 'Danger');
},
});
}
@@ -276,7 +281,7 @@ export class EmployeeBenefitsComponent implements OnInit, AfterViewInit {
const voucher: Voucher = this.getVoucher();
this.ser.saveOrUpdate(voucher).subscribe({
next: (result) => {
this.toaster.show('Success', '');
this.snackBar.open('', 'Success');
if (voucher.id === result.id) {
this.loadVoucher(result);
} else {
@@ -284,7 +289,7 @@ export class EmployeeBenefitsComponent implements OnInit, AfterViewInit {
}
},
error: (error) => {
this.toaster.show('Danger', error);
this.snackBar.open(error, 'Danger');
},
});
}
@@ -298,11 +303,11 @@ export class EmployeeBenefitsComponent implements OnInit, AfterViewInit {
delete() {
this.ser.delete(this.voucher.id as string).subscribe({
next: () => {
this.toaster.show('Success', '');
this.snackBar.open('', 'Success');
this.router.navigate(['/employee-benefits'], { replaceUrl: true });
},
error: (error) => {
this.toaster.show('Danger', error);
this.snackBar.open(error, 'Danger');
},
});
}
@@ -6,13 +6,7 @@
<div class="flex flex-row justify-around content-start items-start sm:max-lg:flex-col">
<mat-form-field class="flex-auto basis-4/5 mr-5">
<mat-label>Date</mat-label>
<input
matInput
[matDatepicker]="creditSalaryMonth"
(focus)="creditSalaryMonth.open()"
formControlName="date"
autocomplete="off"
/>
<input matInput [matDatepicker]="creditSalaryMonth" formControlName="date" autocomplete="off" />
<mat-datepicker-toggle matSuffix [for]="creditSalaryMonth"></mat-datepicker-toggle>
<mat-datepicker
#creditSalaryMonth
@@ -39,25 +33,13 @@
>
<mat-form-field class="flex-auto basis-[35%] mr-5">
<mat-label>Start Date</mat-label>
<input
matInput
[matDatepicker]="attendanceStartDate"
(focus)="attendanceStartDate.open()"
formControlName="startDate"
autocomplete="off"
/>
<input matInput [matDatepicker]="attendanceStartDate" formControlName="startDate" autocomplete="off" />
<mat-datepicker-toggle matSuffix [for]="attendanceStartDate"></mat-datepicker-toggle>
<mat-datepicker #attendanceStartDate></mat-datepicker>
</mat-form-field>
<mat-form-field class="flex-auto basis-[35%] mr-5">
<mat-label>Finish Date</mat-label>
<input
matInput
[matDatepicker]="attendanceFinishDate"
(focus)="attendanceFinishDate.open()"
formControlName="finishDate"
autocomplete="off"
/>
<input matInput [matDatepicker]="attendanceFinishDate" formControlName="finishDate" autocomplete="off" />
<mat-datepicker-toggle matSuffix [for]="attendanceFinishDate"></mat-datepicker-toggle>
<mat-datepicker #attendanceFinishDate></mat-datepicker>
</mat-form-field>
@@ -9,7 +9,7 @@ import { MatTabGroup, MatTab } from '@angular/material/tabs';
import moment from 'moment';
import { Moment } from 'moment';
import { ToasterService } from '../core/toaster.service';
import { MatSnackBar } from '@angular/material/snack-bar';
import { EmployeeFunctionsService } from './employee-functions.service';
@@ -48,7 +48,7 @@ export class EmployeeFunctionsComponent {
fingerprintFile: File | null = null;
constructor(
private toaster: ToasterService,
private snackBar: MatSnackBar,
private ser: EmployeeFunctionsService,
) {
const startDate = moment().date(1);
@@ -80,15 +80,15 @@ export class EmployeeFunctionsComponent {
creditSalary() {
const date = (this.creditSalaryForm.value.date ?? moment()).format('DD-MMM-YYYY');
if (!date) {
this.toaster.show('Danger', 'Please choose a valid date.');
this.snackBar.open('Please choose a valid date.', 'Danger');
return;
}
this.ser.creditSalary(date).subscribe({
next: () => {
this.toaster.show('Success', 'Salaries Credited');
this.snackBar.open('Salaries Credited', 'Success');
},
error: (error) => {
this.toaster.show('Danger', error);
this.snackBar.open(error, 'Danger');
},
});
}
@@ -97,7 +97,7 @@ export class EmployeeFunctionsComponent {
const startDate = (this.attendanceRecordForm.value.startDate ?? moment()).format('DD-MMM-YYYY');
const finishDate = (this.attendanceRecordForm.value.finishDate ?? moment()).format('DD-MMM-YYYY');
if (!startDate || !finishDate) {
// this.toaster.show('Danger', 'Please choose a start and finish date.');
// this.snackBar.open('Please choose a start and finish date.', 'Danger');
return '';
}
return `/attendance-report?s=${startDate}&f=${finishDate}`;
@@ -107,7 +107,7 @@ export class EmployeeFunctionsComponent {
const startDate = (this.attendanceRecordForm.value.startDate ?? moment()).format('DD-MMM-YYYY');
const finishDate = (this.attendanceRecordForm.value.finishDate ?? moment()).format('DD-MMM-YYYY');
if (!startDate || !finishDate) {
// this.toaster.show('Danger', 'Please choose a start and finish date.');
// this.snackBar.open('Please choose a start and finish date.', 'Danger');
return '';
}
return `/fingerprint-report?s=${startDate}&f=${finishDate}`;
@@ -119,15 +119,15 @@ export class EmployeeFunctionsComponent {
uploadFingerprints() {
if (!this.fingerprintFile) {
this.toaster.show('Danger', 'Please choose a file first!');
this.snackBar.open('Please choose a file first!', 'Danger');
return;
}
this.ser.uploadFingerprints(this.fingerprintFile).subscribe({
next: () => {
this.toaster.show('Success', 'Fingerprints uploaded');
this.snackBar.open('Fingerprints uploaded', 'Success');
},
error: (error) => {
this.toaster.show('Danger', error);
this.snackBar.open(error, 'Danger');
},
});
}
@@ -56,26 +56,14 @@
</div>
<mat-form-field class="flex-auto">
<mat-label>Joining Date</mat-label>
<input
matInput
[matDatepicker]="joiningDate"
(focus)="joiningDate.open()"
formControlName="joiningDate"
autocomplete="off"
/>
<input matInput [matDatepicker]="joiningDate" formControlName="joiningDate" autocomplete="off" />
<mat-datepicker-toggle matSuffix [for]="joiningDate"></mat-datepicker-toggle>
<mat-datepicker #joiningDate></mat-datepicker>
</mat-form-field>
@if (!item.isActive) {
<mat-form-field class="flex-auto">
<mat-label>Leaving Date</mat-label>
<input
matInput
[matDatepicker]="leavingDate"
(focus)="leavingDate.open()"
formControlName="leavingDate"
autocomplete="off"
/>
<input matInput [matDatepicker]="leavingDate" formControlName="leavingDate" autocomplete="off" />
<mat-datepicker-toggle matSuffix [for]="leavingDate"></mat-datepicker-toggle>
<mat-datepicker #leavingDate></mat-datepicker>
</mat-form-field>
@@ -21,7 +21,7 @@ import { ActivatedRoute, Router } from '@angular/router';
import moment from 'moment';
import { CostCentre } from '../../core/cost-centre';
import { ToasterService } from '../../core/toaster.service';
import { MatSnackBar } from '@angular/material/snack-bar';
import { ConfirmDialogComponent } from '../../shared/confirm-dialog/confirm-dialog.component';
import { Employee } from '../employee';
import { EmployeeService } from '../employee.service';
@@ -54,7 +54,7 @@ import { EmployeeService } from '../employee.service';
],
})
export class EmployeeDetailComponent implements OnInit, AfterViewInit {
@ViewChild('nameElement', { static: true }) nameElement?: ElementRef;
@ViewChild('nameElement', { static: true }) nameElement!: ElementRef<HTMLInputElement>;
form: FormGroup<{
code: FormControl<string | number>;
name: FormControl<string | null>;
@@ -74,7 +74,7 @@ export class EmployeeDetailComponent implements OnInit, AfterViewInit {
private route: ActivatedRoute,
private router: Router,
private dialog: MatDialog,
private toaster: ToasterService,
private snackBar: MatSnackBar,
private ser: EmployeeService,
) {
this.form = new FormGroup({
@@ -120,20 +120,18 @@ export class EmployeeDetailComponent implements OnInit, AfterViewInit {
ngAfterViewInit() {
setTimeout(() => {
if (this.nameElement) {
this.nameElement.nativeElement.focus();
}
this.nameElement.nativeElement.focus();
}, 0);
}
save() {
this.ser.saveOrUpdate(this.getItem()).subscribe({
next: () => {
this.toaster.show('Success', '');
this.snackBar.open('', 'Success');
this.router.navigateByUrl('/employees');
},
error: (error) => {
this.toaster.show('Danger', error);
this.snackBar.open(error, 'Danger');
},
});
}
@@ -141,11 +139,11 @@ export class EmployeeDetailComponent implements OnInit, AfterViewInit {
delete() {
this.ser.delete(this.item.id as string).subscribe({
next: () => {
this.toaster.show('Success', '');
this.snackBar.open('', 'Success');
this.router.navigateByUrl('/employees');
},
error: (error) => {
this.toaster.show('Danger', error);
this.snackBar.open(error, 'Danger');
},
});
}
@@ -67,9 +67,9 @@ import { EmployeeListDataSource } from './employee-list-datasource';
],
})
export class EmployeeListComponent implements OnInit, AfterViewInit {
@ViewChild('filterElement', { static: true }) filterElement?: ElementRef;
@ViewChild(MatPaginator, { static: true }) paginator?: MatPaginator;
@ViewChild(MatSort, { static: true }) sort?: MatSort;
@ViewChild('filterElement', { static: true }) filterElement!: ElementRef<HTMLInputElement>;
@ViewChild(MatPaginator, { static: true }) paginator!: MatPaginator;
@ViewChild(MatSort, { static: true }) sort!: MatSort;
dataSource: EmployeeListDataSource;
filter: Observable<string>;
form: FormGroup<{
@@ -89,7 +89,7 @@ export class EmployeeListComponent implements OnInit, AfterViewInit {
filter: new FormControl<string>('', { nonNullable: true }),
});
this.filter = this.form.controls.filter.valueChanges.pipe(debounceTime(150), distinctUntilChanged());
this.dataSource = new EmployeeListDataSource(this.list, this.filter);
this.dataSource = new EmployeeListDataSource(this.list, this.filter, this.paginator, this.sort);
}
ngOnInit() {
@@ -103,9 +103,7 @@ export class EmployeeListComponent implements OnInit, AfterViewInit {
ngAfterViewInit() {
setTimeout(() => {
if (this.filterElement) {
this.filterElement.nativeElement.focus();
}
this.filterElement.nativeElement.focus();
}, 0);
}
@@ -7,7 +7,13 @@
<div class="flex flex-row justify-around content-start items-start sm:max-lg:flex-col">
<mat-form-field class="flex-auto basis-2/5 mr-5">
<mat-label>Create / Last Edit Date From</mat-label>
<input matInput [matDatepicker]="startDate" formControlName="startDate" autocomplete="off" />
<input
matInput
#startDateElement
[matDatepicker]="startDate"
formControlName="startDate"
autocomplete="off"
/>
<mat-datepicker-toggle matSuffix [for]="startDate"></mat-datepicker-toggle>
<mat-datepicker #startDate></mat-datepicker>
</mat-form-field>
+17 -7
View File
@@ -1,5 +1,5 @@
import { CurrencyPipe } from '@angular/common';
import { Component, OnInit, ViewChild } from '@angular/core';
import { Component, ElementRef, HostListener, OnInit, ViewChild } from '@angular/core';
import { FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms';
import { MatButton } from '@angular/material/button';
import { MatCard, MatCardHeader, MatCardTitle, MatCardContent } from '@angular/material/card';
@@ -73,10 +73,11 @@ import { Report } from './report';
],
})
export class EntriesComponent implements OnInit {
@ViewChild(MatPaginator, { static: true }) paginator?: MatPaginator;
@ViewChild(MatSort, { static: true }) sort?: MatSort;
@ViewChild(MatPaginator, { static: true }) paginator!: MatPaginator;
@ViewChild(MatSort, { static: true }) sort!: MatSort;
@ViewChild('startDateElement', { static: true }) startDate!: ElementRef<HTMLInputElement>;
info: Report = new Report();
dataSource: EntriesDatasource = new EntriesDatasource(this.info.report, 0);
dataSource: EntriesDatasource;
form: FormGroup<{
startDate: FormControl<Date>;
finishDate: FormControl<Date>;
@@ -88,6 +89,14 @@ export class EntriesComponent implements OnInit {
posted: boolean | null = null;
issue = false;
@HostListener('window:keydown.f2', ['$event'])
focusDate(event: KeyboardEvent) {
event.preventDefault();
this.startDate.nativeElement.focus();
this.startDate.nativeElement.select();
}
constructor(
private route: ActivatedRoute,
private router: Router,
@@ -98,6 +107,7 @@ export class EntriesComponent implements OnInit {
posted: new FormControl<boolean | null>(null),
issue: new FormControl<boolean>(false, { nonNullable: true }),
});
this.dataSource = new EntriesDatasource(this.info.report, 0, this.paginator, this.sort);
}
ngOnInit() {
@@ -141,7 +151,7 @@ export class EntriesComponent implements OnInit {
sortDirection,
);
});
this.sort?.sortChange.subscribe({
this.sort.sortChange.subscribe({
next: () =>
this.router.navigate([], {
relativeTo: this.route,
@@ -149,11 +159,11 @@ export class EntriesComponent implements OnInit {
queryParamsHandling: 'merge',
}),
});
this.paginator?.page.subscribe({
this.paginator.page.subscribe({
next: () =>
this.router.navigate([], {
relativeTo: this.route,
queryParams: { ps: this.paginator?.pageSize, pi: this.paginator?.pageIndex },
queryParams: { ps: this.paginator.pageSize, pi: this.paginator.pageIndex },
queryParamsHandling: 'merge',
}),
});
@@ -7,7 +7,14 @@
<div class="flex flex-row justify-around content-start items-start">
<mat-form-field class="flex-auto">
<mat-label>Date</mat-label>
<input matInput [matDatepicker]="date" (focus)="date.open()" formControlName="date" autocomplete="off" />
<input
matInput
#dateElement
[matDatepicker]="date"
(focus)="dateElement.select()"
formControlName="date"
autocomplete="off"
/>
<mat-datepicker-toggle matSuffix [for]="date"></mat-datepicker-toggle>
<mat-datepicker #date></mat-datepicker>
</mat-form-field>
@@ -36,7 +36,7 @@ import { AuthService } from '../auth/auth.service';
import { Account } from '../core/account';
import { AccountBalance } from '../core/account-balance';
import { Incentive } from '../core/incentive';
import { ToasterService } from '../core/toaster.service';
import { MatSnackBar } from '@angular/material/snack-bar';
import { User } from '../core/user';
import { Voucher } from '../core/voucher';
import { VoucherService } from '../core/voucher.service';
@@ -44,6 +44,9 @@ import { ConfirmDialogComponent } from '../shared/confirm-dialog/confirm-dialog.
import { LocalTimePipe } from '../shared/local-time.pipe';
import { IncentiveDataSource } from './incentive-datasource';
import { ViewChild } from '@angular/core';
import { ElementRef } from '@angular/core';
import { HostListener } from '@angular/core';
@Component({
selector: 'app-incentive',
@@ -85,6 +88,7 @@ import { IncentiveDataSource } from './incentive-datasource';
],
})
export class IncentiveComponent implements OnInit {
@ViewChild('dateElement', { static: true }) dateElement!: ElementRef<HTMLInputElement>;
public incentiveObservable = new BehaviorSubject<Incentive[]>([]);
dataSource: IncentiveDataSource = new IncentiveDataSource(this.incentiveObservable);
form: FormGroup<{
@@ -102,11 +106,18 @@ export class IncentiveComponent implements OnInit {
displayedColumns = ['name', 'designation', 'department', 'daysWorked', 'points', 'amount'];
@HostListener('window:keydown.f2', ['$event'])
focusDate(event: KeyboardEvent) {
event.preventDefault();
this.dateElement.nativeElement.focus();
this.dateElement.nativeElement.select();
}
constructor(
private route: ActivatedRoute,
private router: Router,
private dialog: MatDialog,
private toaster: ToasterService,
private snackBar: MatSnackBar,
public auth: AuthService,
private ser: VoucherService,
) {
@@ -193,10 +204,10 @@ export class IncentiveComponent implements OnInit {
this.ser.post(this.voucher.id as string).subscribe({
next: (result) => {
this.loadVoucher(result);
this.toaster.show('Success', 'Voucher Posted');
this.snackBar.open('Voucher Posted', 'Success');
},
error: (error) => {
this.toaster.show('Danger', error);
this.snackBar.open(error, 'Danger');
},
});
}
@@ -212,7 +223,7 @@ export class IncentiveComponent implements OnInit {
}
},
error: (error) => {
this.toaster.show('Danger', error);
this.snackBar.open(error, 'Danger');
},
});
}
@@ -231,11 +242,11 @@ export class IncentiveComponent implements OnInit {
delete() {
this.ser.delete(this.voucher.id as string).subscribe({
next: () => {
this.toaster.show('Success', '');
this.snackBar.open('', 'Success');
this.router.navigate(['/incentive'], { replaceUrl: true });
},
error: (error) => {
this.toaster.show('Danger', error);
this.snackBar.open(error, 'Danger');
},
});
}
+1 -8
View File
@@ -7,14 +7,7 @@
<div class="flex flex-row justify-around content-start items-start sm:max-lg:flex-col">
<mat-form-field class="flex-auto basis-[28%] mr-5">
<mat-label>Date</mat-label>
<input
matInput
[matDatepicker]="date"
formControlName="date"
autocomplete="off"
#dateElement
(focus)="dateElement.select()"
/>
<input matInput [matDatepicker]="date" formControlName="date" autocomplete="off" #dateElement />
<mat-datepicker-toggle matSuffix [for]="date"></mat-datepicker-toggle>
<mat-datepicker #date></mat-datepicker>
</mat-form-field>
+30 -50
View File
@@ -1,5 +1,5 @@
import { AsyncPipe, DecimalPipe, CurrencyPipe } from '@angular/common';
import { AfterViewInit, Component, ElementRef, OnInit, OnDestroy, ViewChild } from '@angular/core';
import { AfterViewInit, Component, ElementRef, OnInit, ViewChild, HostListener } from '@angular/core';
import { FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms';
import { MatAutocompleteSelectedEvent, MatAutocompleteTrigger, MatAutocomplete } from '@angular/material/autocomplete';
import { MatButton, MatIconButton } from '@angular/material/button';
@@ -32,7 +32,6 @@ import {
MatRow,
} from '@angular/material/table';
import { ActivatedRoute, Router } from '@angular/router';
import { Hotkey, HotkeysService } from 'angular2-hotkeys';
import { round } from 'mathjs';
import moment from 'moment';
import { BehaviorSubject, Observable, of as observableOf } from 'rxjs';
@@ -44,7 +43,7 @@ import { BatchService } from '../core/batch.service';
import { CostCentre } from '../core/cost-centre';
import { Inventory } from '../core/inventory';
import { IssueGridItem } from '../core/issue-grid-item';
import { ToasterService } from '../core/toaster.service';
import { MatSnackBar } from '@angular/material/snack-bar';
import { User } from '../core/user';
import { Voucher } from '../core/voucher';
import { VoucherService } from '../core/voucher.service';
@@ -102,9 +101,25 @@ import { IssueGridService } from './issue-grid.service';
LocalTimePipe,
],
})
export class IssueComponent implements OnInit, AfterViewInit, OnDestroy {
@ViewChild('batchElement', { static: true }) batchElement?: ElementRef;
@ViewChild('dateElement', { static: true }) dateElement?: ElementRef;
export class IssueComponent implements OnInit, AfterViewInit {
@ViewChild('batchElement', { static: true }) batchElement!: ElementRef<HTMLInputElement>;
@ViewChild('dateElement', { static: true }) dateElement!: ElementRef<HTMLInputElement>;
@HostListener('window:keydown.f2', ['$event'])
focusDate(event: KeyboardEvent) {
event.preventDefault();
this.dateElement.nativeElement.focus();
this.dateElement.nativeElement.select();
}
@HostListener('window:keydown.control.s', ['$event'])
saveListner(event: KeyboardEvent) {
event.preventDefault();
if (this.canSave()) {
this.save();
}
}
public inventoryObservable = new BehaviorSubject<Inventory[]>([]);
public gridObservable = new BehaviorSubject<IssueGridItem[]>([]);
dataSource: IssueDataSource = new IssueDataSource(this.inventoryObservable);
@@ -134,8 +149,7 @@ export class IssueComponent implements OnInit, AfterViewInit, OnDestroy {
private route: ActivatedRoute,
private router: Router,
private dialog: MatDialog,
private hotkeys: HotkeysService,
private toaster: ToasterService,
private snackBar: MatSnackBar,
private auth: AuthService,
private math: MathService,
private ser: VoucherService,
@@ -177,42 +191,12 @@ export class IssueComponent implements OnInit, AfterViewInit, OnDestroy {
this.costCentres = data.costCentres;
this.loadVoucher(data.voucher);
});
this.hotkeys.add(
new Hotkey(
'f2',
(): boolean => {
setTimeout(() => {
if (this.dateElement) {
this.dateElement.nativeElement.focus();
}
}, 0);
return false; // Prevent bubbling
},
['INPUT', 'SELECT', 'TEXTAREA'],
),
);
this.hotkeys.add(
new Hotkey(
'ctrl+s',
(): boolean => {
if (this.canSave()) {
this.save();
}
return false; // Prevent bubbling
},
['INPUT', 'SELECT', 'TEXTAREA'],
),
);
}
ngAfterViewInit() {
this.focusBatch();
}
ngOnDestroy() {
this.hotkeys.reset();
}
loadVoucher(voucher: Voucher) {
this.voucher = voucher;
this.form.setValue({
@@ -232,9 +216,7 @@ export class IssueComponent implements OnInit, AfterViewInit, OnDestroy {
focusBatch() {
setTimeout(() => {
if (this.batchElement) {
this.batchElement.nativeElement.focus();
}
this.batchElement.nativeElement.focus();
}, 0);
}
@@ -251,13 +233,13 @@ export class IssueComponent implements OnInit, AfterViewInit, OnDestroy {
const old = this.voucher.inventories.find((x) => x.batch.id === (this.batch as Batch).id);
if (old !== undefined) {
if (isConsumption && old.quantity + quantity > this.batch.quantityRemaining) {
this.toaster.show('Danger', 'Quantity issued cannot be more than quantity available');
this.snackBar.open('Quantity issued cannot be more than quantity available', 'Danger');
return;
}
old.quantity += quantity;
} else {
if (isConsumption && quantity > this.batch.quantityRemaining) {
this.toaster.show('Danger', 'Quantity issued cannot be more than quantity available');
this.snackBar.open('Quantity issued cannot be more than quantity available', 'Danger');
return;
}
this.voucher.inventories.push(
@@ -279,9 +261,7 @@ export class IssueComponent implements OnInit, AfterViewInit, OnDestroy {
this.form.controls.addRow.reset();
this.batch = null;
setTimeout(() => {
if (this.batchElement) {
this.batchElement.nativeElement.focus();
}
this.batchElement.nativeElement.focus();
}, 0);
}
@@ -335,7 +315,7 @@ export class IssueComponent implements OnInit, AfterViewInit, OnDestroy {
const voucher: Voucher = this.getVoucher();
this.ser.saveOrUpdate(voucher).subscribe({
next: (result) => {
this.toaster.show('Success', '');
this.snackBar.open('', 'Success');
if (voucher.id === result.id) {
this.loadVoucher(result);
} else {
@@ -343,7 +323,7 @@ export class IssueComponent implements OnInit, AfterViewInit, OnDestroy {
}
},
error: (error) => {
this.toaster.show('Danger', error);
this.snackBar.open(error, 'Danger');
},
});
}
@@ -364,11 +344,11 @@ export class IssueComponent implements OnInit, AfterViewInit, OnDestroy {
delete() {
this.ser.delete(this.voucher.id as string).subscribe({
next: () => {
this.toaster.show('Success', '');
this.snackBar.open('', 'Success');
this.router.navigate(['/issue'], { replaceUrl: true });
},
error: (error) => {
this.toaster.show('Danger', error);
this.snackBar.open(error, 'Danger');
},
});
}
@@ -17,14 +17,7 @@
<div class="flex flex-row justify-around content-start items-start">
<mat-form-field class="flex-auto">
<mat-label>Date</mat-label>
<input
matInput
[matDatepicker]="date"
formControlName="date"
autocomplete="off"
#dateElement
(focus)="dateElement.select()"
/>
<input matInput [matDatepicker]="date" formControlName="date" autocomplete="off" #dateElement />
<mat-datepicker-toggle matSuffix [for]="date"></mat-datepicker-toggle>
<mat-datepicker #date></mat-datepicker>
</mat-form-field>
+38 -62
View File
@@ -1,6 +1,6 @@
import { COMMA, ENTER } from '@angular/cdk/keycodes';
import { AsyncPipe, CurrencyPipe } from '@angular/common';
import { AfterViewInit, Component, ElementRef, OnInit, OnDestroy, ViewChild } from '@angular/core';
import { AfterViewInit, Component, ElementRef, OnInit, ViewChild, HostListener } from '@angular/core';
import { FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms';
import { MatAutocompleteSelectedEvent, MatAutocompleteTrigger, MatAutocomplete } from '@angular/material/autocomplete';
import { MatButton, MatIconButton } from '@angular/material/button';
@@ -34,7 +34,6 @@ import {
MatRow,
} from '@angular/material/table';
import { ActivatedRoute, Router } from '@angular/router';
import { Hotkey, HotkeysService } from 'angular2-hotkeys';
import { round } from 'mathjs';
import moment from 'moment';
import { BehaviorSubject, Observable, of as observableOf } from 'rxjs';
@@ -48,7 +47,7 @@ import { DbFile } from '../core/db-file';
import { Journal } from '../core/journal';
import { Tag } from '../core/tag';
import { TagService } from '../core/tag.service';
import { ToasterService } from '../core/toaster.service';
import { MatSnackBar } from '@angular/material/snack-bar';
import { User } from '../core/user';
import { Voucher } from '../core/voucher';
import { VoucherService } from '../core/voucher.service';
@@ -112,10 +111,34 @@ import { JournalDialogComponent } from './journal-dialog.component';
LocalTimePipe,
],
})
export class JournalComponent implements OnInit, AfterViewInit, OnDestroy {
@ViewChild('accountElement', { static: true }) accountElement?: ElementRef;
@ViewChild('dateElement', { static: true }) dateElement?: ElementRef;
export class JournalComponent implements OnInit, AfterViewInit {
@ViewChild('accountElement', { static: true }) accountElement!: ElementRef<HTMLInputElement>;
@ViewChild('dateElement', { static: false }) dateElement!: ElementRef<HTMLInputElement>;
@ViewChild('tagInput') tagInput?: ElementRef<HTMLInputElement>;
@HostListener('window:keydown.f2', ['$event'])
focusDate(event: KeyboardEvent) {
event.preventDefault();
this.dateElement.nativeElement.focus();
this.dateElement.nativeElement.select();
}
@HostListener('window:keydown.control.s', ['$event'])
saveListner(event: KeyboardEvent) {
event.preventDefault();
if (this.canSave()) {
this.save();
}
}
@HostListener('window:keydown.control.p', ['$event'])
postListner(event: KeyboardEvent) {
event.preventDefault();
if (this.voucher.id && !this.voucher.posted && this.auth.allowed('post-vouchers')) {
this.post();
}
}
separatorKeysCodes: number[] = [ENTER, COMMA];
public journalObservable = new BehaviorSubject<Journal[]>([]);
dataSource: JournalDataSource = new JournalDataSource(this.journalObservable);
@@ -143,8 +166,7 @@ export class JournalComponent implements OnInit, AfterViewInit, OnDestroy {
private route: ActivatedRoute,
private router: Router,
private dialog: MatDialog,
private hotkeys: HotkeysService,
private toaster: ToasterService,
private snackBar: MatSnackBar,
public auth: AuthService,
private math: MathService,
public image: ImageService,
@@ -184,54 +206,12 @@ export class JournalComponent implements OnInit, AfterViewInit, OnDestroy {
this.loadVoucher(data.voucher);
});
this.hotkeys.add(
new Hotkey(
'f2',
(): boolean => {
setTimeout(() => {
if (this.dateElement) {
this.dateElement.nativeElement.focus();
}
}, 0);
return false; // Prevent bubbling
},
['INPUT', 'SELECT', 'TEXTAREA'],
),
);
this.hotkeys.add(
new Hotkey(
'ctrl+s',
(): boolean => {
if (this.canSave()) {
this.save();
}
return false; // Prevent bubbling
},
['INPUT', 'SELECT', 'TEXTAREA'],
),
);
this.hotkeys.add(
new Hotkey(
'ctrl+p',
(): boolean => {
if (this.voucher.id && !this.voucher.posted && this.auth.allowed('post-vouchers')) {
this.post();
}
return false; // Prevent bubbling
},
['INPUT', 'SELECT', 'TEXTAREA'],
),
);
}
ngAfterViewInit() {
this.focusAccount();
}
ngOnDestroy() {
this.hotkeys.reset();
}
loadVoucher(voucher: Voucher) {
this.voucher = voucher;
this.form.setValue({
@@ -250,9 +230,7 @@ export class JournalComponent implements OnInit, AfterViewInit, OnDestroy {
focusAccount() {
setTimeout(() => {
if (this.accountElement) {
this.accountElement.nativeElement.focus();
}
this.accountElement.nativeElement.focus();
}, 0);
}
@@ -295,9 +273,7 @@ export class JournalComponent implements OnInit, AfterViewInit, OnDestroy {
this.account = null;
this.accBal = null;
setTimeout(() => {
if (this.accountElement) {
this.accountElement.nativeElement.focus();
}
this.accountElement.nativeElement.focus();
}, 0);
}
@@ -350,10 +326,10 @@ export class JournalComponent implements OnInit, AfterViewInit, OnDestroy {
this.ser.post(this.voucher.id as string).subscribe({
next: (result) => {
this.loadVoucher(result);
this.toaster.show('Success', 'Voucher Posted');
this.snackBar.open('Voucher Posted', 'Success');
},
error: (error) => {
this.toaster.show('Danger', error);
this.snackBar.open(error, 'Danger');
},
});
}
@@ -362,7 +338,7 @@ export class JournalComponent implements OnInit, AfterViewInit, OnDestroy {
const voucher: Voucher = this.getVoucher();
this.ser.saveOrUpdate(voucher).subscribe({
next: (result) => {
this.toaster.show('Success', '');
this.snackBar.open('', 'Success');
if (voucher.id === result.id) {
this.loadVoucher(result);
} else {
@@ -370,7 +346,7 @@ export class JournalComponent implements OnInit, AfterViewInit, OnDestroy {
}
},
error: (error) => {
this.toaster.show('Danger', error);
this.snackBar.open(error, 'Danger');
},
});
}
@@ -385,11 +361,11 @@ export class JournalComponent implements OnInit, AfterViewInit, OnDestroy {
delete() {
this.ser.delete(this.voucher.id as string).subscribe({
next: () => {
this.toaster.show('Success', '');
this.snackBar.open('', 'Success');
this.router.navigate(['/journal'], { replaceUrl: true });
},
error: (error) => {
this.toaster.show('Danger', error);
this.snackBar.open(error, 'Danger');
},
});
}
@@ -16,8 +16,8 @@
<mat-label>Start Date</mat-label>
<input
matInput
#startDateElement
[matDatepicker]="startDate"
(focus)="startDate.open()"
formControlName="startDate"
autocomplete="off"
/>
@@ -26,13 +26,7 @@
</mat-form-field>
<mat-form-field class="flex-auto">
<mat-label>Finish Date</mat-label>
<input
matInput
[matDatepicker]="finishDate"
(focus)="finishDate.open()"
formControlName="finishDate"
autocomplete="off"
/>
<input matInput [matDatepicker]="finishDate" formControlName="finishDate" autocomplete="off" />
<mat-datepicker-toggle matSuffix [for]="finishDate"></mat-datepicker-toggle>
<mat-datepicker #finishDate></mat-datepicker>
</mat-form-field>
@@ -109,7 +103,7 @@
<!-- Running Column -->
<ng-container matColumnDef="running">
<mat-header-cell *matHeaderCellDef mat-sort-header class="right">Running</mat-header-cell>
<mat-header-cell *matHeaderCellDef class="right">Running</mat-header-cell>
<mat-cell *matCellDef="let row" class="right">{{ row.running | currency: 'INR' | accounting }}</mat-cell>
<mat-footer-cell *matFooterCellDef class="right">{{ running | currency: 'INR' | accounting }}</mat-footer-cell>
</ng-container>
+11 -3
View File
@@ -92,9 +92,10 @@ import { LedgerService } from './ledger.service';
],
})
export class LedgerComponent implements OnInit, AfterViewInit {
@ViewChild('accountElement', { static: true }) accountElement?: ElementRef;
@ViewChild(MatPaginator, { static: true }) paginator?: MatPaginator;
@ViewChild(MatSort, { static: true }) sort?: MatSort;
@ViewChild('accountElement', { static: true }) accountElement!: ElementRef<HTMLInputElement>;
@ViewChild('startDateElement', { static: true }) startDate!: ElementRef<HTMLInputElement>;
@ViewChild(MatPaginator, { static: true }) paginator!: MatPaginator;
@ViewChild(MatSort, { static: true }) sort!: MatSort;
info: Ledger = new Ledger();
dataSource: LedgerDataSource = new LedgerDataSource(this.info.body);
form: FormGroup<{
@@ -112,6 +113,13 @@ export class LedgerComponent implements OnInit, AfterViewInit {
accounts: Observable<Account[]>;
@HostListener('window:keydown.f2', ['$event'])
focusDate(event: KeyboardEvent) {
event.preventDefault();
this.startDate.nativeElement.focus();
this.startDate.nativeElement.select();
}
constructor(
private route: ActivatedRoute,
private router: Router,
@@ -9,8 +9,8 @@
<mat-label>Start Date</mat-label>
<input
matInput
#startDateElement
[matDatepicker]="startDate"
(focus)="startDate.open()"
formControlName="startDate"
autocomplete="off"
/>
@@ -19,13 +19,7 @@
</mat-form-field>
<mat-form-field class="flex-auto basis-2/5 mr-5">
<mat-label>Finish Date</mat-label>
<input
matInput
[matDatepicker]="finishDate"
(focus)="finishDate.open()"
formControlName="finishDate"
autocomplete="off"
/>
<input matInput [matDatepicker]="finishDate" formControlName="finishDate" autocomplete="off" />
<mat-datepicker-toggle matSuffix [for]="finishDate"></mat-datepicker-toggle>
<mat-datepicker #finishDate></mat-datepicker>
</mat-form-field>
@@ -1,5 +1,5 @@
import { CurrencyPipe } from '@angular/common';
import { Component, OnInit, ViewChild } from '@angular/core';
import { Component, ElementRef, HostListener, OnInit, ViewChild } from '@angular/core';
import { FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms';
import { MatButton } from '@angular/material/button';
import { MatCard, MatCardHeader, MatCardTitle, MatCardContent } from '@angular/material/card';
@@ -65,10 +65,11 @@ import { NetTransactionsDataSource } from './net-transactions-datasource';
],
})
export class NetTransactionsComponent implements OnInit {
@ViewChild(MatPaginator, { static: true }) paginator?: MatPaginator;
@ViewChild(MatSort, { static: true }) sort?: MatSort;
@ViewChild(MatPaginator, { static: true }) paginator!: MatPaginator;
@ViewChild(MatSort, { static: true }) sort!: MatSort;
@ViewChild('startDateElement', { static: true }) startDate!: ElementRef<HTMLInputElement>;
info: NetTransactions = new NetTransactions();
dataSource: NetTransactionsDataSource = new NetTransactionsDataSource(this.info.body);
dataSource: NetTransactionsDataSource = new NetTransactionsDataSource(this.info.body, this.paginator, this.sort);
form: FormGroup<{
startDate: FormControl<Date>;
finishDate: FormControl<Date>;
@@ -78,6 +79,13 @@ export class NetTransactionsComponent implements OnInit {
/** Columns displayed in the table. Columns IDs can be added, removed, or reordered. */
displayedColumns = ['type', 'name', 'debit', 'credit'];
@HostListener('window:keydown.f2', ['$event'])
focusDate(event: KeyboardEvent) {
event.preventDefault();
this.startDate.nativeElement.focus();
this.startDate.nativeElement.select();
}
constructor(
private route: ActivatedRoute,
private router: Router,
@@ -17,14 +17,7 @@
<div class="flex flex-row justify-around content-start items-start sm:max-lg:flex-col">
<mat-form-field class="flex-auto basis-2/5 mr-5">
<mat-label>Date</mat-label>
<input
matInput
[matDatepicker]="date"
formControlName="date"
autocomplete="off"
#dateElement
(focus)="dateElement.select()"
/>
<input matInput [matDatepicker]="date" formControlName="date" autocomplete="off" #dateElement />
<mat-datepicker-toggle matSuffix [for]="date"></mat-datepicker-toggle>
<mat-datepicker #date></mat-datepicker>
</mat-form-field>
+38 -62
View File
@@ -1,6 +1,6 @@
import { COMMA, ENTER } from '@angular/cdk/keycodes';
import { AsyncPipe, CurrencyPipe } from '@angular/common';
import { AfterViewInit, Component, ElementRef, OnInit, OnDestroy, ViewChild } from '@angular/core';
import { AfterViewInit, Component, ElementRef, OnInit, ViewChild, HostListener } from '@angular/core';
import { FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms';
import { MatAutocompleteSelectedEvent, MatAutocompleteTrigger, MatAutocomplete } from '@angular/material/autocomplete';
import { MatButton, MatIconButton } from '@angular/material/button';
@@ -34,7 +34,6 @@ import {
MatRow,
} from '@angular/material/table';
import { ActivatedRoute, Router } from '@angular/router';
import { Hotkey, HotkeysService } from 'angular2-hotkeys';
import { round } from 'mathjs';
import moment from 'moment';
import { BehaviorSubject, Observable, of as observableOf } from 'rxjs';
@@ -48,7 +47,7 @@ import { DbFile } from '../core/db-file';
import { Journal } from '../core/journal';
import { Tag } from '../core/tag';
import { TagService } from '../core/tag.service';
import { ToasterService } from '../core/toaster.service';
import { MatSnackBar } from '@angular/material/snack-bar';
import { User } from '../core/user';
import { Voucher } from '../core/voucher';
import { VoucherService } from '../core/voucher.service';
@@ -112,10 +111,34 @@ import { PaymentDialogComponent } from './payment-dialog.component';
LocalTimePipe,
],
})
export class PaymentComponent implements OnInit, AfterViewInit, OnDestroy {
@ViewChild('accountElement', { static: true }) accountElement?: ElementRef;
@ViewChild('dateElement', { static: true }) dateElement?: ElementRef;
export class PaymentComponent implements OnInit, AfterViewInit {
@ViewChild('accountElement', { static: true }) accountElement!: ElementRef<HTMLInputElement>;
@ViewChild('dateElement', { static: true }) dateElement!: ElementRef<HTMLInputElement>;
@ViewChild('tagInput') tagInput?: ElementRef<HTMLInputElement>;
@HostListener('window:keydown.f2', ['$event'])
focusDate(event: KeyboardEvent) {
event.preventDefault();
this.dateElement.nativeElement.focus();
this.dateElement.nativeElement.select();
}
@HostListener('window:keydown.control.s', ['$event'])
saveListner(event: KeyboardEvent) {
event.preventDefault();
if (this.canSave()) {
this.save();
}
}
@HostListener('window:keydown.control.p', ['$event'])
postListner(event: KeyboardEvent) {
event.preventDefault();
if (this.voucher.id && !this.voucher.posted && this.auth.allowed('post-vouchers')) {
this.post();
}
}
separatorKeysCodes: number[] = [ENTER, COMMA];
public journalObservable = new BehaviorSubject<Journal[]>([]);
dataSource: PaymentDataSource = new PaymentDataSource(this.journalObservable);
@@ -146,8 +169,7 @@ export class PaymentComponent implements OnInit, AfterViewInit, OnDestroy {
private route: ActivatedRoute,
private router: Router,
private dialog: MatDialog,
private hotkeys: HotkeysService,
private toaster: ToasterService,
private snackBar: MatSnackBar,
public auth: AuthService,
private math: MathService,
public image: ImageService,
@@ -197,54 +219,12 @@ export class PaymentComponent implements OnInit, AfterViewInit, OnDestroy {
this.paymentAccounts = data.paymentAccounts;
this.loadVoucher(data.voucher);
});
this.hotkeys.add(
new Hotkey(
'f2',
(): boolean => {
setTimeout(() => {
if (this.dateElement) {
this.dateElement.nativeElement.focus();
}
}, 0);
return false; // Prevent bubbling
},
['INPUT', 'SELECT', 'TEXTAREA'],
),
);
this.hotkeys.add(
new Hotkey(
'ctrl+s',
(): boolean => {
if (this.canSave()) {
this.save();
}
return false; // Prevent bubbling
},
['INPUT', 'SELECT', 'TEXTAREA'],
),
);
this.hotkeys.add(
new Hotkey(
'ctrl+p',
(): boolean => {
if (this.voucher.id && !this.voucher.posted && this.auth.allowed('post-vouchers')) {
this.post();
}
return false; // Prevent bubbling
},
['INPUT', 'SELECT', 'TEXTAREA'],
),
);
}
ngAfterViewInit() {
this.focusAccount();
}
ngOnDestroy() {
this.hotkeys.reset();
}
loadVoucher(voucher: Voucher) {
this.voucher = voucher;
[this.paymentJournal] = this.voucher.journals.filter((x) => x.debit === -1);
@@ -265,9 +245,7 @@ export class PaymentComponent implements OnInit, AfterViewInit, OnDestroy {
focusAccount() {
setTimeout(() => {
if (this.accountElement) {
this.accountElement.nativeElement.focus();
}
this.accountElement.nativeElement.focus();
}, 0);
}
@@ -303,9 +281,7 @@ export class PaymentComponent implements OnInit, AfterViewInit, OnDestroy {
this.account = null;
this.accBal = null;
setTimeout(() => {
if (this.accountElement) {
this.accountElement.nativeElement.focus();
}
this.accountElement.nativeElement.focus();
}, 0);
}
@@ -360,10 +336,10 @@ export class PaymentComponent implements OnInit, AfterViewInit, OnDestroy {
this.ser.post(this.voucher.id as string).subscribe({
next: (result) => {
this.loadVoucher(result);
this.toaster.show('Success', 'Voucher Posted');
this.snackBar.open('Voucher Posted', 'Success');
},
error: (error) => {
this.toaster.show('Danger', error);
this.snackBar.open(error, 'Danger');
},
});
}
@@ -372,7 +348,7 @@ export class PaymentComponent implements OnInit, AfterViewInit, OnDestroy {
const voucher: Voucher = this.getVoucher();
this.ser.saveOrUpdate(voucher).subscribe({
next: (result) => {
this.toaster.show('Success', '');
this.snackBar.open('', 'Success');
if (voucher.id === result.id) {
this.loadVoucher(result);
} else {
@@ -380,7 +356,7 @@ export class PaymentComponent implements OnInit, AfterViewInit, OnDestroy {
}
},
error: (error) => {
this.toaster.show('Danger', error);
this.snackBar.open(error, 'Danger');
},
});
}
@@ -396,11 +372,11 @@ export class PaymentComponent implements OnInit, AfterViewInit, OnDestroy {
delete() {
this.ser.delete(this.voucher.id as string).subscribe({
next: () => {
this.toaster.show('Success', '');
this.snackBar.open('', 'Success');
this.router.navigate(['/payment'], { replaceUrl: true });
},
error: (error) => {
this.toaster.show('Danger', error);
this.snackBar.open(error, 'Danger');
},
});
}
@@ -7,7 +7,13 @@
<div class="flex flex-row justify-around content-start items-start">
<mat-form-field class="flex-auto">
<mat-label>Valid From</mat-label>
<input matInput [matDatepicker]="validFrom" formControlName="validFrom" autocomplete="off" />
<input
matInput
#validFromElement
[matDatepicker]="validFrom"
formControlName="validFrom"
autocomplete="off"
/>
<mat-datepicker-toggle matSuffix [for]="validFrom"></mat-datepicker-toggle>
<mat-datepicker #validFrom></mat-datepicker>
</mat-form-field>
@@ -1,4 +1,4 @@
import { Component, OnInit } from '@angular/core';
import { Component, ElementRef, HostListener, OnInit, ViewChild } from '@angular/core';
import { FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms';
import { MatButton } from '@angular/material/button';
import { MatCard, MatCardHeader, MatCardTitle, MatCardContent, MatCardActions } from '@angular/material/card';
@@ -9,7 +9,7 @@ import { MatInput } from '@angular/material/input';
import { ActivatedRoute, Router } from '@angular/router';
import moment from 'moment';
import { ToasterService } from '../../core/toaster.service';
import { MatSnackBar } from '@angular/material/snack-bar';
import { ConfirmDialogComponent } from '../../shared/confirm-dialog/confirm-dialog.component';
import { Period } from '../period';
import { PeriodService } from '../period.service';
@@ -37,6 +37,7 @@ import { PeriodService } from '../period.service';
],
})
export class PeriodDetailComponent implements OnInit {
@ViewChild('startDateElement', { static: true }) startDate!: ElementRef<HTMLInputElement>;
form: FormGroup<{
validFrom: FormControl<Date>;
validTill: FormControl<Date>;
@@ -44,11 +45,18 @@ export class PeriodDetailComponent implements OnInit {
item: Period = new Period();
@HostListener('window:keydown.f2', ['$event'])
focusDate(event: KeyboardEvent) {
event.preventDefault();
this.startDate.nativeElement.focus();
this.startDate.nativeElement.select();
}
constructor(
private route: ActivatedRoute,
private router: Router,
private dialog: MatDialog,
private toaster: ToasterService,
private snackBar: MatSnackBar,
private ser: PeriodService,
) {
this.form = new FormGroup({
@@ -76,11 +84,11 @@ export class PeriodDetailComponent implements OnInit {
save() {
this.ser.saveOrUpdate(this.getItem()).subscribe({
next: () => {
this.toaster.show('Success', '');
this.snackBar.open('', 'Success');
this.router.navigateByUrl('/periods');
},
error: (error) => {
this.toaster.show('Danger', error);
this.snackBar.open(error, 'Danger');
},
});
}
@@ -88,11 +96,11 @@ export class PeriodDetailComponent implements OnInit {
delete() {
this.ser.delete(this.item.id as string).subscribe({
next: () => {
this.toaster.show('Success', '');
this.snackBar.open('', 'Success');
this.router.navigateByUrl('/periods');
},
error: (error) => {
this.toaster.show('Danger', error);
this.snackBar.open(error, 'Danger');
},
});
}
@@ -8,7 +8,7 @@ import { MatInput } from '@angular/material/input';
import { ActivatedRoute, Router } from '@angular/router';
import { ProductGroup } from '../../core/product-group';
import { ToasterService } from '../../core/toaster.service';
import { MatSnackBar } from '@angular/material/snack-bar';
import { ProductGroupService } from '../product-group.service';
@Component({
@@ -31,7 +31,7 @@ import { ProductGroupService } from '../product-group.service';
],
})
export class ProductGroupDetailComponent implements OnInit, AfterViewInit {
@ViewChild('nameElement', { static: true }) nameElement?: ElementRef;
@ViewChild('nameElement', { static: true }) nameElement!: ElementRef<HTMLInputElement>;
form: FormGroup<{
name: FormControl<string | null>;
nutritional: FormControl<boolean>;
@@ -43,7 +43,7 @@ export class ProductGroupDetailComponent implements OnInit, AfterViewInit {
constructor(
private route: ActivatedRoute,
private router: Router,
private toaster: ToasterService,
private snackBar: MatSnackBar,
private ser: ProductGroupService,
) {
this.form = new FormGroup({
@@ -72,20 +72,18 @@ export class ProductGroupDetailComponent implements OnInit, AfterViewInit {
ngAfterViewInit() {
setTimeout(() => {
if (this.nameElement) {
this.nameElement.nativeElement.focus();
}
this.nameElement.nativeElement.focus();
}, 0);
}
save() {
this.ser.saveOrUpdate(this.getItem()).subscribe({
next: () => {
this.toaster.show('Success', '');
this.snackBar.open('', 'Success');
this.router.navigateByUrl('/product-groups');
},
error: (error) => {
this.toaster.show('Danger', error);
this.snackBar.open(error, 'Danger');
},
});
}
@@ -52,10 +52,10 @@ import { ProductGroupListDataSource } from './product-group-list-datasource';
],
})
export class ProductGroupListComponent implements OnInit {
@ViewChild(MatPaginator, { static: true }) paginator?: MatPaginator;
@ViewChild(MatSort, { static: true }) sort?: MatSort;
@ViewChild(MatPaginator, { static: true }) paginator!: MatPaginator;
@ViewChild(MatSort, { static: true }) sort!: MatSort;
list: ProductGroup[] = [];
dataSource: ProductGroupListDataSource = new ProductGroupListDataSource(this.list);
dataSource: ProductGroupListDataSource = new ProductGroupListDataSource(this.list, this.paginator, this.sort);
/** Columns displayed in the table. Columns IDs can be added, removed, or reordered. */
displayedColumns = ['name', 'isFixture'];
@@ -16,8 +16,8 @@
<mat-label>Start Date</mat-label>
<input
matInput
#startDateElement
[matDatepicker]="startDate"
(focus)="startDate.open()"
formControlName="startDate"
autocomplete="off"
/>
@@ -26,13 +26,7 @@
</mat-form-field>
<mat-form-field class="flex-auto">
<mat-label>Finish Date</mat-label>
<input
matInput
[matDatepicker]="finishDate"
(focus)="finishDate.open()"
formControlName="finishDate"
autocomplete="off"
/>
<input matInput [matDatepicker]="finishDate" formControlName="finishDate" autocomplete="off" />
<mat-datepicker-toggle matSuffix [for]="finishDate"></mat-datepicker-toggle>
<mat-datepicker #finishDate></mat-datepicker>
</mat-form-field>
@@ -1,5 +1,5 @@
import { AsyncPipe, DecimalPipe, CurrencyPipe } from '@angular/common';
import { AfterViewInit, Component, ElementRef, OnInit, ViewChild } from '@angular/core';
import { AfterViewInit, Component, ElementRef, HostListener, OnInit, ViewChild } from '@angular/core';
import { FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms';
import { MatAutocompleteSelectedEvent, MatAutocompleteTrigger, MatAutocomplete } from '@angular/material/autocomplete';
import { MatIconButton, MatButton } from '@angular/material/button';
@@ -90,11 +90,12 @@ import { ProductLedgerService } from './product-ledger.service';
],
})
export class ProductLedgerComponent implements OnInit, AfterViewInit {
@ViewChild('productElement', { static: true }) productElement?: ElementRef;
@ViewChild(MatPaginator, { static: true }) paginator?: MatPaginator;
@ViewChild(MatSort, { static: true }) sort?: MatSort;
@ViewChild('productElement', { static: true }) productElement!: ElementRef<HTMLInputElement>;
@ViewChild(MatPaginator, { static: true }) paginator!: MatPaginator;
@ViewChild(MatSort, { static: true }) sort!: MatSort;
@ViewChild('startDateElement', { static: true }) startDate!: ElementRef<HTMLInputElement>;
info: ProductLedger = new ProductLedger();
dataSource: ProductLedgerDataSource = new ProductLedgerDataSource(this.info.body);
dataSource: ProductLedgerDataSource = new ProductLedgerDataSource(this.info.body, this.paginator, this.sort);
form: FormGroup<{
startDate: FormControl<Date>;
finishDate: FormControl<Date>;
@@ -124,6 +125,13 @@ export class ProductLedgerComponent implements OnInit, AfterViewInit {
products: Observable<ProductSku[]>;
@HostListener('window:keydown.f2', ['$event'])
focusDate(event: KeyboardEvent) {
event.preventDefault();
this.startDate.nativeElement.focus();
this.startDate.nativeElement.select();
}
constructor(
private route: ActivatedRoute,
private router: Router,
@@ -161,9 +169,7 @@ export class ProductLedgerComponent implements OnInit, AfterViewInit {
ngAfterViewInit() {
setTimeout(() => {
if (this.productElement) {
this.productElement.nativeElement.focus();
}
this.productElement.nativeElement.focus();
}, 0);
}
@@ -27,7 +27,7 @@ import { BehaviorSubject } from 'rxjs';
import { Product, StockKeepingUnit } from '../../core/product';
import { ProductGroup } from '../../core/product-group';
import { ToasterService } from '../../core/toaster.service';
import { MatSnackBar } from '@angular/material/snack-bar';
import { ConfirmDialogComponent } from '../../shared/confirm-dialog/confirm-dialog.component';
import { ProductService } from '../product.service';
@@ -69,7 +69,7 @@ import { ProductDetailDialogComponent } from './product-detail-dialog.component'
],
})
export class ProductDetailComponent implements OnInit, AfterViewInit {
@ViewChild('nameElement', { static: true }) nameElement?: ElementRef;
@ViewChild('nameElement', { static: true }) nameElement!: ElementRef<HTMLInputElement>;
form: FormGroup<{
code: FormControl<string | number>;
name: FormControl<string | null>;
@@ -115,7 +115,7 @@ export class ProductDetailComponent implements OnInit, AfterViewInit {
private route: ActivatedRoute,
private router: Router,
private dialog: MatDialog,
private toaster: ToasterService,
private snackBar: MatSnackBar,
private ser: ProductService,
) {
this.form = new FormGroup({
@@ -182,7 +182,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 ?? '') : '',
allergen: this.item.allergen ?? '',
protein: this.item.protein,
@@ -204,9 +204,7 @@ export class ProductDetailComponent implements OnInit, AfterViewInit {
ngAfterViewInit() {
setTimeout(() => {
if (this.nameElement) {
this.nameElement.nativeElement.focus();
}
this.nameElement.nativeElement.focus();
}, 0);
}
@@ -221,22 +219,22 @@ export class ProductDetailComponent implements OnInit, AfterViewInit {
}
const fraction = Number(formValue.fraction);
if (fraction < 1) {
this.toaster.show('Danger', 'Fraction has to be >= 1');
this.snackBar.open('Fraction has to be >= 1', 'Danger');
return;
}
const productYield = Number(formValue.productYield);
if (productYield < 0 || productYield > 1) {
this.toaster.show('Danger', 'Product Yield has to be > 0 and <= 1');
this.snackBar.open('Product Yield has to be > 0 and <= 1', 'Danger');
return;
}
const costPrice = Number(formValue.costPrice);
if (costPrice < 0) {
this.toaster.show('Danger', 'Price has to be >= 0');
this.snackBar.open('Price has to be >= 0', 'Danger');
return;
}
const salePrice = Number(formValue.salePrice);
if (salePrice < 0) {
this.toaster.show('Danger', 'Sale Price has to be >= 0');
this.snackBar.open('Sale Price has to be >= 0', 'Danger');
return;
}
this.item.skus.push(
@@ -285,11 +283,11 @@ export class ProductDetailComponent implements OnInit, AfterViewInit {
save() {
this.ser.saveOrUpdate(this.getItem()).subscribe({
next: () => {
this.toaster.show('Success', '');
this.snackBar.open('', 'Success');
this.router.navigateByUrl('/products');
},
error: (error) => {
this.toaster.show('Danger', error);
this.snackBar.open(error, 'Danger');
},
});
}
@@ -297,11 +295,11 @@ export class ProductDetailComponent implements OnInit, AfterViewInit {
delete() {
this.ser.delete(this.item.id as string).subscribe({
next: () => {
this.toaster.show('Success', '');
this.snackBar.open('', 'Success');
this.router.navigateByUrl('/products');
},
error: (error) => {
this.toaster.show('Danger', error);
this.snackBar.open(error, 'Danger');
},
});
}
@@ -66,9 +66,9 @@ import { ProductListDataSource } from './product-list-datasource';
],
})
export class ProductListComponent implements OnInit, AfterViewInit {
@ViewChild('filterElement', { static: true }) filterElement?: ElementRef;
@ViewChild(MatPaginator, { static: true }) paginator?: MatPaginator;
@ViewChild(MatSort, { static: true }) sort?: MatSort;
@ViewChild('filterElement', { static: true }) filterElement!: ElementRef<HTMLInputElement>;
@ViewChild(MatPaginator, { static: true }) paginator!: MatPaginator;
@ViewChild(MatSort, { static: true }) sort!: MatSort;
list: Product[] = [];
filter: Observable<string>;
dataSource: ProductListDataSource;
@@ -90,7 +90,7 @@ export class ProductListComponent implements OnInit, AfterViewInit {
filter: new FormControl<string>('', { nonNullable: true }),
});
this.filter = this.form.controls.filter.valueChanges.pipe(debounceTime(150), distinctUntilChanged());
this.dataSource = new ProductListDataSource(this.list, this.filter);
this.dataSource = new ProductListDataSource(this.list, this.filter, this.paginator, this.sort);
}
get showExtended(): boolean {
@@ -117,9 +117,7 @@ export class ProductListComponent implements OnInit, AfterViewInit {
ngAfterViewInit() {
setTimeout(() => {
if (this.filterElement) {
this.filterElement.nativeElement.focus();
}
this.filterElement.nativeElement.focus();
}, 0);
}
@@ -9,8 +9,8 @@
<mat-label>Start Date</mat-label>
<input
matInput
#startDateElement
[matDatepicker]="startDate"
(focus)="startDate.open()"
formControlName="startDate"
autocomplete="off"
/>
@@ -19,13 +19,7 @@
</mat-form-field>
<mat-form-field class="flex-auto basis-2/5 mr-5">
<mat-label>Finish Date</mat-label>
<input
matInput
[matDatepicker]="finishDate"
(focus)="finishDate.open()"
formControlName="finishDate"
autocomplete="off"
/>
<input matInput [matDatepicker]="finishDate" formControlName="finishDate" autocomplete="off" />
<mat-datepicker-toggle matSuffix [for]="finishDate"></mat-datepicker-toggle>
<mat-datepicker #finishDate></mat-datepicker>
</mat-form-field>
@@ -1,5 +1,5 @@
import { CurrencyPipe } from '@angular/common';
import { Component, OnInit, ViewChild } from '@angular/core';
import { Component, ElementRef, HostListener, OnInit, ViewChild } from '@angular/core';
import { FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms';
import { MatButton } from '@angular/material/button';
import { MatCard, MatCardHeader, MatCardTitle, MatCardContent } from '@angular/material/card';
@@ -70,10 +70,11 @@ import { ProfitLossDataSource } from './profit-loss-datasource';
],
})
export class ProfitLossComponent implements OnInit {
@ViewChild(MatPaginator, { static: true }) paginator?: MatPaginator;
@ViewChild(MatSort, { static: true }) sort?: MatSort;
@ViewChild(MatPaginator, { static: true }) paginator!: MatPaginator;
@ViewChild(MatSort, { static: true }) sort!: MatSort;
@ViewChild('startDateElement', { static: true }) startDate!: ElementRef<HTMLInputElement>;
info: ProfitLoss = new ProfitLoss();
dataSource: ProfitLossDataSource = new ProfitLossDataSource(this.info.body);
dataSource: ProfitLossDataSource = new ProfitLossDataSource(this.info.body, this.paginator, this.sort);
form: FormGroup<{
startDate: FormControl<Date>;
finishDate: FormControl<Date>;
@@ -83,6 +84,13 @@ export class ProfitLossComponent implements OnInit {
/** Columns displayed in the table. Columns IDs can be added, removed, or reordered. */
displayedColumns = ['group', 'name', 'amount', 'total'];
@HostListener('window:keydown.f2', ['$event'])
focusDate(event: KeyboardEvent) {
event.preventDefault();
this.startDate.nativeElement.focus();
this.startDate.nativeElement.select();
}
constructor(
private route: ActivatedRoute,
private router: Router,
@@ -9,8 +9,8 @@
<mat-label>Start Date</mat-label>
<input
matInput
#startDateElement
[matDatepicker]="startDate"
(focus)="startDate.open()"
formControlName="startDate"
autocomplete="off"
/>
@@ -19,13 +19,7 @@
</mat-form-field>
<mat-form-field class="flex-auto basis-2/5 mr-5">
<mat-label>Finish Date</mat-label>
<input
matInput
[matDatepicker]="finishDate"
(focus)="finishDate.open()"
formControlName="finishDate"
autocomplete="off"
/>
<input matInput [matDatepicker]="finishDate" formControlName="finishDate" autocomplete="off" />
<mat-datepicker-toggle matSuffix [for]="finishDate"></mat-datepicker-toggle>
<mat-datepicker #finishDate></mat-datepicker>
</mat-form-field>
@@ -1,5 +1,5 @@
import { DecimalPipe, PercentPipe, CurrencyPipe } from '@angular/common';
import { Component, OnInit, ViewChild } from '@angular/core';
import { Component, ElementRef, HostListener, OnInit, ViewChild } from '@angular/core';
import { FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms';
import { MatButton } from '@angular/material/button';
import { MatCard, MatCardHeader, MatCardTitle, MatCardContent } from '@angular/material/card';
@@ -65,10 +65,11 @@ import { PurchaseEntriesDataSource } from './purchase-entries-datasource';
],
})
export class PurchaseEntriesComponent implements OnInit {
@ViewChild(MatPaginator, { static: true }) paginator?: MatPaginator;
@ViewChild(MatSort, { static: true }) sort?: MatSort;
@ViewChild(MatPaginator, { static: true }) paginator!: MatPaginator;
@ViewChild(MatSort, { static: true }) sort!: MatSort;
@ViewChild('startDateElement', { static: true }) startDate!: ElementRef<HTMLInputElement>;
info: PurchaseEntries = new PurchaseEntries();
dataSource: PurchaseEntriesDataSource = new PurchaseEntriesDataSource(this.info.body);
dataSource: PurchaseEntriesDataSource = new PurchaseEntriesDataSource(this.info.body, this.paginator, this.sort);
form: FormGroup<{
startDate: FormControl<Date>;
finishDate: FormControl<Date>;
@@ -78,6 +79,13 @@ export class PurchaseEntriesComponent implements OnInit {
/** Columns displayed in the table. Columns IDs can be added, removed, or reordered. */
displayedColumns = ['date', 'supplier', 'product', 'quantity', 'rate', 'tax', 'discount', 'amount'];
@HostListener('window:keydown.f2', ['$event'])
focusDate(event: KeyboardEvent) {
event.preventDefault();
this.startDate.nativeElement.focus();
this.startDate.nativeElement.select();
}
constructor(
private route: ActivatedRoute,
private router: Router,
@@ -17,14 +17,7 @@
<div class="flex flex-row justify-around content-start items-start sm:max-lg:flex-col">
<mat-form-field class="flex-auto basis-2/5 mr-5">
<mat-label>Date</mat-label>
<input
matInput
[matDatepicker]="date"
formControlName="date"
autocomplete="off"
#dateElement
(focus)="dateElement.select()"
/>
<input matInput [matDatepicker]="date" formControlName="date" autocomplete="off" #dateElement />
<mat-datepicker-toggle matSuffix [for]="date"></mat-datepicker-toggle>
<mat-datepicker #date></mat-datepicker>
</mat-form-field>
@@ -1,6 +1,6 @@
import { COMMA, ENTER } from '@angular/cdk/keycodes';
import { AsyncPipe, DecimalPipe, PercentPipe, CurrencyPipe } from '@angular/common';
import { AfterViewInit, Component, ElementRef, OnInit, OnDestroy, ViewChild } from '@angular/core';
import { AfterViewInit, Component, ElementRef, OnInit, ViewChild, HostListener } from '@angular/core';
import { FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms';
import { MatAutocompleteSelectedEvent, MatAutocompleteTrigger, MatAutocomplete } from '@angular/material/autocomplete';
import { MatButton, MatIconButton } from '@angular/material/button';
@@ -33,7 +33,6 @@ import {
MatRow,
} from '@angular/material/table';
import { ActivatedRoute, Router } from '@angular/router';
import { Hotkey, HotkeysService } from 'angular2-hotkeys';
import { round } from 'mathjs';
import moment from 'moment';
import { BehaviorSubject, Observable, of as observableOf } from 'rxjs';
@@ -49,7 +48,7 @@ import { DbFile } from '../core/db-file';
import { Inventory } from '../core/inventory';
import { Tag } from '../core/tag';
import { TagService } from '../core/tag.service';
import { ToasterService } from '../core/toaster.service';
import { MatSnackBar } from '@angular/material/snack-bar';
import { User } from '../core/user';
import { Voucher } from '../core/voucher';
import { VoucherService } from '../core/voucher.service';
@@ -114,11 +113,35 @@ import { PurchaseReturnDialogComponent } from './purchase-return-dialog.componen
LocalTimePipe,
],
})
export class PurchaseReturnComponent implements OnInit, AfterViewInit, OnDestroy {
@ViewChild('accountElement', { static: true }) accountElement?: ElementRef;
@ViewChild('batchElement', { static: true }) batchElement?: ElementRef;
@ViewChild('dateElement', { static: true }) dateElement?: ElementRef;
export class PurchaseReturnComponent implements OnInit, AfterViewInit {
@ViewChild('accountElement', { static: true }) accountElement!: ElementRef<HTMLInputElement>;
@ViewChild('batchElement', { static: true }) batchElement!: ElementRef<HTMLInputElement>;
@ViewChild('dateElement', { static: true }) dateElement!: ElementRef<HTMLInputElement>;
@ViewChild('tagInput') tagInput?: ElementRef<HTMLInputElement>;
@HostListener('window:keydown.f2', ['$event'])
focusDate(event: KeyboardEvent) {
event.preventDefault();
this.dateElement.nativeElement.focus();
this.dateElement.nativeElement.select();
}
@HostListener('window:keydown.control.s', ['$event'])
saveListner(event: KeyboardEvent) {
event.preventDefault();
if (this.canSave()) {
this.save();
}
}
@HostListener('window:keydown.control.p', ['$event'])
postListner(event: KeyboardEvent) {
event.preventDefault();
if (this.voucher.id && !this.voucher.posted && this.auth.allowed('post-vouchers')) {
this.post();
}
}
separatorKeysCodes: number[] = [ENTER, COMMA];
public inventoryObservable = new BehaviorSubject<Inventory[]>([]);
dataSource: PurchaseReturnDataSource = new PurchaseReturnDataSource(this.inventoryObservable);
@@ -148,8 +171,7 @@ export class PurchaseReturnComponent implements OnInit, AfterViewInit, OnDestroy
private route: ActivatedRoute,
private router: Router,
private dialog: MatDialog,
private hotkeys: HotkeysService,
private toaster: ToasterService,
private snackBar: MatSnackBar,
public auth: AuthService,
private math: MathService,
public image: ImageService,
@@ -199,54 +221,12 @@ export class PurchaseReturnComponent implements OnInit, AfterViewInit, OnDestroy
this.loadVoucher(data.voucher);
});
this.hotkeys.add(
new Hotkey(
'f2',
(): boolean => {
setTimeout(() => {
if (this.dateElement) {
this.dateElement.nativeElement.focus();
}
}, 0);
return false; // Prevent bubbling
},
['INPUT', 'SELECT', 'TEXTAREA'],
),
);
this.hotkeys.add(
new Hotkey(
'ctrl+s',
(): boolean => {
if (this.canSave()) {
this.save();
}
return false; // Prevent bubbling
},
['INPUT', 'SELECT', 'TEXTAREA'],
),
);
this.hotkeys.add(
new Hotkey(
'ctrl+p',
(): boolean => {
if (this.voucher.id && !this.voucher.posted && this.auth.allowed('post-vouchers')) {
this.post();
}
return false; // Prevent bubbling
},
['INPUT', 'SELECT', 'TEXTAREA'],
),
);
}
ngAfterViewInit() {
this.focusAccount();
}
ngOnDestroy() {
this.hotkeys.reset();
}
loadVoucher(voucher: Voucher) {
this.voucher = voucher;
this.form.setValue({
@@ -266,9 +246,7 @@ export class PurchaseReturnComponent implements OnInit, AfterViewInit, OnDestroy
focusAccount() {
setTimeout(() => {
if (this.accountElement) {
this.accountElement.nativeElement.focus();
}
this.accountElement.nativeElement.focus();
}, 0);
}
@@ -283,7 +261,7 @@ export class PurchaseReturnComponent implements OnInit, AfterViewInit, OnDestroy
}
const old = this.voucher.inventories.find((x) => x.batch.id === (this.batch as Batch).id);
if (old !== undefined) {
this.toaster.show('Danger', 'Product already added');
this.snackBar.open('Product already added', 'Danger');
return;
}
this.voucher.inventories.push(
@@ -304,9 +282,7 @@ export class PurchaseReturnComponent implements OnInit, AfterViewInit, OnDestroy
this.form.controls.addRow.reset();
this.batch = null;
setTimeout(() => {
if (this.batchElement) {
this.batchElement.nativeElement.focus();
}
this.batchElement.nativeElement.focus();
}, 0);
}
@@ -361,10 +337,10 @@ export class PurchaseReturnComponent implements OnInit, AfterViewInit, OnDestroy
this.ser.post(this.voucher.id as string).subscribe({
next: (result) => {
this.loadVoucher(result);
this.toaster.show('Success', 'Voucher Posted');
this.snackBar.open('Voucher Posted', 'Success');
},
error: (error) => {
this.toaster.show('Danger', error);
this.snackBar.open(error, 'Danger');
},
});
}
@@ -373,7 +349,7 @@ export class PurchaseReturnComponent implements OnInit, AfterViewInit, OnDestroy
const voucher: Voucher = this.getVoucher();
this.ser.saveOrUpdate(voucher).subscribe({
next: (result) => {
this.toaster.show('Success', '');
this.snackBar.open('', 'Success');
if (voucher.id === result.id) {
this.loadVoucher(result);
} else {
@@ -381,7 +357,7 @@ export class PurchaseReturnComponent implements OnInit, AfterViewInit, OnDestroy
}
},
error: (error) => {
this.toaster.show('Danger', error);
this.snackBar.open(error, 'Danger');
},
});
}
@@ -399,11 +375,11 @@ export class PurchaseReturnComponent implements OnInit, AfterViewInit, OnDestroy
delete() {
this.ser.delete(this.voucher.id as string).subscribe({
next: () => {
this.toaster.show('Success', '');
this.snackBar.open('', 'Success');
this.router.navigate(['/purchase-return'], { replaceUrl: true });
},
error: (error) => {
this.toaster.show('Danger', error);
this.snackBar.open(error, 'Danger');
},
});
}
@@ -17,14 +17,7 @@
<div class="flex flex-row justify-around content-start items-start sm:max-lg:flex-col">
<mat-form-field class="flex-auto basis-2/5 mr-5">
<mat-label>Date</mat-label>
<input
matInput
[matDatepicker]="date"
formControlName="date"
autocomplete="off"
#dateElement
(focus)="dateElement.select()"
/>
<input matInput [matDatepicker]="date" formControlName="date" autocomplete="off" #dateElement />
<mat-datepicker-toggle matSuffix [for]="date"></mat-datepicker-toggle>
<mat-datepicker #date></mat-datepicker>
</mat-form-field>
+40 -64
View File
@@ -1,6 +1,6 @@
import { COMMA, ENTER } from '@angular/cdk/keycodes';
import { AsyncPipe, DecimalPipe, PercentPipe, CurrencyPipe } from '@angular/common';
import { AfterViewInit, Component, ElementRef, OnInit, OnDestroy, ViewChild } from '@angular/core';
import { AfterViewInit, Component, ElementRef, OnInit, ViewChild, HostListener } from '@angular/core';
import { FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms';
import { MatAutocompleteSelectedEvent, MatAutocompleteTrigger, MatAutocomplete } from '@angular/material/autocomplete';
import { MatButton, MatIconButton } from '@angular/material/button';
@@ -33,7 +33,6 @@ import {
MatRow,
} from '@angular/material/table';
import { ActivatedRoute, Router } from '@angular/router';
import { Hotkey, HotkeysService } from 'angular2-hotkeys';
import { round } from 'mathjs';
import moment from 'moment';
import { BehaviorSubject, Observable, of as observableOf } from 'rxjs';
@@ -50,7 +49,7 @@ import { Product } from '../core/product';
import { ProductSku } from '../core/product-sku';
import { Tag } from '../core/tag';
import { TagService } from '../core/tag.service';
import { ToasterService } from '../core/toaster.service';
import { MatSnackBar } from '@angular/material/snack-bar';
import { User } from '../core/user';
import { Voucher } from '../core/voucher';
import { VoucherService } from '../core/voucher.service';
@@ -116,11 +115,35 @@ import { PurchaseDialogComponent } from './purchase-dialog.component';
LocalTimePipe,
],
})
export class PurchaseComponent implements OnInit, AfterViewInit, OnDestroy {
@ViewChild('accountElement', { static: true }) accountElement?: ElementRef;
@ViewChild('productElement', { static: true }) productElement?: ElementRef;
@ViewChild('dateElement', { static: true }) dateElement?: ElementRef;
export class PurchaseComponent implements OnInit, AfterViewInit {
@ViewChild('accountElement', { static: true }) accountElement!: ElementRef<HTMLInputElement>;
@ViewChild('productElement', { static: true }) productElement!: ElementRef<HTMLInputElement>;
@ViewChild('dateElement', { static: true }) dateElement!: ElementRef<HTMLInputElement>;
@ViewChild('tagInput') tagInput?: ElementRef<HTMLInputElement>;
@HostListener('window:keydown.f2', ['$event'])
focusDate(event: KeyboardEvent) {
event.preventDefault();
this.dateElement.nativeElement.focus();
this.dateElement.nativeElement.select();
}
@HostListener('window:keydown.control.s', ['$event'])
saveListner(event: KeyboardEvent) {
event.preventDefault();
if (this.canSave()) {
this.save();
}
}
@HostListener('window:keydown.control.p', ['$event'])
postListner(event: KeyboardEvent) {
event.preventDefault();
if (this.voucher.id && !this.voucher.posted && this.auth.allowed('post-vouchers')) {
this.post();
}
}
separatorKeysCodes: number[] = [ENTER, COMMA];
public inventoryObservable = new BehaviorSubject<Inventory[]>([]);
dataSource: PurchaseDataSource = new PurchaseDataSource(this.inventoryObservable);
@@ -153,8 +176,7 @@ export class PurchaseComponent implements OnInit, AfterViewInit, OnDestroy {
private route: ActivatedRoute,
private router: Router,
private dialog: MatDialog,
private hotkeys: HotkeysService,
private toaster: ToasterService,
private snackBar: MatSnackBar,
public auth: AuthService,
private math: MathService,
public image: ImageService,
@@ -214,54 +236,12 @@ export class PurchaseComponent implements OnInit, AfterViewInit, OnDestroy {
this.loadVoucher(data.voucher);
});
this.hotkeys.add(
new Hotkey(
'f2',
(): boolean => {
setTimeout(() => {
if (this.dateElement) {
this.dateElement.nativeElement.focus();
}
}, 0);
return false; // Prevent bubbling
},
['INPUT', 'SELECT', 'TEXTAREA'],
),
);
this.hotkeys.add(
new Hotkey(
'ctrl+s',
(): boolean => {
if (this.canSave()) {
this.save();
}
return false; // Prevent bubbling
},
['INPUT', 'SELECT', 'TEXTAREA'],
),
);
this.hotkeys.add(
new Hotkey(
'ctrl+p',
(): boolean => {
if (this.voucher.id && !this.voucher.posted && this.auth.allowed('post-vouchers')) {
this.post();
}
return false; // Prevent bubbling
},
['INPUT', 'SELECT', 'TEXTAREA'],
),
);
}
ngAfterViewInit() {
this.focusAccount();
}
ngOnDestroy() {
this.hotkeys.reset();
}
loadVoucher(voucher: Voucher) {
this.voucher = voucher;
this.form.setValue({
@@ -284,9 +264,7 @@ export class PurchaseComponent implements OnInit, AfterViewInit, OnDestroy {
focusAccount() {
setTimeout(() => {
if (this.accountElement) {
this.accountElement.nativeElement.focus();
}
this.accountElement.nativeElement.focus();
}, 0);
}
@@ -309,7 +287,7 @@ export class PurchaseComponent implements OnInit, AfterViewInit, OnDestroy {
}
const oldFiltered = this.voucher.inventories.filter((x) => x.batch?.sku.id === (this.product as ProductSku).id);
if (oldFiltered.length) {
this.toaster.show('Danger', 'Product already added');
this.snackBar.open('Product already added', 'Danger');
return;
}
this.voucher.inventories.push(
@@ -333,9 +311,7 @@ export class PurchaseComponent implements OnInit, AfterViewInit, OnDestroy {
this.form.controls.addRow.controls.tax.enable();
this.form.controls.addRow.controls.discount.enable();
setTimeout(() => {
if (this.productElement) {
this.productElement.nativeElement.focus();
}
this.productElement.nativeElement.focus();
}, 0);
}
@@ -387,10 +363,10 @@ export class PurchaseComponent implements OnInit, AfterViewInit, OnDestroy {
this.ser.post(this.voucher.id as string).subscribe({
next: (result) => {
this.loadVoucher(result);
this.toaster.show('Success', 'Voucher Posted');
this.snackBar.open('Voucher Posted', 'Success');
},
error: (error) => {
this.toaster.show('Danger', error);
this.snackBar.open(error, 'Danger');
},
});
}
@@ -399,7 +375,7 @@ export class PurchaseComponent implements OnInit, AfterViewInit, OnDestroy {
const voucher: Voucher = this.getVoucher();
this.ser.saveOrUpdate(voucher).subscribe({
next: (result) => {
this.toaster.show('Success', '');
this.snackBar.open('', 'Success');
if (voucher.id === result.id) {
this.loadVoucher(result);
} else {
@@ -407,7 +383,7 @@ export class PurchaseComponent implements OnInit, AfterViewInit, OnDestroy {
}
},
error: (error) => {
this.toaster.show('Danger', error);
this.snackBar.open(error, 'Danger');
},
});
}
@@ -425,11 +401,11 @@ export class PurchaseComponent implements OnInit, AfterViewInit, OnDestroy {
delete() {
this.ser.delete(this.voucher.id as string).subscribe({
next: () => {
this.toaster.show('Success', '');
this.snackBar.open('', 'Success');
this.router.navigate(['/purchase'], { replaceUrl: true });
},
error: (error) => {
this.toaster.show('Danger', error);
this.snackBar.open(error, 'Danger');
},
});
}
@@ -9,8 +9,8 @@
<mat-label>Start Date</mat-label>
<input
matInput
#startDateElement
[matDatepicker]="startDate"
(focus)="startDate.open()"
formControlName="startDate"
autocomplete="off"
/>
@@ -19,13 +19,7 @@
</mat-form-field>
<mat-form-field class="flex-auto basis-2/5 mr-5">
<mat-label>Finish Date</mat-label>
<input
matInput
[matDatepicker]="finishDate"
(focus)="finishDate.open()"
formControlName="finishDate"
autocomplete="off"
/>
<input matInput [matDatepicker]="finishDate" formControlName="finishDate" autocomplete="off" />
<mat-datepicker-toggle matSuffix [for]="finishDate"></mat-datepicker-toggle>
<mat-datepicker #finishDate></mat-datepicker>
</mat-form-field>
@@ -1,5 +1,5 @@
import { DecimalPipe, CurrencyPipe } from '@angular/common';
import { Component, OnInit, ViewChild } from '@angular/core';
import { Component, ElementRef, HostListener, OnInit, ViewChild } from '@angular/core';
import { FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms';
import { MatButton } from '@angular/material/button';
import { MatCard, MatCardHeader, MatCardTitle, MatCardContent } from '@angular/material/card';
@@ -73,10 +73,11 @@ import { PurchasesItem } from './purchases-item';
],
})
export class PurchasesComponent implements OnInit {
@ViewChild(MatPaginator, { static: true }) paginator?: MatPaginator;
@ViewChild(MatSort, { static: true }) sort?: MatSort;
@ViewChild(MatPaginator, { static: true }) paginator!: MatPaginator;
@ViewChild(MatSort, { static: true }) sort!: MatSort;
@ViewChild('startDateElement', { static: true }) startDate!: ElementRef<HTMLInputElement>;
info: Purchases = new Purchases();
dataSource: PurchasesDataSource = new PurchasesDataSource(this.info.body);
dataSource: PurchasesDataSource = new PurchasesDataSource(this.info.body, this.paginator, this.sort);
form: FormGroup<{
startDate: FormControl<Date>;
finishDate: FormControl<Date>;
@@ -86,6 +87,13 @@ export class PurchasesComponent implements OnInit {
/** Columns displayed in the table. Columns IDs can be added, removed, or reordered. */
displayedColumns = ['product', 'quantity', 'rate', 'amount'];
@HostListener('window:keydown.f2', ['$event'])
focusDate(event: KeyboardEvent) {
event.preventDefault();
this.startDate.nativeElement.focus();
this.startDate.nativeElement.select();
}
constructor(
private route: ActivatedRoute,
private router: Router,
@@ -32,7 +32,7 @@ import { Account } from '../../core/account';
import { AccountService } from '../../core/account.service';
import { Product } from '../../core/product';
import { ProductSku } from '../../core/product-sku';
import { ToasterService } from '../../core/toaster.service';
import { MatSnackBar } from '@angular/material/snack-bar';
import { ProductService } from '../../product/product.service';
import { ConfirmDialogComponent } from '../../shared/confirm-dialog/confirm-dialog.component';
import { MathService } from '../../shared/math.service';
@@ -41,6 +41,7 @@ import { RateContractItem } from '../rate-contract-item';
import { RateContractService } from '../rate-contract.service';
import { RateContractDetailDatasource } from './rate-contract-detail-datasource';
import { HostListener } from '@angular/core';
@Component({
selector: 'app-rate-contract-detail',
@@ -83,8 +84,9 @@ import { RateContractDetailDatasource } from './rate-contract-detail-datasource'
],
})
export class RateContractDetailComponent implements OnInit, AfterViewInit {
@ViewChild('accountElement', { static: true }) accountElement?: ElementRef;
@ViewChild('productElement', { static: true }) productElement?: ElementRef;
@ViewChild('accountElement', { static: true }) accountElement!: ElementRef<HTMLInputElement>;
@ViewChild('productElement', { static: true }) productElement!: ElementRef<HTMLInputElement>;
@ViewChild('dateElement', { static: true }) dateElement!: ElementRef<HTMLInputElement>;
public itemsObservable = new BehaviorSubject<RateContractItem[]>([]);
dataSource: RateContractDetailDatasource = new RateContractDetailDatasource(this.itemsObservable);
form: FormGroup<{
@@ -109,10 +111,17 @@ export class RateContractDetailComponent implements OnInit, AfterViewInit {
accounts: Observable<Account[]>;
products: Observable<ProductSku[]>;
@HostListener('window:keydown.f2', ['$event'])
focusDate(event: KeyboardEvent) {
event.preventDefault();
this.dateElement.nativeElement.focus();
this.dateElement.nativeElement.select();
}
constructor(
private route: ActivatedRoute,
private router: Router,
private toaster: ToasterService,
private snackBar: MatSnackBar,
private dialog: MatDialog,
private math: MathService,
private ser: RateContractService,
@@ -169,9 +178,7 @@ export class RateContractDetailComponent implements OnInit, AfterViewInit {
ngAfterViewInit() {
setTimeout(() => {
if (this.accountElement) {
this.accountElement.nativeElement.focus();
}
this.accountElement.nativeElement.focus();
}, 0);
}
@@ -186,7 +193,7 @@ export class RateContractDetailComponent implements OnInit, AfterViewInit {
}
const oldFiltered = this.item.items.filter((x) => x.sku.id === (this.product as Product).id);
if (oldFiltered.length) {
this.toaster.show('Danger', 'Product already added');
this.snackBar.open('Product already added', 'Danger');
return;
}
this.item.items.push(
@@ -203,9 +210,7 @@ export class RateContractDetailComponent implements OnInit, AfterViewInit {
this.form.controls.addRow.reset();
this.product = null;
setTimeout(() => {
if (this.productElement) {
this.productElement.nativeElement.focus();
}
this.productElement.nativeElement.focus();
}, 0);
}
@@ -233,11 +238,11 @@ export class RateContractDetailComponent implements OnInit, AfterViewInit {
save() {
this.ser.saveOrUpdate(this.getItem()).subscribe({
next: () => {
this.toaster.show('Success', '');
this.snackBar.open('', 'Success');
this.router.navigateByUrl('/rate-contracts');
},
error: (error) => {
this.toaster.show('Danger', error);
this.snackBar.open(error, 'Danger');
},
});
}
@@ -245,11 +250,11 @@ export class RateContractDetailComponent implements OnInit, AfterViewInit {
delete() {
this.ser.delete(this.item.id as string).subscribe({
next: () => {
this.toaster.show('Success', '');
this.snackBar.open('', 'Success');
this.router.navigateByUrl('/rate-contracts');
},
error: (error) => {
this.toaster.show('Danger', error);
this.snackBar.open(error, 'Danger');
},
});
}
@@ -54,10 +54,10 @@ import { RateContractListDatasource } from './rate-contract-list-datasource';
],
})
export class RateContractListComponent implements OnInit {
@ViewChild(MatPaginator, { static: true }) paginator?: MatPaginator;
@ViewChild(MatSort, { static: true }) sort?: MatSort;
@ViewChild(MatPaginator, { static: true }) paginator!: MatPaginator;
@ViewChild(MatSort, { static: true }) sort!: MatSort;
list: RateContract[] = [];
dataSource: RateContractListDatasource = new RateContractListDatasource(this.list);
dataSource: RateContractListDatasource = new RateContractListDatasource(this.list, this.paginator, this.sort);
/** Columns displayed in the table. Columns IDs can be added, removed, or reordered. */
displayedColumns = ['vendor', 'validity', 'products'];
@@ -16,8 +16,8 @@
<mat-label>Start Date</mat-label>
<input
matInput
#startDateElement
[matDatepicker]="startDate"
(focus)="startDate.open()"
formControlName="startDate"
autocomplete="off"
/>
@@ -26,13 +26,7 @@
</mat-form-field>
<mat-form-field class="flex-auto basis-2/5 mr-5">
<mat-label>Finish Date</mat-label>
<input
matInput
[matDatepicker]="finishDate"
(focus)="finishDate.open()"
formControlName="finishDate"
autocomplete="off"
/>
<input matInput [matDatepicker]="finishDate" formControlName="finishDate" autocomplete="off" />
<mat-datepicker-toggle matSuffix [for]="finishDate"></mat-datepicker-toggle>
<mat-datepicker #finishDate></mat-datepicker>
</mat-form-field>
@@ -1,5 +1,5 @@
import { DecimalPipe, PercentPipe, CurrencyPipe } from '@angular/common';
import { Component, OnInit, ViewChild } from '@angular/core';
import { Component, ElementRef, HostListener, OnInit, ViewChild } from '@angular/core';
import { FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms';
import { MatIconButton, MatButton } from '@angular/material/button';
import { MatCard, MatCardHeader, MatCardTitleGroup, MatCardTitle, MatCardContent } from '@angular/material/card';
@@ -79,10 +79,11 @@ import { RawMaterialCostDataSource } from './raw-material-cost-datasource';
],
})
export class RawMaterialCostComponent implements OnInit {
@ViewChild(MatPaginator, { static: true }) paginator?: MatPaginator;
@ViewChild(MatSort, { static: true }) sort?: MatSort;
@ViewChild(MatPaginator, { static: true }) paginator!: MatPaginator;
@ViewChild(MatSort, { static: true }) sort!: MatSort;
@ViewChild('startDateElement', { static: true }) startDate!: ElementRef<HTMLInputElement>;
info: RawMaterialCost = new RawMaterialCost();
dataSource: RawMaterialCostDataSource = new RawMaterialCostDataSource(this.info.body);
dataSource: RawMaterialCostDataSource = new RawMaterialCostDataSource(this.info.body, this.paginator, this.sort);
form: FormGroup<{
startDate: FormControl<Date>;
finishDate: FormControl<Date>;
@@ -99,6 +100,13 @@ export class RawMaterialCostComponent implements OnInit {
columnsNoId = ['name', 'issue', 'sale', 'rmc'];
columnsId = ['name', 'group', 'quantity', 'net', 'gross'];
@HostListener('window:keydown.f2', ['$event'])
focusDate(event: KeyboardEvent) {
event.preventDefault();
this.startDate.nativeElement.focus();
this.startDate.nativeElement.select();
}
constructor(
private route: ActivatedRoute,
private router: Router,
@@ -144,7 +152,7 @@ export class RawMaterialCostComponent implements OnInit {
}
exportCsv() {
let headers: { [display: string]: string };
let headers: Record<string, string>;
if (this.info.id) {
headers = { Name: 'name', Group: 'group', Quantity: 'quantity', Net: 'net', Gross: 'gross' };
} else {
@@ -17,14 +17,7 @@
<div class="flex flex-row justify-around content-start items-start sm:max-lg:flex-col">
<mat-form-field class="flex-auto basis-2/5 mr-5">
<mat-label>Date</mat-label>
<input
matInput
[matDatepicker]="date"
formControlName="date"
autocomplete="off"
#dateElement
(focus)="dateElement.select()"
/>
<input matInput [matDatepicker]="date" formControlName="date" autocomplete="off" #dateElement />
<mat-datepicker-toggle matSuffix [for]="date"></mat-datepicker-toggle>
<mat-datepicker #date></mat-datepicker>
</mat-form-field>
+38 -62
View File
@@ -1,6 +1,6 @@
import { COMMA, ENTER } from '@angular/cdk/keycodes';
import { AsyncPipe, CurrencyPipe } from '@angular/common';
import { AfterViewInit, Component, ElementRef, OnInit, OnDestroy, ViewChild } from '@angular/core';
import { AfterViewInit, Component, ElementRef, OnInit, ViewChild, HostListener } from '@angular/core';
import { FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms';
import { MatAutocompleteSelectedEvent, MatAutocompleteTrigger, MatAutocomplete } from '@angular/material/autocomplete';
import { MatButton, MatIconButton } from '@angular/material/button';
@@ -34,7 +34,6 @@ import {
MatRow,
} from '@angular/material/table';
import { ActivatedRoute, Router } from '@angular/router';
import { Hotkey, HotkeysService } from 'angular2-hotkeys';
import { round } from 'mathjs';
import moment from 'moment';
import { BehaviorSubject, Observable, of as observableOf } from 'rxjs';
@@ -48,7 +47,7 @@ import { DbFile } from '../core/db-file';
import { Journal } from '../core/journal';
import { Tag } from '../core/tag';
import { TagService } from '../core/tag.service';
import { ToasterService } from '../core/toaster.service';
import { MatSnackBar } from '@angular/material/snack-bar';
import { User } from '../core/user';
import { Voucher } from '../core/voucher';
import { VoucherService } from '../core/voucher.service';
@@ -112,10 +111,34 @@ import { ReceiptDialogComponent } from './receipt-dialog.component';
LocalTimePipe,
],
})
export class ReceiptComponent implements OnInit, AfterViewInit, OnDestroy {
@ViewChild('accountElement', { static: true }) accountElement?: ElementRef;
@ViewChild('dateElement', { static: true }) dateElement?: ElementRef;
export class ReceiptComponent implements OnInit, AfterViewInit {
@ViewChild('accountElement', { static: true }) accountElement!: ElementRef<HTMLInputElement>;
@ViewChild('dateElement', { static: true }) dateElement!: ElementRef<HTMLInputElement>;
@ViewChild('tagInput') tagInput?: ElementRef<HTMLInputElement>;
@HostListener('window:keydown.f2', ['$event'])
focusDate(event: KeyboardEvent) {
event.preventDefault();
this.dateElement.nativeElement.focus();
this.dateElement.nativeElement.select();
}
@HostListener('window:keydown.control.s', ['$event'])
saveListner(event: KeyboardEvent) {
event.preventDefault();
if (this.canSave()) {
this.save();
}
}
@HostListener('window:keydown.control.p', ['$event'])
postListner(event: KeyboardEvent) {
event.preventDefault();
if (this.voucher.id && !this.voucher.posted && this.auth.allowed('post-vouchers')) {
this.post();
}
}
separatorKeysCodes: number[] = [ENTER, COMMA];
public journalObservable = new BehaviorSubject<Journal[]>([]);
dataSource: ReceiptDataSource = new ReceiptDataSource(this.journalObservable);
@@ -146,8 +169,7 @@ export class ReceiptComponent implements OnInit, AfterViewInit, OnDestroy {
private route: ActivatedRoute,
private router: Router,
private dialog: MatDialog,
private hotkeys: HotkeysService,
private toaster: ToasterService,
private snackBar: MatSnackBar,
public auth: AuthService,
private math: MathService,
public image: ImageService,
@@ -196,54 +218,12 @@ export class ReceiptComponent implements OnInit, AfterViewInit, OnDestroy {
this.receiptAccounts = data.receiptAccounts;
this.loadVoucher(data.voucher);
});
this.hotkeys.add(
new Hotkey(
'f2',
(): boolean => {
setTimeout(() => {
if (this.dateElement) {
this.dateElement.nativeElement.focus();
}
}, 0);
return false; // Prevent bubbling
},
['INPUT', 'SELECT', 'TEXTAREA'],
),
);
this.hotkeys.add(
new Hotkey(
'ctrl+s',
(): boolean => {
if (this.canSave()) {
this.save();
}
return false; // Prevent bubbling
},
['INPUT', 'SELECT', 'TEXTAREA'],
),
);
this.hotkeys.add(
new Hotkey(
'ctrl+p',
(): boolean => {
if (this.voucher.id && !this.voucher.posted && this.auth.allowed('post-vouchers')) {
this.post();
}
return false; // Prevent bubbling
},
['INPUT', 'SELECT', 'TEXTAREA'],
),
);
}
ngAfterViewInit() {
this.focusAccount();
}
ngOnDestroy() {
this.hotkeys.reset();
}
loadVoucher(voucher: Voucher) {
this.voucher = voucher;
[this.receiptJournal] = this.voucher.journals.filter((x) => x.debit === 1);
@@ -264,9 +244,7 @@ export class ReceiptComponent implements OnInit, AfterViewInit, OnDestroy {
focusAccount() {
setTimeout(() => {
if (this.accountElement) {
this.accountElement.nativeElement.focus();
}
this.accountElement.nativeElement.focus();
}, 0);
}
@@ -302,9 +280,7 @@ export class ReceiptComponent implements OnInit, AfterViewInit, OnDestroy {
this.account = null;
this.accBal = null;
setTimeout(() => {
if (this.accountElement) {
this.accountElement.nativeElement.focus();
}
this.accountElement.nativeElement.focus();
}, 0);
}
@@ -359,10 +335,10 @@ export class ReceiptComponent implements OnInit, AfterViewInit, OnDestroy {
this.ser.post(this.voucher.id as string).subscribe({
next: (result) => {
this.loadVoucher(result);
this.toaster.show('Success', 'Voucher Posted');
this.snackBar.open('Voucher Posted', 'Success');
},
error: (error) => {
this.toaster.show('Danger', error);
this.snackBar.open(error, 'Danger');
},
});
}
@@ -371,7 +347,7 @@ export class ReceiptComponent implements OnInit, AfterViewInit, OnDestroy {
const voucher: Voucher = this.getVoucher();
this.ser.saveOrUpdate(voucher).subscribe({
next: (result) => {
this.toaster.show('Success', '');
this.snackBar.open('', 'Success');
if (voucher.id === result.id) {
this.loadVoucher(result);
} else {
@@ -379,7 +355,7 @@ export class ReceiptComponent implements OnInit, AfterViewInit, OnDestroy {
}
},
error: (error) => {
this.toaster.show('Danger', error);
this.snackBar.open(error, 'Danger');
},
});
}
@@ -395,11 +371,11 @@ export class ReceiptComponent implements OnInit, AfterViewInit, OnDestroy {
delete() {
this.ser.delete(this.voucher.id as string).subscribe({
next: () => {
this.toaster.show('Success', '');
this.snackBar.open('', 'Success');
this.router.navigate(['/receipt'], { replaceUrl: true });
},
error: (error) => {
this.toaster.show('Danger', error);
this.snackBar.open(error, 'Danger');
},
});
}
@@ -12,14 +12,7 @@
</mat-form-field>
<mat-form-field class="flex-auto">
<mat-label>Date</mat-label>
<input
matInput
[matDatepicker]="date"
formControlName="date"
autocomplete="off"
#dateElement
(focus)="dateElement.select()"
/>
<input matInput [matDatepicker]="date" formControlName="date" autocomplete="off" #dateElement />
<mat-datepicker-toggle matSuffix [for]="date"></mat-datepicker-toggle>
<mat-datepicker #date></mat-datepicker>
</mat-form-field>
@@ -10,7 +10,7 @@ import { MatInput } from '@angular/material/input';
import { ActivatedRoute, Router } from '@angular/router';
import moment from 'moment';
import { ToasterService } from '../../core/toaster.service';
import { MatSnackBar } from '@angular/material/snack-bar';
import { ConfirmDialogComponent } from '../../shared/confirm-dialog/confirm-dialog.component';
import { RecipeTemplate } from '../recipe-template';
import { RecipeTemplateService } from '../recipe-template.service';
@@ -39,7 +39,7 @@ import { RecipeTemplateService } from '../recipe-template.service';
],
})
export class RecipeTemplateDetailComponent implements OnInit, AfterViewInit {
@ViewChild('nameElement', { static: true }) nameElement?: ElementRef;
@ViewChild('nameElement', { static: true }) nameElement!: ElementRef<HTMLInputElement>;
form: FormGroup<{
name: FormControl<string>;
date: FormControl<Date>;
@@ -53,7 +53,7 @@ export class RecipeTemplateDetailComponent implements OnInit, AfterViewInit {
private route: ActivatedRoute,
private router: Router,
private dialog: MatDialog,
private toaster: ToasterService,
private snackBar: MatSnackBar,
private ser: RecipeTemplateService,
) {
this.form = new FormGroup({
@@ -84,20 +84,18 @@ export class RecipeTemplateDetailComponent implements OnInit, AfterViewInit {
ngAfterViewInit() {
setTimeout(() => {
if (this.nameElement) {
this.nameElement.nativeElement.focus();
}
this.nameElement.nativeElement.focus();
}, 0);
}
save() {
this.ser.saveOrUpdate(this.getItem()).subscribe({
next: () => {
this.toaster.show('Success', '');
this.snackBar.open('', 'Success');
this.router.navigateByUrl('/recipe-templates');
},
error: (error) => {
this.toaster.show('Danger', error);
this.snackBar.open(error, 'Danger');
},
});
}
@@ -105,11 +103,11 @@ export class RecipeTemplateDetailComponent implements OnInit, AfterViewInit {
delete() {
this.ser.delete(this.item.id).subscribe({
next: () => {
this.toaster.show('Success', '');
this.snackBar.open('', 'Success');
this.router.navigateByUrl('/recipe-templates');
},
error: (error) => {
this.toaster.show('Danger', error);
this.snackBar.open(error, 'Danger');
},
});
}
@@ -52,10 +52,10 @@ import { RecipeTemplateListDataSource } from './recipe-template-list-datasource'
],
})
export class RecipeTemplateListComponent implements OnInit {
@ViewChild(MatPaginator, { static: true }) paginator?: MatPaginator;
@ViewChild(MatSort, { static: true }) sort?: MatSort;
@ViewChild(MatPaginator, { static: true }) paginator!: MatPaginator;
@ViewChild(MatSort, { static: true }) sort!: MatSort;
list: RecipeTemplate[] = [];
dataSource: RecipeTemplateListDataSource = new RecipeTemplateListDataSource(this.list);
dataSource: RecipeTemplateListDataSource = new RecipeTemplateListDataSource(this.list, this.paginator, this.sort);
/** Columns displayed in the table. Columns IDs can be added, removed, or reordered. */
displayedColumns = ['name', 'selected', 'date'];
@@ -7,14 +7,7 @@
<div class="flex flex-row justify-around content-start items-start">
<mat-form-field class="flex-auto mr-5">
<mat-label>Date</mat-label>
<input
matInput
[matDatepicker]="date"
formControlName="date"
autocomplete="off"
#dateElement
(focus)="dateElement.select()"
/>
<input matInput [matDatepicker]="date" formControlName="date" autocomplete="off" #dateElement />
<mat-datepicker-toggle matSuffix [for]="date"></mat-datepicker-toggle>
<mat-datepicker #date></mat-datepicker>
</mat-form-field>
@@ -31,7 +31,7 @@ import { Period } from 'src/app/period/period';
import { Product } from '../../core/product';
import { ProductSku } from '../../core/product-sku';
import { ToasterService } from '../../core/toaster.service';
import { MatSnackBar } from '@angular/material/snack-bar';
import { ProductService } from '../../product/product.service';
import { ConfirmDialogComponent } from '../../shared/confirm-dialog/confirm-dialog.component';
import { MathService } from '../../shared/math.service';
@@ -82,8 +82,8 @@ import { RecipeDetailDatasource } from './recipe-detail-datasource';
],
})
export class RecipeDetailComponent implements OnInit, AfterViewInit {
@ViewChild('productElement', { static: true }) productElement?: ElementRef;
@ViewChild('ingredientElement', { static: true }) ingredientElement?: ElementRef;
@ViewChild('productElement', { static: true }) productElement!: ElementRef<HTMLInputElement>;
@ViewChild('ingredientElement', { static: true }) ingredientElement!: ElementRef<HTMLInputElement>;
public itemsObservable = new BehaviorSubject<RecipeItem[]>([]);
dataSource: RecipeDetailDatasource = new RecipeDetailDatasource(this.itemsObservable);
form: FormGroup<{
@@ -114,7 +114,7 @@ export class RecipeDetailComponent implements OnInit, AfterViewInit {
private route: ActivatedRoute,
private router: Router,
private dialog: MatDialog,
private toaster: ToasterService,
private snackBar: MatSnackBar,
private math: MathService,
private ser: RecipeService,
private productSer: ProductService,
@@ -182,9 +182,7 @@ export class RecipeDetailComponent implements OnInit, AfterViewInit {
ngAfterViewInit() {
setTimeout(() => {
if (this.productElement) {
this.productElement.nativeElement.focus();
}
this.productElement.nativeElement.focus();
}, 0);
}
@@ -218,7 +216,7 @@ export class RecipeDetailComponent implements OnInit, AfterViewInit {
}
const oldFiltered = this.item.items.filter((x) => x.product.id === (this.ingredient as ProductSku).id);
if (oldFiltered.length) {
this.toaster.show('Danger', 'Product already added');
this.snackBar.open('Product already added', 'Danger');
return;
}
this.item.items.push(
@@ -236,9 +234,7 @@ export class RecipeDetailComponent implements OnInit, AfterViewInit {
this.form.controls.addRow.reset();
this.ingredient = null;
setTimeout(() => {
if (this.ingredientElement) {
this.ingredientElement.nativeElement.focus();
}
this.ingredientElement.nativeElement.focus();
}, 0);
}
@@ -254,11 +250,11 @@ export class RecipeDetailComponent implements OnInit, AfterViewInit {
save() {
this.ser.saveOrUpdate(this.getItem()).subscribe({
next: () => {
this.toaster.show('Success', '');
this.snackBar.open('', 'Success');
this.router.navigateByUrl('/recipes');
},
error: (error) => {
this.toaster.show('Danger', error);
this.snackBar.open(error, 'Danger');
},
});
}
@@ -266,11 +262,11 @@ export class RecipeDetailComponent implements OnInit, AfterViewInit {
delete() {
this.ser.delete(this.item.id as string).subscribe({
next: () => {
this.toaster.show('Success', '');
this.snackBar.open('', 'Success');
this.router.navigate(['/recipes']);
},
error: (error) => {
this.toaster.show('Danger', error);
this.snackBar.open(error, 'Danger');
},
});
}
@@ -65,8 +65,8 @@ import { RecipeListDatasource } from './recipe-list-datasource';
],
})
export class RecipeListComponent implements OnInit {
@ViewChild(MatPaginator, { static: true }) paginator?: MatPaginator;
@ViewChild(MatSort, { static: true }) sort?: MatSort;
@ViewChild(MatPaginator, { static: true }) paginator!: MatPaginator;
@ViewChild(MatSort, { static: true }) sort!: MatSort;
form: FormGroup<{
period: FormControl<Period>;
productGroup: FormControl<ProductGroup | string | null>;
@@ -75,10 +75,16 @@ export class RecipeListComponent implements OnInit {
productGroups: ProductGroup[] = [];
periods: Period[] = [];
periodFilter: BehaviorSubject<Period> = new BehaviorSubject<Period>(new Period());
productGroupFilter: BehaviorSubject<string> = new BehaviorSubject('');
productGroupFilter = new BehaviorSubject<string>('');
list: Recipe[] = [];
data: BehaviorSubject<Recipe[]> = new BehaviorSubject<Recipe[]>([]);
dataSource: RecipeListDatasource = new RecipeListDatasource(this.productGroupFilter, this.data);
dataSource: RecipeListDatasource = new RecipeListDatasource(
this.productGroupFilter,
this.data,
this.paginator,
this.sort,
);
period: Period = new Period();
/** Columns displayed in the table. Columns IDs can be added, removed, or reordered. */
@@ -9,7 +9,7 @@ import { MatFormField, MatLabel } from '@angular/material/form-field';
import { MatInput } from '@angular/material/input';
import { ActivatedRoute, Router } from '@angular/router';
import { ToasterService } from '../../core/toaster.service';
import { MatSnackBar } from '@angular/material/snack-bar';
import { ConfirmDialogComponent } from '../../shared/confirm-dialog/confirm-dialog.component';
import { Role } from '../role';
import { RoleService } from '../role.service';
@@ -35,7 +35,7 @@ import { RoleService } from '../role.service';
],
})
export class RoleDetailComponent implements OnInit, AfterViewInit {
@ViewChild('nameElement', { static: true }) nameElement?: ElementRef;
@ViewChild('nameElement', { static: true }) nameElement!: ElementRef<HTMLInputElement>;
form: FormGroup<{
name: FormControl<string | null>;
permissions: FormArray<
@@ -50,7 +50,7 @@ export class RoleDetailComponent implements OnInit, AfterViewInit {
constructor(
private route: ActivatedRoute,
private router: Router,
private toaster: ToasterService,
private snackBar: MatSnackBar,
private dialog: MatDialog,
private ser: RoleService,
) {
@@ -79,20 +79,18 @@ export class RoleDetailComponent implements OnInit, AfterViewInit {
ngAfterViewInit() {
setTimeout(() => {
if (this.nameElement) {
this.nameElement.nativeElement.focus();
}
this.nameElement.nativeElement.focus();
}, 0);
}
save() {
this.ser.saveOrUpdate(this.getItem()).subscribe({
next: () => {
this.toaster.show('Success', '');
this.snackBar.open('', 'Success');
this.router.navigateByUrl('/roles');
},
error: (error) => {
this.toaster.show('Danger', error);
this.snackBar.open(error, 'Danger');
},
});
}
@@ -100,11 +98,11 @@ export class RoleDetailComponent implements OnInit, AfterViewInit {
delete() {
this.ser.delete(this.item.id as string).subscribe({
next: () => {
this.toaster.show('Success', '');
this.snackBar.open('', 'Success');
this.router.navigateByUrl('/roles');
},
error: (error) => {
this.toaster.show('Danger', error);
this.snackBar.open(error, 'Danger');
},
});
}
@@ -52,10 +52,10 @@ import { RoleListDatasource } from './role-list-datasource';
],
})
export class RoleListComponent implements OnInit {
@ViewChild(MatPaginator, { static: true }) paginator?: MatPaginator;
@ViewChild(MatSort, { static: true }) sort?: MatSort;
@ViewChild(MatPaginator, { static: true }) paginator!: MatPaginator;
@ViewChild(MatSort, { static: true }) sort!: MatSort;
list: Role[] = [];
dataSource: RoleListDatasource = new RoleListDatasource(this.list);
dataSource: RoleListDatasource = new RoleListDatasource(this.list, this.paginator, this.sort);
/** Columns displayed in the table. Columns IDs can be added, removed, or reordered. */
displayedColumns = ['name', 'permissions'];
@@ -29,7 +29,7 @@ import { BehaviorSubject } from 'rxjs';
import { environment } from '../app.environment';
import { AuthService } from '../auth/auth.service';
import { AccountType } from '../core/account-type';
import { ToasterService } from '../core/toaster.service';
import { MatSnackBar } from '@angular/material/snack-bar';
import { ConfirmDialogComponent } from '../shared/confirm-dialog/confirm-dialog.component';
import { LockDataSource } from './lock-datasource';
@@ -115,7 +115,7 @@ export class SettingsComponent implements OnInit {
private route: ActivatedRoute,
private router: Router,
private dialog: MatDialog,
private toaster: ToasterService,
private snackBar: MatSnackBar,
public auth: AuthService,
private ser: SettingsService,
) {
@@ -243,10 +243,10 @@ export class SettingsComponent implements OnInit {
this.ser.setLockInformation(item).subscribe({
next: (result) => {
this.showLockInformation(result);
this.toaster.show('Success', 'Lock information Updated');
this.snackBar.open('Lock information Updated', 'Success');
},
error: (error) => {
this.toaster.show('Danger', error);
this.snackBar.open(error, 'Danger');
},
});
}
@@ -277,10 +277,10 @@ export class SettingsComponent implements OnInit {
rebaseData(rebaseDate: string) {
this.ser.rebaseDatabase(rebaseDate).subscribe({
next: () => {
this.toaster.show('Success', 'Data has been rebased!');
this.snackBar.open('Data has been rebased!', 'Success');
},
error: (error) => {
this.toaster.show('Danger', error);
this.snackBar.open(error, 'Danger');
},
});
}
+1 -1
View File
@@ -5,7 +5,7 @@ import { Injectable } from '@angular/core';
})
export class CookieService {
public getCookie(name: string) {
const ca: Array<string> = document.cookie.split(';');
const ca: string[] = document.cookie.split(';');
const caLen: number = ca.length;
const cookieName = `${name}=`;
let c: string;
+1 -3
View File
@@ -1,3 +1 @@
export interface ToCsvType {
[column: string]: string | number | boolean | null;
}
export type ToCsvType = Record<string, string | number | boolean | null>;
+1 -1
View File
@@ -6,7 +6,7 @@ import { ToCsvType } from './to-csv-type';
providedIn: 'root',
})
export class ToCsvService {
toCsv(headers: { [display: string]: string }, data: unknown[]): string {
toCsv(headers: Record<string, string>, data: unknown[]): string {
const header = Object.keys(headers);
const replacer = (key: string, value: string | number | null) => (value === null ? '' : value);
const csv = data.map((row) =>
@@ -9,8 +9,8 @@
<mat-label>Start Date</mat-label>
<input
matInput
#startDateElement
[matDatepicker]="startDate"
(focus)="startDate.open()"
formControlName="startDate"
autocomplete="off"
/>
@@ -19,13 +19,7 @@
</mat-form-field>
<mat-form-field class="flex-auto basis-2/5 mr-5">
<mat-label>Finish Date</mat-label>
<input
matInput
[matDatepicker]="finishDate"
(focus)="finishDate.open()"
formControlName="finishDate"
autocomplete="off"
/>
<input matInput [matDatepicker]="finishDate" formControlName="finishDate" autocomplete="off" />
<mat-datepicker-toggle matSuffix [for]="finishDate"></mat-datepicker-toggle>
<mat-datepicker #finishDate></mat-datepicker>
</mat-form-field>
@@ -1,5 +1,5 @@
import { DecimalPipe } from '@angular/common';
import { Component, OnInit, ViewChild } from '@angular/core';
import { Component, ElementRef, HostListener, OnInit, ViewChild } from '@angular/core';
import { FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms';
import { MatButton } from '@angular/material/button';
import { MatCard, MatCardHeader, MatCardTitle, MatCardContent } from '@angular/material/card';
@@ -63,10 +63,11 @@ import { StockMovementDataSource } from './stock-movement-datasource';
],
})
export class StockMovementComponent implements OnInit {
@ViewChild(MatPaginator, { static: true }) paginator?: MatPaginator;
@ViewChild(MatSort, { static: true }) sort?: MatSort;
@ViewChild(MatPaginator, { static: true }) paginator!: MatPaginator;
@ViewChild(MatSort, { static: true }) sort!: MatSort;
@ViewChild('startDateElement', { static: true }) startDate!: ElementRef<HTMLInputElement>;
info: StockMovement = new StockMovement();
dataSource: StockMovementDataSource = new StockMovementDataSource(this.info.body);
dataSource: StockMovementDataSource = new StockMovementDataSource(this.info.body, this.paginator, this.sort);
form: FormGroup<{
startDate: FormControl<Date>;
finishDate: FormControl<Date>;
@@ -76,6 +77,13 @@ export class StockMovementComponent implements OnInit {
/** Columns displayed in the table. Columns IDs can be added, removed, or reordered. */
displayedColumns = ['group', 'name', 'opening', 'purchase', 'issue', 'closing'];
@HostListener('window:keydown.f2', ['$event'])
focusDate(event: KeyboardEvent) {
event.preventDefault();
this.startDate.nativeElement.focus();
this.startDate.nativeElement.select();
}
constructor(
private route: ActivatedRoute,
private router: Router,
@@ -7,13 +7,7 @@
<div class="flex flex-row justify-around content-start items-start sm:max-lg:flex-col">
<mat-form-field class="flex-auto basis-4/5 mr-5">
<mat-label>Date</mat-label>
<input
matInput
[matDatepicker]="dateInput"
(focus)="dateInput.open()"
formControlName="date"
autocomplete="off"
/>
<input matInput #dateElement [matDatepicker]="dateInput" formControlName="date" autocomplete="off" />
<mat-datepicker-toggle matSuffix [for]="dateInput"></mat-datepicker-toggle>
<mat-datepicker #dateInput></mat-datepicker>
</mat-form-field>
@@ -1,5 +1,5 @@
import { CurrencyPipe } from '@angular/common';
import { Component, OnInit, ViewChild } from '@angular/core';
import { Component, ElementRef, HostListener, OnInit, ViewChild } from '@angular/core';
import { FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms';
import { MatButton } from '@angular/material/button';
import { MatCard, MatCardHeader, MatCardTitle, MatCardContent } from '@angular/material/card';
@@ -65,10 +65,11 @@ import { TrialBalanceDataSource } from './trial-balance-datasource';
],
})
export class TrialBalanceComponent implements OnInit {
@ViewChild(MatPaginator, { static: true }) paginator?: MatPaginator;
@ViewChild(MatSort, { static: true }) sort?: MatSort;
@ViewChild(MatPaginator, { static: true }) paginator!: MatPaginator;
@ViewChild(MatSort, { static: true }) sort!: MatSort;
@ViewChild('dateElement', { static: true }) dateElement!: ElementRef<HTMLInputElement>;
info: TrialBalance = new TrialBalance();
dataSource: TrialBalanceDataSource = new TrialBalanceDataSource(this.info.body);
dataSource: TrialBalanceDataSource = new TrialBalanceDataSource(this.info.body, this.paginator, this.sort);
form: FormGroup<{
date: FormControl<Date>;
}>;
@@ -76,6 +77,13 @@ export class TrialBalanceComponent implements OnInit {
/** Columns displayed in the table. Columns IDs can be added, removed, or reordered. */
displayedColumns = ['type', 'name', 'debit', 'credit'];
@HostListener('window:keydown.f2', ['$event'])
focusDate(event: KeyboardEvent) {
event.preventDefault();
this.dateElement.nativeElement.focus();
this.dateElement.nativeElement.select();
}
constructor(
private route: ActivatedRoute,
private router: Router,
@@ -10,7 +10,7 @@ import { MatIcon } from '@angular/material/icon';
import { MatInput } from '@angular/material/input';
import { ActivatedRoute, Router } from '@angular/router';
import { ToasterService } from '../../core/toaster.service';
import { MatSnackBar } from '@angular/material/snack-bar';
import { User } from '../../core/user';
import { ConfirmDialogComponent } from '../../shared/confirm-dialog/confirm-dialog.component';
import { UserService } from '../user.service';
@@ -38,7 +38,7 @@ import { UserService } from '../user.service';
],
})
export class UserDetailComponent implements OnInit, AfterViewInit {
@ViewChild('nameElement', { static: true }) nameElement?: ElementRef;
@ViewChild('nameElement', { static: true }) nameElement!: ElementRef<HTMLInputElement>;
form: FormGroup<{
name: FormControl<string | null>;
password: FormControl<string | null>;
@@ -56,7 +56,7 @@ export class UserDetailComponent implements OnInit, AfterViewInit {
constructor(
private route: ActivatedRoute,
private router: Router,
private toaster: ToasterService,
private snackBar: MatSnackBar,
private dialog: MatDialog,
private ser: UserService,
) {
@@ -94,9 +94,7 @@ export class UserDetailComponent implements OnInit, AfterViewInit {
ngAfterViewInit() {
setTimeout(() => {
if (this.nameElement) {
this.nameElement.nativeElement.focus();
}
this.nameElement.nativeElement.focus();
}, 0);
}
@@ -104,21 +102,21 @@ export class UserDetailComponent implements OnInit, AfterViewInit {
if (this.route.snapshot.paramMap.get('id') === 'me') {
this.ser.updateMe(this.getItem()).subscribe({
next: () => {
this.toaster.show('Success', '');
this.snackBar.open('', 'Success');
this.router.navigateByUrl('/');
},
error: (error) => {
this.toaster.show('Danger', error);
this.snackBar.open(error, 'Danger');
},
});
} else {
this.ser.saveOrUpdate(this.getItem()).subscribe({
next: () => {
this.toaster.show('Success', '');
this.snackBar.open('', 'Success');
this.router.navigateByUrl('/users');
},
error: (error) => {
this.toaster.show('Danger', error);
this.snackBar.open(error, 'Danger');
},
});
}
@@ -127,11 +125,11 @@ export class UserDetailComponent implements OnInit, AfterViewInit {
delete() {
this.ser.delete(this.item.id as string).subscribe({
next: () => {
this.toaster.show('Success', '');
this.snackBar.open('', 'Success');
this.router.navigateByUrl('/users');
},
error: (error) => {
this.toaster.show('Danger', error);
this.snackBar.open(error, 'Danger');
},
});
}
@@ -54,8 +54,8 @@ import { UserListDataSource } from './user-list-datasource';
],
})
export class UserListComponent implements OnInit {
@ViewChild(MatPaginator, { static: true }) paginator?: MatPaginator = undefined;
@ViewChild(MatSort, { static: true }) sort?: MatSort = undefined;
@ViewChild(MatPaginator, { static: true }) paginator!: MatPaginator;
@ViewChild(MatSort, { static: true }) sort!: MatSort;
list: User[] = [];
dataSource: UserListDataSource = new UserListDataSource(this.list);
/** Columns displayed in the table. Columns IDs can be added, removed, or reordered. */
+5
View File
@@ -3,6 +3,11 @@ import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app/app.component';
import { appConfig } from './app/app.config';
import enIn from '@angular/common/locales/en-IN';
import {registerLocaleData} from '@angular/common'; //function to register it.
registerLocaleData(enIn);
bootstrapApplication(AppComponent, appConfig)
.catch((err) => console.error(err));