diff --git a/api/src/app.module.ts b/api/src/app.module.ts index 5d1579e..a9622d5 100644 --- a/api/src/app.module.ts +++ b/api/src/app.module.ts @@ -7,6 +7,7 @@ import { AuthModule } from './modules/auth/auth.module'; import { AuthGuard } from './core/guards/auth.guard'; import { UserModule } from './modules/user/user.module'; import { RoleModule } from './modules/role/role.module'; +import { KeyModule } from './modules/key/key.module'; @Module({ imports: [ @@ -18,6 +19,7 @@ import { RoleModule } from './modules/role/role.module'; AuthModule, UserModule, RoleModule, + KeyModule, ], controllers: [AppController], providers: [AppService, AuthGuard], diff --git a/api/src/model/dto/create-key-system.dto.ts b/api/src/model/dto/create-key-system.dto.ts new file mode 100644 index 0000000..bb6afd6 --- /dev/null +++ b/api/src/model/dto/create-key-system.dto.ts @@ -0,0 +1,8 @@ +import { IsNotEmpty, MaxLength, MinLength } from 'class-validator'; + +export class CreateKeySystemDto { + @IsNotEmpty() + @MinLength(2) + @MaxLength(255) + name: string; +} diff --git a/api/src/model/dto/index.ts b/api/src/model/dto/index.ts index 0ab5487..3dabed8 100644 --- a/api/src/model/dto/index.ts +++ b/api/src/model/dto/index.ts @@ -1,2 +1,3 @@ export * from './login.dto'; export * from './auth-code.dto'; +export * from './create-key-system.dto'; diff --git a/api/src/model/entitites/cylinder.entity.ts b/api/src/model/entitites/cylinder.entity.ts new file mode 100644 index 0000000..b7881be --- /dev/null +++ b/api/src/model/entitites/cylinder.entity.ts @@ -0,0 +1,32 @@ +import { + Column, + CreateDateColumn, + Entity, + ManyToOne, + OneToMany, + PrimaryGeneratedColumn, + UpdateDateColumn, +} from 'typeorm'; +import { Key } from './key.entity'; +import { KeySystem } from './system.entity'; + +@Entity() +export class Cylinder { + @PrimaryGeneratedColumn('uuid') + id: string; + + @Column({ nullable: false, unique: true }) + name: string; + + @OneToMany(() => Key, (key) => key.cylinder) + keys: Key[]; + + @ManyToOne(() => KeySystem, (sys) => sys.cylinders) + system: KeySystem; + + @CreateDateColumn({ name: 'created_at' }) + createdAt: Date; + + @UpdateDateColumn({ name: 'updatet_at' }) + updatedAt: Date; +} diff --git a/api/src/model/entitites/index.ts b/api/src/model/entitites/index.ts index 6ed37e1..5143349 100644 --- a/api/src/model/entitites/index.ts +++ b/api/src/model/entitites/index.ts @@ -1,3 +1,6 @@ export * from './sso.user.entity'; export * from './user.entity'; export * from './role.entity'; +export * from './cylinder.entity'; +export * from './key.entity'; +export * from './key_activity.entity'; diff --git a/api/src/model/entitites/key.entity.ts b/api/src/model/entitites/key.entity.ts new file mode 100644 index 0000000..0624815 --- /dev/null +++ b/api/src/model/entitites/key.entity.ts @@ -0,0 +1,34 @@ +import { + Column, + CreateDateColumn, + Entity, + ManyToOne, + PrimaryGeneratedColumn, + UpdateDateColumn, +} from 'typeorm'; +import { Cylinder } from './cylinder.entity'; +import { IKey } from '../interface/key.interface'; + +@Entity() +export class Key implements IKey { + @PrimaryGeneratedColumn('uuid') + id: string; + + @Column({ nullable: true }) + name: string; + + @Column({ name: 'key_number', unique: true }) + nr: number; + + @Column({ name: 'handed_out', default: false }) + handedOut: boolean; + + @ManyToOne(() => Cylinder, (cylinder) => cylinder.keys) + cylinder: Cylinder; + + @CreateDateColumn({ name: 'created_at' }) + createdAt: Date; + + @UpdateDateColumn({ name: 'updatet_at' }) + updatedAt: Date; +} diff --git a/api/src/model/entitites/key_activity.entity.ts b/api/src/model/entitites/key_activity.entity.ts new file mode 100644 index 0000000..a179006 --- /dev/null +++ b/api/src/model/entitites/key_activity.entity.ts @@ -0,0 +1,37 @@ +import { + Column, + CreateDateColumn, + Entity, + ManyToOne, + PrimaryGeneratedColumn, +} from 'typeorm'; +import { User } from './user.entity'; +import { IKey } from '../interface/key.interface'; +import { Cylinder } from './cylinder.entity'; + +@Entity() +export class KeyActivity implements IKey { + @PrimaryGeneratedColumn() + primaryId: number; + + @Column() + id: string; + + @Column({ nullable: true }) + name: string; + + @Column({ name: 'key_number' }) + nr: number; + + @Column({ name: 'handed_out', default: false }) + handedOut: boolean; + + @ManyToOne(() => Cylinder) + cylinder: Cylinder; + + @CreateDateColumn({ name: 'created_at' }) + createdAt: Date; + + @ManyToOne(() => User) + user: User; +} diff --git a/api/src/model/entitites/system.entity.ts b/api/src/model/entitites/system.entity.ts new file mode 100644 index 0000000..e5ef465 --- /dev/null +++ b/api/src/model/entitites/system.entity.ts @@ -0,0 +1,35 @@ +import { + Column, + CreateDateColumn, + Entity, + JoinTable, + ManyToMany, + OneToMany, + PrimaryGeneratedColumn, + UpdateDateColumn, +} from 'typeorm'; +import { IKeySystem } from '../interface'; +import { User } from './user.entity'; +import { Cylinder } from './cylinder.entity'; + +@Entity() +export class KeySystem implements IKeySystem { + @PrimaryGeneratedColumn('uuid') + id: string; + + @CreateDateColumn({ name: 'created_at' }) + createdAt: Date; + + @Column({ nullable: false, unique: true }) + name: string; + + @ManyToMany(() => User, (manager) => manager.systems) + @JoinTable() + managers: User[]; + + @OneToMany(() => Cylinder, (cylinder) => cylinder.system) + cylinders: Cylinder[]; + + @UpdateDateColumn({ name: 'updatet_at' }) + updatedAt: Date; +} diff --git a/api/src/model/entitites/user.entity.ts b/api/src/model/entitites/user.entity.ts index c2a3c5a..d7cbc65 100644 --- a/api/src/model/entitites/user.entity.ts +++ b/api/src/model/entitites/user.entity.ts @@ -4,6 +4,7 @@ import { CreateDateColumn, Entity, JoinColumn, + ManyToMany, ManyToOne, OneToOne, PrimaryGeneratedColumn, @@ -12,6 +13,7 @@ import { IUser } from '../interface'; import { SSOUser } from './sso.user.entity'; import { IsEmail } from 'class-validator'; import { Role } from './role.entity'; +import { KeySystem } from './system.entity'; @Entity() export class User implements IUser { @@ -46,6 +48,9 @@ export class User implements IUser { @Transform(({ value }) => value.name) role: Role; + @ManyToMany(() => KeySystem, (system) => system.managers) + systems: KeySystem[]; + accessToken?: string; refreshToken?: string; } diff --git a/api/src/model/interface/authenticated-request.interface.ts b/api/src/model/interface/authenticated-request.interface.ts new file mode 100644 index 0000000..f59c585 --- /dev/null +++ b/api/src/model/interface/authenticated-request.interface.ts @@ -0,0 +1,6 @@ +import { Request } from 'express'; +import { User } from '../entitites'; + +export interface AuthenticatedRequest extends Request { + user: User; +} diff --git a/api/src/model/interface/index.ts b/api/src/model/interface/index.ts index 6912f0d..c6a8758 100644 --- a/api/src/model/interface/index.ts +++ b/api/src/model/interface/index.ts @@ -1,3 +1,4 @@ export * from './user.interface'; export * from './external-access-token.payload.interface'; export * from './payload.interface'; +export * from './key-system.interface'; diff --git a/api/src/model/interface/key-system.interface.ts b/api/src/model/interface/key-system.interface.ts new file mode 100644 index 0000000..9fc0416 --- /dev/null +++ b/api/src/model/interface/key-system.interface.ts @@ -0,0 +1,7 @@ +import { IUser } from './user.interface'; + +export interface IKeySystem { + id: string; + name: string; + managers: IUser[]; +} diff --git a/api/src/model/interface/key.interface.ts b/api/src/model/interface/key.interface.ts new file mode 100644 index 0000000..4e5d830 --- /dev/null +++ b/api/src/model/interface/key.interface.ts @@ -0,0 +1,10 @@ +import { Cylinder } from '../entitites'; + +export interface IKey { + id: string; + name: string; + nr: number; + handedOut: boolean; + cylinder: Cylinder; + createdAt: Date; +} diff --git a/api/src/model/repositories/cylinder.repository.ts b/api/src/model/repositories/cylinder.repository.ts new file mode 100644 index 0000000..30805c8 --- /dev/null +++ b/api/src/model/repositories/cylinder.repository.ts @@ -0,0 +1,10 @@ +import { Injectable } from '@nestjs/common'; +import { Repository, DataSource } from 'typeorm'; +import { Cylinder } from '../entitites'; + +@Injectable() +export class CylinderRepository extends Repository { + constructor(dataSource: DataSource) { + super(Cylinder, dataSource.createEntityManager()); + } +} diff --git a/api/src/model/repositories/index.ts b/api/src/model/repositories/index.ts index ed41468..49cf029 100644 --- a/api/src/model/repositories/index.ts +++ b/api/src/model/repositories/index.ts @@ -1,3 +1,7 @@ export * from './user.repository'; export * from './ssouser.repository'; export * from './role.repository'; +export * from './system.repository'; +export * from './cylinder.repository'; +export * from './key.repository'; +export * from './key_activity.repository'; diff --git a/api/src/model/repositories/key.repository.ts b/api/src/model/repositories/key.repository.ts new file mode 100644 index 0000000..913922c --- /dev/null +++ b/api/src/model/repositories/key.repository.ts @@ -0,0 +1,10 @@ +import { Injectable } from '@nestjs/common'; +import { Repository, DataSource } from 'typeorm'; +import { Key } from '../entitites'; + +@Injectable() +export class KeyRepository extends Repository { + constructor(dataSource: DataSource) { + super(Key, dataSource.createEntityManager()); + } +} diff --git a/api/src/model/repositories/key_activity.repository.ts b/api/src/model/repositories/key_activity.repository.ts new file mode 100644 index 0000000..1e23e4a --- /dev/null +++ b/api/src/model/repositories/key_activity.repository.ts @@ -0,0 +1,10 @@ +import { Injectable } from '@nestjs/common'; +import { Repository, DataSource } from 'typeorm'; +import { KeyActivity } from '../entitites'; + +@Injectable() +export class KeyActivityRepository extends Repository { + constructor(dataSource: DataSource) { + super(KeyActivity, dataSource.createEntityManager()); + } +} diff --git a/api/src/model/repositories/system.repository.ts b/api/src/model/repositories/system.repository.ts new file mode 100644 index 0000000..950ba73 --- /dev/null +++ b/api/src/model/repositories/system.repository.ts @@ -0,0 +1,10 @@ +import { Injectable } from '@nestjs/common'; +import { Repository, DataSource } from 'typeorm'; +import { KeySystem } from '../entitites/system.entity'; + +@Injectable() +export class KeySystemRepository extends Repository { + constructor(dataSource: DataSource) { + super(KeySystem, dataSource.createEntityManager()); + } +} diff --git a/api/src/modules/key/key.controller.ts b/api/src/modules/key/key.controller.ts new file mode 100644 index 0000000..efa6dc9 --- /dev/null +++ b/api/src/modules/key/key.controller.ts @@ -0,0 +1,40 @@ +import { + Body, + Controller, + Get, + Post, + Put, + Req, + UseGuards, +} from '@nestjs/common'; +import { KeyService } from './key.service'; +import { AuthenticatedRequest } from 'src/model/interface/authenticated-request.interface'; +import { AuthGuard } from 'src/core/guards/auth.guard'; +import { Key } from 'src/model/entitites'; +import { CreateKeySystemDto } from 'src/model/dto/create-key-system.dto'; + +@UseGuards(AuthGuard) +@Controller('key') +export class KeyController { + constructor(private service: KeyService) {} + + @Get() + getKeys(@Req() req: AuthenticatedRequest) { + return this.service.getUsersKeys(req.user); + } + + @Put() + updateKey(@Req() req: AuthenticatedRequest, @Body() key: Key) { + return this.service.updateKey(req.user, key); + } + + @Get('cylinder') + getCylinders(@Req() req: AuthenticatedRequest) { + return this.service.getUsersCylinders(req.user); + } + + @Post('system') + createKeySystem(@Req() req: AuthenticatedRequest, @Body() body: CreateKeySystemDto) { + return this.service.createKeySystem(req.user, body); + } +} diff --git a/api/src/modules/key/key.module.ts b/api/src/modules/key/key.module.ts new file mode 100644 index 0000000..17b8783 --- /dev/null +++ b/api/src/modules/key/key.module.ts @@ -0,0 +1,12 @@ +import { Module } from '@nestjs/common'; +import { KeyController } from './key.controller'; +import { KeyService } from './key.service'; +import { DatabaseModule } from 'src/shared/database/database.module'; +import { AuthModule } from '../auth/auth.module'; + +@Module({ + controllers: [KeyController], + providers: [KeyService], + imports: [DatabaseModule, AuthModule], +}) +export class KeyModule {} diff --git a/api/src/modules/key/key.service.ts b/api/src/modules/key/key.service.ts new file mode 100644 index 0000000..c29cf84 --- /dev/null +++ b/api/src/modules/key/key.service.ts @@ -0,0 +1,77 @@ +import { HttpException, HttpStatus, Injectable } from '@nestjs/common'; +import { CreateKeySystemDto } from 'src/model/dto'; +import { Cylinder, Key, User } from 'src/model/entitites'; +import { + CylinderRepository, + KeyActivityRepository, + KeyRepository, + KeySystemRepository, +} from 'src/model/repositories'; + +@Injectable() +export class KeyService { + constructor( + private readonly keyrepository: KeyRepository, + private readonly cylinderRepository: CylinderRepository, + private readonly systemRepo: KeySystemRepository, + private activityRepo: KeyActivityRepository, + ) {} + + async getUsersKeys(user: User): Promise { + return this.keyrepository.find({ + where: { cylinder: { system: { managers: { id: user.id } } } }, + relations: ['cylinder', 'cylinder.system'], + }); + } + + async updateKey(user: User, key: Key) { + if (!user || !user.id) { + throw new HttpException('forbidden', HttpStatus.FORBIDDEN); + } + await this.keyrepository.findOneOrFail({ + where: { cylinder: { system: { managers: { id: user.id } } } }, + }); + + const original = await this.keyrepository.findOne({ + where: { id: key.id }, + relations: ['cylinder'], + }); + this.saveLog(original, user); + return this.keyrepository.save(this.keyrepository.create(key)); + } + + private saveLog(key: Key, user: User) { + const l = this.activityRepo.create({ + cylinder: key.cylinder, + handedOut: key.handedOut, + name: key.name, + id: key.id, + nr: key.nr, + user: user, + }); + this.activityRepo.save(l); + } + + async getUsersCylinders(user: User): Promise { + if (!user || !user.id) { + throw new HttpException('forbidden', HttpStatus.FORBIDDEN); + } + + return this.cylinderRepository.find({ + where: { system: { managers: { id: user.id } } }, + order: { name: { direction: 'ASC' } }, + relations: ['system'], + }); + } + + async createKeySystem(user: User, systemDTO: CreateKeySystemDto) { + const sys = this.systemRepo.create(systemDTO); + sys.managers = [user]; + try { + const res = await this.systemRepo.save(sys); + return res; + } catch (e) { + throw new HttpException(e.code, HttpStatus.UNPROCESSABLE_ENTITY); + } + } +} diff --git a/api/src/shared/database/database.module.ts b/api/src/shared/database/database.module.ts index dbcafd7..cfc723e 100644 --- a/api/src/shared/database/database.module.ts +++ b/api/src/shared/database/database.module.ts @@ -1,10 +1,27 @@ import { Module } from '@nestjs/common'; import { TypeOrmModule } from '@nestjs/typeorm'; -import { Role, SSOUser, User } from 'src/model/entitites'; -import { RoleRepository, SsoUserRepository, UserRepository } from 'src/model/repositories'; +import { Cylinder, Key, KeyActivity, Role, SSOUser, User } from 'src/model/entitites'; +import { KeySystem } from 'src/model/entitites/system.entity'; +import { + CylinderRepository, + KeyActivityRepository, + KeyRepository, + KeySystemRepository, + RoleRepository, + SsoUserRepository, + UserRepository, +} from 'src/model/repositories'; -const ENTITIES = [User, SSOUser, Role]; -const REPOSITORIES = [UserRepository, SsoUserRepository, RoleRepository]; +const ENTITIES = [User, SSOUser, Role, KeySystem, Key, Cylinder, KeyActivity]; +const REPOSITORIES = [ + UserRepository, + SsoUserRepository, + RoleRepository, + KeySystemRepository, + KeyRepository, + CylinderRepository, + KeyActivityRepository, +]; @Module({ imports: [ diff --git a/client/src/app/app.routes.ts b/client/src/app/app.routes.ts index be19801..6ff15c0 100644 --- a/client/src/app/app.routes.ts +++ b/client/src/app/app.routes.ts @@ -6,11 +6,13 @@ import { LoginComponent } from './modules/auth/login/login.component'; import { LayoutComponent } from './core/layout/layout.component'; import { DashboardComponent } from './modules/dashboard/dashboard.component'; import { AllUsersComponent } from './modules/admin/all-users/all-users.component'; +import { KeysComponent } from './modules/keys/keys.component'; export const routes: Routes = [ { path: '', component: LayoutComponent, canActivate: [AuthenticatedGuard], children: [ { path: '', component: DashboardComponent }, - { path: 'users', component: AllUsersComponent } + { path: 'users', component: AllUsersComponent }, + { path: 'keys', component: KeysComponent } ]}, { path: 'login', component: LoginComponent}, ]; diff --git a/client/src/app/core/auth/auth.service.ts b/client/src/app/core/auth/auth.service.ts index cf87c03..1c0ac69 100644 --- a/client/src/app/core/auth/auth.service.ts +++ b/client/src/app/core/auth/auth.service.ts @@ -32,7 +32,6 @@ export class AuthService { } get isAdmin(): boolean { - console.log(this.user, this.user.role == 'admin') return this.user != null && this.user.role == 'admin'; } diff --git a/client/src/app/core/layout/layout.component.html b/client/src/app/core/layout/layout.component.html index 092edc1..b35f6c3 100644 --- a/client/src/app/core/layout/layout.component.html +++ b/client/src/app/core/layout/layout.component.html @@ -13,6 +13,7 @@ + diff --git a/client/src/app/model/interface/key.interface.ts b/client/src/app/model/interface/key.interface.ts new file mode 100644 index 0000000..ad9dae6 --- /dev/null +++ b/client/src/app/model/interface/key.interface.ts @@ -0,0 +1,9 @@ +export interface IKey { + id: string; + name: string; + createdAt: string; + updatedAt: string; + handedOut: boolean; + cylinder: any; + nr: number; +} \ No newline at end of file diff --git a/client/src/app/modules/admin/all-users/all-users.component.ts b/client/src/app/modules/admin/all-users/all-users.component.ts index d90de35..5a7a8ca 100644 --- a/client/src/app/modules/admin/all-users/all-users.component.ts +++ b/client/src/app/modules/admin/all-users/all-users.component.ts @@ -48,7 +48,7 @@ export class AllUsersComponent { , cellRenderer: (data: any) => this.datePipe.transform(new Date(data.value)) , tooltipValueGetter: (data: any) => this.datePipe.transform(new Date(data.value), 'medium') }, - { + { field: 'lastLogin' , headerName: 'Letzter Login' , width: 170 @@ -61,6 +61,7 @@ export class AllUsersComponent { } ngOnInit(): void { + } @@ -69,6 +70,7 @@ export class AllUsersComponent { next: n => { this.gridApi.setGridOption("rowData", n) this.gridApi.setGridOption("loading", false); + n.filter(u => u.username == 'mail@bastian-wagner.de').map((u: any) => { console.log(u['lastLogin'])}) } }) } diff --git a/client/src/app/modules/keys/keys.component.html b/client/src/app/modules/keys/keys.component.html new file mode 100644 index 0000000..e87e1ba --- /dev/null +++ b/client/src/app/modules/keys/keys.component.html @@ -0,0 +1,7 @@ +@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 new file mode 100644 index 0000000..e69de29 diff --git a/client/src/app/modules/keys/keys.component.spec.ts b/client/src/app/modules/keys/keys.component.spec.ts new file mode 100644 index 0000000..b7938ed --- /dev/null +++ b/client/src/app/modules/keys/keys.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { KeysComponent } from './keys.component'; + +describe('KeysComponent', () => { + let component: KeysComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [KeysComponent] + }) + .compileComponents(); + + fixture = TestBed.createComponent(KeysComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/client/src/app/modules/keys/keys.component.ts b/client/src/app/modules/keys/keys.component.ts new file mode 100644 index 0000000..70e0739 --- /dev/null +++ b/client/src/app/modules/keys/keys.component.ts @@ -0,0 +1,112 @@ +import { Component, inject } from '@angular/core'; +import { AG_GRID_LOCALE_DE } from '@ag-grid-community/locale'; +import { AgGridAngular } from 'ag-grid-angular'; +import { GridOptions,GridApi, GridReadyEvent, CellEditingStoppedEvent, ICellEditorParams } from 'ag-grid-community'; +import { CommonModule, DatePipe } from '@angular/common'; +import { ApiService } from '../../shared/api.service'; +import { IKey } from '../../model/interface/key.interface'; +import { HotToastService } from '@ngxpert/hot-toast'; + +@Component({ + selector: 'app-keys', + standalone: true, + imports: [AgGridAngular], + providers: [DatePipe], + templateUrl: './keys.component.html', + styleUrl: './keys.component.scss' +}) +export class KeysComponent { + private api: ApiService = inject(ApiService); + private datePipe = inject(DatePipe); + private toast: HotToastService = inject(HotToastService); + + cylinders: any[] = [{name: 'dummy'}]; + + gridApi!: GridApi; + + gridOptions: GridOptions = { + localeText: AG_GRID_LOCALE_DE, + rowData: [], + columnDefs: [ + { field: 'handedOut' , headerName: 'Ausgegeben', width: 100,editable: true, filter: true, headerTooltip: 'Ausgegeben' }, + { field: 'name' , headerName: 'Name', flex: 1, editable: true, sort: 'asc', filter: true }, + { field: 'nr' , headerName: 'Schlüsselnummer', flex: 1, editable: true, filter: true }, + { field: 'cylinder' , headerName: 'Zylinder', flex: 1, editable: true, filter: true, cellRenderer: (data: any) => {return data.value?.name}, cellEditor: 'agSelectCellEditor', + cellEditorParams: () => { + return { + values: this.cylinders, + } + }, + valueFormatter: (val) => { + return val.value?.name; + } + }, + { field: 'cylinder.system' , headerName: 'Schließanlage', flex: 1, editable: false, filter: true, cellRenderer: (data: any) => {return data.value?.name} }, + { + field: 'createdAt' + , headerName: 'Erstellt' + , width: 120 + , type: 'date' + , cellRenderer: (data: any) => this.datePipe.transform(new Date(data.value)) + , tooltipValueGetter: (data: any) => this.datePipe.transform(new Date(data.value), 'medium') + },{ + field: 'updatedAt' + , headerName: 'Geändert' + , width: 120 + , type: 'date' + , cellRenderer: (data: any) => data.value ? this.datePipe.transform(new Date(data.value), 'medium') : '-' + , tooltipValueGetter: (data: any) => this.datePipe.transform(new Date(data.value), 'medium') + }, + ], + loading: true, + } + + ngOnInit(): void { + this.api.getCylinders().subscribe({ + next: n => { + this.cylinders = n; + } + }) + this.api.postKeySystem({ name: 'Development' }).subscribe() + } + + loadKeys() { + this.gridApi.setGridOption("loading", true); + this.api.getKeys().subscribe(res => { + this.gridApi.setGridOption("rowData", res); + this.gridApi.setGridOption("loading", false); + res.map((r: any) => console.log(r.updatedAt)) + }) + } + + onGridReady(params: GridReadyEvent) { + this.gridApi = params.api; + this.gridApi.addEventListener("cellEditingStopped", evt => this.cellEditEnd(evt)) + this.loadKeys(); + } + + cellEditEnd(event: CellEditingStoppedEvent) { + const key: IKey = event.data; + console.log(event) + + if (!event.valueChanged || event.newValue == event.oldValue) { return; } + + this.gridApi.setGridOption("loading", true); + this.api.updateKey(key) + .pipe( + this.toast.observe({ + loading: 'speichern...', + success: 'Änderungen gespeichert', + error: 'Änderungen konnten nicht gespeichert werden!' + }) + ).subscribe({ + next: () => { + + this.gridApi.setGridOption("loading", false); + }, + error: () => { + this.loadKeys(); + } + }) + } +} diff --git a/client/src/app/shared/api.service.ts b/client/src/app/shared/api.service.ts index 4e2097c..f512457 100644 --- a/client/src/app/shared/api.service.ts +++ b/client/src/app/shared/api.service.ts @@ -2,6 +2,7 @@ import { HttpClient } from '@angular/common/http'; import { inject, Injectable } from '@angular/core'; import { Observable } from 'rxjs'; import { IUser } from '../model/interface/user.interface'; +import { IKey } from '../model/interface/key.interface'; @Injectable({ providedIn: 'root' @@ -23,4 +24,22 @@ export class ApiService { getRoles(): Observable<{id: string, name: string}[]> { return this.http.get<{id: string, name: string}[]>('/api/role'); } + + getKeys(): Observable { + return this.http.get('api/key') + } + + updateKey(key: IKey): Observable { + return this.http.put('api/key', key); + } + + getCylinders(): Observable { + return this.http.get('api/key/cylinder'); + } + + postKey(key: IKey) {} + + postKeySystem(keySystem: any) { + return this.http.post('api/key/system', keySystem); + } }