Chore: Upgrade to Angular v18
Chore: Upgrade to Python 3.12 Chore: Upgrade to psycopg3
This commit is contained in:
@ -1,19 +0,0 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { ActivatedRouteSnapshot } from '@angular/router';
|
||||
import { Observable } from 'rxjs';
|
||||
|
||||
import { GuestBook } from './guest-book';
|
||||
import { GuestBookService } from './guest-book.service';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class GuestBookDetailResolver {
|
||||
constructor(private ser: GuestBookService) {}
|
||||
|
||||
resolve(route: ActivatedRouteSnapshot): Observable<GuestBook> {
|
||||
const id = route.paramMap.get('id');
|
||||
const account = route.queryParamMap.get('t') || 'walk_in';
|
||||
return this.ser.get(id, account);
|
||||
}
|
||||
}
|
||||
11
bookie/src/app/guest-book/guest-book-detail.resolver.ts
Normal file
11
bookie/src/app/guest-book/guest-book-detail.resolver.ts
Normal file
@ -0,0 +1,11 @@
|
||||
import { inject } from '@angular/core';
|
||||
import { ResolveFn } from '@angular/router';
|
||||
|
||||
import { GuestBook } from './guest-book';
|
||||
import { GuestBookService } from './guest-book.service';
|
||||
|
||||
export const guestBookDetailResolver: ResolveFn<GuestBook> = (route) => {
|
||||
const id = route.paramMap.get('id');
|
||||
const account = route.queryParamMap.get('t') || 'walk_in';
|
||||
return inject(GuestBookService).get(id, account);
|
||||
};
|
||||
@ -8,7 +8,9 @@
|
||||
<mat-form-field class="flex-auto">
|
||||
<mat-label>Name</mat-label>
|
||||
<input matInput #name formControlName="name" />
|
||||
<mat-error *ngIf="form.controls['name'].hasError('required')"> Name is <strong>required</strong> </mat-error>
|
||||
@if (form.controls['name'].hasError('required')) {
|
||||
<mat-error> Name is <strong>required</strong> </mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
</div>
|
||||
<div class="flex flex-row justify-around content-start items-start">
|
||||
@ -22,9 +24,9 @@
|
||||
[displayWith]="displayFn"
|
||||
(optionSelected)="selected($event)"
|
||||
>
|
||||
<mat-option *ngFor="let customer of customers | async" [value]="customer"
|
||||
>{{ customer.name }} - {{ customer.phone }}</mat-option
|
||||
>
|
||||
@for (customer of customers | async; track customer) {
|
||||
<mat-option [value]="customer">{{ customer.name }} - {{ customer.phone }}</mat-option>
|
||||
}
|
||||
</mat-autocomplete>
|
||||
</div>
|
||||
<div class="flex flex-row justify-around content-start items-start">
|
||||
@ -65,6 +67,8 @@
|
||||
</mat-card-content>
|
||||
<mat-card-actions>
|
||||
<button mat-raised-button color="primary" class="mr-5" (click)="save()">Save</button>
|
||||
<button mat-raised-button color="warn" (click)="confirmDelete()" *ngIf="!!item.id">Delete</button>
|
||||
@if (!!item.id) {
|
||||
<button mat-raised-button color="warn" (click)="confirmDelete()">Delete</button>
|
||||
}
|
||||
</mat-card-actions>
|
||||
</mat-card>
|
||||
|
||||
@ -1,9 +1,16 @@
|
||||
import { AsyncPipe } from '@angular/common';
|
||||
import { AfterViewInit, Component, ElementRef, OnInit, ViewChild } from '@angular/core';
|
||||
import { FormControl, FormGroup, Validators } from '@angular/forms';
|
||||
import { MatAutocompleteSelectedEvent } from '@angular/material/autocomplete';
|
||||
import { FormControl, FormGroup, Validators, ReactiveFormsModule } from '@angular/forms';
|
||||
import { MatAutocompleteSelectedEvent, MatAutocompleteTrigger, MatAutocomplete } from '@angular/material/autocomplete';
|
||||
import { MatButton } from '@angular/material/button';
|
||||
import { MatCard, MatCardHeader, MatCardTitle, MatCardContent, MatCardActions } from '@angular/material/card';
|
||||
import { MatOption } from '@angular/material/core';
|
||||
import { MatDatepickerInput, MatDatepickerToggle, MatDatepicker } from '@angular/material/datepicker';
|
||||
import { MatDialog } from '@angular/material/dialog';
|
||||
import { MatFormField, MatLabel, MatError, MatSuffix } from '@angular/material/form-field';
|
||||
import { MatInput } from '@angular/material/input';
|
||||
import { ActivatedRoute, Router } from '@angular/router';
|
||||
import * as moment from 'moment';
|
||||
import moment from 'moment';
|
||||
import { Observable, of as observableOf } from 'rxjs';
|
||||
import { debounceTime, distinctUntilChanged, map, startWith, switchMap } from 'rxjs/operators';
|
||||
|
||||
@ -18,6 +25,28 @@ import { GuestBookService } from '../guest-book.service';
|
||||
selector: 'app-guest-book-detail',
|
||||
templateUrl: './guest-book-detail.component.html',
|
||||
styleUrls: ['./guest-book-detail.component.css'],
|
||||
standalone: true,
|
||||
imports: [
|
||||
MatCard,
|
||||
MatCardHeader,
|
||||
MatCardTitle,
|
||||
MatCardContent,
|
||||
ReactiveFormsModule,
|
||||
MatFormField,
|
||||
MatLabel,
|
||||
MatInput,
|
||||
MatError,
|
||||
MatAutocompleteTrigger,
|
||||
MatAutocomplete,
|
||||
MatOption,
|
||||
MatDatepickerInput,
|
||||
MatDatepickerToggle,
|
||||
MatSuffix,
|
||||
MatDatepicker,
|
||||
MatCardActions,
|
||||
MatButton,
|
||||
AsyncPipe,
|
||||
],
|
||||
})
|
||||
export class GuestBookDetailComponent implements OnInit, AfterViewInit {
|
||||
@ViewChild('phone', { static: true }) phoneElement?: ElementRef;
|
||||
@ -104,15 +133,15 @@ export class GuestBookDetailComponent implements OnInit, AfterViewInit {
|
||||
}
|
||||
|
||||
save() {
|
||||
this.ser.saveOrUpdate(this.getItem()).subscribe(
|
||||
() => {
|
||||
this.ser.saveOrUpdate(this.getItem()).subscribe({
|
||||
next: () => {
|
||||
this.toaster.show('Success', '');
|
||||
this.router.navigateByUrl('/guest-book');
|
||||
},
|
||||
(error) => {
|
||||
error: (error) => {
|
||||
this.toaster.show('Error', error);
|
||||
},
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
displayFn(customer?: Customer): string {
|
||||
|
||||
@ -1,16 +0,0 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Observable } from 'rxjs';
|
||||
|
||||
import { GuestBookList } from './guest-book-list';
|
||||
import { GuestBookService } from './guest-book.service';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class GuestBookListResolver {
|
||||
constructor(private ser: GuestBookService) {}
|
||||
|
||||
resolve(): Observable<GuestBookList> {
|
||||
return this.ser.list(null);
|
||||
}
|
||||
}
|
||||
9
bookie/src/app/guest-book/guest-book-list.resolver.ts
Normal file
9
bookie/src/app/guest-book/guest-book-list.resolver.ts
Normal file
@ -0,0 +1,9 @@
|
||||
import { inject } from '@angular/core';
|
||||
import { ResolveFn } from '@angular/router';
|
||||
|
||||
import { GuestBookList } from './guest-book-list';
|
||||
import { GuestBookService } from './guest-book.service';
|
||||
|
||||
export const guestBookListResolver: ResolveFn<GuestBookList> = () => {
|
||||
return inject(GuestBookService).list(null);
|
||||
};
|
||||
@ -62,32 +62,30 @@
|
||||
<ng-container matColumnDef="action">
|
||||
<mat-header-cell *matHeaderCellDef class="center">Action</mat-header-cell>
|
||||
<mat-cell *matCellDef="let row" class="center">
|
||||
<button
|
||||
mat-icon-button
|
||||
[routerLink]="['/sales']"
|
||||
[queryParams]="{ guest: row.id }"
|
||||
*ngIf="row.status === 'old' || (!row.tableId && !row.voucherId)"
|
||||
>
|
||||
<mat-icon>chair</mat-icon>
|
||||
</button>
|
||||
<button
|
||||
mat-stroked-button
|
||||
color="primary"
|
||||
[routerLink]="['/sales', 'bill']"
|
||||
[queryParams]="{ table: row.tableId, voucher: row.voucherId }"
|
||||
*ngIf="row.tableId"
|
||||
>
|
||||
{{ row.tableName }}
|
||||
</button>
|
||||
@if (row.status === 'old' || (!row.tableId && !row.voucherId)) {
|
||||
<button mat-icon-button [routerLink]="['/sales']" [queryParams]="{ guest: row.id }">
|
||||
<mat-icon>chair</mat-icon>
|
||||
</button>
|
||||
}
|
||||
@if (row.tableId) {
|
||||
<button
|
||||
mat-stroked-button
|
||||
color="primary"
|
||||
[routerLink]="['/sales', 'bill']"
|
||||
[queryParams]="{ table: row.tableId, voucher: row.voucherId }"
|
||||
>
|
||||
{{ row.tableName }}
|
||||
</button>
|
||||
}
|
||||
<!-- <button
|
||||
mat-stroked-button
|
||||
color="primary"
|
||||
[routerLink]="['/sales', 'bill']"
|
||||
[queryParams]="{ voucher: row.voucherId }"
|
||||
*ngIf="!row.tableId && row.voucherId"
|
||||
>
|
||||
{{ row.tableName }}
|
||||
</button> -->
|
||||
mat-stroked-button
|
||||
color="primary"
|
||||
[routerLink]="['/sales', 'bill']"
|
||||
[queryParams]="{ voucher: row.voucherId }"
|
||||
*ngIf="!row.tableId && row.voucherId"
|
||||
>
|
||||
{{ row.tableName }}
|
||||
</button> -->
|
||||
</mat-cell>
|
||||
</ng-container>
|
||||
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
@use '@angular/material' as mat
|
||||
|
||||
$my-primary: mat.define-palette(mat.$indigo-palette, 500)
|
||||
$my-accent: mat.define-palette(mat.$amber-palette, A200, A100, A400)
|
||||
$my-primary: mat.m2-define-palette(mat.$m2-indigo-palette, 500)
|
||||
$my-accent: mat.m2-define-palette(mat.$m2-amber-palette, A200, A100, A400)
|
||||
|
||||
table
|
||||
width: 100%
|
||||
@ -12,13 +12,13 @@ table
|
||||
|
||||
.accent
|
||||
/* Read the 200 hue from the primary color palete.*/
|
||||
color: mat.get-color-from-palette($my-accent, '200-contrast')
|
||||
background: mat.get-color-from-palette($my-accent, 200)
|
||||
color: mat.m2-get-color-from-palette($my-accent, '200-contrast')
|
||||
background: mat.m2-get-color-from-palette($my-accent, 200)
|
||||
|
||||
.strong-accent
|
||||
/* Read the 700 hue from the primary color palete.*/
|
||||
color: mat.get-color-from-palette($my-accent, '700-contrast')
|
||||
background: mat.get-color-from-palette($my-accent, 700)
|
||||
color: mat.m2-get-color-from-palette($my-accent, '700-contrast')
|
||||
background: mat.m2-get-color-from-palette($my-accent, 700)
|
||||
|
||||
.grey300
|
||||
background-color: #ede7f6
|
||||
|
||||
@ -1,11 +1,30 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { FormControl, FormGroup } from '@angular/forms';
|
||||
import { ActivatedRoute, Router } from '@angular/router';
|
||||
import * as moment from 'moment';
|
||||
import { FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms';
|
||||
import { MatAnchor, MatIconButton, MatButton } from '@angular/material/button';
|
||||
import { MatCard, MatCardHeader, MatCardTitleGroup, MatCardTitle, MatCardContent } from '@angular/material/card';
|
||||
import { MatDatepickerInput, MatDatepickerToggle, MatDatepicker } from '@angular/material/datepicker';
|
||||
import { MatFormField, MatLabel, MatSuffix } from '@angular/material/form-field';
|
||||
import { MatIcon } from '@angular/material/icon';
|
||||
import { MatInput } from '@angular/material/input';
|
||||
import {
|
||||
MatTable,
|
||||
MatColumnDef,
|
||||
MatHeaderCellDef,
|
||||
MatHeaderCell,
|
||||
MatCellDef,
|
||||
MatCell,
|
||||
MatHeaderRowDef,
|
||||
MatHeaderRow,
|
||||
MatRowDef,
|
||||
MatRow,
|
||||
} from '@angular/material/table';
|
||||
import { ActivatedRoute, Router, RouterLink } from '@angular/router';
|
||||
import moment from 'moment';
|
||||
import { BehaviorSubject } from 'rxjs';
|
||||
import { map } from 'rxjs/operators';
|
||||
|
||||
import { ToasterService } from '../../core/toaster.service';
|
||||
import { LocalTimePipe } from '../../shared/local-time.pipe';
|
||||
import { GuestBook } from '../guest-book';
|
||||
import { GuestBookList } from '../guest-book-list';
|
||||
import { GuestBookService } from '../guest-book.service';
|
||||
@ -16,6 +35,38 @@ import { GuestBookListDataSource } from './guest-book-list-datasource';
|
||||
selector: 'app-guest-book-list',
|
||||
templateUrl: './guest-book-list.component.html',
|
||||
styleUrls: ['./guest-book-list.component.sass'],
|
||||
standalone: true,
|
||||
imports: [
|
||||
MatCard,
|
||||
MatCardHeader,
|
||||
MatCardTitleGroup,
|
||||
MatCardTitle,
|
||||
MatAnchor,
|
||||
RouterLink,
|
||||
MatIcon,
|
||||
MatCardContent,
|
||||
ReactiveFormsModule,
|
||||
MatFormField,
|
||||
MatLabel,
|
||||
MatInput,
|
||||
MatDatepickerInput,
|
||||
MatDatepickerToggle,
|
||||
MatSuffix,
|
||||
MatDatepicker,
|
||||
MatTable,
|
||||
MatColumnDef,
|
||||
MatHeaderCellDef,
|
||||
MatHeaderCell,
|
||||
MatCellDef,
|
||||
MatCell,
|
||||
MatIconButton,
|
||||
MatButton,
|
||||
MatHeaderRowDef,
|
||||
MatHeaderRow,
|
||||
MatRowDef,
|
||||
MatRow,
|
||||
LocalTimePipe,
|
||||
],
|
||||
})
|
||||
export class GuestBookListComponent implements OnInit {
|
||||
data: BehaviorSubject<GuestBook[]> = new BehaviorSubject<GuestBook[]>([]);
|
||||
|
||||
@ -1,54 +0,0 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { Routes, RouterModule } from '@angular/router';
|
||||
|
||||
import { AuthGuard } from '../auth/auth-guard.service';
|
||||
|
||||
import { GuestBookDetailComponent } from './guest-book-detail/guest-book-detail.component';
|
||||
import { GuestBookDetailResolver } from './guest-book-detail-resolver.service';
|
||||
import { GuestBookListComponent } from './guest-book-list/guest-book-list.component';
|
||||
import { GuestBookListResolver } from './guest-book-list-resolver.service';
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
path: '',
|
||||
component: GuestBookListComponent,
|
||||
canActivate: [AuthGuard],
|
||||
data: {
|
||||
permission: 'Customers',
|
||||
},
|
||||
resolve: {
|
||||
list: GuestBookListResolver,
|
||||
},
|
||||
runGuardsAndResolvers: 'always',
|
||||
},
|
||||
{
|
||||
path: 'new',
|
||||
component: GuestBookDetailComponent,
|
||||
canActivate: [AuthGuard],
|
||||
data: {
|
||||
permission: 'Customers',
|
||||
},
|
||||
resolve: {
|
||||
item: GuestBookDetailResolver,
|
||||
},
|
||||
},
|
||||
{
|
||||
path: ':id',
|
||||
component: GuestBookDetailComponent,
|
||||
canActivate: [AuthGuard],
|
||||
data: {
|
||||
permission: 'Customers',
|
||||
},
|
||||
resolve: {
|
||||
item: GuestBookDetailResolver,
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
declarations: [],
|
||||
imports: [RouterModule.forChild(routes)],
|
||||
exports: [RouterModule],
|
||||
providers: [GuestBookListResolver, GuestBookDetailResolver],
|
||||
})
|
||||
export class GuestBookRoutingModule {}
|
||||
@ -1,57 +0,0 @@
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { NgModule } from '@angular/core';
|
||||
import { ReactiveFormsModule } from '@angular/forms';
|
||||
import { MatAutocompleteModule } from '@angular/material/autocomplete';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatCardModule } from '@angular/material/card';
|
||||
import { MatNativeDateModule, MAT_DATE_FORMATS, MAT_DATE_LOCALE, DateAdapter } from '@angular/material/core';
|
||||
import { MatDatepickerModule } from '@angular/material/datepicker';
|
||||
import { MatIconModule } from '@angular/material/icon';
|
||||
import { MatInputModule } from '@angular/material/input';
|
||||
import { MatRadioModule } from '@angular/material/radio';
|
||||
import { MatSelectModule } from '@angular/material/select';
|
||||
import { MatTableModule } from '@angular/material/table';
|
||||
import { MomentDateAdapter } from '@angular/material-moment-adapter';
|
||||
|
||||
import { SharedModule } from '../shared/shared.module';
|
||||
|
||||
import { GuestBookDetailComponent } from './guest-book-detail/guest-book-detail.component';
|
||||
import { GuestBookListComponent } from './guest-book-list/guest-book-list.component';
|
||||
import { GuestBookRoutingModule } from './guest-book-routing.module';
|
||||
|
||||
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({
|
||||
declarations: [GuestBookDetailComponent, GuestBookListComponent],
|
||||
imports: [
|
||||
CommonModule,
|
||||
MatTableModule,
|
||||
MatInputModule,
|
||||
MatButtonModule,
|
||||
MatSelectModule,
|
||||
MatRadioModule,
|
||||
MatCardModule,
|
||||
MatIconModule,
|
||||
MatDatepickerModule,
|
||||
MatNativeDateModule,
|
||||
ReactiveFormsModule,
|
||||
GuestBookRoutingModule,
|
||||
SharedModule,
|
||||
MatAutocompleteModule,
|
||||
],
|
||||
providers: [
|
||||
{ provide: DateAdapter, useClass: MomentDateAdapter, deps: [MAT_DATE_LOCALE] },
|
||||
{ provide: MAT_DATE_FORMATS, useValue: MY_FORMATS },
|
||||
],
|
||||
})
|
||||
export class GuestBookModule {}
|
||||
45
bookie/src/app/guest-book/guest-book.routes.ts
Normal file
45
bookie/src/app/guest-book/guest-book.routes.ts
Normal file
@ -0,0 +1,45 @@
|
||||
import { Routes } from '@angular/router';
|
||||
|
||||
import { authGuard } from '../auth/auth-guard.service';
|
||||
|
||||
import { GuestBookDetailComponent } from './guest-book-detail/guest-book-detail.component';
|
||||
import { guestBookDetailResolver } from './guest-book-detail.resolver';
|
||||
import { GuestBookListComponent } from './guest-book-list/guest-book-list.component';
|
||||
import { guestBookListResolver } from './guest-book-list.resolver';
|
||||
|
||||
export const routes: Routes = [
|
||||
{
|
||||
path: '',
|
||||
component: GuestBookListComponent,
|
||||
canActivate: [authGuard],
|
||||
data: {
|
||||
permission: 'Customers',
|
||||
},
|
||||
resolve: {
|
||||
list: guestBookListResolver,
|
||||
},
|
||||
runGuardsAndResolvers: 'always',
|
||||
},
|
||||
{
|
||||
path: 'new',
|
||||
component: GuestBookDetailComponent,
|
||||
canActivate: [authGuard],
|
||||
data: {
|
||||
permission: 'Customers',
|
||||
},
|
||||
resolve: {
|
||||
item: guestBookDetailResolver,
|
||||
},
|
||||
},
|
||||
{
|
||||
path: ':id',
|
||||
component: GuestBookDetailComponent,
|
||||
canActivate: [authGuard],
|
||||
data: {
|
||||
permission: 'Customers',
|
||||
},
|
||||
resolve: {
|
||||
item: guestBookDetailResolver,
|
||||
},
|
||||
},
|
||||
];
|
||||
Reference in New Issue
Block a user