...
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,8 +3,6 @@ import {
|
||||
Controller,
|
||||
Delete,
|
||||
Get,
|
||||
HttpException,
|
||||
HttpStatus,
|
||||
Param,
|
||||
Post,
|
||||
Put,
|
||||
|
||||
@@ -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({
|
||||
|
||||
18
client/package-lock.json
generated
18
client/package-lock.json
generated
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
.floating-btn-container {
|
||||
position: absolute;
|
||||
bottom: 12px;
|
||||
right: 12px;
|
||||
bottom: 48px;
|
||||
right: 24px;
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
}
|
||||
@@ -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) {
|
||||
|
||||
@@ -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>
|
||||
@@ -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');
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
<div class="handover icon-btn-sm" (click)="openDialog()" matTooltip="Schlüsselübergaben" [matTooltipShowDelay]="600"></div>
|
||||
@@ -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');
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -10,7 +10,8 @@ export class HELPER {
|
||||
rowData: [],
|
||||
columnDefs: [],
|
||||
loading: true,
|
||||
loadingOverlayComponent: AgLoadingComponent
|
||||
loadingOverlayComponent: AgLoadingComponent,
|
||||
rowHeight: 54,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user