From 8a4a617c331a409e0e93d6360dcf37a978f3437b Mon Sep 17 00:00:00 2001 From: Jan Klattenhoff Date: Thu, 16 Jan 2025 11:06:30 +0100 Subject: [PATCH 1/2] feat: add qualifications management component and routes --- src/app/app.routes.ts | 6 ++ .../qualifikationsverwaltung.component.css | 90 +++++++++++++++++++ .../qualifikationsverwaltung.component.html | 47 ++++++++++ ...qualifikationsverwaltung.component.spec.ts | 23 +++++ .../qualifikationsverwaltung.component.ts | 12 +++ 5 files changed, 178 insertions(+) create mode 100644 src/app/components/qualifikationsverwaltung/qualifikationsverwaltung.component.css create mode 100644 src/app/components/qualifikationsverwaltung/qualifikationsverwaltung.component.html create mode 100644 src/app/components/qualifikationsverwaltung/qualifikationsverwaltung.component.spec.ts create mode 100644 src/app/components/qualifikationsverwaltung/qualifikationsverwaltung.component.ts diff --git a/src/app/app.routes.ts b/src/app/app.routes.ts index c9981e2..0300bf6 100644 --- a/src/app/app.routes.ts +++ b/src/app/app.routes.ts @@ -6,6 +6,7 @@ import { QualifikatonBearbeitenViewComponent } from "./components/qualifikaton-b import { MitarbeiterBearbeitenViewComponent } from "./components/mitarbeiter-bearbeiten-view/mitarbeiter-bearbeiten-view.component"; import { AuthGuard } from "./service/auth.service"; import { MitarbeiterErstellenComponent } from "./components/mitarbeiter-erstellen/mitarbeiter-erstellen.component"; +import { QualifikationsverwaltungComponent } from "./components/qualifikationsverwaltung/qualifikationsverwaltung.component"; export const routes: Routes = [ { @@ -27,6 +28,11 @@ export const routes: Routes = [ component: MitarbeiterBearbeitenViewComponent, canActivate: [AuthGuard], }, + { + path: "qualifikationsverwaltung", + component: QualifikationsverwaltungComponent, + canActivate: [AuthGuard], + }, { path: "mitarbeiterdetails", component: EmployeeDetailComponent, diff --git a/src/app/components/qualifikationsverwaltung/qualifikationsverwaltung.component.css b/src/app/components/qualifikationsverwaltung/qualifikationsverwaltung.component.css new file mode 100644 index 0000000..3d3b957 --- /dev/null +++ b/src/app/components/qualifikationsverwaltung/qualifikationsverwaltung.component.css @@ -0,0 +1,90 @@ +body { + font-family: sans-serif; + margin: 0; + padding: 20px; + background-color: #f0f0f0; +} + +.container { + width: 100%; + margin: 0 auto; + background-color: #fff; + padding: 20px; +} + +h1 { + font-size: 2rem; + margin-bottom: 20px; +} + +.search-bar { + display: flex; + margin-bottom: 10px; + align-items: center; +} + +.search-bar input[type="text"] { + padding: 8px; + border: 1px solid #ccc; + border-radius: 3px; + flex-grow: 1; + margin-right: 10px; +} + +.search-bar button { + padding: 10px 15px; + background-color: #007bff; + color: #fff; + border: none; + border-radius: 3px; + cursor: pointer; +} + +.add-button { + background-color: #07af16; + color: #fff; + padding: 10px 15px; + border: none; + border-radius: 3px; + cursor: pointer; + float: left; + margin-bottom: 10px; +} + +.employee-table { + width: 100%; + border-collapse: collapse; + margin-top: 20px; +} + +.employee-table th, +.employee-table td { + padding: 12px 15px; + border: 1px solid #ddd; + text-align: left; +} + +.employee-table th { + background-color: #f0f0f0; + font-weight: bold; +} + +.sortable { + cursor: pointer; +} + +.logout-button { + background-color: transparent; + border: none; + cursor: pointer; + border-radius: 50%; + width: 30px; + height: 30px; + display: flex; + float: right; +} + +.logout-button img { + width: 20px; + height: 20px; +} diff --git a/src/app/components/qualifikationsverwaltung/qualifikationsverwaltung.component.html b/src/app/components/qualifikationsverwaltung/qualifikationsverwaltung.component.html new file mode 100644 index 0000000..602304f --- /dev/null +++ b/src/app/components/qualifikationsverwaltung/qualifikationsverwaltung.component.html @@ -0,0 +1,47 @@ +
+
+ +

Qualifications

+
+ +
+
+ +

Search for a propertiy of a Qualification. eg. First Name

+
+ +
+ + + + + + + + + + @if (skills) { + @for (skill of skills; track skill) { + + + + + } + } + +
First NameActions
{{ skill.skill }} + + +
+
diff --git a/src/app/components/qualifikationsverwaltung/qualifikationsverwaltung.component.spec.ts b/src/app/components/qualifikationsverwaltung/qualifikationsverwaltung.component.spec.ts new file mode 100644 index 0000000..537fe1a --- /dev/null +++ b/src/app/components/qualifikationsverwaltung/qualifikationsverwaltung.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { QualifikationsverwaltungComponent } from './qualifikationsverwaltung.component'; + +describe('QualifikationsverwaltungComponent', () => { + let component: QualifikationsverwaltungComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [QualifikationsverwaltungComponent] + }) + .compileComponents(); + + fixture = TestBed.createComponent(QualifikationsverwaltungComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/components/qualifikationsverwaltung/qualifikationsverwaltung.component.ts b/src/app/components/qualifikationsverwaltung/qualifikationsverwaltung.component.ts new file mode 100644 index 0000000..1e0cd21 --- /dev/null +++ b/src/app/components/qualifikationsverwaltung/qualifikationsverwaltung.component.ts @@ -0,0 +1,12 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'app-qualifikationsverwaltung', + standalone: true, + imports: [], + templateUrl: './qualifikationsverwaltung.component.html', + styleUrl: './qualifikationsverwaltung.component.css' +}) +export class QualifikationsverwaltungComponent { + +} From 3d2f0493122224b68ae8f7499950abd5070fc782 Mon Sep 17 00:00:00 2001 From: Jan Klattenhoff Date: Thu, 16 Jan 2025 16:42:02 +0100 Subject: [PATCH 2/2] feat(qualifikation): add skill management features and fixes --- angular.json | 3 ++ .../qualifikation-form.component.html | 2 +- .../qualifikation-form.component.ts | 6 ++- .../qualifikationsverwaltung.component.html | 6 +-- .../qualifikationsverwaltung.component.ts | 47 ++++++++++++++++++- src/app/service/employee.service.ts | 14 +++--- src/app/service/skill.service.ts | 12 ++++- 7 files changed, 77 insertions(+), 13 deletions(-) diff --git a/angular.json b/angular.json index 954709f..2cbf973 100644 --- a/angular.json +++ b/angular.json @@ -93,5 +93,8 @@ } } } + }, + "cli": { + "analytics": false } } diff --git a/src/app/components/qualifikation-form/qualifikation-form.component.html b/src/app/components/qualifikation-form/qualifikation-form.component.html index a881a16..a6652d1 100644 --- a/src/app/components/qualifikation-form/qualifikation-form.component.html +++ b/src/app/components/qualifikation-form/qualifikation-form.component.html @@ -1,6 +1,6 @@
- +
@if (errorMessages['name']) { diff --git a/src/app/components/qualifikation-form/qualifikation-form.component.ts b/src/app/components/qualifikation-form/qualifikation-form.component.ts index 608ac05..21ccf24 100644 --- a/src/app/components/qualifikation-form/qualifikation-form.component.ts +++ b/src/app/components/qualifikation-form/qualifikation-form.component.ts @@ -76,6 +76,10 @@ export class QualifikationFormComponent { } } + returnToSkillList() { + this.router.navigate(["qualifikationsverwaltung"]); + } + updateEmployeeLists() { if (this.skill.id != -1) { this.employeeService.getAllEmployees().subscribe(employees => { @@ -105,7 +109,7 @@ export class QualifikationFormComponent { } for (const employee of this.addableEmployees) { - this.employeeService.removeSkillFromEmployee(this.skill.id, employee); + this.employeeService.removeSkillFromEmployee(this.skill.id, employee.id); } this.skill.skill = this.skillForm.get("name")?.value; diff --git a/src/app/components/qualifikationsverwaltung/qualifikationsverwaltung.component.html b/src/app/components/qualifikationsverwaltung/qualifikationsverwaltung.component.html index 602304f..e09d23c 100644 --- a/src/app/components/qualifikationsverwaltung/qualifikationsverwaltung.component.html +++ b/src/app/components/qualifikationsverwaltung/qualifikationsverwaltung.component.html @@ -18,15 +18,15 @@
-

Search for a propertiy of a Qualification. eg. First Name

+

Search for a propertiy of a Qualification. eg. Name

- +
- + diff --git a/src/app/components/qualifikationsverwaltung/qualifikationsverwaltung.component.ts b/src/app/components/qualifikationsverwaltung/qualifikationsverwaltung.component.ts index 1e0cd21..cfe298b 100644 --- a/src/app/components/qualifikationsverwaltung/qualifikationsverwaltung.component.ts +++ b/src/app/components/qualifikationsverwaltung/qualifikationsverwaltung.component.ts @@ -1,12 +1,57 @@ import { Component } from '@angular/core'; +import { QualificationGetDTO } from '../../models/skill'; +import { FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms'; +import { SkillService } from '../../service/skill.service'; +import { Router } from '@angular/router'; @Component({ selector: 'app-qualifikationsverwaltung', standalone: true, - imports: [], + imports: [ReactiveFormsModule], templateUrl: './qualifikationsverwaltung.component.html', styleUrl: './qualifikationsverwaltung.component.css' }) export class QualifikationsverwaltungComponent { + skills: Array = []; + public searchForm!: FormGroup; + constructor(private skillService: SkillService, private router: Router) {} + + submit() { + const searchTerm = this.searchForm.get("search")?.value || ''; + + this.skillService.getAllSkills().subscribe(skills => { + let foundSkills: Array = []; + for (const skill of skills) { + if ( + skill.skill.toLowerCase().includes(searchTerm.toLowerCase()) || + searchTerm == '' + ) { + foundSkills.push(skill); + } + } + + this.skills = foundSkills; + }); + } + + editSkill(id: number) { + this.router.navigate([`/qualifikationbearbeiten/${id}`]); + } + + createSkill() { + this.router.navigate(['/qualifikationerstellen']); + } + + deleteSkill(id: number) { + this.skillService.deleteSkill(id); + this.skills = this.skills.filter(skill => skill.id != id); + } + + ngOnInit(): void { + this.searchForm = new FormGroup({ + search: new FormControl(''), + }); + this.skillService.getAllSkills().subscribe(skills => this.skills = skills); + } } diff --git a/src/app/service/employee.service.ts b/src/app/service/employee.service.ts index caaf5e1..fe1d9db 100644 --- a/src/app/service/employee.service.ts +++ b/src/app/service/employee.service.ts @@ -54,13 +54,15 @@ export class EmployeeService { return this.http.get(`${SkillService.BASE_URL}/employees/${id}`); } - removeSkillFromEmployee(skillId: number, employee: EmployeeResponseDTO) { - let employeePut = this.responseDtoToPutDto(employee); - if (employeePut.skillSet.indexOf(skillId) != 1) { - employeePut.skillSet = employeePut.skillSet.filter(skill => skill != skillId); - } + removeSkillFromEmployee(skillId: number, employeeId: number) { + this.getEmployeeById(employeeId).subscribe(employee => { + let employeePut = this.responseDtoToPutDto(employee); + if (employeePut.skillSet.indexOf(skillId) != 1) { + employeePut.skillSet = employeePut.skillSet.filter(skill => skill != skillId); + } - this.http.put(`${SkillService.BASE_URL}/employees/${employee.id}`, employeePut).subscribe(); + this.http.put(`${SkillService.BASE_URL}/employees/${employee.id}`, employeePut).subscribe(); + }); } addSkillToEmployee(skillId: number, employee: EmployeeResponseDTO) { diff --git a/src/app/service/skill.service.ts b/src/app/service/skill.service.ts index 9e0beb1..b9ac3a6 100644 --- a/src/app/service/skill.service.ts +++ b/src/app/service/skill.service.ts @@ -3,11 +3,21 @@ import { Injectable } from "@angular/core"; import { EmployeesForAQualificationDTO, QualificationGetDTO, QualificationPostDTO } from "../models/skill"; import { Observable } from "rxjs"; import { EmployeeNameDataDTO } from "../models/mitarbeiter"; +import { EmployeeService } from "./employee.service"; @Injectable({ providedIn: 'root' }) export class SkillService { + deleteSkill(id: number) { + this.getEmployeesBySkill(id).subscribe(employees => { + for (let employee of employees.employees) { + this.employeeService.removeSkillFromEmployee(id, employee.id); + } + }); + + this.http.delete(`${SkillService.BASE_URL}/qualifications/${id}`).subscribe(); + } public static readonly BASE_URL = "http://localhost:8089"; @@ -17,7 +27,7 @@ export class SkillService { } } - constructor(private http: HttpClient) { + constructor(private http: HttpClient, private employeeService: EmployeeService) { }
First NameName Actions