diff --git a/api/src/model/entitites/key.entity.ts b/api/src/model/entitites/key.entity.ts
index 5e26cf2..ca7c9a3 100644
--- a/api/src/model/entitites/key.entity.ts
+++ b/api/src/model/entitites/key.entity.ts
@@ -1,6 +1,7 @@
import {
Column,
CreateDateColumn,
+ DeleteDateColumn,
Entity,
ManyToOne,
PrimaryGeneratedColumn,
@@ -18,7 +19,7 @@ export class Key implements IKey {
@Column({ nullable: true })
name: string;
- @Column({ name: 'key_number', unique: true })
+ @Column({ name: 'key_number', unique: false })
nr: number;
@Column({ name: 'handed_out', default: false })
@@ -35,4 +36,7 @@ export class Key implements IKey {
@UpdateDateColumn({ name: 'updatet_at' })
updatedAt: Date;
+
+ @DeleteDateColumn()
+ deletedAt: Date;
}
diff --git a/api/src/modules/key/key.controller.ts b/api/src/modules/key/key.controller.ts
index 1962aaa..0f14213 100644
--- a/api/src/modules/key/key.controller.ts
+++ b/api/src/modules/key/key.controller.ts
@@ -1,7 +1,10 @@
import {
Body,
Controller,
+ Delete,
Get,
+ HttpException,
+ HttpStatus,
Param,
Post,
Put,
@@ -13,7 +16,6 @@ import { AuthenticatedRequest } from 'src/model/interface/authenticated-request.
import { AuthGuard } from 'src/core/guards/auth.guard';
import { Key } from 'src/model/entitites';
import { CreateKeySystemDto } from 'src/model/dto/create-key-system.dto';
-import { HandoverKeyDto } from 'src/model/dto';
@UseGuards(AuthGuard)
@Controller('key')
@@ -25,11 +27,26 @@ export class KeyController {
return this.service.getUsersKeys(req.user);
}
+ @Post()
+ postKey(@Req() req: AuthenticatedRequest, @Body() key: Key) {
+ return this.service.createKey(req.user, key);
+ }
+
@Put()
updateKey(@Req() req: AuthenticatedRequest, @Body() key: Key) {
return this.service.updateKey(req.user, key);
}
+ @Put(':id/restore')
+ restoreKey(@Req() req: AuthenticatedRequest, @Param('id') id: string) {
+ return this.service.restoreKey(req.user, id);
+ }
+
+ @Delete(':id')
+ deleteKey(@Req() req: AuthenticatedRequest, @Param('id') id: string) {
+ return this.service.deleteKey(req.user, id);
+ }
+
@Get('cylinder')
getCylinders(@Req() req: AuthenticatedRequest) {
return this.service.getUsersCylinders(req.user);
@@ -56,4 +73,9 @@ export class KeyController {
getKeyHandouts(@Req() req: AuthenticatedRequest, @Param('id') id: string) {
return this.service.getKeyHandovers(req.user, id);
}
+
+ @Get('Archive')
+ getArchive(@Req() req: AuthenticatedRequest) {
+ return this.service.getDeletedKeys(req.user);
+ }
}
diff --git a/api/src/modules/key/key.service.ts b/api/src/modules/key/key.service.ts
index f9607cf..d3678ac 100644
--- a/api/src/modules/key/key.service.ts
+++ b/api/src/modules/key/key.service.ts
@@ -9,6 +9,7 @@ import {
KeySystemRepository,
} from 'src/model/repositories';
import { KeyHandoutRepository } from 'src/model/repositories/key-handout.repository';
+import { IsNull, Not } from 'typeorm';
@Injectable()
export class KeyService {
@@ -108,4 +109,35 @@ export class KeyService {
relations: ['customer'],
});
}
+
+ createKey(user: User, key: any) {
+ return this.keyrepository.save(this.keyrepository.create(key));
+ }
+
+ async deleteKey(user: User, id: string) {
+ const key = await this.keyrepository.findOneOrFail({
+ where: { id, cylinder: { system: { managers: { id: user.id } } } },
+ });
+ return this.keyrepository.softRemove(key);
+ }
+
+ getDeletedKeys(user: User) {
+ return this.keyrepository.find({
+ where: {
+ cylinder: { system: { managers: { id: user.id } } },
+ deletedAt: Not(IsNull()),
+ },
+ withDeleted: true,
+ order: { deletedAt: { direction: 'DESC' } },
+ });
+ }
+
+ async restoreKey(user: User, keyID: string) {
+ const key = await this.keyrepository.findOneOrFail({
+ where: { cylinder: { system: { managers: { id: user.id } } }, id: keyID },
+ withDeleted: true,
+ });
+ key.deletedAt = null;
+ return this.keyrepository.save(key);
+ }
}
diff --git a/client/src/app/model/interface/key.interface.ts b/client/src/app/model/interface/key.interface.ts
index ad9dae6..f881d4b 100644
--- a/client/src/app/model/interface/key.interface.ts
+++ b/client/src/app/model/interface/key.interface.ts
@@ -6,4 +6,5 @@ export interface IKey {
handedOut: boolean;
cylinder: any;
nr: number;
+ deletedAt?: string;
}
\ No newline at end of file
diff --git a/client/src/app/modules/keys/components/archive/archive.component.html b/client/src/app/modules/keys/components/archive/archive.component.html
new file mode 100644
index 0000000..c27ca19
--- /dev/null
+++ b/client/src/app/modules/keys/components/archive/archive.component.html
@@ -0,0 +1,12 @@
+
Gelöschte Schlüssel
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/client/src/app/modules/keys/components/archive/archive.component.scss b/client/src/app/modules/keys/components/archive/archive.component.scss
new file mode 100644
index 0000000..0c10519
--- /dev/null
+++ b/client/src/app/modules/keys/components/archive/archive.component.scss
@@ -0,0 +1,3 @@
+mat-dialog-content{
+
+}
\ No newline at end of file
diff --git a/client/src/app/modules/keys/components/archive/archive.component.spec.ts b/client/src/app/modules/keys/components/archive/archive.component.spec.ts
new file mode 100644
index 0000000..642dd39
--- /dev/null
+++ b/client/src/app/modules/keys/components/archive/archive.component.spec.ts
@@ -0,0 +1,23 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { ArchiveComponent } from './archive.component';
+
+describe('ArchiveComponent', () => {
+ let component: ArchiveComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ imports: [ArchiveComponent]
+ })
+ .compileComponents();
+
+ fixture = TestBed.createComponent(ArchiveComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/client/src/app/modules/keys/components/archive/archive.component.ts b/client/src/app/modules/keys/components/archive/archive.component.ts
new file mode 100644
index 0000000..088ae36
--- /dev/null
+++ b/client/src/app/modules/keys/components/archive/archive.component.ts
@@ -0,0 +1,91 @@
+import { AG_GRID_LOCALE_DE } from '@ag-grid-community/locale';
+import { Component, inject, LOCALE_ID } from '@angular/core';
+import { MatDialogModule } from '@angular/material/dialog';
+import { AgGridAngular } from 'ag-grid-angular';
+import { GridApi, GridOptions, GridReadyEvent } from 'ag-grid-community';
+import { ApiService } from '../../../../shared/api.service';
+import { DatePipe } from '@angular/common';
+import { MatButtonModule } from '@angular/material/button';
+import { MatIconModule } from '@angular/material/icon';
+import { IKey } from '../../../../model/interface/key.interface';
+import { HotToastService } from '@ngxpert/hot-toast';
+import { AgLoadingComponent } from '../../../../shared/ag-grid/components/ag-loading/ag-loading.component';
+import { HELPER } from '../../../../shared/helper.service';
+
+@Component({
+ selector: 'app-archive',
+ standalone: true,
+ imports: [MatDialogModule, AgGridAngular, MatButtonModule, MatIconModule],
+ providers: [DatePipe, { provide: LOCALE_ID, useValue: 'de-DE' }],
+ templateUrl: './archive.component.html',
+ styleUrl: './archive.component.scss'
+})
+export class ArchiveComponent {
+ private api: ApiService = inject(ApiService);
+ private datePipe = inject(DatePipe);
+ private toast = inject(HotToastService);
+
+ public dataChanged = false;
+
+ gridApi!: GridApi;
+
+ gridOptions: GridOptions = HELPER.getGridOptions();
+
+ constructor() {
+ this.gridOptions.columnDefs = [
+ { 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 },
+ {
+ field: 'deletedAt'
+ , headerName: 'Gelöscht'
+ , width: 160
+ , type: 'date'
+ , cellRenderer: (data: any) => this.datePipe.transform(new Date(data.value), 'short')
+ },
+ {
+ width: 40,
+ cellRenderer: () => '',
+ onCellClicked: (event) => { this.restoreKey(event.data);}
+ }
+ ]
+ }
+
+ onGridReady(params: GridReadyEvent) {
+ this.gridApi = params.api;
+ this.loadKeys();
+ }
+
+
+ loadKeys() {
+ this.gridApi.setGridOption("loading", true);
+ this.api.getKeyArchive().subscribe({
+ next: n => {
+ this.gridApi.setGridOption("rowData", n);
+ this.gridApi.setGridOption("loading", false);
+ }
+ })
+ }
+
+ restoreKey(key: IKey) {
+ this.gridApi.setGridOption("loading", true);
+ key.deletedAt = undefined;
+ this.api.restoreKey(key.id)
+ .pipe(
+ this.toast.observe({
+ loading: 'Stelle wiederher...',
+ success: 'Schlüssel wiederhergestellt',
+ error: 'Es ist ein Fehler aufgetreten'
+ })
+ )
+ .subscribe({
+ next: () => {
+ this.dataChanged = true;
+ this.loadKeys();
+ },
+ error: () => {
+ this.gridApi.setGridOption("loading", false);
+ }
+ });
+ }
+
+}
diff --git a/client/src/app/modules/keys/components/delete-key/delete-key.component.html b/client/src/app/modules/keys/components/delete-key/delete-key.component.html
new file mode 100644
index 0000000..de34798
--- /dev/null
+++ b/client/src/app/modules/keys/components/delete-key/delete-key.component.html
@@ -0,0 +1,9 @@
+Schlüssel {{key.name}} löschen?
+
+ Soll der Schlüssel wirklich gelöscht werden?
+
+
+
+
+
+
\ No newline at end of file
diff --git a/client/src/app/modules/keys/components/delete-key/delete-key.component.scss b/client/src/app/modules/keys/components/delete-key/delete-key.component.scss
new file mode 100644
index 0000000..e69de29
diff --git a/client/src/app/modules/keys/components/delete-key/delete-key.component.spec.ts b/client/src/app/modules/keys/components/delete-key/delete-key.component.spec.ts
new file mode 100644
index 0000000..421d870
--- /dev/null
+++ b/client/src/app/modules/keys/components/delete-key/delete-key.component.spec.ts
@@ -0,0 +1,23 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { DeleteKeyComponent } from './delete-key.component';
+
+describe('DeleteKeyComponent', () => {
+ let component: DeleteKeyComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ imports: [DeleteKeyComponent]
+ })
+ .compileComponents();
+
+ fixture = TestBed.createComponent(DeleteKeyComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/client/src/app/modules/keys/components/delete-key/delete-key.component.ts b/client/src/app/modules/keys/components/delete-key/delete-key.component.ts
new file mode 100644
index 0000000..95af08e
--- /dev/null
+++ b/client/src/app/modules/keys/components/delete-key/delete-key.component.ts
@@ -0,0 +1,17 @@
+import { Component, inject } from '@angular/core';
+import { IKey } from '../../../../model/interface/key.interface';
+import { MatDialogRef, MAT_DIALOG_DATA, MatDialogModule } from '@angular/material/dialog';
+import { MatButtonModule } from '@angular/material/button';
+
+@Component({
+ selector: 'app-delete-key',
+ standalone: true,
+ imports: [MatDialogModule, MatButtonModule],
+ templateUrl: './delete-key.component.html',
+ styleUrl: './delete-key.component.scss'
+})
+export class DeleteKeyComponent {
+ readonly dialogRef = inject(MatDialogRef);
+ readonly key = inject(MAT_DIALOG_DATA);
+
+}
diff --git a/client/src/app/modules/keys/components/handover-dialog/handover-dialog.component.ts b/client/src/app/modules/keys/components/handover-dialog/handover-dialog.component.ts
index dabde7d..5d46749 100644
--- a/client/src/app/modules/keys/components/handover-dialog/handover-dialog.component.ts
+++ b/client/src/app/modules/keys/components/handover-dialog/handover-dialog.component.ts
@@ -51,6 +51,7 @@ export class HandoverDialogComponent {
gridOptions: GridOptions = {
localeText: AG_GRID_LOCALE_DE,
rowData: [],
+ isRowSelectable: () => false,
columnDefs: [
{ colId: 'customer', field: 'customer.name' , headerName: 'Kunde', flex: 1, editable: false, filter: false},
{
diff --git a/client/src/app/modules/keys/create/create.component.html b/client/src/app/modules/keys/create/create.component.html
index 7910add..ddd11f7 100644
--- a/client/src/app/modules/keys/create/create.component.html
+++ b/client/src/app/modules/keys/create/create.component.html
@@ -1,15 +1,21 @@
-Schlüssel anlegen
+Neuen Schlüssel anlegen
diff --git a/client/src/app/modules/keys/create/create.component.scss b/client/src/app/modules/keys/create/create.component.scss
index df8ee7a..1057c49 100644
--- a/client/src/app/modules/keys/create/create.component.scss
+++ b/client/src/app/modules/keys/create/create.component.scss
@@ -1,4 +1,5 @@
form {
display: flex;
flex-direction: column;
+ gap: 12px;
}
\ No newline at end of file
diff --git a/client/src/app/modules/keys/create/create.component.ts b/client/src/app/modules/keys/create/create.component.ts
index a3b3073..cabe021 100644
--- a/client/src/app/modules/keys/create/create.component.ts
+++ b/client/src/app/modules/keys/create/create.component.ts
@@ -1,24 +1,27 @@
import { Component, inject } from '@angular/core';
import { FormControl, FormGroup, FormsModule, ReactiveFormsModule, Validators } from '@angular/forms';
import { MatButtonModule } from '@angular/material/button';
-import { MatDialogModule } from '@angular/material/dialog';
+import { MatDialogModule, MatDialogRef } from '@angular/material/dialog';
import { ApiService } from '../../../shared/api.service';
import { MatAutocompleteModule } from '@angular/material/autocomplete';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatInputModule } from '@angular/material/input';
import { map, Observable, startWith } from 'rxjs';
import { MatSelectModule } from '@angular/material/select';
+import { HotToastService } from '@ngxpert/hot-toast';
@Component({
selector: 'app-create',
standalone: true,
- imports: [MatDialogModule, MatButtonModule, ReactiveFormsModule, FormsModule, MatFormFieldModule, MatInputModule, MatSelectModule],
+ imports: [MatDialogModule, MatButtonModule, ReactiveFormsModule, FormsModule, MatFormFieldModule, MatInputModule, MatSelectModule, MatDialogModule],
templateUrl: './create.component.html',
styleUrl: './create.component.scss'
})
export class CreateKeyComponent {
private api: ApiService = inject(ApiService);
+ private toast: HotToastService = inject(HotToastService);
+ readonly dialogRef = inject(MatDialogRef);
createForm = new FormGroup({
name: new FormControl(null, Validators.required),
@@ -54,7 +57,19 @@ export class CreateKeyComponent {
}
save() {
- console.log(this.createForm.value)
this.api.createKey(this.createForm.value as any)
+ .pipe(
+ this.toast.observe({
+ error: 'Konnte nicht angelegt werden...',
+ loading: 'Speichern...',
+ success: 'Gespeichert'
+ })
+ )
+ .subscribe({
+ next: key => {
+ this.createForm.reset();
+ this.dialogRef.close(key);
+ }
+ })
}
}
diff --git a/client/src/app/modules/keys/keys.component.html b/client/src/app/modules/keys/keys.component.html
index a53fd3b..6bcc26b 100644
--- a/client/src/app/modules/keys/keys.component.html
+++ b/client/src/app/modules/keys/keys.component.html
@@ -1,9 +1,10 @@
-@if (gridOptions || true) {
-
-}
+
-
\ No newline at end of file
+
+
+
+
diff --git a/client/src/app/modules/keys/keys.component.scss b/client/src/app/modules/keys/keys.component.scss
index 1472c97..495a9a3 100644
--- a/client/src/app/modules/keys/keys.component.scss
+++ b/client/src/app/modules/keys/keys.component.scss
@@ -1,5 +1,7 @@
-.btn-create {
+.floating-btn-container {
position: absolute;
bottom: 12px;
right: 12px;
+ display: flex;
+ gap: 12px;
}
\ No newline at end of file
diff --git a/client/src/app/modules/keys/keys.component.ts b/client/src/app/modules/keys/keys.component.ts
index f650a6e..80f3fff 100644
--- a/client/src/app/modules/keys/keys.component.ts
+++ b/client/src/app/modules/keys/keys.component.ts
@@ -10,11 +10,15 @@ 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';
+import { AgLoadingComponent } from '../../shared/ag-grid/components/ag-loading/ag-loading.component';
@Component({
selector: 'app-keys',
standalone: true,
- imports: [AgGridAngular, MatButtonModule, MatDialogModule],
+ imports: [AgGridAngular, MatButtonModule, MatDialogModule, MatIconModule],
providers: [DatePipe],
templateUrl: './keys.component.html',
styleUrl: './keys.component.scss'
@@ -70,9 +74,24 @@ export class KeysComponent {
, 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'
+ , width: 120
+ , cellRenderer: AgDeleteKeyComponent
+ // , onCellClicked: (event) => { this.deleteKey(event.data.id)}
+ }
],
loading: true,
rowHeight: 36,
+ loadingOverlayComponent: AgLoadingComponent
+ }
+
+ deleteKey(id: string) {
+ this.api.deleteKey(id).subscribe({
+ next: n => console.log(n)
+ })
}
ngOnInit(): void {
@@ -118,6 +137,31 @@ export class KeysComponent {
}
openCreateKey() {
- this.dialog.open(CreateKeyComponent)
+ this.dialog.open(CreateKeyComponent).afterClosed().subscribe({
+ next: key => {
+ if (key) {
+ let d = [...this.gridApi.getGridOption("rowData") || [], key];
+ this.gridApi.setGridOption("rowData", d);
+ this.loadKeys();
+ }
+ }
+ })
+ }
+
+ openArchive() {
+ this.dialog.open(ArchiveComponent, {
+ maxHeight: "calc(100vh - 24px)",
+ maxWidth: "calc(100vw - 24px)",
+ width: "50vw",
+ minWidth: "300px",
+ height: "70vh",
+ disableClose: true
+ }).afterClosed().subscribe({
+ next: changed => {
+ if (changed) {
+ this.loadKeys();
+ }
+ }
+ })
}
}
diff --git a/client/src/app/shared/ag-grid/components/ag-delete-key/ag-delete-key.component.html b/client/src/app/shared/ag-grid/components/ag-delete-key/ag-delete-key.component.html
new file mode 100644
index 0000000..322d90b
--- /dev/null
+++ b/client/src/app/shared/ag-grid/components/ag-delete-key/ag-delete-key.component.html
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/client/src/app/shared/ag-grid/components/ag-delete-key/ag-delete-key.component.scss b/client/src/app/shared/ag-grid/components/ag-delete-key/ag-delete-key.component.scss
new file mode 100644
index 0000000..9584b42
--- /dev/null
+++ b/client/src/app/shared/ag-grid/components/ag-delete-key/ag-delete-key.component.scss
@@ -0,0 +1,8 @@
+:host {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ width: 100%;
+ height: 100%;
+}
\ No newline at end of file
diff --git a/client/src/app/shared/ag-grid/components/ag-delete-key/ag-delete-key.component.spec.ts b/client/src/app/shared/ag-grid/components/ag-delete-key/ag-delete-key.component.spec.ts
new file mode 100644
index 0000000..66a7904
--- /dev/null
+++ b/client/src/app/shared/ag-grid/components/ag-delete-key/ag-delete-key.component.spec.ts
@@ -0,0 +1,23 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { AgDeleteKeyComponent } from './ag-delete-key.component';
+
+describe('AgDeleteKeyComponent', () => {
+ let component: AgDeleteKeyComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ imports: [AgDeleteKeyComponent]
+ })
+ .compileComponents();
+
+ fixture = TestBed.createComponent(AgDeleteKeyComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/client/src/app/shared/ag-grid/components/ag-delete-key/ag-delete-key.component.ts b/client/src/app/shared/ag-grid/components/ag-delete-key/ag-delete-key.component.ts
new file mode 100644
index 0000000..5472e8e
--- /dev/null
+++ b/client/src/app/shared/ag-grid/components/ag-delete-key/ag-delete-key.component.ts
@@ -0,0 +1,69 @@
+import { Component, inject } from '@angular/core';
+import { ICellRendererAngularComp } from 'ag-grid-angular';
+import { ICellRendererParams } from 'ag-grid-community';
+import { IKey } from '../../../../model/interface/key.interface';
+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';
+
+@Component({
+ selector: 'app-ag-delete-key',
+ standalone: true,
+ imports: [MatDialogModule],
+ templateUrl: './ag-delete-key.component.html',
+ styleUrl: './ag-delete-key.component.scss'
+})
+export class AgDeleteKeyComponent implements ICellRendererAngularComp {
+ key!: IKey;
+ params!: ICellRendererParams;
+
+ private api: ApiService = inject(ApiService);
+ private dialog: MatDialog = inject(MatDialog);
+ private toast = inject(HotToastService);
+
+ agInit(params: ICellRendererParams): void {
+ this.params = params;
+ this.key = params.data;
+ }
+ refresh(params: ICellRendererParams): boolean {
+ return false;
+ }
+
+ delete() {
+ const ref = this.dialog.open(DeleteKeyComponent, {
+ data: this.key,
+ autoFocus: false
+ })
+
+ ref.afterClosed().subscribe({
+ next: n => {
+ if (n) {
+ this.deleteThisKey();
+ }
+ }
+ })
+ }
+
+ deleteThisKey() {
+ this.params.api.setGridOption("loading", true);
+ this.api.deleteKey(this.key.id).pipe(
+ this.toast.observe({
+ loading: 'Lösche Schlüssel ' + this.key.name,
+ success: 'Schlüssel ' + this.key.name + ' gelöscht',
+ error: 'Konnte nicht gelöscht werden'
+ })
+ ).subscribe({
+ next: () => {
+ let data = this.params.api.getGridOption("rowData");
+ data = data?.filter(d => d.id != this.key.id);
+ this.params.api.setGridOption("rowData", data);
+ this.params.api.setGridOption("loading", false);
+ },
+ error: () => {
+ this.params.api.setGridOption("loading", false);
+ }
+ })
+
+ }
+}
diff --git a/client/src/app/shared/ag-grid/components/ag-loading/ag-loading.component.html b/client/src/app/shared/ag-grid/components/ag-loading/ag-loading.component.html
new file mode 100644
index 0000000..7ba13e9
--- /dev/null
+++ b/client/src/app/shared/ag-grid/components/ag-loading/ag-loading.component.html
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/client/src/app/shared/ag-grid/components/ag-loading/ag-loading.component.scss b/client/src/app/shared/ag-grid/components/ag-loading/ag-loading.component.scss
new file mode 100644
index 0000000..e69de29
diff --git a/client/src/app/shared/ag-grid/components/ag-loading/ag-loading.component.spec.ts b/client/src/app/shared/ag-grid/components/ag-loading/ag-loading.component.spec.ts
new file mode 100644
index 0000000..bb05d19
--- /dev/null
+++ b/client/src/app/shared/ag-grid/components/ag-loading/ag-loading.component.spec.ts
@@ -0,0 +1,23 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { AgLoadingComponent } from './ag-loading.component';
+
+describe('AgLoadingComponent', () => {
+ let component: AgLoadingComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ imports: [AgLoadingComponent]
+ })
+ .compileComponents();
+
+ fixture = TestBed.createComponent(AgLoadingComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/client/src/app/shared/ag-grid/components/ag-loading/ag-loading.component.ts b/client/src/app/shared/ag-grid/components/ag-loading/ag-loading.component.ts
new file mode 100644
index 0000000..c68916a
--- /dev/null
+++ b/client/src/app/shared/ag-grid/components/ag-loading/ag-loading.component.ts
@@ -0,0 +1,21 @@
+import { Component } from '@angular/core';
+import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
+import { ILoadingOverlayAngularComp } from 'ag-grid-angular';
+import { ILoadingOverlayParams } from 'ag-grid-community';
+
+@Component({
+ selector: 'app-ag-loading',
+ standalone: true,
+ imports: [MatProgressSpinnerModule],
+ templateUrl: './ag-loading.component.html',
+ styleUrl: './ag-loading.component.scss'
+})
+export class AgLoadingComponent implements ILoadingOverlayAngularComp {
+ agInit(params: ILoadingOverlayParams): void {
+
+ }
+ refresh?(params: ILoadingOverlayParams): void {
+
+ }
+
+}
diff --git a/client/src/app/shared/api.service.ts b/client/src/app/shared/api.service.ts
index a506d72..312a9b6 100644
--- a/client/src/app/shared/api.service.ts
+++ b/client/src/app/shared/api.service.ts
@@ -38,6 +38,7 @@ export class ApiService {
}
createKey(key: any) {
+ return this.http.post('api/key', key);
}
postKeySystem(keySystem: any) {
@@ -60,4 +61,15 @@ export class ApiService {
return this.http.get('api/customer')
}
+ deleteKey(id: string) {
+ return this.http.delete(`api/key/${id}`);
+ }
+
+ getKeyArchive(): Observable {
+ return this.http.get('api/key/archive');
+ }
+
+ restoreKey(id: string) {
+ return this.http.put(`api/key/${id}/restore`, null);
+ }
}
diff --git a/client/src/app/shared/helper.service.ts b/client/src/app/shared/helper.service.ts
new file mode 100644
index 0000000..0e8b2a9
--- /dev/null
+++ b/client/src/app/shared/helper.service.ts
@@ -0,0 +1,16 @@
+import { AG_GRID_LOCALE_DE } from "@ag-grid-community/locale";
+import { GridOptions } from "ag-grid-community";
+import { AgLoadingComponent } from "./ag-grid/components/ag-loading/ag-loading.component";
+
+export class HELPER {
+
+ static getGridOptions(): GridOptions {
+ return {
+ localeText: AG_GRID_LOCALE_DE,
+ rowData: [],
+ columnDefs: [],
+ loading: true,
+ loadingOverlayComponent: AgLoadingComponent
+ }
+ }
+}
\ No newline at end of file
diff --git a/client/src/assets/img/delete.svg b/client/src/assets/img/delete.svg
new file mode 100644
index 0000000..31daf21
--- /dev/null
+++ b/client/src/assets/img/delete.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/client/src/assets/img/inbox.svg b/client/src/assets/img/inbox.svg
new file mode 100644
index 0000000..10263c2
--- /dev/null
+++ b/client/src/assets/img/inbox.svg
@@ -0,0 +1,60 @@
+
+
+
diff --git a/client/src/assets/img/restore.svg b/client/src/assets/img/restore.svg
new file mode 100644
index 0000000..1cdea84
--- /dev/null
+++ b/client/src/assets/img/restore.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/client/src/styles.scss b/client/src/styles.scss
index 0254bb8..ebd7531 100644
--- a/client/src/styles.scss
+++ b/client/src/styles.scss
@@ -51,6 +51,13 @@ html, body {
justify-content: center;
}
+.delete {
+ background-image: url("./assets/img/delete.svg");
+}
+
+.restore {
+ background-image: url("./assets/img/restore.svg");
+}
/* Core Data Grid CSS */
@import "ag-grid-community/styles/ag-grid.css";