TODO: Refactor the product and productgroup tables as per the comments added.

rename the product group table to either product category or menu category
move the group_type field from productgroup to products and name it sales category eg. Food, beverage, etc. also, set the tax for sales category and not individual product
Added the printers permission to end of permissions and only for owner, set them right
This commit is contained in:
Amritanshu
2019-06-20 01:59:11 +05:30
parent c51a9bd5ff
commit 16455fdcac
38 changed files with 770 additions and 128 deletions

View File

@ -85,7 +85,7 @@ class Tax(Base):
class ProductGroup(Base):
__tablename__ = "product_groups"
# Peoduct/menu category
id = Column("id", GUID(), primary_key=True, default=uuid.uuid4)
name = Column("name", Unicode(255), nullable=False, unique=True)
discount_limit = Column("discount_limit", Numeric, nullable=False)
@ -120,7 +120,7 @@ class ProductGroup(Base):
class Product(Base):
__tablename__ = "products"
__table_args__ = (UniqueConstraint("name", "units"),)
# add sales category instead of group_type in productgroups
id = Column("id", GUID(), primary_key=True, default=uuid.uuid4)
name = Column("name", Unicode(255), nullable=False)
units = Column("units", Unicode(255), nullable=False)
@ -271,11 +271,13 @@ class Printer(Base):
id = Column("id", GUID(), primary_key=True, default=uuid.uuid4)
name = Column("name", Unicode(255), unique=True, nullable=False)
address = Column("address", Unicode(255), unique=True, nullable=False)
cut_code = Column("cut_code", Unicode(255), nullable=False)
def __init__(self, id=None, name=None, cut_code=None):
def __init__(self, name=None, address=None, cut_code=None, id=None):
self.id = id
self.name = name
self.address = address
self.cut_code = cut_code

View File

@ -86,6 +86,13 @@ def includeme(config):
config.add_route('users_id', '/users/{id}')
config.add_route('users_list', '/users')
config.add_route('v1_printers_new', '/v1/printers/new')
config.add_route('v1_printers_id', '/v1/printers/{id}')
config.add_route('v1_printers_list', '/v1/printers')
config.add_route('printers_new', '/printers/new')
config.add_route('printers_id', '/printers/{id}')
config.add_route('printers_list', '/printers')
config.add_route('v1_roles_new', '/v1/roles/new')
config.add_route('v1_roles_id', '/v1/roles/{id}')
config.add_route('v1_roles_list', '/v1/roles')

View File

@ -77,7 +77,8 @@ def main(argv=sys.argv):
Permission('Taxes', uuid.UUID('5c8fcdde-460d-4047-810f-e34fb899fadc')),
Permission('Users', uuid.UUID('243447b8-b403-47e6-8b3d-8e76f4df44a9')),
Permission('Void Bill', uuid.UUID('e3c76262-adc0-4936-8b4d-217c6292298b')),
Permission('Void or Reprinted Bill Report', uuid.UUID('30c8e743-c710-42d7-843a-0b75543b3516'))]
Permission('Void or Reprinted Bill Report', uuid.UUID('30c8e743-c710-42d7-843a-0b75543b3516')),
Permission('Printers', uuid.UUID('5b66c6f6-003a-4ef8-ba28-49b8ff1ac33c'))]
for permission in permissions:
dbsession.add(permission)

131
barker/views/printer.py Normal file
View File

@ -0,0 +1,131 @@
import uuid
import transaction
from pyramid.view import view_config
from barker.models import Printer
from barker.models.validation_exception import ValidationError
@view_config(
request_method="POST",
route_name="v1_printers_new",
renderer="json",
permission="Printers",
trans=True,
)
def save(request):
json = request.json_body
name = json.get("name", "").strip()
if name == "":
raise ValidationError("Name cannot be blank")
address = json.get("address", "").strip()
if address == "":
raise ValidationError("Address cannot be blank")
cut_code = json.get("cutCode", "")
item = Printer(name, address, cut_code)
request.dbsession.add(item)
transaction.commit()
return printer_info(item.id, request.dbsession)
@view_config(
request_method="PUT",
route_name="v1_printers_id",
renderer="json",
permission="Printers",
trans=True,
)
def update(request):
json = request.json_body
item = (
request.dbsession.query(Printer)
.filter(Printer.id == uuid.UUID(request.matchdict["id"]))
.first()
)
item.name = json.get("name", "").strip()
if item.name == "":
raise ValidationError("Name cannot be blank")
item.address = json.get("address", "").strip()
if item.address == "":
raise ValidationError("Address cannot be blank")
item.cut_code = json.get("cutCode", "")
transaction.commit()
item = request.dbsession.query(Printer).filter(Printer.id == item.id).first()
return printer_info(item.id, request.dbsession)
@view_config(
request_method="DELETE",
route_name="v1_printers_id",
renderer="json",
permission="Printers",
trans=True,
)
def delete(request):
item = (
request.dbsession.query(Printer)
.filter(Printer.id == uuid.UUID(request.matchdict["id"]))
.first()
)
if item.is_fixture:
raise ValidationError(
"{0} is a fixture and cannot be edited or deleted.".format(item.full_name)
)
request.dbsession.delete(item)
transaction.commit()
return printer_info(None, request.dbsession)
@view_config(
request_method="GET",
route_name="v1_printers_new",
renderer="json",
permission="Authenticated",
)
def show_blank(request):
return printer_info(None, request.dbsession)
@view_config(
request_method="GET",
route_name="v1_printers_id",
renderer="json",
permission="Authenticated",
)
def show_id(request):
return printer_info(uuid.UUID(request.matchdict["id"]), request.dbsession)
@view_config(
request_method="GET",
route_name="v1_printers_list",
renderer="json",
permission="Authenticated",
)
def show_list(request):
list_ = request.dbsession.query(Printer).order_by(Printer.name).all()
printers = []
for item in list_:
printers.append(
{
"id": item.id,
"name": item.name,
"address": item.address,
"cutCode": item.cut_code,
}
)
return printers
def printer_info(id_, dbsession):
if id_ is None:
printer = {"name": "", "address": "", "cutCode": ""}
else:
item = dbsession.query(Printer).filter(Printer.id == id_).first()
printer = {
"id": item.id,
"name": item.name,
"address": item.address,
"cutCode": item.cut_code,
}
return printer

View File

@ -8,7 +8,13 @@ from barker.models import Tax
from barker.models.validation_exception import ValidationError
@view_config(request_method='POST', route_name='v1_taxes_new', renderer='json', permission='Taxes', trans=True)
@view_config(
request_method="POST",
route_name="v1_taxes_new",
renderer="json",
permission="Taxes",
trans=True,
)
def save(request):
json = request.json_body
name = json.get("name", "").strip()
@ -26,7 +32,13 @@ def save(request):
return tax_info(item.id, request.dbsession)
@view_config(request_method='PUT', route_name='v1_taxes_id', renderer='json', permission='Taxes', trans=True)
@view_config(
request_method="PUT",
route_name="v1_taxes_id",
renderer="json",
permission="Taxes",
trans=True,
)
def update(request):
json = request.json_body
item = (
@ -38,20 +50,27 @@ def update(request):
raise ValidationError(
"{0} is a fixture and cannot be edited or deleted.".format(item.full_name)
)
item.name = json['name'].strip()
item.name = json("name", "").strip()
if item.name == "":
raise ValidationError("Name cannot be blank")
try:
item.rate = Decimal(json["rate"]) / 100
if item.rate <= 0:
raise ValidationError("Tax Rate must be a decimal >= 0")
except (ValueError, InvalidOperation):
raise ValidationError("Tax Rate must be a decimal >= 0")
item.rate = json['rate']
transaction.commit()
item = request.dbsession.query(Tax).filter(Tax.id == item.id).first()
return tax_info(item.id, request.dbsession)
@view_config(request_method='DELETE', route_name='v1_taxes_id', renderer='json', permission='Taxes', trans=True)
@view_config(
request_method="DELETE",
route_name="v1_taxes_id",
renderer="json",
permission="Taxes",
trans=True,
)
def delete(request):
item = (
request.dbsession.query(Tax)
@ -67,43 +86,56 @@ def delete(request):
return tax_info(None, request.dbsession)
@view_config(request_method='GET', route_name='v1_taxes_new', renderer='json', permission='Authenticated')
@view_config(
request_method="GET",
route_name="v1_taxes_new",
renderer="json",
permission="Authenticated",
)
def show_blank(request):
return tax_info(None, request.dbsession)
@view_config(request_method='GET', route_name='v1_taxes_id', renderer='json', permission='Authenticated')
@view_config(
request_method="GET",
route_name="v1_taxes_id",
renderer="json",
permission="Authenticated",
)
def show_id(request):
return tax_info(uuid.UUID(request.matchdict["id"]), request.dbsession)
@view_config(request_method='GET', route_name='v1_taxes_list', renderer='json', permission='Authenticated')
@view_config(
request_method="GET",
route_name="v1_taxes_list",
renderer="json",
permission="Authenticated",
)
def show_list(request):
list_ = request.dbsession.query(Tax).order_by(Tax.name).all()
taxes = []
for item in list_:
taxes.append({
'id': item.id,
'name': item.name,
'rate': item.rate,
'isFixture': item.is_fixture
})
taxes.append(
{
"id": item.id,
"name": item.name,
"rate": item.rate,
"isFixture": item.is_fixture,
}
)
return taxes
def tax_info(id_, dbsession):
if id_ is None:
tax = {
"name": "",
"rate": 0,
"isFixture": False
}
tax = {"name": "", "rate": 0, "isFixture": False}
else:
item = dbsession.query(Tax).filter(Tax.id == id_).first()
tax = {
'id': item.id,
'name': item.name,
'rate': item.rate * 100,
'isFixture': item.is_fixture
"id": item.id,
"name": item.name,
"rate": item.rate * 100,
"isFixture": item.is_fixture,
}
return tax

View File

@ -13,6 +13,10 @@ const routes: Routes = [
path: 'guest-book',
loadChildren: () => import('./guest-book/guest-book.module').then(mod => mod.GuestBookModule)
},
{
path: 'printers',
loadChildren: () => import('./printers/printers.module').then(mod => mod.PrintersModule)
},
{
path: 'products',
loadChildren: () => import('./product/products.module').then(mod => mod.ProductsModule)

View File

@ -2,11 +2,6 @@ import { DataSource } from '@angular/cdk/collections';
import { Observable } from 'rxjs';
import { GuestBook } from "../guest-book";
/**
* Data source for the GuestBookList view. This class should
* encapsulate all logic for fetching and manipulating the displayed data
* (including sorting, pagination, and filtering).
*/
export class GuestBookListDataSource extends DataSource<GuestBook> {
constructor(private readonly dataObs: Observable<GuestBook[]>

View File

@ -6,10 +6,8 @@ import { MatNativeDateModule, MAT_DATE_FORMATS, MAT_DATE_LOCALE, DateAdapter } f
import { MatDatepickerModule } from '@angular/material/datepicker';
import { MatIconModule } from '@angular/material/icon';
import { MatInputModule } from '@angular/material/input';
import { MatPaginatorModule } from '@angular/material/paginator';
import { MatRadioModule } from '@angular/material/radio';
import { MatSelectModule } from '@angular/material/select';
import { MatSortModule } from '@angular/material/sort';
import { MatTableModule } from '@angular/material/table';
import { MomentDateAdapter } from '@angular/material-moment-adapter';
import { ReactiveFormsModule } from '@angular/forms';
@ -35,8 +33,6 @@ export const MY_FORMATS = {
imports: [
CommonModule,
MatTableModule,
MatPaginatorModule,
MatSortModule,
MatInputModule,
MatButtonModule,
MatSelectModule,

View File

@ -19,6 +19,9 @@
<a mat-raised-button routerLink="/taxes">
Taxes
</a>
<a mat-raised-button routerLink="/printers">
Printers
</a>
<a mat-raised-button routerLink="/roles">
Roles
</a>

View File

@ -0,0 +1,3 @@
.right-align {
text-align: right;
}

View File

@ -0,0 +1,33 @@
<div fxLayout="row" fxFlex="50%" fxLayoutAlign="space-around center" class="example-card">
<mat-card fxFlex>
<mat-card-title-group>
<mat-card-title>Printer</mat-card-title>
</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">
<mat-form-field fxFlex>
<mat-label>Name</mat-label>
<input matInput #nameElement placeholder="Name" formControlName="name">
</mat-form-field>
</div>
<div fxLayout="row" fxLayoutAlign="space-around start" fxLayout.lt-md="column" fxLayoutGap="20px"
fxLayoutGap.lt-md="0px">
<mat-form-field fxFlex>
<mat-label>Address</mat-label>
<input matInput placeholder="Address" formControlName="address">
</mat-form-field>
<mat-form-field fxFlex>
<mat-label>Cut Code</mat-label>
<input matInput placeholder="Cut code" formControlName="cutCode">
</mat-form-field>
</div>
</form>
</mat-card-content>
<mat-card-actions>
<button mat-raised-button [disabled]="item.isFixture" color="primary" (click)="save()">Save</button>
<button mat-raised-button [disabled]="item.isFixture" color="warn" (click)="confirmDelete()" *ngIf="!!item.id">Delete</button>
</mat-card-actions>
</mat-card>
</div>

View File

@ -0,0 +1,25 @@
import {async, ComponentFixture, TestBed} from '@angular/core/testing';
import {PrinterDetailComponent} from './printer-detail.component';
describe('PrinterDetailComponent', () => {
let component: PrinterDetailComponent;
let fixture: ComponentFixture<PrinterDetailComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [PrinterDetailComponent]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(PrinterDetailComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,108 @@
import { AfterViewInit, Component, ElementRef, OnInit, ViewChild } from '@angular/core';
import { FormBuilder, FormGroup } from '@angular/forms';
import { ActivatedRoute, Router } from '@angular/router';
import { MatDialog } from "@angular/material/dialog";
import { PrinterService } from '../printer.service';
import { Printer } from '../printer';
import { ToasterService } from '../../core/toaster.service';
import { ConfirmDialogComponent } from "../../shared/confirm-dialog/confirm-dialog.component";
@Component({
selector: 'app-printer-detail',
templateUrl: './printer-detail.component.html',
styleUrls: ['./printer-detail.component.css']
})
export class PrinterDetailComponent implements OnInit, AfterViewInit {
@ViewChild('nameElement', { static: true }) nameElement: ElementRef;
form: FormGroup;
item: Printer;
constructor(
private route: ActivatedRoute,
private router: Router,
private dialog: MatDialog,
private fb: FormBuilder,
private toaster: ToasterService,
private ser: PrinterService
) {
this.createForm();
}
createForm() {
this.form = this.fb.group({
name: '',
address: '',
cutCode: ''
});
}
ngOnInit() {
this.route.data
.subscribe((data: { item: Printer }) => {
this.showItem(data.item);
});
}
showItem(item: Printer) {
this.item = item;
this.form.setValue({
name: this.item.name || '',
address: this.item.address || '',
cutCode: this.item.cutCode || ''
});
}
ngAfterViewInit() {
setTimeout(() => {
this.nameElement.nativeElement.focus();
}, 0);
}
save() {
this.ser.saveOrUpdate(this.getItem())
.subscribe(
(result) => {
this.toaster.show('Success', '');
this.router.navigateByUrl('/printers');
},
(error) => {
this.toaster.show('Danger', error.error);
}
);
}
delete() {
this.ser.delete(this.item.id)
.subscribe(
(result) => {
this.toaster.show('Success', '');
this.router.navigateByUrl('/printers');
},
(error) => {
this.toaster.show('Danger', error.error);
}
);
}
confirmDelete(): void {
const dialogRef = this.dialog.open(ConfirmDialogComponent, {
width: '250px',
data: {title: 'Delete Printer?', content: 'Are you sure? This cannot be undone.'}
});
dialogRef.afterClosed().subscribe((result: boolean) => {
if (result) {
this.delete();
}
});
}
getItem(): Printer {
const formModel = this.form.value;
this.item.name = formModel.name;
this.item.address = formModel.address;
this.item.cutCode = formModel.cutCode;
return this.item;
}
}

View File

@ -0,0 +1,15 @@
import {inject, TestBed} from '@angular/core/testing';
import {PrinterListResolver} from './printer-list-resolver.service';
describe('PrinterListResolverService', () => {
beforeEach(() => {
TestBed.configureTestingModule({
providers: [PrinterListResolver]
});
});
it('should be created', inject([PrinterListResolver], (service: PrinterListResolver) => {
expect(service).toBeTruthy();
}));
});

View File

@ -0,0 +1,18 @@
import {Injectable} from '@angular/core';
import {ActivatedRouteSnapshot, Resolve, Router, RouterStateSnapshot} from '@angular/router';
import {Printer} from './printer';
import {Observable} from 'rxjs/internal/Observable';
import {PrinterService} from './printer.service';
@Injectable({
providedIn: 'root'
})
export class PrinterListResolver implements Resolve<Printer[]> {
constructor(private ser: PrinterService, private router: Router) {
}
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<Printer[]> {
return this.ser.list();
}
}

View File

@ -0,0 +1,17 @@
import {DataSource} from '@angular/cdk/collections';
import {Observable, of as observableOf} from 'rxjs';
import {Printer} from '../printer';
export class PrinterListDataSource extends DataSource<Printer> {
constructor(public data: Printer[]) {
super();
}
connect(): Observable<Printer[]> {
return observableOf(this.data);
}
disconnect() {
}
}

View File

@ -0,0 +1,35 @@
<mat-card>
<mat-card-title-group>
<mat-card-title>Printers</mat-card-title>
<a mat-button [routerLink]="['/printers', 'new']">
<mat-icon>add_box</mat-icon>
Add
</a>
</mat-card-title-group>
<mat-card-content>
<mat-table #table [dataSource]="dataSource" aria-label="Elements">
<!-- Name Column -->
<ng-container matColumnDef="name">
<mat-header-cell *matHeaderCellDef>Name</mat-header-cell>
<mat-cell *matCellDef="let row"><a [routerLink]="['/printers', row.id]">{{row.name}}</a></mat-cell>
</ng-container>
<!-- Address Column -->
<ng-container matColumnDef="address">
<mat-header-cell *matHeaderCellDef>Address</mat-header-cell>
<mat-cell *matCellDef="let row">{{row.address}}</mat-cell>
</ng-container>
<!-- Cut Code Column -->
<ng-container matColumnDef="cutCode">
<mat-header-cell *matHeaderCellDef>Cut Code</mat-header-cell>
<mat-cell *matCellDef="let row">{{row.cutCode}}</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>

View File

@ -0,0 +1,23 @@
import {ComponentFixture, fakeAsync, TestBed} from '@angular/core/testing';
import {PrinterListComponent} from './printer-list.component';
describe('PrinterListComponent', () => {
let component: PrinterListComponent;
let fixture: ComponentFixture<PrinterListComponent>;
beforeEach(fakeAsync(() => {
TestBed.configureTestingModule({
declarations: [PrinterListComponent]
})
.compileComponents();
fixture = TestBed.createComponent(PrinterListComponent);
component = fixture.componentInstance;
fixture.detectChanges();
}));
it('should compile', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,27 @@
import { Component, OnInit } from '@angular/core';
import { PrinterListDataSource } from './printer-list-datasource';
import { Printer } from '../printer';
import { ActivatedRoute } from '@angular/router';
@Component({
selector: 'app-printer-list',
templateUrl: './printer-list.component.html',
styleUrls: ['./printer-list.component.css']
})
export class PrinterListComponent implements OnInit {
dataSource: PrinterListDataSource;
list: Printer[];
/** Columns displayed in the table. Columns IDs can be added, removed, or reordered. */
displayedColumns = ['name', 'address', 'cutCode'];
constructor(private route: ActivatedRoute) {
}
ngOnInit() {
this.route.data
.subscribe((data: { list: Printer[] }) => {
this.list = data.list;
});
this.dataSource = new PrinterListDataSource(this.list);
}
}

View File

@ -0,0 +1,15 @@
import {inject, TestBed} from '@angular/core/testing';
import {PrinterResolver} from './printer-resolver.service';
describe('PrinterResolver', () => {
beforeEach(() => {
TestBed.configureTestingModule({
providers: [PrinterResolver]
});
});
it('should be created', inject([PrinterResolver], (service: PrinterResolver) => {
expect(service).toBeTruthy();
}));
});

View File

@ -0,0 +1,19 @@
import {Injectable} from '@angular/core';
import {ActivatedRouteSnapshot, Resolve, Router, RouterStateSnapshot} from '@angular/router';
import {PrinterService} from './printer.service';
import {Printer} from './printer';
import {Observable} from 'rxjs/internal/Observable';
@Injectable({
providedIn: 'root'
})
export class PrinterResolver implements Resolve<Printer> {
constructor(private ser: PrinterService, private router: Router) {
}
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<Printer> {
const id = route.paramMap.get('id');
return this.ser.get(id);
}
}

View File

@ -0,0 +1,15 @@
import {inject, TestBed} from '@angular/core/testing';
import {PrinterService} from './printer.service';
describe('PrinterService', () => {
beforeEach(() => {
TestBed.configureTestingModule({
providers: [PrinterService]
});
});
it('should be created', inject([PrinterService], (service: PrinterService) => {
expect(service).toBeTruthy();
}));
});

View File

@ -0,0 +1,65 @@
import {Injectable} from '@angular/core';
import {HttpClient, HttpHeaders, HttpParams} from '@angular/common/http';
import {ErrorLoggerService} from '../core/error-logger.service';
import {catchError} from 'rxjs/operators';
import {Observable} from 'rxjs/internal/Observable';
import {Printer} from './printer';
const httpOptions = {
headers: new HttpHeaders({'Content-Type': 'application/json'})
};
const url = '/v1/printers';
const serviceName = 'PrinterService';
@Injectable({
providedIn: 'root'
})
export class PrinterService {
constructor(private http: HttpClient, private log: ErrorLoggerService) {
}
get(id: string): Observable<Printer> {
const getUrl: string = (id === null) ? `${url}/new` : `${url}/${id}`;
return <Observable<Printer>>this.http.get<Printer>(getUrl)
.pipe(
catchError(this.log.handleError(serviceName, `get id=${id}`))
);
}
list(): Observable<Printer[]> {
const options = {params: new HttpParams().set('l', '')};
return <Observable<Printer[]>>this.http.get<Printer[]>(url, options)
.pipe(
catchError(this.log.handleError(serviceName, 'list'))
);
}
save(printer: Printer): Observable<Printer> {
return <Observable<Printer>>this.http.post<Printer>(`${url}/new`, printer, httpOptions)
.pipe(
catchError(this.log.handleError(serviceName, 'save'))
);
}
update(printer: Printer): Observable<Printer> {
return <Observable<Printer>>this.http.put<Printer>(`${url}/${printer.id}`, printer, httpOptions)
.pipe(
catchError(this.log.handleError(serviceName, 'update'))
);
}
saveOrUpdate(printer: Printer): Observable<Printer> {
if (!printer.id) {
return this.save(printer);
} else {
return this.update(printer);
}
}
delete(id: string): Observable<Printer> {
return <Observable<Printer>>this.http.delete<Printer>(`${url}/${id}`, httpOptions)
.pipe(
catchError(this.log.handleError(serviceName, 'delete'))
);
}
}

View File

@ -0,0 +1,6 @@
export class Printer {
id: string;
name: string;
address: string;
cutCode: string;
}

View File

@ -0,0 +1,13 @@
import {PrintersRoutingModule} from './printers-routing.module';
describe('PrintersRoutingModule', () => {
let printersRoutingModule: PrintersRoutingModule;
beforeEach(() => {
printersRoutingModule = new PrintersRoutingModule();
});
it('should create an instance', () => {
expect(printersRoutingModule).toBeTruthy();
});
});

View File

@ -0,0 +1,61 @@
import {NgModule} from '@angular/core';
import {CommonModule} from '@angular/common';
import {RouterModule, Routes} from '@angular/router';
import {PrinterListResolver} from './printer-list-resolver.service';
import {PrinterResolver} from './printer-resolver.service';
import {PrinterListComponent} from './printer-list/printer-list.component';
import {PrinterDetailComponent} from './printer-detail/printer-detail.component';
import {AuthGuard} from '../auth/auth-guard.service';
const printersRoutes: Routes = [
{
path: '',
component: PrinterListComponent,
canActivate: [AuthGuard],
data: {
permission: 'Printers'
},
resolve: {
list: PrinterListResolver
}
},
{
path: 'new',
component: PrinterDetailComponent,
canActivate: [AuthGuard],
data: {
permission: 'Printers'
},
resolve: {
item: PrinterResolver
}
},
{
path: ':id',
component: PrinterDetailComponent,
canActivate: [AuthGuard],
data: {
permission: 'Printers'
},
resolve: {
item: PrinterResolver
}
}
];
@NgModule({
imports: [
CommonModule,
RouterModule.forChild(printersRoutes)
],
exports: [
RouterModule
],
providers: [
PrinterListResolver,
PrinterResolver
]
})
export class PrintersRoutingModule {
}

View File

@ -0,0 +1,13 @@
import {PrintersModule} from './printers.module';
describe('PrintersModule', () => {
let printersModule: PrintersModule;
beforeEach(() => {
printersModule = new PrintersModule();
});
it('should create an instance', () => {
expect(printersModule).toBeTruthy();
});
});

View File

@ -0,0 +1,37 @@
import {NgModule} from '@angular/core';
import {CommonModule} from '@angular/common';
import {PrinterListComponent} from './printer-list/printer-list.component';
import {PrinterDetailComponent} from './printer-detail/printer-detail.component';
import {PrintersRoutingModule} from './printers-routing.module';
import { MatButtonModule } from '@angular/material/button';
import { MatCardModule } from '@angular/material/card';
import { MatIconModule } from '@angular/material/icon';
import { MatInputModule } from '@angular/material/input';
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
import { MatTableModule } from '@angular/material/table';
import {CdkTableModule} from '@angular/cdk/table';
import {ReactiveFormsModule} from '@angular/forms';
import {FlexLayoutModule} from '@angular/flex-layout';
@NgModule({
imports: [
CommonModule,
CdkTableModule,
FlexLayoutModule,
MatButtonModule,
MatCardModule,
MatIconModule,
MatInputModule,
MatProgressSpinnerModule,
MatTableModule,
ReactiveFormsModule,
PrintersRoutingModule
],
declarations: [
PrinterListComponent,
PrinterDetailComponent
]
})
export class PrintersModule {
}

View File

@ -9,9 +9,7 @@ import { MatCardModule } from '@angular/material/card';
import { MatCheckboxModule } from '@angular/material/checkbox';
import { MatIconModule } from '@angular/material/icon';
import { MatInputModule } from '@angular/material/input';
import { MatPaginatorModule } from '@angular/material/paginator';
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
import { MatSortModule } from '@angular/material/sort';
import { MatTableModule } from '@angular/material/table';
import { CdkTableModule } from '@angular/cdk/table';
import { DragDropModule } from '@angular/cdk/drag-drop';
@ -25,8 +23,6 @@ import {ReactiveFormsModule} from '@angular/forms';
DragDropModule,
FlexLayoutModule,
MatTableModule,
MatPaginatorModule,
MatSortModule,
MatCardModule,
MatCheckboxModule,
MatProgressSpinnerModule,

View File

@ -10,10 +10,8 @@ import { MatCheckboxModule } from '@angular/material/checkbox';
import { MatOptionModule } from '@angular/material/core';
import { MatIconModule } from '@angular/material/icon';
import { MatInputModule } from '@angular/material/input';
import { MatPaginatorModule } from '@angular/material/paginator';
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 { CdkTableModule } from '@angular/cdk/table';
import { ReactiveFormsModule } from '@angular/forms';
@ -27,8 +25,6 @@ import { DragDropModule } from "@angular/cdk/drag-drop";
DragDropModule,
FlexLayoutModule,
MatTableModule,
MatPaginatorModule,
MatSortModule,
MatCardModule,
MatProgressSpinnerModule,
MatInputModule,

View File

@ -10,9 +10,7 @@ import { MatCheckboxModule } from '@angular/material/checkbox';
import { MatDividerModule } from '@angular/material/divider';
import { MatIconModule } from '@angular/material/icon';
import { MatInputModule } from '@angular/material/input';
import { MatPaginatorModule } from '@angular/material/paginator';
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
import { MatSortModule } from '@angular/material/sort';
import { MatTableModule } from '@angular/material/table';
import {CdkTableModule} from '@angular/cdk/table';
import {ReactiveFormsModule} from '@angular/forms';
@ -30,9 +28,7 @@ import {FlexLayoutModule} from '@angular/flex-layout';
MatDividerModule,
MatIconModule,
MatInputModule,
MatPaginatorModule,
MatProgressSpinnerModule,
MatSortModule,
MatTableModule,
ReactiveFormsModule,
SharedModule,

View File

@ -6,9 +6,7 @@ import { MatCardModule } from '@angular/material/card';
import { MatCheckboxModule } from '@angular/material/checkbox';
import { MatIconModule } from '@angular/material/icon';
import { MatInputModule } from '@angular/material/input';
import { MatPaginatorModule } from '@angular/material/paginator';
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
import { MatSortModule } from '@angular/material/sort';
import { MatTableModule } from '@angular/material/table';
import { CdkTableModule } from '@angular/cdk/table';
import { DragDropModule } from "@angular/cdk/drag-drop";
@ -28,9 +26,7 @@ import { TableRoutingModule } from './tables-routing.module';
MatCheckboxModule,
MatIconModule,
MatInputModule,
MatPaginatorModule,
MatProgressSpinnerModule,
MatSortModule,
MatTableModule,
ReactiveFormsModule,
TableRoutingModule

View File

@ -1,59 +1,17 @@
import {DataSource} from '@angular/cdk/collections';
import { MatPaginator } from '@angular/material/paginator';
import { MatSort } from '@angular/material/sort';
import {map} from 'rxjs/operators';
import {merge, Observable, of as observableOf} from 'rxjs';
import {Tax} from '../../core/tax';
import { DataSource} from '@angular/cdk/collections';
import { Observable, of as observableOf} from 'rxjs';
import { Tax} from '../../core/tax';
export class TaxListDataSource extends DataSource<Tax> {
constructor(private paginator: MatPaginator, private sort: MatSort, public data: Tax[]) {
constructor(public data: Tax[]) {
super();
}
connect(): Observable<Tax[]> {
const dataMutations = [
observableOf(this.data),
this.paginator.page,
this.sort.sortChange
];
// Set the paginators length
this.paginator.length = this.data.length;
return merge(...dataMutations).pipe(map(() => {
return this.getPagedData(this.getSortedData([...this.data]));
}));
return observableOf(this.data);
}
disconnect() {
}
private getPagedData(data: Tax[]) {
const startIndex = this.paginator.pageIndex * this.paginator.pageSize;
return data.splice(startIndex, this.paginator.pageSize);
}
private getSortedData(data: Tax[]) {
if (!this.sort.active || this.sort.direction === '') {
return data;
}
return data.sort((a, b) => {
const isAsc = this.sort.direction === 'asc';
switch (this.sort.active) {
case 'name':
return compare(a.name, b.name, isAsc);
case 'id':
return compare(+a.id, +b.id, isAsc);
default:
return 0;
}
});
}
}
/** Simple sort comparator for example ID/Name columns (for client-side sorting). */
function compare(a, b, isAsc) {
return (a < b ? -1 : 1) * (isAsc ? 1 : -1);
}

View File

@ -7,35 +7,28 @@
</a>
</mat-card-title-group>
<mat-card-content>
<mat-table #table [dataSource]="dataSource" matSort aria-label="Elements">
<mat-table #table [dataSource]="dataSource" aria-label="Elements">
<!-- Name Column -->
<ng-container matColumnDef="name">
<mat-header-cell *matHeaderCellDef mat-sort-header>Name</mat-header-cell>
<mat-header-cell *matHeaderCellDef>Name</mat-header-cell>
<mat-cell *matCellDef="let row"><a [routerLink]="['/taxes', row.id]">{{row.name}}</a></mat-cell>
</ng-container>
<!-- Rate Column -->
<ng-container matColumnDef="rate">
<mat-header-cell *matHeaderCellDef mat-sort-header>Rate</mat-header-cell>
<mat-header-cell *matHeaderCellDef>Rate</mat-header-cell>
<mat-cell *matCellDef="let row">{{row.rate | percent:'1.2-2'}}</mat-cell>
</ng-container>
<!-- Name Column -->
<ng-container matColumnDef="isFixture">
<mat-header-cell *matHeaderCellDef mat-sort-header>Is Fixture?</mat-header-cell>
<mat-header-cell *matHeaderCellDef>Is Fixture?</mat-header-cell>
<mat-cell *matCellDef="let row">{{row.isFixture}}</mat-cell>
</ng-container>
<mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
<mat-row *matRowDef="let row; columns: displayedColumns;"></mat-row>
</mat-table>
<mat-paginator #paginator
[length]="dataSource.data.length"
[pageIndex]="0"
[pageSize]="50"
[pageSizeOptions]="[25, 50, 100, 250]">
</mat-paginator>
</mat-card-content>
</mat-card>

View File

@ -1,9 +1,7 @@
import {Component, OnInit, ViewChild} from '@angular/core';
import { MatPaginator } from '@angular/material/paginator';
import { MatSort } from '@angular/material/sort';
import {TaxListDataSource} from './tax-list-datasource';
import {Tax} from '../../core/tax';
import {ActivatedRoute} from '@angular/router';
import { Component, OnInit } from '@angular/core';
import { TaxListDataSource } from './tax-list-datasource';
import { Tax } from '../../core/tax';
import { ActivatedRoute } from '@angular/router';
@Component({
selector: 'app-tax-list',
@ -11,8 +9,6 @@ import {ActivatedRoute} from '@angular/router';
styleUrls: ['./tax-list.component.css']
})
export class TaxListComponent implements OnInit {
@ViewChild(MatPaginator, { static: true }) paginator: MatPaginator;
@ViewChild(MatSort, { static: true }) sort: MatSort;
dataSource: TaxListDataSource;
list: Tax[];
/** Columns displayed in the table. Columns IDs can be added, removed, or reordered. */
@ -26,6 +22,6 @@ export class TaxListComponent implements OnInit {
.subscribe((data: { list: Tax[] }) => {
this.list = data.list;
});
this.dataSource = new TaxListDataSource(this.paginator, this.sort, this.list);
this.dataSource = new TaxListDataSource(this.list);
}
}

View File

@ -8,9 +8,7 @@ import { MatButtonModule } from '@angular/material/button';
import { MatCardModule } from '@angular/material/card';
import { MatIconModule } from '@angular/material/icon';
import { MatInputModule } from '@angular/material/input';
import { MatPaginatorModule } from '@angular/material/paginator';
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
import { MatSortModule } from '@angular/material/sort';
import { MatTableModule } from '@angular/material/table';
import {CdkTableModule} from '@angular/cdk/table';
import {ReactiveFormsModule} from '@angular/forms';
@ -25,9 +23,7 @@ import {FlexLayoutModule} from '@angular/flex-layout';
MatCardModule,
MatIconModule,
MatInputModule,
MatPaginatorModule,
MatProgressSpinnerModule,
MatSortModule,
MatTableModule,
ReactiveFormsModule,
TaxesRoutingModule

View File

@ -10,9 +10,7 @@ import { MatCheckboxModule } from '@angular/material/checkbox';
import { MatDividerModule } from '@angular/material/divider';
import { MatIconModule } from '@angular/material/icon';
import { MatInputModule } from '@angular/material/input';
import { MatPaginatorModule } from '@angular/material/paginator';
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
import { MatSortModule } from '@angular/material/sort';
import { MatTableModule } from '@angular/material/table';
import {CdkTableModule} from '@angular/cdk/table';
import {ReactiveFormsModule} from '@angular/forms';
@ -30,9 +28,7 @@ import {FlexLayoutModule} from '@angular/flex-layout';
MatDividerModule,
MatIconModule,
MatInputModule,
MatPaginatorModule,
MatProgressSpinnerModule,
MatSortModule,
MatTableModule,
ReactiveFormsModule,
SharedModule,