This commit is contained in:
Bastian Wagner
2024-10-23 15:16:00 +02:00
parent b453945183
commit 03ae75c83d
23 changed files with 138 additions and 103 deletions

View File

@@ -20,7 +20,7 @@ export class Key implements IKey {
name: string;
@Column({ name: 'key_number', unique: false })
nr: number;
nr: string;
@Column({ name: 'handed_out', default: false })
handedOut: boolean;

View File

@@ -22,7 +22,7 @@ export class KeyActivity implements IKey {
name: string;
@Column({ name: 'key_number' })
nr: number;
nr: string;
@Column({ name: 'handed_out', default: false })
handedOut: boolean;

View File

@@ -3,7 +3,7 @@ import { Customer, Cylinder } from '../entitites';
export interface IKey {
id: string;
name: string;
nr: number;
nr: string;
handedOut: boolean;
cylinder: Cylinder;
customer: Customer;

View File

@@ -22,7 +22,6 @@ export class AuthController {
@Body() authDto: AuthCodeDto,
): Promise<User> {
const user = await this.authService.registerOrLoginWithAuthCode(authDto);
console.log(user)
if (user == null) {
throw new HttpException('forbidden', HttpStatus.FORBIDDEN);
}

View File

@@ -131,6 +131,7 @@ export class AuthService {
this.generateTokens(user);
return user;
} catch (e) {
console.log(e);
throw new HttpException('invalid token', HttpStatus.BAD_REQUEST);
}
}

View File

@@ -3,8 +3,6 @@ import {
Controller,
Delete,
Get,
HttpException,
HttpStatus,
Param,
Post,
Put,

View File

@@ -10,6 +10,7 @@ import {
} from 'src/model/repositories';
import { KeyHandoutRepository } from 'src/model/repositories/key-handout.repository';
import { IsNull, Not } from 'typeorm';
import { faker } from '@faker-js/faker';
@Injectable()
export class KeyService {
@@ -19,7 +20,27 @@ export class KeyService {
private readonly systemRepo: KeySystemRepository,
private activityRepo: KeyActivityRepository,
private handoverRepo: KeyHandoutRepository,
) {}
) {
this.create()
}
async create() {
const c = await this.cylinderRepository.findOneBy({ name: 'DevCylinder1' });
const keys = [];
for (let x = 0; x < 1000; x++) {
keys.push(
this.keyrepository.create({
name: faker.commerce.productName(),
nr: faker.commerce.isbn(),
cylinder: c,
createdAt: new Date(faker.date.past())
})
);
}
await this.keyrepository.save(keys);
console.log("edn")
}
async getUsersKeys(user: User): Promise<Key[]> {
return this.keyrepository.find({

View File

@@ -32,6 +32,7 @@
"@angular-devkit/build-angular": "^18.0.2",
"@angular/cli": "^18.0.2",
"@angular/compiler-cli": "^18.0.0",
"@faker-js/faker": "^9.0.3",
"@types/jasmine": "~5.1.0",
"jasmine-core": "~5.1.0",
"karma": "~6.4.0",
@@ -2752,6 +2753,23 @@
"node": ">=18"
}
},
"node_modules/@faker-js/faker": {
"version": "9.0.3",
"resolved": "https://registry.npmjs.org/@faker-js/faker/-/faker-9.0.3.tgz",
"integrity": "sha512-lWrrK4QNlFSU+13PL9jMbMKLJYXDFu3tQfayBsMXX7KL/GiQeqfB1CzHkqD5UHBUtPAuPo6XwGbMFNdVMZObRA==",
"dev": true,
"funding": [
{
"type": "opencollective",
"url": "https://opencollective.com/fakerjs"
}
],
"license": "MIT",
"engines": {
"node": ">=18.0.0",
"npm": ">=9.0.0"
}
},
"node_modules/@inquirer/checkbox": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/@inquirer/checkbox/-/checkbox-2.5.0.tgz",

View File

@@ -34,6 +34,7 @@
"@angular-devkit/build-angular": "^18.0.2",
"@angular/cli": "^18.0.2",
"@angular/compiler-cli": "^18.0.0",
"@faker-js/faker": "^9.0.3",
"@types/jasmine": "~5.1.0",
"jasmine-core": "~5.1.0",
"karma": "~6.4.0",

View File

@@ -11,7 +11,7 @@
</mat-toolbar>
<mat-drawer-container class="example-container" autosize>
<mat-drawer #drawer class="main_sidenav" mode="side" opened="true">
<mat-drawer #drawer class="main_sidenav" mode="side" opened="true" style="border-right: 1px solid #dfdfdf">
<button mat-button routerLink="/" routerLinkActive="mat-elevation-z1" [routerLinkActiveOptions]="{exact: true}">Home</button>
<button mat-button routerLink="/keys" routerLinkActive="mat-elevation-z1">Schlüssel</button>
<button mat-button routerLink="/users" routerLinkActive="mat-elevation-z1">Alle User</button>

View File

@@ -1,14 +1,21 @@
import { Component, inject } from '@angular/core';
import { MatButtonModule } from '@angular/material/button';
import { AuthService } from '../../../core/auth/auth.service';
import { MatDialog, MatDialogActions, MatDialogModule, MatDialogRef } from '@angular/material/dialog';
@Component({
selector: 'app-login',
standalone: true,
imports: [MatButtonModule],
imports: [MatButtonModule, MatDialogModule],
templateUrl: './login.component.html',
styleUrl: './login.component.scss'
})
export class LoginComponent {
public authService: AuthService = inject(AuthService);
readonly dialogRef = inject(MatDialog);
ngOnInit() {
this.dialogRef.closeAll();
}
}

View File

@@ -44,10 +44,12 @@ export class ArchiveComponent {
},
{
width: 40,
cellRenderer: () => '<div class="icon-btn-sm restore" ></div>',
onCellClicked: (event) => { this.restoreKey(event.data);}
cellRenderer: () => '<div class="icon-btn-sm restore icon-btn-xs" ></div>',
onCellClicked: (event) => { this.restoreKey(event.data);},
sortable: false
}
]
];
this.gridOptions.rowHeight = 36;
}
onGridReady(params: GridReadyEvent) {

View File

@@ -5,6 +5,6 @@
/>
<div class="floating-btn-container">
<button mat-raised-button class="btn-create" (click)="openCreateKey()" >Schlüssel anlegen</button>
<button mat-flat-button class="btn-create mat-elevation-z8" (click)="openCreateKey()" color="accent" >Schlüssel anlegen</button>
<button mat-mini-fab (click)="openArchive()"><mat-icon>inventory_2</mat-icon></button>
</div>

View File

@@ -1,7 +1,7 @@
.floating-btn-container {
position: absolute;
bottom: 12px;
right: 12px;
bottom: 48px;
right: 24px;
display: flex;
gap: 12px;
}

View File

@@ -9,7 +9,6 @@ import { HotToastService } from '@ngxpert/hot-toast';
import { MatButtonModule } from '@angular/material/button';
import { MatDialog, MatDialogModule } from '@angular/material/dialog';
import { CreateKeyComponent } from './create/create.component';
import { AgOpenHandoutComponent } from '../../shared/ag-grid/components/ag-open-handout/ag-open-handout.component';
import { AgDeleteKeyComponent } from '../../shared/ag-grid/components/ag-delete-key/ag-delete-key.component';
import { MatIconModule } from '@angular/material/icon';
import { ArchiveComponent } from './components/archive/archive.component';
@@ -37,14 +36,7 @@ export class KeysComponent {
localeText: AG_GRID_LOCALE_DE,
rowData: [],
columnDefs: [
{
cellRenderer: AgOpenHandoutComponent,
width: 100,
headerName: 'Übergabe',
sortable: false,
colId: 'handover',
},
{ colId: 'handedOut', field: 'handedOut' , headerName: 'Ausgegeben', width: 100, editable: false, filter: false, headerTooltip: 'Ausgegeben' },
{ colId: 'name', field: 'name' , headerName: 'Name', flex: 1, editable: true, sort: 'asc', filter: true },
{ colId: 'nr', field: 'nr' , headerName: 'Schlüsselnummer', flex: 1, editable: true, filter: true },
{ colId: 'cylinder', field: 'cylinder' , headerName: 'Zylinder', flex: 1, editable: true, filter: true, cellRenderer: (data: any) => {return data.value?.name}, cellEditor: 'agSelectCellEditor',
@@ -54,8 +46,9 @@ export class KeysComponent {
}
},
valueFormatter: (val) => {
return val.value?.name;
}
return val.value?.name + ` (${val.value?.system?.name})`;
},
cellEditorPopup: false
},
{ colId: 'system', field: 'cylinder.system' , headerName: 'Schließanlage', flex: 1, editable: false, filter: true, cellRenderer: (data: any) => {return data.value?.name} },
{
@@ -73,19 +66,20 @@ export class KeysComponent {
, type: 'date'
, cellRenderer: (data: any) => data.value ? this.datePipe.transform(new Date(data.value)) : '-'
, tooltipValueGetter: (data: any) => this.datePipe.transform(new Date(data.value), 'medium')
}
,{
colId: 'delete'
, headerName: 'Löschen'
},
{ colId: 'handedOut', field: 'handedOut' , headerName: 'Ausgegeben', width: 100, editable: false, filter: false, headerTooltip: 'Ausgegeben' },
{
colId: 'actions'
, headerName: 'Aktionen'
, width: 120
, cellRenderer: AgDeleteKeyComponent
// , onCellClicked: (event) => { this.deleteKey(event.data.id)}
}
],
loading: true,
rowHeight: 36,
loadingOverlayComponent: AgLoadingComponent
rowHeight: 54,
loadingOverlayComponent: AgLoadingComponent,
pagination: true,
}
deleteKey(id: string) {

View File

@@ -1 +1,3 @@
<div class="delete icon-btn-sm" (click)="delete()" ></div>
<div class="handover icon-btn-sm" (click)="openHandoutDialog()" matTooltip="Schlüsselübergaben" [matTooltipShowDelay]="600"></div>
<div class="delete icon-btn-sm" (click)="delete()" matTooltip="Löschen" [matTooltipShowDelay]="600"></div>

View File

@@ -1,8 +1,13 @@
:host {
display: flex;
flex-direction: column;
flex-direction: row;
align-items: center;
justify-content: center;
width: 100%;
height: 100%;
gap: 12px;
}
.handover {
background-image: url('../../../../../assets/img/key_2.svg');
}

View File

@@ -6,11 +6,13 @@ import { ApiService } from '../../../api.service';
import { MatDialog, MatDialogModule } from '@angular/material/dialog';
import { DeleteKeyComponent } from '../../../../modules/keys/components/delete-key/delete-key.component';
import { HotToastService } from '@ngxpert/hot-toast';
import { HandoverDialogComponent } from '../../../../modules/keys/components/handover-dialog/handover-dialog.component';
import { MatTooltipModule } from '@angular/material/tooltip';
@Component({
selector: 'app-ag-delete-key',
standalone: true,
imports: [MatDialogModule],
imports: [MatDialogModule, MatTooltipModule],
templateUrl: './ag-delete-key.component.html',
styleUrl: './ag-delete-key.component.scss'
})
@@ -66,4 +68,20 @@ export class AgDeleteKeyComponent implements ICellRendererAngularComp {
})
}
openHandoutDialog() {
this.dialog.open(HandoverDialogComponent, {
data: this.key,
autoFocus: false,
maxWidth: '100vw',
maxHeight: '100vh'
}).afterClosed().subscribe({
next: n => {
if (n != null) {
this.key.handedOut = n;
this.params.api.refreshCells();
}
}
})
}
}

View File

@@ -1 +0,0 @@
<div class="handover icon-btn-sm" (click)="openDialog()" matTooltip="Schlüsselübergaben" [matTooltipShowDelay]="600"></div>

View File

@@ -1,11 +0,0 @@
:host {
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
height: 100%;
}
.handover {
background-image: url('../../../../../assets/img/key_2.svg');
}

View File

@@ -1,45 +0,0 @@
import { Component, HostBinding, inject } from '@angular/core';
import { ICellRendererAngularComp } from 'ag-grid-angular';
import { ICellRendererParams } from 'ag-grid-community';
import { IKey } from '../../../../model/interface/key.interface';
import { MatDialog, MatDialogModule } from '@angular/material/dialog';
import { HandoverDialogComponent } from '../../../../modules/keys/components/handover-dialog/handover-dialog.component';
import {MatTooltipModule} from '@angular/material/tooltip';
@Component({
selector: 'app-ag-open-handout',
standalone: true,
imports: [MatDialogModule, MatTooltipModule],
templateUrl: './ag-open-handout.component.html',
styleUrl: './ag-open-handout.component.scss'
})
export class AgOpenHandoutComponent implements ICellRendererAngularComp {
private dialog: MatDialog = inject(MatDialog);
key!: IKey;
params!: ICellRendererParams<any, any, any>;
agInit(params: ICellRendererParams<any, any, any>): void {
this.params = params;
this.key = params.data;
}
refresh(params: ICellRendererParams<any, any, any>): boolean {
return false;
}
openDialog() {
this.dialog.open(HandoverDialogComponent, {
data: this.key,
autoFocus: false,
maxWidth: '100vw',
maxHeight: '100vh'
}).afterClosed().subscribe({
next: n => {
if (n != null) {
this.key.handedOut = n;
this.params.api.refreshCells();
}
}
})
}
}

View File

@@ -10,7 +10,8 @@ export class HELPER {
rowData: [],
columnDefs: [],
loading: true,
loadingOverlayComponent: AgLoadingComponent
loadingOverlayComponent: AgLoadingComponent,
rowHeight: 54,
}
}
}

View File

@@ -1,4 +1,8 @@
/* You can add global styles to this file, and also import other style files */
/* Core Data Grid CSS */
@import "ag-grid-community/styles/ag-grid.css";
/* Quartz Theme Specific CSS */
@import 'ag-grid-community/styles/ag-theme-quartz.css';
html, body {
height: 100vh;
width: 100vw;
@@ -6,6 +10,7 @@ html, body {
margin: 0;
padding: 0;
background-color: #e2e2e2;
font-family: Roboto, "Helvetica Neue", sans-serif;
}
.flex {
@@ -22,7 +27,7 @@ html, body {
}
.icon-btn-sm {
box-shadow: 0 0 0 4px transparent,0 1px 2px #0c111d11;
// box-shadow: 0 0 0 4px transparent,0 1px 2px #0c111d11;
border: 1px solid #d0d5dd;
background-color: white;
cursor: pointer;
@@ -32,9 +37,23 @@ html, body {
background-size: 20px;
background-position: center;
background-repeat: no-repeat;
width: 26px;
height: 26px;
width: 38px;
height: 38px;
transition: box-shadow 0.1s ease-in-out;
&:hover {
// box-shadow: 0 0 0 4px transparent,0 1px 2px #0c111d11;
box-shadow: 0px 3px 5px -1px rgba(0, 0, 0, 0.2),
0px 6px 10px 0px rgba(0, 0, 0, 0.14),
0px 1px 18px 0px rgba(0, 0, 0, 0.12);
}
}
.icon-btn-xs {
width: 28px;
height: 28px;
background-size: 20px;
}
.loading-spinner {
@@ -59,9 +78,15 @@ html, body {
background-image: url("./assets/img/restore.svg");
}
/* Core Data Grid CSS */
@import "ag-grid-community/styles/ag-grid.css";
/* Quartz Theme Specific CSS */
@import 'ag-grid-community/styles/ag-theme-quartz.css';
html, body { height: 100%; }
body { margin: 0; font-family: Roboto, "Helvetica Neue", sans-serif; }
.ag-row {
transition: background-color 0.2s ease-in-out;
}
.ag-row .ag-cell {
display: flex;
// justify-content: center; /* align horizontal */
align-items: center;
}