Simplified some permissions
Renamed Accounts Audit to Audit Renamed Machines to Devices as it made sense Sections and Tables are now under Sections Permission Guest Book is now under Customers Permission Renamed Beer Consumption Report to Beer Sale Report Fix: Move Kot and Table to check what the final effect is
This commit is contained in:
@ -0,0 +1,16 @@
|
||||
import { DataSource } from '@angular/cdk/collections';
|
||||
import { Observable, of as observableOf } from 'rxjs';
|
||||
|
||||
import { BeerSaleReportItem } from './beer-sale-report-item';
|
||||
|
||||
export class BeerSaleReportDataSource extends DataSource<BeerSaleReportItem> {
|
||||
constructor(public data: BeerSaleReportItem[]) {
|
||||
super();
|
||||
}
|
||||
|
||||
connect(): Observable<BeerSaleReportItem[]> {
|
||||
return observableOf(this.data);
|
||||
}
|
||||
|
||||
disconnect() {}
|
||||
}
|
||||
5
bookie/src/app/beer-sale-report/beer-sale-report-item.ts
Normal file
5
bookie/src/app/beer-sale-report/beer-sale-report-item.ts
Normal file
@ -0,0 +1,5 @@
|
||||
export class BeerSaleReportItem {
|
||||
date: string;
|
||||
name: string;
|
||||
quantity: number;
|
||||
}
|
||||
@ -0,0 +1,15 @@
|
||||
import { inject, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { BeerSaleReportResolver } from './beer-sale-report-resolver.service';
|
||||
|
||||
describe('BeerSaleReportResolver', () => {
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
providers: [BeerSaleReportResolver],
|
||||
});
|
||||
});
|
||||
|
||||
it('should be created', inject([BeerSaleReportResolver], (service: BeerSaleReportResolver) => {
|
||||
expect(service).toBeTruthy();
|
||||
}));
|
||||
});
|
||||
@ -0,0 +1,19 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { ActivatedRouteSnapshot, Resolve } from '@angular/router';
|
||||
import { Observable } from 'rxjs/internal/Observable';
|
||||
|
||||
import { BeerSaleReport } from './beer-sale-report';
|
||||
import { BeerSaleReportService } from './beer-sale-report.service';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class BeerSaleReportResolver implements Resolve<BeerSaleReport> {
|
||||
constructor(private ser: BeerSaleReportService) {}
|
||||
|
||||
resolve(route: ActivatedRouteSnapshot): Observable<BeerSaleReport> {
|
||||
const startDate = route.queryParamMap.get('startDate') || null;
|
||||
const finishDate = route.queryParamMap.get('finishDate') || null;
|
||||
return this.ser.get(startDate, finishDate);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,13 @@
|
||||
import { BeerSaleReportRoutingModule } from './beer-sale-report-routing.module';
|
||||
|
||||
describe('BeerSaleReportRoutingModule', () => {
|
||||
let beerSaleReportRoutingModule: BeerSaleReportRoutingModule;
|
||||
|
||||
beforeEach(() => {
|
||||
beerSaleReportRoutingModule = new BeerSaleReportRoutingModule();
|
||||
});
|
||||
|
||||
it('should create an instance', () => {
|
||||
expect(beerSaleReportRoutingModule).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@ -0,0 +1,30 @@
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { NgModule } from '@angular/core';
|
||||
import { RouterModule, Routes } from '@angular/router';
|
||||
|
||||
import { AuthGuard } from '../auth/auth-guard.service';
|
||||
|
||||
import { BeerSaleReportResolver } from './beer-sale-report-resolver.service';
|
||||
import { BeerSaleReportComponent } from './beer-sale-report.component';
|
||||
|
||||
const beerSaleReportRoutes: Routes = [
|
||||
{
|
||||
path: '',
|
||||
component: BeerSaleReportComponent,
|
||||
canActivate: [AuthGuard],
|
||||
data: {
|
||||
permission: 'Beer Sale Report',
|
||||
},
|
||||
resolve: {
|
||||
info: BeerSaleReportResolver,
|
||||
},
|
||||
runGuardsAndResolvers: 'always',
|
||||
},
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [CommonModule, RouterModule.forChild(beerSaleReportRoutes)],
|
||||
exports: [RouterModule],
|
||||
providers: [BeerSaleReportResolver],
|
||||
})
|
||||
export class BeerSaleReportRoutingModule {}
|
||||
@ -0,0 +1,4 @@
|
||||
.right {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
@ -0,0 +1,73 @@
|
||||
<mat-card>
|
||||
<mat-card-title-group>
|
||||
<mat-card-title>Beer Sale Report</mat-card-title>
|
||||
<button mat-button mat-icon-button (click)="exportCsv()">
|
||||
<mat-icon>save_alt</mat-icon>
|
||||
</button>
|
||||
</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"
|
||||
fxLayoutAlign="space-around start"
|
||||
>
|
||||
<mat-form-field fxFlex="40">
|
||||
<input
|
||||
matInput
|
||||
[matDatepicker]="startDate"
|
||||
(focus)="startDate.open()"
|
||||
placeholder="Start Date"
|
||||
formControlName="startDate"
|
||||
autocomplete="off"
|
||||
/>
|
||||
<mat-datepicker-toggle matSuffix [for]="startDate"></mat-datepicker-toggle>
|
||||
<mat-datepicker #startDate></mat-datepicker>
|
||||
</mat-form-field>
|
||||
<mat-form-field fxFlex="40">
|
||||
<input
|
||||
matInput
|
||||
[matDatepicker]="finishDate"
|
||||
(focus)="finishDate.open()"
|
||||
placeholder="Finish Date"
|
||||
formControlName="finishDate"
|
||||
autocomplete="off"
|
||||
/>
|
||||
<mat-datepicker-toggle matSuffix [for]="finishDate"></mat-datepicker-toggle>
|
||||
<mat-datepicker #finishDate></mat-datepicker>
|
||||
</mat-form-field>
|
||||
<button fxFlex="20" mat-raised-button color="primary" (click)="show()">Show</button>
|
||||
</div>
|
||||
</form>
|
||||
<mat-table #table [dataSource]="dataSource" aria-label="Elements">
|
||||
<!-- Date Column -->
|
||||
<ng-container matColumnDef="date">
|
||||
<mat-header-cell *matHeaderCellDef>Time</mat-header-cell>
|
||||
<mat-cell *matCellDef="let row">{{ row.date }}</mat-cell>
|
||||
</ng-container>
|
||||
|
||||
<!-- Name Column -->
|
||||
<ng-container *ngFor="let col of info.headers" matColumnDef="{{ col }}">
|
||||
<mat-header-cell *matHeaderCellDef class="right">{{ col }}</mat-header-cell>
|
||||
<mat-cell *matCellDef="let row" class="right">{{ row[col] }}</mat-cell>
|
||||
</ng-container>
|
||||
|
||||
<!-- <!– Name Column –>-->
|
||||
<!-- <ng-container matColumnDef="name">-->
|
||||
<!-- <mat-header-cell *matHeaderCellDef class="right">Name</mat-header-cell>-->
|
||||
<!-- <mat-cell *matCellDef="let row" class="right">{{row.name}}</mat-cell>-->
|
||||
<!-- </ng-container>-->
|
||||
|
||||
<!-- <!– Quantity Column –>-->
|
||||
<!-- <ng-container matColumnDef="quantity">-->
|
||||
<!-- <mat-header-cell *matHeaderCellDef class="right">Quantity</mat-header-cell>-->
|
||||
<!-- <mat-cell *matCellDef="let row" class="right">{{row.quantity | number:'1.2-2'}}</mat-cell>-->
|
||||
<!-- </ng-container>-->
|
||||
|
||||
<mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
|
||||
<mat-row *matRowDef="let row; columns: displayedColumns"></mat-row>
|
||||
</mat-table>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
@ -0,0 +1,24 @@
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { BeerSaleReportComponent } from './beer-sale-report.component';
|
||||
|
||||
describe('BeerSaleReportComponent', () => {
|
||||
let component: BeerSaleReportComponent;
|
||||
let fixture: ComponentFixture<BeerSaleReportComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [BeerSaleReportComponent],
|
||||
}).compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(BeerSaleReportComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@ -0,0 +1,91 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { FormBuilder, FormGroup } from '@angular/forms';
|
||||
import { ActivatedRoute, Router } from '@angular/router';
|
||||
import * as moment from 'moment';
|
||||
|
||||
import { ToCsvService } from '../shared/to-csv.service';
|
||||
|
||||
import { BeerSaleReport } from './beer-sale-report';
|
||||
import { BeerSaleReportDataSource } from './beer-sale-report-datasource';
|
||||
|
||||
@Component({
|
||||
selector: 'app-beer-sale-report',
|
||||
templateUrl: './beer-sale-report.component.html',
|
||||
styleUrls: ['./beer-sale-report.component.css'],
|
||||
})
|
||||
export class BeerSaleReportComponent implements OnInit {
|
||||
dataSource: BeerSaleReportDataSource;
|
||||
form: FormGroup;
|
||||
info: BeerSaleReport;
|
||||
|
||||
/** Columns displayed in the table. Columns IDs can be added, removed, or reordered. */
|
||||
displayedColumns: string[] = ['date'];
|
||||
|
||||
constructor(
|
||||
private route: ActivatedRoute,
|
||||
private router: Router,
|
||||
private fb: FormBuilder,
|
||||
private toCsv: ToCsvService,
|
||||
) {
|
||||
this.createForm();
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.route.data.subscribe((data: { info: BeerSaleReport }) => {
|
||||
this.info = data.info;
|
||||
this.displayedColumns = ['date'].concat(this.info.headers);
|
||||
this.form.setValue({
|
||||
startDate: moment(this.info.startDate, 'DD-MMM-YYYY').toDate(),
|
||||
finishDate: moment(this.info.finishDate, 'DD-MMM-YYYY').toDate(),
|
||||
});
|
||||
this.dataSource = new BeerSaleReportDataSource(this.info.data);
|
||||
});
|
||||
}
|
||||
|
||||
show() {
|
||||
const info = this.getInfo();
|
||||
this.router.navigate(['beer-sale-report'], {
|
||||
queryParams: {
|
||||
startDate: info.startDate,
|
||||
finishDate: info.finishDate,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
createForm() {
|
||||
this.form = this.fb.group({
|
||||
startDate: '',
|
||||
finishDate: '',
|
||||
});
|
||||
}
|
||||
|
||||
getInfo(): BeerSaleReport {
|
||||
const formModel = this.form.value;
|
||||
|
||||
return {
|
||||
startDate: moment(formModel.startDate).format('DD-MMM-YYYY'),
|
||||
finishDate: moment(formModel.finishDate).format('DD-MMM-YYYY'),
|
||||
};
|
||||
}
|
||||
|
||||
exportCsv() {
|
||||
const headers = this.info.headers.reduce(
|
||||
(a, c) => {
|
||||
a[c] = c;
|
||||
return a;
|
||||
},
|
||||
{
|
||||
Date: 'date',
|
||||
},
|
||||
);
|
||||
const csvData = new Blob([this.toCsv.toCsv(headers, this.info.data)], {
|
||||
type: 'text/csv;charset=utf-8;',
|
||||
});
|
||||
const link = document.createElement('a');
|
||||
link.href = window.URL.createObjectURL(csvData);
|
||||
link.setAttribute('download', 'beer-sale-report.csv');
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
document.body.removeChild(link);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,13 @@
|
||||
import { BeerSaleReportModule } from './beer-sale-report.module';
|
||||
|
||||
describe('BeerSaleReportModule', () => {
|
||||
let beerSaleReportModule: BeerSaleReportModule;
|
||||
|
||||
beforeEach(() => {
|
||||
beerSaleReportModule = new BeerSaleReportModule();
|
||||
});
|
||||
|
||||
it('should create an instance', () => {
|
||||
expect(beerSaleReportModule).toBeTruthy();
|
||||
});
|
||||
});
|
||||
65
bookie/src/app/beer-sale-report/beer-sale-report.module.ts
Normal file
65
bookie/src/app/beer-sale-report/beer-sale-report.module.ts
Normal file
@ -0,0 +1,65 @@
|
||||
import { A11yModule } from '@angular/cdk/a11y';
|
||||
import { CdkTableModule } from '@angular/cdk/table';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { NgModule } from '@angular/core';
|
||||
import { FlexLayoutModule } from '@angular/flex-layout';
|
||||
import { ReactiveFormsModule } from '@angular/forms';
|
||||
import { MomentDateAdapter } from '@angular/material-moment-adapter';
|
||||
import { MatAutocompleteModule } from '@angular/material/autocomplete';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatCardModule } from '@angular/material/card';
|
||||
import {
|
||||
DateAdapter,
|
||||
MAT_DATE_FORMATS,
|
||||
MAT_DATE_LOCALE,
|
||||
MatNativeDateModule,
|
||||
} from '@angular/material/core';
|
||||
import { MatDatepickerModule } from '@angular/material/datepicker';
|
||||
import { MatFormFieldModule } from '@angular/material/form-field';
|
||||
import { MatIconModule } from '@angular/material/icon';
|
||||
import { MatInputModule } from '@angular/material/input';
|
||||
import { MatTableModule } from '@angular/material/table';
|
||||
|
||||
import { SharedModule } from '../shared/shared.module';
|
||||
|
||||
import { BeerSaleReportRoutingModule } from './beer-sale-report-routing.module';
|
||||
import { BeerSaleReportComponent } from './beer-sale-report.component';
|
||||
|
||||
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,
|
||||
FlexLayoutModule,
|
||||
MatAutocompleteModule,
|
||||
MatButtonModule,
|
||||
MatCardModule,
|
||||
MatDatepickerModule,
|
||||
MatFormFieldModule,
|
||||
MatIconModule,
|
||||
MatInputModule,
|
||||
MatNativeDateModule,
|
||||
MatTableModule,
|
||||
ReactiveFormsModule,
|
||||
SharedModule,
|
||||
BeerSaleReportRoutingModule,
|
||||
],
|
||||
declarations: [BeerSaleReportComponent],
|
||||
providers: [
|
||||
{ provide: DateAdapter, useClass: MomentDateAdapter, deps: [MAT_DATE_LOCALE] },
|
||||
{ provide: MAT_DATE_FORMATS, useValue: MY_FORMATS },
|
||||
],
|
||||
})
|
||||
export class BeerSaleReportModule {}
|
||||
@ -0,0 +1,15 @@
|
||||
import { inject, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { BeerSaleReportService } from './beer-sale-report.service';
|
||||
|
||||
describe('BeerSaleReportService', () => {
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
providers: [BeerSaleReportService],
|
||||
});
|
||||
});
|
||||
|
||||
it('should be created', inject([BeerSaleReportService], (service: BeerSaleReportService) => {
|
||||
expect(service).toBeTruthy();
|
||||
}));
|
||||
});
|
||||
33
bookie/src/app/beer-sale-report/beer-sale-report.service.ts
Normal file
33
bookie/src/app/beer-sale-report/beer-sale-report.service.ts
Normal file
@ -0,0 +1,33 @@
|
||||
import { HttpClient, HttpParams } from '@angular/common/http';
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Observable } from 'rxjs/internal/Observable';
|
||||
import { catchError } from 'rxjs/operators';
|
||||
|
||||
import { ErrorLoggerService } from '../core/error-logger.service';
|
||||
|
||||
import { BeerSaleReport } from './beer-sale-report';
|
||||
|
||||
const url = '/api/beer-sale-report';
|
||||
const serviceName = 'BeerSaleReportService';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class BeerSaleReportService {
|
||||
constructor(private http: HttpClient, private log: ErrorLoggerService) {}
|
||||
|
||||
get(startDate: string, finishDate): Observable<BeerSaleReport> {
|
||||
const options = { params: new HttpParams() };
|
||||
if (startDate !== null) {
|
||||
options.params = options.params.set('s', startDate);
|
||||
}
|
||||
if (finishDate !== null) {
|
||||
options.params = options.params.set('f', finishDate);
|
||||
}
|
||||
return <Observable<BeerSaleReport>>(
|
||||
this.http
|
||||
.get<BeerSaleReport>(url, options)
|
||||
.pipe(catchError(this.log.handleError(serviceName, 'get')))
|
||||
);
|
||||
}
|
||||
}
|
||||
8
bookie/src/app/beer-sale-report/beer-sale-report.ts
Normal file
8
bookie/src/app/beer-sale-report/beer-sale-report.ts
Normal file
@ -0,0 +1,8 @@
|
||||
import { BeerSaleReportItem } from './beer-sale-report-item';
|
||||
|
||||
export class BeerSaleReport {
|
||||
startDate: string;
|
||||
finishDate: string;
|
||||
headers?: string[];
|
||||
data?: BeerSaleReportItem[];
|
||||
}
|
||||
Reference in New Issue
Block a user