keys
This commit is contained in:
@@ -7,6 +7,7 @@ import { AuthModule } from './modules/auth/auth.module';
|
|||||||
import { AuthGuard } from './core/guards/auth.guard';
|
import { AuthGuard } from './core/guards/auth.guard';
|
||||||
import { UserModule } from './modules/user/user.module';
|
import { UserModule } from './modules/user/user.module';
|
||||||
import { RoleModule } from './modules/role/role.module';
|
import { RoleModule } from './modules/role/role.module';
|
||||||
|
import { KeyModule } from './modules/key/key.module';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [
|
imports: [
|
||||||
@@ -18,6 +19,7 @@ import { RoleModule } from './modules/role/role.module';
|
|||||||
AuthModule,
|
AuthModule,
|
||||||
UserModule,
|
UserModule,
|
||||||
RoleModule,
|
RoleModule,
|
||||||
|
KeyModule,
|
||||||
],
|
],
|
||||||
controllers: [AppController],
|
controllers: [AppController],
|
||||||
providers: [AppService, AuthGuard],
|
providers: [AppService, AuthGuard],
|
||||||
|
|||||||
8
api/src/model/dto/create-key-system.dto.ts
Normal file
8
api/src/model/dto/create-key-system.dto.ts
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
import { IsNotEmpty, MaxLength, MinLength } from 'class-validator';
|
||||||
|
|
||||||
|
export class CreateKeySystemDto {
|
||||||
|
@IsNotEmpty()
|
||||||
|
@MinLength(2)
|
||||||
|
@MaxLength(255)
|
||||||
|
name: string;
|
||||||
|
}
|
||||||
@@ -1,2 +1,3 @@
|
|||||||
export * from './login.dto';
|
export * from './login.dto';
|
||||||
export * from './auth-code.dto';
|
export * from './auth-code.dto';
|
||||||
|
export * from './create-key-system.dto';
|
||||||
|
|||||||
32
api/src/model/entitites/cylinder.entity.ts
Normal file
32
api/src/model/entitites/cylinder.entity.ts
Normal file
@@ -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;
|
||||||
|
}
|
||||||
@@ -1,3 +1,6 @@
|
|||||||
export * from './sso.user.entity';
|
export * from './sso.user.entity';
|
||||||
export * from './user.entity';
|
export * from './user.entity';
|
||||||
export * from './role.entity';
|
export * from './role.entity';
|
||||||
|
export * from './cylinder.entity';
|
||||||
|
export * from './key.entity';
|
||||||
|
export * from './key_activity.entity';
|
||||||
|
|||||||
34
api/src/model/entitites/key.entity.ts
Normal file
34
api/src/model/entitites/key.entity.ts
Normal file
@@ -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;
|
||||||
|
}
|
||||||
37
api/src/model/entitites/key_activity.entity.ts
Normal file
37
api/src/model/entitites/key_activity.entity.ts
Normal file
@@ -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;
|
||||||
|
}
|
||||||
35
api/src/model/entitites/system.entity.ts
Normal file
35
api/src/model/entitites/system.entity.ts
Normal file
@@ -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;
|
||||||
|
}
|
||||||
@@ -4,6 +4,7 @@ import {
|
|||||||
CreateDateColumn,
|
CreateDateColumn,
|
||||||
Entity,
|
Entity,
|
||||||
JoinColumn,
|
JoinColumn,
|
||||||
|
ManyToMany,
|
||||||
ManyToOne,
|
ManyToOne,
|
||||||
OneToOne,
|
OneToOne,
|
||||||
PrimaryGeneratedColumn,
|
PrimaryGeneratedColumn,
|
||||||
@@ -12,6 +13,7 @@ import { IUser } from '../interface';
|
|||||||
import { SSOUser } from './sso.user.entity';
|
import { SSOUser } from './sso.user.entity';
|
||||||
import { IsEmail } from 'class-validator';
|
import { IsEmail } from 'class-validator';
|
||||||
import { Role } from './role.entity';
|
import { Role } from './role.entity';
|
||||||
|
import { KeySystem } from './system.entity';
|
||||||
|
|
||||||
@Entity()
|
@Entity()
|
||||||
export class User implements IUser {
|
export class User implements IUser {
|
||||||
@@ -46,6 +48,9 @@ export class User implements IUser {
|
|||||||
@Transform(({ value }) => value.name)
|
@Transform(({ value }) => value.name)
|
||||||
role: Role;
|
role: Role;
|
||||||
|
|
||||||
|
@ManyToMany(() => KeySystem, (system) => system.managers)
|
||||||
|
systems: KeySystem[];
|
||||||
|
|
||||||
accessToken?: string;
|
accessToken?: string;
|
||||||
refreshToken?: string;
|
refreshToken?: string;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
import { Request } from 'express';
|
||||||
|
import { User } from '../entitites';
|
||||||
|
|
||||||
|
export interface AuthenticatedRequest extends Request {
|
||||||
|
user: User;
|
||||||
|
}
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
export * from './user.interface';
|
export * from './user.interface';
|
||||||
export * from './external-access-token.payload.interface';
|
export * from './external-access-token.payload.interface';
|
||||||
export * from './payload.interface';
|
export * from './payload.interface';
|
||||||
|
export * from './key-system.interface';
|
||||||
|
|||||||
7
api/src/model/interface/key-system.interface.ts
Normal file
7
api/src/model/interface/key-system.interface.ts
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
import { IUser } from './user.interface';
|
||||||
|
|
||||||
|
export interface IKeySystem {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
managers: IUser[];
|
||||||
|
}
|
||||||
10
api/src/model/interface/key.interface.ts
Normal file
10
api/src/model/interface/key.interface.ts
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
import { Cylinder } from '../entitites';
|
||||||
|
|
||||||
|
export interface IKey {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
nr: number;
|
||||||
|
handedOut: boolean;
|
||||||
|
cylinder: Cylinder;
|
||||||
|
createdAt: Date;
|
||||||
|
}
|
||||||
10
api/src/model/repositories/cylinder.repository.ts
Normal file
10
api/src/model/repositories/cylinder.repository.ts
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
import { Injectable } from '@nestjs/common';
|
||||||
|
import { Repository, DataSource } from 'typeorm';
|
||||||
|
import { Cylinder } from '../entitites';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class CylinderRepository extends Repository<Cylinder> {
|
||||||
|
constructor(dataSource: DataSource) {
|
||||||
|
super(Cylinder, dataSource.createEntityManager());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,3 +1,7 @@
|
|||||||
export * from './user.repository';
|
export * from './user.repository';
|
||||||
export * from './ssouser.repository';
|
export * from './ssouser.repository';
|
||||||
export * from './role.repository';
|
export * from './role.repository';
|
||||||
|
export * from './system.repository';
|
||||||
|
export * from './cylinder.repository';
|
||||||
|
export * from './key.repository';
|
||||||
|
export * from './key_activity.repository';
|
||||||
|
|||||||
10
api/src/model/repositories/key.repository.ts
Normal file
10
api/src/model/repositories/key.repository.ts
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
import { Injectable } from '@nestjs/common';
|
||||||
|
import { Repository, DataSource } from 'typeorm';
|
||||||
|
import { Key } from '../entitites';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class KeyRepository extends Repository<Key> {
|
||||||
|
constructor(dataSource: DataSource) {
|
||||||
|
super(Key, dataSource.createEntityManager());
|
||||||
|
}
|
||||||
|
}
|
||||||
10
api/src/model/repositories/key_activity.repository.ts
Normal file
10
api/src/model/repositories/key_activity.repository.ts
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
import { Injectable } from '@nestjs/common';
|
||||||
|
import { Repository, DataSource } from 'typeorm';
|
||||||
|
import { KeyActivity } from '../entitites';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class KeyActivityRepository extends Repository<KeyActivity> {
|
||||||
|
constructor(dataSource: DataSource) {
|
||||||
|
super(KeyActivity, dataSource.createEntityManager());
|
||||||
|
}
|
||||||
|
}
|
||||||
10
api/src/model/repositories/system.repository.ts
Normal file
10
api/src/model/repositories/system.repository.ts
Normal file
@@ -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<KeySystem> {
|
||||||
|
constructor(dataSource: DataSource) {
|
||||||
|
super(KeySystem, dataSource.createEntityManager());
|
||||||
|
}
|
||||||
|
}
|
||||||
40
api/src/modules/key/key.controller.ts
Normal file
40
api/src/modules/key/key.controller.ts
Normal file
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
12
api/src/modules/key/key.module.ts
Normal file
12
api/src/modules/key/key.module.ts
Normal file
@@ -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 {}
|
||||||
77
api/src/modules/key/key.service.ts
Normal file
77
api/src/modules/key/key.service.ts
Normal file
@@ -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<Key[]> {
|
||||||
|
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<Cylinder[]> {
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,10 +1,27 @@
|
|||||||
import { Module } from '@nestjs/common';
|
import { Module } from '@nestjs/common';
|
||||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||||
import { Role, SSOUser, User } from 'src/model/entitites';
|
import { Cylinder, Key, KeyActivity, Role, SSOUser, User } from 'src/model/entitites';
|
||||||
import { RoleRepository, SsoUserRepository, UserRepository } from 'src/model/repositories';
|
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 ENTITIES = [User, SSOUser, Role, KeySystem, Key, Cylinder, KeyActivity];
|
||||||
const REPOSITORIES = [UserRepository, SsoUserRepository, RoleRepository];
|
const REPOSITORIES = [
|
||||||
|
UserRepository,
|
||||||
|
SsoUserRepository,
|
||||||
|
RoleRepository,
|
||||||
|
KeySystemRepository,
|
||||||
|
KeyRepository,
|
||||||
|
CylinderRepository,
|
||||||
|
KeyActivityRepository,
|
||||||
|
];
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [
|
imports: [
|
||||||
|
|||||||
@@ -6,11 +6,13 @@ import { LoginComponent } from './modules/auth/login/login.component';
|
|||||||
import { LayoutComponent } from './core/layout/layout.component';
|
import { LayoutComponent } from './core/layout/layout.component';
|
||||||
import { DashboardComponent } from './modules/dashboard/dashboard.component';
|
import { DashboardComponent } from './modules/dashboard/dashboard.component';
|
||||||
import { AllUsersComponent } from './modules/admin/all-users/all-users.component';
|
import { AllUsersComponent } from './modules/admin/all-users/all-users.component';
|
||||||
|
import { KeysComponent } from './modules/keys/keys.component';
|
||||||
|
|
||||||
export const routes: Routes = [
|
export const routes: Routes = [
|
||||||
{ path: '', component: LayoutComponent, canActivate: [AuthenticatedGuard], children: [
|
{ path: '', component: LayoutComponent, canActivate: [AuthenticatedGuard], children: [
|
||||||
{ path: '', component: DashboardComponent },
|
{ path: '', component: DashboardComponent },
|
||||||
{ path: 'users', component: AllUsersComponent }
|
{ path: 'users', component: AllUsersComponent },
|
||||||
|
{ path: 'keys', component: KeysComponent }
|
||||||
]},
|
]},
|
||||||
{ path: 'login', component: LoginComponent},
|
{ path: 'login', component: LoginComponent},
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -32,7 +32,6 @@ export class AuthService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
get isAdmin(): boolean {
|
get isAdmin(): boolean {
|
||||||
console.log(this.user, this.user.role == 'admin')
|
|
||||||
return this.user != null && this.user.role == 'admin';
|
return this.user != null && this.user.role == 'admin';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
<mat-drawer-container class="example-container" autosize>
|
<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">
|
||||||
<button mat-button routerLink="/">Home</button>
|
<button mat-button routerLink="/">Home</button>
|
||||||
|
<button mat-button routerLink="/keys">Schlüssel</button>
|
||||||
<button mat-button routerLink="/users">Alle User</button>
|
<button mat-button routerLink="/users">Alle User</button>
|
||||||
</mat-drawer>
|
</mat-drawer>
|
||||||
|
|
||||||
|
|||||||
9
client/src/app/model/interface/key.interface.ts
Normal file
9
client/src/app/model/interface/key.interface.ts
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
export interface IKey {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
createdAt: string;
|
||||||
|
updatedAt: string;
|
||||||
|
handedOut: boolean;
|
||||||
|
cylinder: any;
|
||||||
|
nr: number;
|
||||||
|
}
|
||||||
@@ -61,6 +61,7 @@ export class AllUsersComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -69,6 +70,7 @@ export class AllUsersComponent {
|
|||||||
next: n => {
|
next: n => {
|
||||||
this.gridApi.setGridOption("rowData", n)
|
this.gridApi.setGridOption("rowData", n)
|
||||||
this.gridApi.setGridOption("loading", false);
|
this.gridApi.setGridOption("loading", false);
|
||||||
|
n.filter(u => u.username == 'mail@bastian-wagner.de').map((u: any) => { console.log(u['lastLogin'])})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
7
client/src/app/modules/keys/keys.component.html
Normal file
7
client/src/app/modules/keys/keys.component.html
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
@if (gridOptions || true) {
|
||||||
|
<ag-grid-angular
|
||||||
|
style="width: 100%; height: 100%;"
|
||||||
|
(gridReady)="onGridReady($event)"
|
||||||
|
[gridOptions]="gridOptions!"
|
||||||
|
/>
|
||||||
|
}
|
||||||
0
client/src/app/modules/keys/keys.component.scss
Normal file
0
client/src/app/modules/keys/keys.component.scss
Normal file
23
client/src/app/modules/keys/keys.component.spec.ts
Normal file
23
client/src/app/modules/keys/keys.component.spec.ts
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { KeysComponent } from './keys.component';
|
||||||
|
|
||||||
|
describe('KeysComponent', () => {
|
||||||
|
let component: KeysComponent;
|
||||||
|
let fixture: ComponentFixture<KeysComponent>;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
await TestBed.configureTestingModule({
|
||||||
|
imports: [KeysComponent]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
|
||||||
|
fixture = TestBed.createComponent(KeysComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
112
client/src/app/modules/keys/keys.component.ts
Normal file
112
client/src/app/modules/keys/keys.component.ts
Normal file
@@ -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();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,6 +2,7 @@ import { HttpClient } from '@angular/common/http';
|
|||||||
import { inject, Injectable } from '@angular/core';
|
import { inject, Injectable } from '@angular/core';
|
||||||
import { Observable } from 'rxjs';
|
import { Observable } from 'rxjs';
|
||||||
import { IUser } from '../model/interface/user.interface';
|
import { IUser } from '../model/interface/user.interface';
|
||||||
|
import { IKey } from '../model/interface/key.interface';
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root'
|
providedIn: 'root'
|
||||||
@@ -23,4 +24,22 @@ export class ApiService {
|
|||||||
getRoles(): Observable<{id: string, name: string}[]> {
|
getRoles(): Observable<{id: string, name: string}[]> {
|
||||||
return this.http.get<{id: string, name: string}[]>('/api/role');
|
return this.http.get<{id: string, name: string}[]>('/api/role');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getKeys(): Observable<IKey[]> {
|
||||||
|
return this.http.get<IKey[]>('api/key')
|
||||||
|
}
|
||||||
|
|
||||||
|
updateKey(key: IKey): Observable<IKey> {
|
||||||
|
return this.http.put<IKey>('api/key', key);
|
||||||
|
}
|
||||||
|
|
||||||
|
getCylinders(): Observable<any[]> {
|
||||||
|
return this.http.get<any[]>('api/key/cylinder');
|
||||||
|
}
|
||||||
|
|
||||||
|
postKey(key: IKey) {}
|
||||||
|
|
||||||
|
postKeySystem(keySystem: any) {
|
||||||
|
return this.http.post('api/key/system', keySystem);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user