Moved from tslint to eslint as tslint was depreciated.

Added prettier and also prettied all the typescript files using prettier

ESLint is using the AirBnB rules which are the most strict to lint the files.
This commit is contained in:
2020-10-01 20:51:22 +05:30
parent 40e79ff949
commit 1350870f9e
545 changed files with 8455 additions and 7036 deletions

View File

@ -1,11 +1,11 @@
import {inject, TestBed} from '@angular/core/testing';
import { inject, TestBed } from '@angular/core/testing';
import {ReceiptAccountsResolver} from './receipt-accounts-resolver.service';
import { ReceiptAccountsResolver } from './receipt-accounts-resolver.service';
describe('ReceiptAccountsResolver', () => {
beforeEach(() => {
TestBed.configureTestingModule({
providers: [ReceiptAccountsResolverService]
providers: [ReceiptAccountsResolverService],
});
});

View File

@ -1,16 +1,14 @@
import {Injectable} from '@angular/core';
import {ActivatedRouteSnapshot, Resolve, RouterStateSnapshot} from '@angular/router';
import {Observable} from 'rxjs/internal/Observable';
import {Account} from '../core/account';
import {AccountService} from '../core/account.service';
import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, Resolve, RouterStateSnapshot } from '@angular/router';
import { Observable } from 'rxjs/internal/Observable';
import { Account } from '../core/account';
import { AccountService } from '../core/account.service';
@Injectable({
providedIn: 'root'
providedIn: 'root',
})
export class ReceiptAccountsResolver implements Resolve<Account[]> {
constructor(private ser: AccountService) {
}
constructor(private ser: AccountService) {}
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<Account[]> {
return this.ser.receiptAutocomplete('');

View File

@ -1,10 +1,8 @@
import {DataSource} from '@angular/cdk/collections';
import {Observable} from 'rxjs';
import {Journal} from '../core/voucher';
import { DataSource } from '@angular/cdk/collections';
import { Observable } from 'rxjs';
import { Journal } from '../core/voucher';
export class ReceiptDataSource extends DataSource<Journal> {
constructor(private data: Observable<Journal[]>) {
super();
}
@ -13,6 +11,5 @@ export class ReceiptDataSource extends DataSource<Journal> {
return this.data;
}
disconnect() {
}
disconnect() {}
}

View File

@ -1,24 +1,49 @@
<h1 mat-dialog-title>Edit Receipt Entry</h1>
<div mat-dialog-content>
<form [formGroup]="form">
<div fxLayout="row" fxLayout="row" fxLayoutAlign="space-around start" fxLayout.lt-md="column" fxLayoutGap="20px"
fxLayoutGap.lt-md="0px">
<div
fxLayout="row"
fxLayout="row"
fxLayoutAlign="space-around start"
fxLayout.lt-md="column"
fxLayoutGap="20px"
fxLayoutGap.lt-md="0px"
>
<mat-form-field fxFlex="65">
<input type="text" matInput placeholder="Account" #accountElement [matAutocomplete]="auto"
formControlName="account" autocomplete="off">
<input
type="text"
matInput
placeholder="Account"
#accountElement
[matAutocomplete]="auto"
formControlName="account"
autocomplete="off"
/>
<mat-hint *ngIf="accBal">
Balance as on Date: <strong>{{accBal.date | currency:'INR' | accounting}}</strong> /
Final balance: <strong>{{accBal.total | currency:'INR' | accounting}}</strong>
Balance as on Date: <strong>{{ accBal.date | currency: 'INR' | accounting }}</strong> /
Final balance: <strong>{{ accBal.total | currency: 'INR' | accounting }}</strong>
</mat-hint>
</mat-form-field>
<mat-autocomplete #auto="matAutocomplete" autoActiveFirstOption [displayWith]="displayAccount"
(optionSelected)="accountSelected($event)">
<mat-option *ngFor="let account of accounts | async" [value]="account">{{account.name}}</mat-option>
<mat-autocomplete
#auto="matAutocomplete"
autoActiveFirstOption
[displayWith]="displayAccount"
(optionSelected)="accountSelected($event)"
>
<mat-option *ngFor="let account of accounts | async" [value]="account">{{
account.name
}}</mat-option>
</mat-autocomplete>
<mat-form-field fxFlex="35">
<mat-label>Amount</mat-label>
<span matPrefix></span>
<input type="text" matInput placeholder="Amount" formControlName="amount" autocomplete="off">
<input
type="text"
matInput
placeholder="Amount"
formControlName="amount"
autocomplete="off"
/>
</mat-form-field>
</div>
</form>
@ -27,4 +52,3 @@
<button mat-button [mat-dialog-close]="false" cdkFocusInitial>Cancel</button>
<button mat-button (click)="accept()" color="primary">Ok</button>
</div>

View File

@ -8,9 +8,8 @@ describe('ReceiptDialogComponent', () => {
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ ReceiptDialogComponent ]
})
.compileComponents();
declarations: [ReceiptDialogComponent],
}).compileComponents();
}));
beforeEach(() => {

View File

@ -1,16 +1,16 @@
import {Component, Inject, OnInit} from '@angular/core';
import { Component, Inject, OnInit } from '@angular/core';
import { MatAutocompleteSelectedEvent } from '@angular/material/autocomplete';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import {debounceTime, distinctUntilChanged, map, startWith, switchMap} from 'rxjs/operators';
import {Account} from '../core/account';
import {AccountService} from '../core/account.service';
import {FormBuilder, FormGroup} from '@angular/forms';
import {Observable, of as observableOf} from 'rxjs';
import { debounceTime, distinctUntilChanged, map, startWith, switchMap } from 'rxjs/operators';
import { Account } from '../core/account';
import { AccountService } from '../core/account.service';
import { FormBuilder, FormGroup } from '@angular/forms';
import { Observable, of as observableOf } from 'rxjs';
@Component({
selector: 'app-receipt-dialog',
templateUrl: './receipt-dialog.component.html',
styleUrls: ['./receipt-dialog.component.css']
styleUrls: ['./receipt-dialog.component.css'],
})
export class ReceiptDialogComponent implements OnInit {
accounts: Observable<Account[]>;
@ -22,7 +22,8 @@ export class ReceiptDialogComponent implements OnInit {
public dialogRef: MatDialogRef<ReceiptDialogComponent>,
@Inject(MAT_DIALOG_DATA) public data: any,
private fb: FormBuilder,
private accountSer: AccountService) {
private accountSer: AccountService,
) {
this.createForm();
this.setupAccountAutocomplete();
}
@ -30,7 +31,7 @@ export class ReceiptDialogComponent implements OnInit {
ngOnInit() {
this.form.setValue({
account: this.data.journal.account,
amount: this.data.journal.amount
amount: this.data.journal.amount,
});
this.account = this.data.journal.account;
}
@ -38,22 +39,20 @@ export class ReceiptDialogComponent implements OnInit {
createForm() {
this.form = this.fb.group({
account: '',
amount: ''
amount: '',
});
this.accBal = null;
}
setupAccountAutocomplete(): void {
const control = this.form.get('account');
this.accounts = control.valueChanges
.pipe(
startWith(null),
map(x => (x !== null && x.length >= 1) ? x : null),
debounceTime(150),
distinctUntilChanged(),
switchMap(x => (x === null) ? observableOf([]) : this.accountSer.autocomplete(x))
);
this.accounts = control.valueChanges.pipe(
startWith(null),
map((x) => (x !== null && x.length >= 1 ? x : null)),
debounceTime(150),
distinctUntilChanged(),
switchMap((x) => (x === null ? observableOf([]) : this.accountSer.autocomplete(x))),
);
}
displayAccount(account?: Account): string | undefined {

View File

@ -1,11 +1,11 @@
import {inject, TestBed} from '@angular/core/testing';
import { inject, TestBed } from '@angular/core/testing';
import {ReceiptResolver} from './receipt-resolver.service';
import { ReceiptResolver } from './receipt-resolver.service';
describe('ReceiptResolver', () => {
beforeEach(() => {
TestBed.configureTestingModule({
providers: [ReceiptResolver]
providers: [ReceiptResolver],
});
});

View File

@ -1,16 +1,14 @@
import {Injectable} from '@angular/core';
import {ActivatedRouteSnapshot, Resolve, RouterStateSnapshot} from '@angular/router';
import {Observable} from 'rxjs/internal/Observable';
import {Voucher} from '../core/voucher';
import {VoucherService} from '../core/voucher.service';
import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, Resolve, RouterStateSnapshot } from '@angular/router';
import { Observable } from 'rxjs/internal/Observable';
import { Voucher } from '../core/voucher';
import { VoucherService } from '../core/voucher.service';
@Injectable({
providedIn: 'root'
providedIn: 'root',
})
export class ReceiptResolver implements Resolve<Voucher> {
constructor(private ser: VoucherService) {
}
constructor(private ser: VoucherService) {}
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<Voucher> {
const id = route.paramMap.get('id');

View File

@ -1,4 +1,4 @@
import {ReceiptRoutingModule} from './receipt-routing.module';
import { ReceiptRoutingModule } from './receipt-routing.module';
describe('ReceiptRoutingModule', () => {
let receiptRoutingModule: ReceiptRoutingModule;

View File

@ -1,10 +1,10 @@
import {NgModule} from '@angular/core';
import {CommonModule} from '@angular/common';
import {RouterModule, Routes} from '@angular/router';
import {ReceiptResolver} from './receipt-resolver.service';
import {AuthGuard} from '../auth/auth-guard.service';
import {ReceiptComponent} from './receipt.component';
import {ReceiptAccountsResolver} from './receipt-accounts-resolver.service';
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { RouterModule, Routes } from '@angular/router';
import { ReceiptResolver } from './receipt-resolver.service';
import { AuthGuard } from '../auth/auth-guard.service';
import { ReceiptComponent } from './receipt.component';
import { ReceiptAccountsResolver } from './receipt-accounts-resolver.service';
const receiptRoutes: Routes = [
{
@ -12,41 +12,32 @@ const receiptRoutes: Routes = [
component: ReceiptComponent,
canActivate: [AuthGuard],
data: {
permission: 'journal'
permission: 'journal',
},
resolve: {
receiptAccounts: ReceiptAccountsResolver,
voucher: ReceiptResolver
voucher: ReceiptResolver,
},
runGuardsAndResolvers: 'paramsChange'
runGuardsAndResolvers: 'paramsChange',
},
{
path: ':id',
component: ReceiptComponent,
canActivate: [AuthGuard],
data: {
permission: 'journal'
permission: 'journal',
},
resolve: {
receiptAccounts: ReceiptAccountsResolver,
voucher: ReceiptResolver
voucher: ReceiptResolver,
},
runGuardsAndResolvers: 'paramsChange'
}
runGuardsAndResolvers: 'paramsChange',
},
];
@NgModule({
imports: [
CommonModule,
RouterModule.forChild(receiptRoutes)
],
exports: [
RouterModule
],
providers: [
ReceiptResolver
]
imports: [CommonModule, RouterModule.forChild(receiptRoutes)],
exports: [RouterModule],
providers: [ReceiptResolver],
})
export class ReceiptRoutingModule {
}
export class ReceiptRoutingModule {}

View File

@ -4,11 +4,11 @@
}
.selected {
background: #fff3cd
background: #fff3cd;
}
.unposted {
background: #f8d7da
background: #f8d7da;
}
.center {

View File

@ -1,18 +1,34 @@
<mat-card>
<mat-card-title-group>
<mat-card-title>Receipt</mat-card-title>
<mat-icon matSuffix (click)="voucher.isStarred = !voucher.isStarred" class="pointer"
[class.gold]="voucher.isStarred">
<mat-icon
matSuffix
(click)="voucher.isStarred = !voucher.isStarred"
class="pointer"
[class.gold]="voucher.isStarred"
>
{{ voucher.isStarred ? 'star' : 'star_border' }}
</mat-icon>
</mat-card-title-group>
<mat-card-content>
<form [formGroup]="form" fxLayout="column">
<div fxLayout="row" fxLayoutAlign="space-around start" fxLayout.lt-md="column" fxLayoutGap="20px"
fxLayoutGap.lt-md="0px">
<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" placeholder="Date" formControlName="date" autocomplete="off"
#dateElement (focus)="dateElement.select()">
<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>
@ -26,44 +42,70 @@
<mat-form-field fxFlex="20">
<mat-label>Receipt Amount</mat-label>
<span matPrefix></span>
<input type="text" matInput formControlName="receiptAmount">
<input type="text" matInput formControlName="receiptAmount" />
</mat-form-field>
</div>
<div formGroupName="addRow" fxLayout="row" fxLayoutAlign="space-around start" fxLayout.lt-md="column"
fxLayoutGap="20px" fxLayoutGap.lt-md="0px">
<div
formGroupName="addRow"
fxLayout="row"
fxLayoutAlign="space-around start"
fxLayout.lt-md="column"
fxLayoutGap="20px"
fxLayoutGap.lt-md="0px"
>
<mat-form-field fxFlex="55">
<input type="text" matInput placeholder="Account" #accountElement [matAutocomplete]="auto"
formControlName="account" autocomplete="off">
<input
type="text"
matInput
placeholder="Account"
#accountElement
[matAutocomplete]="auto"
formControlName="account"
autocomplete="off"
/>
<mat-hint *ngIf="accBal">
Balance as on Date: <strong>{{accBal.date | currency:'INR' | accounting}}</strong> /
Final balance: <strong>{{accBal.total | currency:'INR' | accounting}}</strong>
Balance as on Date: <strong>{{ accBal.date | currency: 'INR' | accounting }}</strong> /
Final balance: <strong>{{ accBal.total | currency: 'INR' | accounting }}</strong>
</mat-hint>
</mat-form-field>
<mat-autocomplete #auto="matAutocomplete" autoActiveFirstOption [displayWith]="displayAccount"
(optionSelected)="accountSelected($event)">
<mat-option *ngFor="let account of accounts | async" [value]="account">{{account.name}}</mat-option>
<mat-autocomplete
#auto="matAutocomplete"
autoActiveFirstOption
[displayWith]="displayAccount"
(optionSelected)="accountSelected($event)"
>
<mat-option *ngFor="let account of accounts | async" [value]="account">{{
account.name
}}</mat-option>
</mat-autocomplete>
<mat-form-field fxFlex="25">
<mat-label>Amount</mat-label>
<span matPrefix></span>
<input type="text" matInput placeholder="Amount" formControlName="amount" autocomplete="off">
<input
type="text"
matInput
placeholder="Amount"
formControlName="amount"
autocomplete="off"
/>
</mat-form-field>
<button mat-raised-button color="primary" (click)="addRow()" fxFlex="20">Add</button>
</div>
<mat-table #table [dataSource]="dataSource" matSort aria-label="Elements">
<!-- Account Column -->
<ng-container matColumnDef="account">
<mat-header-cell *matHeaderCellDef>Account</mat-header-cell>
<mat-cell *matCellDef="let row">{{row.account.name}}</mat-cell>
<mat-cell *matCellDef="let row">{{ row.account.name }}</mat-cell>
</ng-container>
<!-- Amount Column -->
<ng-container matColumnDef="amount">
<mat-header-cell *matHeaderCellDef class="right">Amount</mat-header-cell>
<mat-cell *matCellDef="let row" class="right">{{row.amount | currency:'INR'}}</mat-cell>
<mat-cell *matCellDef="let row" class="right">{{
row.amount | currency: 'INR'
}}</mat-cell>
</ng-container>
<!-- Action Column -->
@ -80,16 +122,21 @@
</ng-container>
<mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
<mat-row *matRowDef="let row; columns: displayedColumns;"></mat-row>
<mat-row *matRowDef="let row; columns: displayedColumns"></mat-row>
</mat-table>
<mat-form-field>
<mat-label>Narration</mat-label>
<textarea matInput matTextareaAutosize matAutosizeMinRows="5" placeholder="Narration"
formControlName="narration"></textarea>
<textarea
matInput
matTextareaAutosize
matAutosizeMinRows="5"
placeholder="Narration"
formControlName="narration"
></textarea>
</mat-form-field>
<div fxLayout="row" fxLayoutGap="0.5%" fxLayoutAlign="center">
<div class="img-container" fxFlex="20%" *ngFor="let item of voucher.files">
<img [src]="item.thumbnail" (click)="zoomImage(item)">
<img [src]="item.thumbnail" (click)="zoomImage(item)" />
<button mat-icon-button class="overlay" (click)="deleteImage(item)">
<mat-icon>delete</mat-icon>
</button>
@ -97,29 +144,47 @@
<div class="img-container" fxFlex="20%">
<label ng-href for="fileUp">
<img
src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxMDAiIGhlaWdodD0iMTUwIj48cmVjdCB3aWR0aD0iMTAwIiBoZWlnaHQ9IjE1MCIgZmlsbD0iI2VlZSIvPjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjUwIiB5PSI3NSIgc3R5bGU9ImZpbGw6I2FhYTtmb250LXdlaWdodDpib2xkO2ZvbnQtc2l6ZToxMDBweDtmb250LWZhbWlseTpBcmlhbCxIZWx2ZXRpY2Esc2Fucy1zZXJpZjtkb21pbmFudC1iYXNlbGluZTpjZW50cmFsIj4rPC90ZXh0Pjwvc3ZnPg==">
src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxMDAiIGhlaWdodD0iMTUwIj48cmVjdCB3aWR0aD0iMTAwIiBoZWlnaHQ9IjE1MCIgZmlsbD0iI2VlZSIvPjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjUwIiB5PSI3NSIgc3R5bGU9ImZpbGw6I2FhYTtmb250LXdlaWdodDpib2xkO2ZvbnQtc2l6ZToxMDBweDtmb250LWZhbWlseTpBcmlhbCxIZWx2ZXRpY2Esc2Fucy1zZXJpZjtkb21pbmFudC1iYXNlbGluZTpjZW50cmFsIj4rPC90ZXh0Pjwvc3ZnPg=="
/>
</label>
<input type="file" id="fileUp" multiple accept="image/*" style="display: none;"
(change)="detectFiles($event)">
<input
type="file"
id="fileUp"
multiple
accept="image/*"
style="display: none"
(change)="detectFiles($event)"
/>
</div>
</div>
</form>
</mat-card-content>
<mat-card-actions>
<button mat-raised-button color="primary" (click)="save()" [disabled]="!canSave()">
{{(voucher.id) ? 'Update' : 'Save'}}
{{ voucher.id ? 'Update' : 'Save' }}
</button>
<button mat-raised-button (click)="post()" *ngIf="voucher.id"
[disabled]="voucher.posted || auth.user.perms.indexOf('post-vouchers') === -1">
{{(voucher.posted) ? 'Posted' : 'Post'}}
<button
mat-raised-button
(click)="post()"
*ngIf="voucher.id"
[disabled]="voucher.posted || auth.user.perms.indexOf('post-vouchers') === -1"
>
{{ voucher.posted ? 'Posted' : 'Post' }}
</button>
<button mat-raised-button color="warn" (click)="confirmDelete()" *ngIf="voucher.id" [disabled]="!canSave()">
<button
mat-raised-button
color="warn"
(click)="confirmDelete()"
*ngIf="voucher.id"
[disabled]="!canSave()"
>
Delete
</button>
</mat-card-actions>
<mat-card-subtitle *ngIf="voucher.id">
Created on <strong>{{voucher.creationDate | localTime}}</strong> and
Last Edited on <strong>{{voucher.lastEditDate | localTime}}</strong>
by <strong>{{voucher.user.name}}</strong>. {{(voucher.poster) ? 'Posted by ' + voucher.poster : ''}}
Created on <strong>{{ voucher.creationDate | localTime }}</strong> and Last Edited on
<strong>{{ voucher.lastEditDate | localTime }}</strong> by
<strong>{{ voucher.user.name }}</strong
>. {{ voucher.poster ? 'Posted by ' + voucher.poster : '' }}
</mat-card-subtitle>
</mat-card>

View File

@ -1,6 +1,6 @@
import {async, ComponentFixture, TestBed} from '@angular/core/testing';
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import {ReceiptComponent} from './receipt.component';
import { ReceiptComponent } from './receipt.component';
describe('ReceiptComponent', () => {
let component: ReceiptComponent;
@ -8,9 +8,8 @@ describe('ReceiptComponent', () => {
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ReceiptComponent]
})
.compileComponents();
declarations: [ReceiptComponent],
}).compileComponents();
}));
beforeEach(() => {

View File

@ -22,7 +22,7 @@ import { Hotkey, HotkeysService } from 'angular2-hotkeys';
@Component({
selector: 'app-receipt',
templateUrl: './receipt.component.html',
styleUrls: ['./receipt.component.css']
styleUrls: ['./receipt.component.css'],
})
export class ReceiptComponent implements OnInit, AfterViewInit, OnDestroy {
@ViewChild('accountElement', { static: true }) accountElement: ElementRef;
@ -49,7 +49,7 @@ export class ReceiptComponent implements OnInit, AfterViewInit, OnDestroy {
private toaster: ToasterService,
private auth: AuthService,
private ser: VoucherService,
private accountSer: AccountService
private accountSer: AccountService,
) {
this.account = null;
this.createForm();
@ -58,29 +58,50 @@ export class ReceiptComponent implements OnInit, AfterViewInit, OnDestroy {
}
ngOnInit() {
this.route.data
.subscribe((data: { voucher: Voucher, receiptAccounts: Account[] }) => {
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']));
this.route.data.subscribe((data: { voucher: Voucher; receiptAccounts: Account[] }) => {
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() {
@ -93,16 +114,16 @@ export class ReceiptComponent implements OnInit, AfterViewInit, OnDestroy {
loadVoucher(voucher: Voucher) {
this.voucher = voucher;
this.receiptJournal = this.voucher.journals.filter(x => x.debit === 1)[0];
this.receiptJournal = this.voucher.journals.filter((x) => x.debit === 1)[0];
this.form.setValue({
date: moment(this.voucher.date, 'DD-MMM-YYYY').toDate(),
receiptAccount: this.receiptJournal.account.id,
receiptAmount: this.receiptJournal.amount,
addRow: {
account: '',
amount: 0
amount: 0,
},
narration: this.voucher.narration
narration: this.voucher.narration,
});
this.dataSource = new ReceiptDataSource(this.journalObservable);
this.updateView();
@ -133,7 +154,7 @@ export class ReceiptComponent implements OnInit, AfterViewInit, OnDestroy {
debit: debit,
amount: amount,
account: this.account,
costCentre: null
costCentre: null,
});
}
this.resetAddRow();
@ -142,7 +163,7 @@ export class ReceiptComponent implements OnInit, AfterViewInit, OnDestroy {
rowAmount(amount: string = ''): number {
try {
amount = amount.replace(new RegExp('(₹[\s]*)|(,)|(\s)', 'g'), '');
amount = amount.replace(new RegExp('(₹[s]*)|(,)|(s)', 'g'), '');
return evaluate(amount);
} catch {
return 0;
@ -152,7 +173,7 @@ export class ReceiptComponent implements OnInit, AfterViewInit, OnDestroy {
resetAddRow() {
this.form.get('addRow').reset({
account: null,
amount: null
amount: null,
});
this.account = null;
this.accBal = null;
@ -162,7 +183,7 @@ export class ReceiptComponent implements OnInit, AfterViewInit, OnDestroy {
}
updateView() {
const journals = this.voucher.journals.filter(x => x.debit === -1);
const journals = this.voucher.journals.filter((x) => x.debit === -1);
this.journalObservable.next(journals);
this.receiptJournal.amount = Math.abs(journals.map((x) => x.amount).reduce((p, c) => p + c, 0));
this.form.get('receiptAmount').setValue(this.receiptJournal.amount);
@ -171,7 +192,10 @@ export class ReceiptComponent implements OnInit, AfterViewInit, OnDestroy {
editRow(row: Journal) {
const dialogRef = this.dialog.open(ReceiptDialogComponent, {
width: '750px',
data: {journal: Object.assign({}, row), date: moment(this.form.get('date').value).format('DD-MMM-YYYY')}
data: {
journal: Object.assign({}, row),
date: moment(this.form.get('date').value).format('DD-MMM-YYYY'),
},
});
dialogRef.afterClosed().subscribe((result: boolean | Journal) => {
@ -179,7 +203,10 @@ export class ReceiptComponent implements OnInit, AfterViewInit, OnDestroy {
return;
}
const j = result as Journal;
if (j.account.id !== row.account.id && this.voucher.journals.filter((x) => x.account.id === j.account.id).length) {
if (
j.account.id !== row.account.id &&
this.voucher.journals.filter((x) => x.account.id === j.account.id).length
) {
return;
}
Object.assign(row, j);
@ -196,12 +223,12 @@ export class ReceiptComponent implements OnInit, AfterViewInit, OnDestroy {
this.form = this.fb.group({
date: '',
receiptAccount: '',
receiptAmount: {value: '', disabled: true},
receiptAmount: { value: '', disabled: true },
addRow: this.fb.group({
account: '',
amount: ''
amount: '',
}),
narration: ''
narration: '',
});
this.accBal = null;
}
@ -212,39 +239,40 @@ export class ReceiptComponent implements OnInit, AfterViewInit, OnDestroy {
} else if (this.voucher.posted && this.auth.user.perms.indexOf('edit-posted-vouchers') !== -1) {
return true;
} else {
return this.voucher.user.id === this.auth.user.id || this.auth.user.perms.indexOf("edit-other-user's-vouchers") !== -1;
return (
this.voucher.user.id === this.auth.user.id ||
this.auth.user.perms.indexOf("edit-other-user's-vouchers") !== -1
);
}
}
post() {
this.ser.post(this.voucher.id)
.subscribe(
(result) => {
this.loadVoucher(result);
this.toaster.show('Success', 'Voucher Posted');
},
(error) => {
this.toaster.show('Danger', error);
}
);
this.ser.post(this.voucher.id).subscribe(
(result) => {
this.loadVoucher(result);
this.toaster.show('Success', 'Voucher Posted');
},
(error) => {
this.toaster.show('Danger', error);
},
);
}
save() {
const voucher: Voucher = this.getVoucher();
this.ser.saveOrUpdate(voucher)
.subscribe(
(result) => {
this.toaster.show('Success', '');
if (voucher.id === result.id) {
this.loadVoucher(result);
} else {
this.ser.saveOrUpdate(voucher).subscribe(
(result) => {
this.toaster.show('Success', '');
if (voucher.id === result.id) {
this.loadVoucher(result);
} else {
this.router.navigate(['/receipt', result.id]);
}
},
(error) => {
this.toaster.show('Danger', error);
}
);
},
(error) => {
this.toaster.show('Danger', error);
},
);
}
getVoucher(): Voucher {
@ -256,22 +284,21 @@ export class ReceiptComponent implements OnInit, AfterViewInit, OnDestroy {
}
delete() {
this.ser.delete(this.voucher.id)
.subscribe(
(result) => {
this.toaster.show('Success', '');
this.router.navigate(['/receipt'], {replaceUrl: true});
},
(error) => {
this.toaster.show('Danger', error);
}
);
this.ser.delete(this.voucher.id).subscribe(
(result) => {
this.toaster.show('Success', '');
this.router.navigate(['/receipt'], { replaceUrl: true });
},
(error) => {
this.toaster.show('Danger', error);
},
);
}
confirmDelete(): void {
const dialogRef = this.dialog.open(ConfirmDialogComponent, {
width: '250px',
data: {title: 'Delete Voucher?', content: 'Are you sure? This cannot be undone.'}
data: { title: 'Delete Voucher?', content: 'Are you sure? This cannot be undone.' },
});
dialogRef.afterClosed().subscribe((result: boolean) => {
@ -283,24 +310,23 @@ export class ReceiptComponent implements OnInit, AfterViewInit, OnDestroy {
listenToAccountAutocompleteChange(): void {
const control = this.form.get('addRow').get('account');
this.accounts = control.valueChanges
.pipe(
startWith(null),
map(x => (x !== null && x.length >= 1) ? x : null),
debounceTime(150),
distinctUntilChanged(),
switchMap(x => (x === null) ? observableOf([]) : this.accountSer.autocomplete(x))
);
this.accounts = control.valueChanges.pipe(
startWith(null),
map((x) => (x !== null && x.length >= 1 ? x : null)),
debounceTime(150),
distinctUntilChanged(),
switchMap((x) => (x === null ? observableOf([]) : this.accountSer.autocomplete(x))),
);
}
listenToReceiptAccountChange(): void {
this.form.get('receiptAccount').valueChanges
.subscribe(x => this.router.navigate([], {
relativeTo: this.route,
queryParams: {a: x},
replaceUrl: true
})
);
this.form.get('receiptAccount').valueChanges.subscribe((x) =>
this.router.navigate([], {
relativeTo: this.route,
queryParams: { a: x },
replaceUrl: true,
}),
);
}
displayAccount(account?: Account): string | undefined {
@ -318,7 +344,7 @@ export class ReceiptComponent implements OnInit, AfterViewInit, OnDestroy {
zoomImage(file: DbFile) {
this.dialog.open(ImageDialogComponent, {
width: '750px',
data: file.resized
data: file.resized,
});
}
@ -333,11 +359,12 @@ export class ReceiptComponent implements OnInit, AfterViewInit, OnDestroy {
for (const file of files) {
const reader = new FileReader();
reader.onload = (e: any) => {
zip(of(e.target.result),
zip(
of(e.target.result),
this.resizeImage(e.target.result, 100, 150),
this.resizeImage(e.target.result, 825, 1170)
).subscribe(
val => this.voucher.files.push({id: null, thumbnail: val[1], resized: val[2]})
this.resizeImage(e.target.result, 825, 1170),
).subscribe((val) =>
this.voucher.files.push({ id: null, thumbnail: val[1], resized: val[2] }),
);
};
reader.readAsDataURL(file);
@ -366,7 +393,7 @@ export class ReceiptComponent implements OnInit, AfterViewInit, OnDestroy {
canvas.height = height;
ctx.drawImage(img, 0, 0, width, height);
return canvas.toDataURL('image/jpeg', 0.95);
})
}),
);
img.src = image;
return ex;

View File

@ -1,4 +1,4 @@
import {ReceiptModule} from './receipt.module';
import { ReceiptModule } from './receipt.module';
describe('ReceiptModule', () => {
let receiptModule: ReceiptModule;

View File

@ -1,10 +1,15 @@
import {NgModule} from '@angular/core';
import {CommonModule} from '@angular/common';
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { MatAutocompleteModule } from '@angular/material/autocomplete';
import { MatButtonModule } from '@angular/material/button';
import { MatCardModule } from '@angular/material/card';
import { MatCheckboxModule } from '@angular/material/checkbox';
import { DateAdapter, MAT_DATE_FORMATS, MAT_DATE_LOCALE, MatNativeDateModule } from '@angular/material/core';
import {
DateAdapter,
MAT_DATE_FORMATS,
MAT_DATE_LOCALE,
MatNativeDateModule,
} from '@angular/material/core';
import { MatDatepickerModule } from '@angular/material/datepicker';
import { MatDialogModule } from '@angular/material/dialog';
import { MatFormFieldModule } from '@angular/material/form-field';
@ -15,16 +20,16 @@ import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
import { MatSelectModule } from '@angular/material/select';
import { MatSortModule } from '@angular/material/sort';
import { MatTableModule } from '@angular/material/table';
import {SharedModule} from '../shared/shared.module';
import {ReactiveFormsModule} from '@angular/forms';
import {CdkTableModule} from '@angular/cdk/table';
import {ReceiptRoutingModule} from './receipt-routing.module';
import {ReceiptComponent} from './receipt.component';
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";
import { SharedModule } from '../shared/shared.module';
import { ReactiveFormsModule } from '@angular/forms';
import { CdkTableModule } from '@angular/cdk/table';
import { ReceiptRoutingModule } from './receipt-routing.module';
import { ReceiptComponent } from './receipt.component';
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: {
@ -62,16 +67,12 @@ export const MY_FORMATS = {
MatTableModule,
ReactiveFormsModule,
SharedModule,
ReceiptRoutingModule
],
declarations: [
ReceiptComponent,
ReceiptDialogComponent
ReceiptRoutingModule,
],
declarations: [ReceiptComponent, ReceiptDialogComponent],
providers: [
{provide: DateAdapter, useClass: MomentDateAdapter, deps: [MAT_DATE_LOCALE]},
{provide: MAT_DATE_FORMATS, useValue: MY_FORMATS},
]
{ provide: DateAdapter, useClass: MomentDateAdapter, deps: [MAT_DATE_LOCALE] },
{ provide: MAT_DATE_FORMATS, useValue: MY_FORMATS },
],
})
export class ReceiptModule {
}
export class ReceiptModule {}

View File

@ -1,11 +1,11 @@
import {inject, TestBed} from '@angular/core/testing';
import { inject, TestBed } from '@angular/core/testing';
import {VoucherService} from './receipt.service';
import { VoucherService } from './receipt.service';
describe('ReceiptService', () => {
beforeEach(() => {
TestBed.configureTestingModule({
providers: [VoucherService]
providers: [VoucherService],
});
});