diff --git a/overlord/package.json b/overlord/package.json index 6f230f6c..6fe8d3be 100644 --- a/overlord/package.json +++ b/overlord/package.json @@ -26,6 +26,7 @@ "@angular/router": "^7.1.0", "@ngx-loading-bar/http-client": "^3.0.0", "@ngx-loading-bar/router": "^3.0.0", + "angular2-hotkeys": "^2.1.4", "core-js": "^2.5.7", "hammerjs": "^2.0.8", "mathjs": "^5.0.4", diff --git a/overlord/src/app/app.module.ts b/overlord/src/app/app.module.ts index 60a2088c..dcfa31ec 100644 --- a/overlord/src/app/app.module.ts +++ b/overlord/src/app/app.module.ts @@ -66,6 +66,7 @@ import {AttendanceModule} from './attendance/attendance.module'; import {EmployeeAttendanceModule} from './employee-attendance/employee-attendance.module'; import {RawMaterialCostModule} from './raw-material-cost/raw-material-cost.module'; import {FlexLayoutModule} from "@angular/flex-layout"; +import {HotkeyModule} from "angular2-hotkeys"; registerLocaleData(enIN); @@ -81,6 +82,7 @@ registerLocaleData(enIN); BrowserModule, BrowserAnimationsModule, FlexLayoutModule.withConfig({useColumnBasisZero: true}), + HotkeyModule.forRoot(), HttpClientModule, LayoutModule, MatButtonModule, diff --git a/overlord/src/app/issue/issue.component.html b/overlord/src/app/issue/issue.component.html index f1d987e0..4d01f7c7 100644 --- a/overlord/src/app/issue/issue.component.html +++ b/overlord/src/app/issue/issue.component.html @@ -7,8 +7,8 @@ <div fxLayout="row" fxLayoutAlign="space-around start" fxLayout.lt-md="column" fxLayoutGap="20px" fxLayoutGap.lt-md="0px"> <mat-form-field fxFlex="40"> - <input matInput [matDatepicker]="date" (focus)="date.open()" placeholder="Date" formControlName="date" - autocomplete="off"> + <input matInput [matDatepicker]="date" placeholder="Date" formControlName="date" autocomplete="off" + #dateElement (focus)="dateElement.select()"> <mat-datepicker-toggle matSuffix [for]="date"></mat-datepicker-toggle> <mat-datepicker #date></mat-datepicker> </mat-form-field> diff --git a/overlord/src/app/issue/issue.component.ts b/overlord/src/app/issue/issue.component.ts index 8075c51c..8f80ce70 100644 --- a/overlord/src/app/issue/issue.component.ts +++ b/overlord/src/app/issue/issue.component.ts @@ -1,4 +1,4 @@ -import {AfterViewInit, Component, ElementRef, OnInit, ViewChild} from '@angular/core'; +import {AfterViewInit, Component, ElementRef, OnInit, OnDestroy, ViewChild} from '@angular/core'; import {FormBuilder, FormGroup} from '@angular/forms'; import {MatAutocompleteSelectedEvent, MatDialog} from '@angular/material'; import {ActivatedRoute, Router} from '@angular/router'; @@ -16,14 +16,16 @@ import {BatchService} from '../purchase-return/batch.service'; import {IssueGridService} from './issue-grid.service'; import {CostCentre} from '../cost-centre/cost-centre'; import {IssueGridDataSource} from './issue-grid-datasource'; +import {Hotkey, HotkeysService} from "angular2-hotkeys"; @Component({ selector: 'app-issue', templateUrl: './issue.component.html', styleUrls: ['./issue.component.css'] }) -export class IssueComponent implements OnInit, AfterViewInit { +export class IssueComponent implements OnInit, AfterViewInit, OnDestroy { @ViewChild('batchElement') batchElement: ElementRef; + @ViewChild('dateElement') dateElement: ElementRef; public inventoryObservable = new BehaviorSubject<Inventory[]>([]); public gridObservable = new BehaviorSubject<any[]>([]); dataSource: IssueDataSource; @@ -45,6 +47,7 @@ export class IssueComponent implements OnInit, AfterViewInit { private router: Router, private fb: FormBuilder, private dialog: MatDialog, + private hotkeys: HotkeysService, private toaster: ToasterService, private auth: AuthService, private ser: VoucherService, @@ -63,12 +66,27 @@ export class IssueComponent implements OnInit, AfterViewInit { this.costCentres = data.costCentres; this.loadVoucher(data.voucher); }); + this.hotkeys.add(new Hotkey('f2', (event: KeyboardEvent): boolean => { + setTimeout(() => { + this.dateElement.nativeElement.focus(); + }, 0); + return false; // Prevent bubbling + }, ['INPUT', 'SELECT', 'TEXTAREA'])); + this.hotkeys.add(new Hotkey('ctrl+s', (event: KeyboardEvent): 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.sourceJournal = this.voucher.journals.filter(x => x.debit === -1)[0]; diff --git a/overlord/src/app/issue/issue.module.ts b/overlord/src/app/issue/issue.module.ts index 689dadd7..f13b0e27 100644 --- a/overlord/src/app/issue/issue.module.ts +++ b/overlord/src/app/issue/issue.module.ts @@ -29,6 +29,7 @@ import {MomentDateAdapter} from '@angular/material-moment-adapter'; import {A11yModule} from '@angular/cdk/a11y'; import {IssueDialogComponent} from './issue-dialog.component'; import {FlexLayoutModule} from '@angular/flex-layout'; +import {HotkeyModule} from "angular2-hotkeys"; export const MY_FORMATS = { parse: { @@ -48,6 +49,7 @@ export const MY_FORMATS = { CommonModule, CdkTableModule, FlexLayoutModule, + HotkeyModule, MatAutocompleteModule, MatButtonModule, MatCardModule, diff --git a/overlord/src/app/journal/journal.component.html b/overlord/src/app/journal/journal.component.html index 89e09f31..604c5084 100644 --- a/overlord/src/app/journal/journal.component.html +++ b/overlord/src/app/journal/journal.component.html @@ -10,8 +10,8 @@ <form [formGroup]="form" fxLayout="column"> <div fxLayout="row" fxLayout.lt-md="column" fxLayoutGap="20px" fxLayoutGap.lt-md="0px"> <mat-form-field fxFlex> - <input matInput [matDatepicker]="date" (focus)="date.open()" placeholder="Date" formControlName="date" - autocomplete="off"> + <input matInput [matDatepicker]="date" placeholder="Date" formControlName="date" autocomplete="off" + #dateElement (focus)="dateElement.select()"> <mat-datepicker-toggle matSuffix [for]="date"></mat-datepicker-toggle> <mat-datepicker #date></mat-datepicker> </mat-form-field> diff --git a/overlord/src/app/journal/journal.component.ts b/overlord/src/app/journal/journal.component.ts index e32d95a4..8c9ae2ee 100644 --- a/overlord/src/app/journal/journal.component.ts +++ b/overlord/src/app/journal/journal.component.ts @@ -1,4 +1,4 @@ -import {AfterViewInit, Component, ElementRef, OnInit, ViewChild} from '@angular/core'; +import {AfterViewInit, Component, ElementRef, OnInit, OnDestroy, ViewChild} from '@angular/core'; import {FormBuilder, FormGroup} from '@angular/forms'; import {MatAutocompleteSelectedEvent, MatDialog} from '@angular/material'; import {ActivatedRoute, Router} from '@angular/router'; @@ -16,14 +16,16 @@ import {ToasterService} from '../core/toaster.service'; import {debounceTime, distinctUntilChanged, map, startWith, switchMap} from 'rxjs/operators'; import {JournalDialogComponent} from './journal-dialog.component'; import {ImageDialogComponent} from '../shared/image-dialog/image-dialog.component'; +import {Hotkey, HotkeysService} from "angular2-hotkeys"; @Component({ selector: 'app-journal', templateUrl: './journal.component.html', styleUrls: ['./journal.component.css'] }) -export class JournalComponent implements OnInit, AfterViewInit { +export class JournalComponent implements OnInit, AfterViewInit, OnDestroy { @ViewChild('accountElement') accountElement: ElementRef; + @ViewChild('dateElement') dateElement: ElementRef; public journalObservable = new BehaviorSubject<Journal[]>([]); dataSource: JournalDataSource; form: FormGroup; @@ -40,6 +42,7 @@ export class JournalComponent implements OnInit, AfterViewInit { private router: Router, private fb: FormBuilder, private dialog: MatDialog, + private hotkeys: HotkeysService, private toaster: ToasterService, private auth: AuthService, private ser: VoucherService, @@ -55,12 +58,32 @@ export class JournalComponent implements OnInit, AfterViewInit { .subscribe((data: { voucher: Voucher }) => { this.loadVoucher(data.voucher); }); + this.hotkeys.add(new Hotkey('f2', (event: KeyboardEvent): boolean => { + setTimeout(() => { + this.dateElement.nativeElement.focus(); + }, 0); + return false; // Prevent bubbling + }, ['INPUT', 'SELECT', 'TEXTAREA'])); + this.hotkeys.add(new Hotkey('ctrl+s', (event: KeyboardEvent): boolean => { + if (this.canSave()) + this.save(); + return false; // Prevent bubbling + }, ['INPUT', 'SELECT', 'TEXTAREA'])); + this.hotkeys.add(new Hotkey('ctrl+p', (event: KeyboardEvent): boolean => { + if (this.voucher.id && !this.voucher.posted && this.auth.user.perms.indexOf('Post Vouchers') !== -1) + this.post(); + return false; // Prevent bubbling + }, ['INPUT', 'SELECT', 'TEXTAREA'])); } ngAfterViewInit() { this.focusAccount(); } + ngOnDestroy() { + this.hotkeys.reset(); + } + loadVoucher(voucher) { this.voucher = voucher; this.form.setValue({ diff --git a/overlord/src/app/journal/journal.module.ts b/overlord/src/app/journal/journal.module.ts index 4952e067..317688aa 100644 --- a/overlord/src/app/journal/journal.module.ts +++ b/overlord/src/app/journal/journal.module.ts @@ -29,6 +29,7 @@ import {MomentDateAdapter} from '@angular/material-moment-adapter'; import {A11yModule} from '@angular/cdk/a11y'; import {JournalDialogComponent} from './journal-dialog.component'; import {FlexLayoutModule} from '@angular/flex-layout'; +import {HotkeyModule} from "angular2-hotkeys"; export const MY_FORMATS = { parse: { @@ -48,6 +49,7 @@ export const MY_FORMATS = { CommonModule, CdkTableModule, FlexLayoutModule, + HotkeyModule, MatAutocompleteModule, MatButtonModule, MatCardModule, diff --git a/overlord/src/app/payment/payment.component.html b/overlord/src/app/payment/payment.component.html index 8b9932ce..47eea8ca 100644 --- a/overlord/src/app/payment/payment.component.html +++ b/overlord/src/app/payment/payment.component.html @@ -11,8 +11,8 @@ <div fxLayout="row" fxLayoutAlign="space-around start" fxLayout.lt-md="column" fxLayoutGap="20px" fxLayoutGap.lt-md="0px"> <mat-form-field fxFlex="40"> - <input matInput [matDatepicker]="date" (focus)="date.open()" placeholder="Date" formControlName="date" - autocomplete="off"> + <input matInput [matDatepicker]="date" placeholder="Date" formControlName="date" autocomplete="off" + #dateElement (focus)="dateElement.select()"> <mat-datepicker-toggle matSuffix [for]="date"></mat-datepicker-toggle> <mat-datepicker #date></mat-datepicker> </mat-form-field> diff --git a/overlord/src/app/payment/payment.component.ts b/overlord/src/app/payment/payment.component.ts index db51524d..8ea60932 100644 --- a/overlord/src/app/payment/payment.component.ts +++ b/overlord/src/app/payment/payment.component.ts @@ -1,4 +1,4 @@ -import {AfterViewInit, Component, ElementRef, OnInit, ViewChild} from '@angular/core'; +import {AfterViewInit, Component, ElementRef, OnInit, OnDestroy, ViewChild} from '@angular/core'; import {FormBuilder, FormGroup} from '@angular/forms'; import {MatAutocompleteSelectedEvent, MatDialog} from '@angular/material'; import {ActivatedRoute, Router} from '@angular/router'; @@ -16,14 +16,16 @@ import {ToasterService} from '../core/toaster.service'; import {debounceTime, distinctUntilChanged, map, startWith, switchMap} from 'rxjs/operators'; import {PaymentDialogComponent} from './payment-dialog.component'; import {ImageDialogComponent} from '../shared/image-dialog/image-dialog.component'; +import {Hotkey, HotkeysService} from "angular2-hotkeys"; @Component({ selector: 'app-payment', templateUrl: './payment.component.html', styleUrls: ['./payment.component.css'] }) -export class PaymentComponent implements OnInit, AfterViewInit { +export class PaymentComponent implements OnInit, AfterViewInit, OnDestroy { @ViewChild('accountElement') accountElement: ElementRef; + @ViewChild('dateElement') dateElement: ElementRef; public journalObservable = new BehaviorSubject<Journal[]>([]); dataSource: PaymentDataSource; form: FormGroup; @@ -42,6 +44,7 @@ export class PaymentComponent implements OnInit, AfterViewInit { private router: Router, private fb: FormBuilder, private dialog: MatDialog, + private hotkeys: HotkeysService, private toaster: ToasterService, private auth: AuthService, private ser: VoucherService, @@ -59,12 +62,32 @@ export class PaymentComponent implements OnInit, AfterViewInit { this.paymentAccounts = data.paymentAccounts; this.loadVoucher(data.voucher); }); + this.hotkeys.add(new Hotkey('f2', (event: KeyboardEvent): boolean => { + setTimeout(() => { + this.dateElement.nativeElement.focus(); + }, 0); + return false; // Prevent bubbling + }, ['INPUT', 'SELECT', 'TEXTAREA'])); + this.hotkeys.add(new Hotkey('ctrl+s', (event: KeyboardEvent): boolean => { + if (this.canSave()) + this.save(); + return false; // Prevent bubbling + }, ['INPUT', 'SELECT', 'TEXTAREA'])); + this.hotkeys.add(new Hotkey('ctrl+p', (event: KeyboardEvent): boolean => { + if (this.voucher.id && !this.voucher.posted && this.auth.user.perms.indexOf('Post Vouchers') !== -1) + 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)[0]; diff --git a/overlord/src/app/payment/payment.module.ts b/overlord/src/app/payment/payment.module.ts index 3dd597cf..472423a8 100644 --- a/overlord/src/app/payment/payment.module.ts +++ b/overlord/src/app/payment/payment.module.ts @@ -29,6 +29,7 @@ import {MomentDateAdapter} from '@angular/material-moment-adapter'; import {A11yModule} from '@angular/cdk/a11y'; import {PaymentDialogComponent} from './payment-dialog.component'; import {FlexLayoutModule} from '@angular/flex-layout'; +import {HotkeyModule} from "angular2-hotkeys"; export const MY_FORMATS = { parse: { @@ -48,6 +49,7 @@ export const MY_FORMATS = { CommonModule, CdkTableModule, FlexLayoutModule, + HotkeyModule, MatAutocompleteModule, MatButtonModule, MatCardModule, diff --git a/overlord/src/app/product/product-detail/product-detail.component.ts b/overlord/src/app/product/product-detail/product-detail.component.ts index b0dd28a4..865cec2b 100644 --- a/overlord/src/app/product/product-detail/product-detail.component.ts +++ b/overlord/src/app/product/product-detail/product-detail.component.ts @@ -57,7 +57,6 @@ export class ProductDetailComponent implements OnInit, AfterViewInit { showItem(item: Product) { this.item = item; - console.log(item); this.form.setValue({ code: this.item.code || '(Auto)', name: this.item.name || '', diff --git a/overlord/src/app/purchase-return/purchase-return.component.html b/overlord/src/app/purchase-return/purchase-return.component.html index 182f3d29..58df7f40 100644 --- a/overlord/src/app/purchase-return/purchase-return.component.html +++ b/overlord/src/app/purchase-return/purchase-return.component.html @@ -11,8 +11,8 @@ <div fxLayout="row" fxLayoutAlign="space-around start" fxLayout.lt-md="column" fxLayoutGap="20px" fxLayoutGap.lt-md="0px"> <mat-form-field fxFlex="40"> - <input matInput [matDatepicker]="date" (focus)="date.open()" placeholder="Date" formControlName="date" - autocomplete="off"> + <input matInput [matDatepicker]="date" placeholder="Date" formControlName="date" autocomplete="off" + #dateElement (focus)="dateElement.select()"> <mat-datepicker-toggle matSuffix [for]="date"></mat-datepicker-toggle> <mat-datepicker #date></mat-datepicker> </mat-form-field> diff --git a/overlord/src/app/purchase-return/purchase-return.component.ts b/overlord/src/app/purchase-return/purchase-return.component.ts index a367d467..2d7cc2f8 100644 --- a/overlord/src/app/purchase-return/purchase-return.component.ts +++ b/overlord/src/app/purchase-return/purchase-return.component.ts @@ -1,4 +1,4 @@ -import {AfterViewInit, Component, ElementRef, OnInit, ViewChild} from '@angular/core'; +import {AfterViewInit, Component, ElementRef, OnInit, OnDestroy, ViewChild} from '@angular/core'; import {FormBuilder, FormGroup} from '@angular/forms'; import {MatAutocompleteSelectedEvent, MatDialog} from '@angular/material'; import {ActivatedRoute, Router} from '@angular/router'; @@ -16,15 +16,17 @@ import {debounceTime, distinctUntilChanged, map, startWith, switchMap} from 'rxj import {PurchaseReturnDialogComponent} from './purchase-return-dialog.component'; import {ImageDialogComponent} from '../shared/image-dialog/image-dialog.component'; import {BatchService} from './batch.service'; +import {Hotkey, HotkeysService} from "angular2-hotkeys"; @Component({ selector: 'app-purchase-return', templateUrl: './purchase-return.component.html', styleUrls: ['./purchase-return.component.css'] }) -export class PurchaseReturnComponent implements OnInit, AfterViewInit { +export class PurchaseReturnComponent implements OnInit, AfterViewInit, OnDestroy { @ViewChild('accountElement') accountElement: ElementRef; @ViewChild('batchElement') batchElement: ElementRef; + @ViewChild('dateElement') dateElement: ElementRef; public inventoryObservable = new BehaviorSubject<Inventory[]>([]); dataSource: PurchaseReturnDataSource; form: FormGroup; @@ -44,6 +46,7 @@ export class PurchaseReturnComponent implements OnInit, AfterViewInit { private router: Router, private fb: FormBuilder, private dialog: MatDialog, + private hotkeys: HotkeysService, private toaster: ToasterService, private auth: AuthService, private ser: VoucherService, @@ -60,12 +63,32 @@ export class PurchaseReturnComponent implements OnInit, AfterViewInit { .subscribe((data: { voucher: Voucher }) => { this.loadVoucher(data.voucher); }); + this.hotkeys.add(new Hotkey('f2', (event: KeyboardEvent): boolean => { + setTimeout(() => { + this.dateElement.nativeElement.focus(); + }, 0); + return false; // Prevent bubbling + }, ['INPUT', 'SELECT', 'TEXTAREA'])); + this.hotkeys.add(new Hotkey('ctrl+s', (event: KeyboardEvent): boolean => { + if (this.canSave()) + this.save(); + return false; // Prevent bubbling + }, ['INPUT', 'SELECT', 'TEXTAREA'])); + this.hotkeys.add(new Hotkey('ctrl+p', (event: KeyboardEvent): boolean => { + if (this.voucher.id && !this.voucher.posted && this.auth.user.perms.indexOf('Post Vouchers') !== -1) + this.post(); + return false; // Prevent bubbling + }, ['INPUT', 'SELECT', 'TEXTAREA'])); } ngAfterViewInit() { this.focusAccount(); } + ngOnDestroy() { + this.hotkeys.reset(); + } + loadVoucher(voucher: Voucher) { this.voucher = voucher; this.purchaseReturnJournal = this.voucher.journals.filter(x => x.debit === 1)[0]; diff --git a/overlord/src/app/purchase-return/purchase-return.module.ts b/overlord/src/app/purchase-return/purchase-return.module.ts index 06938f7b..b62cf123 100644 --- a/overlord/src/app/purchase-return/purchase-return.module.ts +++ b/overlord/src/app/purchase-return/purchase-return.module.ts @@ -29,6 +29,7 @@ import {MomentDateAdapter} from '@angular/material-moment-adapter'; import {A11yModule} from '@angular/cdk/a11y'; import {PurchaseReturnDialogComponent} from './purchase-return-dialog.component'; import {FlexLayoutModule} from '@angular/flex-layout'; +import {HotkeyModule} from "angular2-hotkeys"; export const MY_FORMATS = { parse: { @@ -48,6 +49,7 @@ export const MY_FORMATS = { CommonModule, CdkTableModule, FlexLayoutModule, + HotkeyModule, MatAutocompleteModule, MatButtonModule, MatCardModule, diff --git a/overlord/src/app/purchase/purchase.component.html b/overlord/src/app/purchase/purchase.component.html index 0c919be6..201c43dd 100644 --- a/overlord/src/app/purchase/purchase.component.html +++ b/overlord/src/app/purchase/purchase.component.html @@ -11,8 +11,8 @@ <div fxLayout="row" fxLayoutAlign="space-around start" fxLayout.lt-md="column" fxLayoutGap="20px" fxLayoutGap.lt-md="0px"> <mat-form-field fxFlex="40"> - <input matInput [matDatepicker]="date" (focus)="date.open()" placeholder="Date" formControlName="date" - autocomplete="off"> + <input matInput [matDatepicker]="date" placeholder="Date" formControlName="date" autocomplete="off" + #dateElement (focus)="dateElement.select()"> <mat-datepicker-toggle matSuffix [for]="date"></mat-datepicker-toggle> <mat-datepicker #date></mat-datepicker> </mat-form-field> diff --git a/overlord/src/app/purchase/purchase.component.ts b/overlord/src/app/purchase/purchase.component.ts index f5329af6..bc8eaacd 100644 --- a/overlord/src/app/purchase/purchase.component.ts +++ b/overlord/src/app/purchase/purchase.component.ts @@ -1,4 +1,4 @@ -import {AfterViewInit, Component, ElementRef, OnInit, ViewChild} from '@angular/core'; +import {AfterViewInit, Component, ElementRef, OnInit, OnDestroy, ViewChild} from '@angular/core'; import {FormBuilder, FormGroup} from '@angular/forms'; import {MatAutocompleteSelectedEvent, MatDialog} from '@angular/material'; import {ActivatedRoute, Router} from '@angular/router'; @@ -17,15 +17,17 @@ import {PurchaseDialogComponent} from './purchase-dialog.component'; import {ImageDialogComponent} from '../shared/image-dialog/image-dialog.component'; import {ProductService} from '../product/product.service'; import {Product} from '../product/product'; +import {Hotkey, HotkeysService} from "angular2-hotkeys"; @Component({ selector: 'app-purchase', templateUrl: './purchase.component.html', styleUrls: ['./purchase.component.css'] }) -export class PurchaseComponent implements OnInit, AfterViewInit { +export class PurchaseComponent implements OnInit, AfterViewInit, OnDestroy { @ViewChild('accountElement') accountElement: ElementRef; @ViewChild('productElement') productElement: ElementRef; + @ViewChild('dateElement') dateElement: ElementRef; public inventoryObservable = new BehaviorSubject<Inventory[]>([]); dataSource: PurchaseDataSource; form: FormGroup; @@ -45,6 +47,7 @@ export class PurchaseComponent implements OnInit, AfterViewInit { private router: Router, private fb: FormBuilder, private dialog: MatDialog, + private hotkeys: HotkeysService, private toaster: ToasterService, private auth: AuthService, private ser: VoucherService, @@ -61,12 +64,32 @@ export class PurchaseComponent implements OnInit, AfterViewInit { .subscribe((data: { voucher: Voucher }) => { this.loadVoucher(data.voucher); }); + this.hotkeys.add(new Hotkey('f2', (event: KeyboardEvent): boolean => { + setTimeout(() => { + this.dateElement.nativeElement.focus(); + }, 0); + return false; // Prevent bubbling + }, ['INPUT', 'SELECT', 'TEXTAREA'])); + this.hotkeys.add(new Hotkey('ctrl+s', (event: KeyboardEvent): boolean => { + if (this.canSave()) + this.save(); + return false; // Prevent bubbling + }, ['INPUT', 'SELECT', 'TEXTAREA'])); + this.hotkeys.add(new Hotkey('ctrl+p', (event: KeyboardEvent): boolean => { + if (this.voucher.id && !this.voucher.posted && this.auth.user.perms.indexOf('Post Vouchers') !== -1) + this.post(); + return false; // Prevent bubbling + }, ['INPUT', 'SELECT', 'TEXTAREA'])); } ngAfterViewInit() { this.focusAccount(); } + ngOnDestroy() { + this.hotkeys.reset(); + } + loadVoucher(voucher) { this.voucher = voucher; this.purchaseJournal = this.voucher.journals.filter(x => x.debit === -1)[0]; diff --git a/overlord/src/app/purchase/purchase.module.ts b/overlord/src/app/purchase/purchase.module.ts index 07dd69bc..a6f65716 100644 --- a/overlord/src/app/purchase/purchase.module.ts +++ b/overlord/src/app/purchase/purchase.module.ts @@ -29,6 +29,7 @@ import {MomentDateAdapter} from '@angular/material-moment-adapter'; import {A11yModule} from '@angular/cdk/a11y'; import {PurchaseDialogComponent} from './purchase-dialog.component'; import {FlexLayoutModule} from '@angular/flex-layout'; +import {HotkeyModule} from "angular2-hotkeys"; export const MY_FORMATS = { parse: { @@ -48,6 +49,7 @@ export const MY_FORMATS = { CommonModule, CdkTableModule, FlexLayoutModule, + HotkeyModule, MatAutocompleteModule, MatButtonModule, MatCardModule, diff --git a/overlord/src/app/receipt/receipt.component.html b/overlord/src/app/receipt/receipt.component.html index 1458c40f..bd7ed44d 100644 --- a/overlord/src/app/receipt/receipt.component.html +++ b/overlord/src/app/receipt/receipt.component.html @@ -11,8 +11,8 @@ <div fxLayout="row" fxLayoutAlign="space-around start" fxLayout.lt-md="column" fxLayoutGap="20px" fxLayoutGap.lt-md="0px"> <mat-form-field fxFlex="40"> - <input matInput [matDatepicker]="date" (focus)="date.open()" placeholder="Date" formControlName="date" - autocomplete="off"> + <input matInput [matDatepicker]="date" placeholder="Date" formControlName="date" autocomplete="off" + #dateElement (focus)="dateElement.select()"> <mat-datepicker-toggle matSuffix [for]="date"></mat-datepicker-toggle> <mat-datepicker #date></mat-datepicker> </mat-form-field> diff --git a/overlord/src/app/receipt/receipt.component.ts b/overlord/src/app/receipt/receipt.component.ts index d65977db..aea221af 100644 --- a/overlord/src/app/receipt/receipt.component.ts +++ b/overlord/src/app/receipt/receipt.component.ts @@ -1,4 +1,4 @@ -import {AfterViewInit, Component, ElementRef, OnInit, ViewChild} from '@angular/core'; +import {AfterViewInit, Component, ElementRef, OnInit, OnDestroy, ViewChild} from '@angular/core'; import {FormBuilder, FormGroup} from '@angular/forms'; import {MatAutocompleteSelectedEvent, MatDialog} from '@angular/material'; import {ActivatedRoute, Router} from '@angular/router'; @@ -16,14 +16,16 @@ import {ToasterService} from '../core/toaster.service'; import {debounceTime, distinctUntilChanged, map, startWith, switchMap} from 'rxjs/operators'; import {ReceiptDialogComponent} from './receipt-dialog.component'; import {ImageDialogComponent} from '../shared/image-dialog/image-dialog.component'; +import {Hotkey, HotkeysService} from "angular2-hotkeys"; @Component({ selector: 'app-receipt', templateUrl: './receipt.component.html', styleUrls: ['./receipt.component.css'] }) -export class ReceiptComponent implements OnInit, AfterViewInit { +export class ReceiptComponent implements OnInit, AfterViewInit, OnDestroy { @ViewChild('accountElement') accountElement: ElementRef; + @ViewChild('dateElement') dateElement: ElementRef; public journalObservable = new BehaviorSubject<Journal[]>([]); dataSource: ReceiptDataSource; form: FormGroup; @@ -42,6 +44,7 @@ export class ReceiptComponent implements OnInit, AfterViewInit { private router: Router, private fb: FormBuilder, private dialog: MatDialog, + private hotkeys: HotkeysService, private toaster: ToasterService, private auth: AuthService, private ser: VoucherService, @@ -59,12 +62,32 @@ export class ReceiptComponent implements OnInit, AfterViewInit { this.receiptAccounts = data.receiptAccounts; this.loadVoucher(data.voucher); }); + this.hotkeys.add(new Hotkey('f2', (event: KeyboardEvent): boolean => { + setTimeout(() => { + this.dateElement.nativeElement.focus(); + }, 0); + return false; // Prevent bubbling + }, ['INPUT', 'SELECT', 'TEXTAREA'])); + this.hotkeys.add(new Hotkey('ctrl+s', (event: KeyboardEvent): boolean => { + if (this.canSave()) + this.save(); + return false; // Prevent bubbling + }, ['INPUT', 'SELECT', 'TEXTAREA'])); + this.hotkeys.add(new Hotkey('ctrl+p', (event: KeyboardEvent): boolean => { + if (this.voucher.id && !this.voucher.posted && this.auth.user.perms.indexOf('Post Vouchers') !== -1) + 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)[0]; diff --git a/overlord/src/app/receipt/receipt.module.ts b/overlord/src/app/receipt/receipt.module.ts index 974560a6..941b9a4e 100644 --- a/overlord/src/app/receipt/receipt.module.ts +++ b/overlord/src/app/receipt/receipt.module.ts @@ -29,6 +29,7 @@ import {MomentDateAdapter} from '@angular/material-moment-adapter'; import {A11yModule} from '@angular/cdk/a11y'; import {ReceiptDialogComponent} from './receipt-dialog.component'; import {FlexLayoutModule} from '@angular/flex-layout'; +import {HotkeyModule} from "angular2-hotkeys"; export const MY_FORMATS = { parse: { @@ -48,6 +49,7 @@ export const MY_FORMATS = { CommonModule, CdkTableModule, FlexLayoutModule, + HotkeyModule, MatAutocompleteModule, MatButtonModule, MatCardModule,