Moved to Angular 6.0

----

Pending
* Table width for the points column in incentive
* Linting
* keyboard navigation where it was used earlier
* can remove the unused totals calculated serverside in productledger
* spinner and loading bars
* Activate Guard for Employee Function tabs
* Progress for Fingerprint uploads
* deleted reconcile and receipe features as they were not being used
* focus the right control on component load
This commit is contained in:
tanshu
2018-06-09 17:05:11 +05:30
parent b3cb01da02
commit 6be1dd5a3a
1380 changed files with 23914 additions and 18722 deletions
@@ -0,0 +1,18 @@
import {DataSource} from '@angular/cdk/collections';
import {Observable} from 'rxjs';
import {Incentive} from '../journal/voucher';
export class IncentiveDataSource extends DataSource<Incentive> {
constructor(private data: Observable<Incentive[]>) {
super();
}
connect(): Observable<Incentive[]> {
return this.data;
}
disconnect() {
}
}
@@ -0,0 +1,15 @@
import {inject, TestBed} from '@angular/core/testing';
import {IncentiveResolver} from './incentive-resolver.service';
describe('IncentiveResolver', () => {
beforeEach(() => {
TestBed.configureTestingModule({
providers: [IncentiveResolver]
});
});
it('should be created', inject([IncentiveResolver], (service: IncentiveResolver) => {
expect(service).toBeTruthy();
}));
});
@@ -0,0 +1,24 @@
import {Injectable} from '@angular/core';
import {ActivatedRouteSnapshot, Resolve, RouterStateSnapshot} from '@angular/router';
import {Observable} from 'rxjs/internal/Observable';
import {Voucher} from '../journal/voucher';
import {VoucherService} from '../journal/voucher.service';
import {tap} from 'rxjs/operators';
@Injectable({
providedIn: 'root'
})
export class IncentiveResolver implements Resolve<Voucher> {
constructor(private ser: VoucherService) {
}
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<Voucher> {
const id = route.paramMap.get('id');
if (id === null) {
return this.ser.getOfType('Service Charge');
} else {
return this.ser.get(id);
}
}
}
@@ -0,0 +1,13 @@
import {IncentiveRoutingModule} from './incentive-routing.module';
describe('IncentiveRoutingModule', () => {
let incentiveRoutingModule: IncentiveRoutingModule;
beforeEach(() => {
incentiveRoutingModule = new IncentiveRoutingModule();
});
it('should create an instance', () => {
expect(incentiveRoutingModule).toBeTruthy();
});
});
@@ -0,0 +1,49 @@
import {NgModule} from '@angular/core';
import {CommonModule} from '@angular/common';
import {RouterModule, Routes} from '@angular/router';
import {IncentiveResolver} from './incentive-resolver.service';
import {AuthGuard} from '../auth/auth-guard.service';
import {IncentiveComponent} from './incentive.component';
const incentiveRoutes: Routes = [
{
path: 'Incentive',
component: IncentiveComponent,
canActivate: [AuthGuard],
data: {
permission: 'Service Charge'
},
resolve: {
voucher: IncentiveResolver
},
runGuardsAndResolvers: 'always'
},
{
path: 'Incentive/:id',
component: IncentiveComponent,
canActivate: [AuthGuard],
data: {
permission: 'Service Charge'
},
resolve: {
voucher: IncentiveResolver
},
runGuardsAndResolvers: 'always'
}
];
@NgModule({
imports: [
CommonModule,
RouterModule.forChild(incentiveRoutes)
],
exports: [
RouterModule
],
providers: [
IncentiveResolver
]
})
export class IncentiveRoutingModule {
}
@@ -0,0 +1,32 @@
.right {
display: flex;
justify-content: flex-end;
}
.selected {
background: #fff3cd
}
.unposted {
background: #f8d7da
}
.center {
display: flex;
justify-content: center;
}
.img-container {
position: relative;
}
.img-container .overlay {
display: none;
}
.img-container:hover > .overlay {
display: inline-block;
position: absolute;
left: 60px;
top: 0;
}
@@ -0,0 +1,90 @@
<mat-card>
<mat-card-title-group>
<mat-card-title>Incentives</mat-card-title>
</mat-card-title-group>
<mat-card-content>
<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">
<mat-datepicker-toggle matSuffix [for]="date"></mat-datepicker-toggle>
<mat-datepicker #date></mat-datepicker>
</mat-form-field>
</div>
<div fxLayout="row" fxLayout.lt-md="column" fxLayoutGap="20px" fxLayoutGap.lt-md="0px">
Total Service Charge: <strong>{{voucher.incentive | number:'1.2-2'}}</strong>
Total Points: <strong>{{totalPoints() | number:'1.2-2'}}</strong>
Point Value: <strong>{{pointValue() | number:'1.2-2'}}</strong>
</div>
<mat-table #table [dataSource]="dataSource" formArrayName="incentives">
<!-- Name Column -->
<ng-container matColumnDef="name">
<mat-header-cell *matHeaderCellDef>Name</mat-header-cell>
<mat-cell *matCellDef="let row">{{row.name}}</mat-cell>
</ng-container>
<!-- Designation Column -->
<ng-container matColumnDef="designation">
<mat-header-cell *matHeaderCellDef>Designation</mat-header-cell>
<mat-cell *matCellDef="let row">{{row.designation}}</mat-cell>
</ng-container>
<!-- Department Column -->
<ng-container matColumnDef="department">
<mat-header-cell *matHeaderCellDef>Department</mat-header-cell>
<mat-cell *matCellDef="let row">{{row.department}}</mat-cell>
</ng-container>
<!-- DaysWorked Column -->
<ng-container matColumnDef="daysWorked">
<mat-header-cell *matHeaderCellDef class="right">DaysWorked</mat-header-cell>
<mat-cell *matCellDef="let row" class="right">{{row.daysWorked | number:'1.2-2'}}</mat-cell>
</ng-container>
<!-- Points Column -->
<ng-container matColumnDef="points">
<mat-header-cell *matHeaderCellDef class="center" fxFlex>Service Points</mat-header-cell>
<mat-cell *matCellDef="let row; let i = index" class="center" [formGroupName]="i" fxFlex>
<mat-form-field>
<button matPrefix (click)="less(row, i)">
<mat-icon>remove</mat-icon>
</button>
<input matInput formControlName="points" autocomplete="off">
<button matSuffix color="warn" (click)="more(row, i)">
<mat-icon>add</mat-icon>
</button>
</mat-form-field>
</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">{{amount(row) | currency:'INR'}}</mat-cell>
</ng-container>
<mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
<mat-row *matRowDef="let row; columns: displayedColumns;"></mat-row>
</mat-table>
</form>
</mat-card-content>
<mat-card-actions>
<button mat-raised-button color="primary" (click)="save()" [disabled]="!canSave()">
{{(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>
<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 : ''}}
</mat-card-subtitle>
</mat-card>
@@ -0,0 +1,25 @@
import {async, ComponentFixture, TestBed} from '@angular/core/testing';
import {IncentiveComponent} from './incentive.component';
describe('IncentiveComponent', () => {
let component: IncentiveComponent;
let fixture: ComponentFixture<IncentiveComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [IncentiveComponent]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(IncentiveComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
@@ -0,0 +1,192 @@
import {Component, OnInit} from '@angular/core';
import {FormArray, FormBuilder, FormGroup} from '@angular/forms';
import {MatDialog} from '@angular/material';
import {ActivatedRoute, Router} from '@angular/router';
import {BehaviorSubject, Observable} from 'rxjs';
import {IncentiveDataSource} from './incentive-datasource';
import {Account} from '../account/account';
import {VoucherService} from '../journal/voucher.service';
import {Incentive, Voucher} from '../journal/voucher';
import * as moment from 'moment';
import {AuthService} from '../auth/auth.service';
import {ConfirmDialogComponent} from '../shared/confirm-dialog/confirm-dialog.component';
import {ToasterService} from '../core/toaster.service';
import {map} from 'rxjs/operators';
@Component({
selector: 'app-incentive',
templateUrl: './incentive.component.html',
styleUrls: ['./incentive.component.css']
})
export class IncentiveComponent implements OnInit {
public incentiveObservable = new BehaviorSubject<Incentive[]>([]);
dataSource: IncentiveDataSource;
form: FormGroup;
voucher: Voucher;
account: Account;
accBal: any;
displayedColumns = ['name', 'designation', 'department', 'daysWorked', 'points', 'amount'];
accounts: Observable<Account[]>;
constructor(
private route: ActivatedRoute,
private router: Router,
private fb: FormBuilder,
private dialog: MatDialog,
private toaster: ToasterService,
private auth: AuthService,
private ser: VoucherService
) {
this.createForm();
this.listenToDateChange();
}
ngOnInit() {
this.route.data
.subscribe((data: { voucher: Voucher }) => {
this.voucher = data.voucher;
this.form.get('date').setValue(moment(this.voucher.date, 'DD-MMM-YYYY').toDate());
this.form.setControl('incentives', this.fb.array(
this.voucher.incentives.map(
x => this.fb.group({
points: x.points
})
)
));
this.dataSource = new IncentiveDataSource(this.incentiveObservable);
this.incentiveObservable.next(this.voucher.incentives);
});
}
createForm() {
this.form = this.fb.group({
date: '',
incentives: this.fb.array([])
});
}
listenToDateChange(): void {
this.form.get('date').valueChanges.pipe(
map(x => moment(x).format('DD-MMM-YYYY'))
).subscribe(x => {
if (x !== this.voucher.date && !this.voucher.id) {
return this.ser.getIncentive(x)
.subscribe((voucher: Voucher) => {
this.voucher = voucher;
this.form.get('date').setValue(moment(this.voucher.date, 'DD-MMM-YYYY').toDate());
this.form.setControl('incentives', this.fb.array(
this.voucher.incentives.map(
i => this.fb.group({
points: i.points
})
)
));
this.dataSource = new IncentiveDataSource(this.incentiveObservable);
this.incentiveObservable.next(this.voucher.incentives);
});
}
});
}
totalPoints() {
return this.voucher.incentives.map((item) => {
return item.daysWorked * item.points;
}).reduce((sum, item) => {
return sum + item;
});
}
pointValue() {
return Math.round(this.voucher.incentive * 100 / this.totalPoints()) / 100;
}
less(row: Incentive, i: number) {
if (row.points >= 1) {
row.points -= 1;
this.form.get('incentives').get('' + i).setValue({'points': '' + row.points});
}
}
more(row: Incentive, i: number) {
row.points += 1;
this.form.get('incentives').get('' + i).setValue({'points': '' + row.points});
}
amount(row) {
return row.points * row.daysWorked * this.pointValue();
}
canSave() {
if (!this.voucher.id) {
return true;
} 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;
}
}
post() {
this.ser.post(this.voucher.id)
.subscribe(
(result) => {
this.toaster.show('Success', 'Voucher Posted');
},
(error) => {
this.toaster.show('Danger', error.error);
}
);
}
save() {
this.ser.save(this.getVoucher())
.subscribe(
(result) => {
this.toaster.show('Success', '');
this.router.navigate(['/Incentive', result.id]);
},
(error) => {
this.toaster.show('Danger', error.error);
}
);
}
getVoucher(): Voucher {
const formModel = this.form.value;
this.voucher.date = moment(formModel.date).format('DD-MMM-YYYY');
const array = this.form.get('attendances') as FormArray;
this.voucher.incentives.forEach((item, index) => {
item.points = array.controls[index].value.points;
});
this.voucher.narration = formModel.narration;
return this.voucher;
}
delete() {
this.ser.delete(this.voucher.id)
.subscribe(
(result) => {
this.toaster.show('Success', '');
this.router.navigate(['/Incentive'], {replaceUrl: true});
},
(error) => {
this.toaster.show('Danger', error.error);
}
);
}
confirmDelete(): void {
const dialogRef = this.dialog.open(ConfirmDialogComponent, {
width: '250px',
data: {title: 'Delete Voucher?', content: 'Are you sure? This cannot be undone.'}
});
dialogRef.afterClosed().subscribe((result: boolean) => {
if (result) {
this.delete();
}
});
}
}
@@ -0,0 +1,13 @@
import {IncentiveModule} from './incentive.module';
describe('IncentiveModule', () => {
let incentiveModule: IncentiveModule;
beforeEach(() => {
incentiveModule = new IncentiveModule();
});
it('should create an instance', () => {
expect(incentiveModule).toBeTruthy();
});
});
@@ -0,0 +1,79 @@
import {NgModule} from '@angular/core';
import {CommonModule} from '@angular/common';
import {
DateAdapter,
MAT_DATE_FORMATS,
MAT_DATE_LOCALE,
MatAutocompleteModule,
MatButtonModule,
MatCardModule,
MatCheckboxModule,
MatDatepickerModule,
MatDialogModule,
MatFormFieldModule,
MatIconModule,
MatInputModule,
MatNativeDateModule,
MatPaginatorModule,
MatProgressSpinnerModule,
MatSelectModule,
MatSortModule,
MatTableModule
} from '@angular/material';
import {SharedModule} from '../shared/shared.module';
import {ReactiveFormsModule} from '@angular/forms';
import {CdkTableModule} from '@angular/cdk/table';
import {IncentiveRoutingModule} from './incentive-routing.module';
import {IncentiveComponent} from './incentive.component';
import {MomentDateAdapter} from '@angular/material-moment-adapter';
import {A11yModule} from '@angular/cdk/a11y';
import {FlexLayoutModule, FlexModule} from '@angular/flex-layout';
export const MY_FORMATS = {
parse: {
dateInput: 'DD-MMM-YYYY',
},
display: {
dateInput: 'DD-MMM-YYYY',
monthYearLabel: 'MMM YYYY',
dateA11yLabel: 'DD-MMM-YYYY',
monthYearA11yLabel: 'MMM YYYY',
},
};
@NgModule({
imports: [
A11yModule,
CommonModule,
CdkTableModule,
FlexModule,
FlexLayoutModule,
MatAutocompleteModule,
MatButtonModule,
MatCardModule,
MatCheckboxModule,
MatDatepickerModule,
MatDialogModule,
MatFormFieldModule,
MatIconModule,
MatInputModule,
MatNativeDateModule,
MatPaginatorModule,
MatProgressSpinnerModule,
MatSelectModule,
MatSortModule,
MatTableModule,
ReactiveFormsModule,
SharedModule,
IncentiveRoutingModule
],
declarations: [
IncentiveComponent
],
providers: [
{provide: DateAdapter, useClass: MomentDateAdapter, deps: [MAT_DATE_LOCALE]},
{provide: MAT_DATE_FORMATS, useValue: MY_FORMATS},
]
})
export class IncentiveModule {
}
@@ -0,0 +1,15 @@
import {inject, TestBed} from '@angular/core/testing';
import {VoucherService} from './incentive.service';
describe('IncentiveService', () => {
beforeEach(() => {
TestBed.configureTestingModule({
providers: [VoucherService]
});
});
it('should be created', inject([VoucherService], (service: VoucherService) => {
expect(service).toBeTruthy();
}));
});