diff --git a/src/app/app.routes.ts b/src/app/app.routes.ts
index 5fcbcba..c9981e2 100644
--- a/src/app/app.routes.ts
+++ b/src/app/app.routes.ts
@@ -32,8 +32,9 @@ export const routes: Routes = [
component: EmployeeDetailComponent,
},
{
- path: "qualifikationbearbeiten",
+ path: "qualifikationbearbeiten/:id",
component: QualifikatonBearbeitenViewComponent,
+ canActivate: [AuthGuard],
},
{
path: "**",
diff --git a/src/app/components/mitarbeiter-form/mitarbeiter-form.component.ts b/src/app/components/mitarbeiter-form/mitarbeiter-form.component.ts
index 0e73354..f9ed6af 100644
--- a/src/app/components/mitarbeiter-form/mitarbeiter-form.component.ts
+++ b/src/app/components/mitarbeiter-form/mitarbeiter-form.component.ts
@@ -104,7 +104,7 @@ export class MitarbeiterFormComponent {
Object.keys(this.mitarbeiterForm.controls).forEach(field => {
const control = this.mitarbeiterForm.get(field);
- if (control && control.errors && control.touched) {
+ if (control && control.errors) {
this.errorMessages[field] = Object.keys(control.errors)
.map(errorKey => this.validationErrorMessages[errorKey] || `Unknown error: ${errorKey}`)
.join(' ');
diff --git a/src/app/components/qualifikation-form/qualifikation-form.component.css b/src/app/components/qualifikation-form/qualifikation-form.component.css
new file mode 100644
index 0000000..886cc52
--- /dev/null
+++ b/src/app/components/qualifikation-form/qualifikation-form.component.css
@@ -0,0 +1,131 @@
+body {
+ font-family: sans-serif;
+ margin: 0;
+ padding: 20px;
+ background-color: #f0f0f0;
+}
+
+.container {
+ width: 100%;
+ max-width: 800px;
+ margin: 0 auto;
+ padding: 20px;
+ background-color: #fff;
+}
+
+h1, h2 {
+ font-size: 1.8rem;
+ margin-bottom: 15px;
+}
+
+.back-button {
+ background-color: #ccc;
+ color: #333;
+ border: none;
+ padding: 8px 12px;
+ border-radius: 3px;
+ margin-bottom: 15px;
+}
+
+.form-group {
+ margin-bottom: 15px;
+}
+
+label {
+ display: block;
+ margin-bottom: 5px;
+}
+
+input[type="text"] {
+ width: 100%;
+ padding: 10px;
+ border: 1px solid #ccc;
+ border-radius: 1px;
+}
+
+.employee-list {
+ list-style: none;
+ padding: 0;
+}
+
+.employee-list li {
+ display: flex;
+ align-items: center;
+ margin-bottom: 5px;
+}
+
+.employee-icon {
+ margin-right: 5px;
+}
+
+.add-employee-section {
+ margin-top: 15px;
+}
+
+.add-employee-section select {
+ padding: 10px;
+ border: 1px solid #ddd;
+ border-radius: 3px;
+ margin-right: 10px;
+}
+
+.add-employee-button {
+ background-color: #06a63b;
+ color: #fff;
+ padding: 10px 15px;
+ border: none;
+ border-radius: 3px;
+ cursor: pointer;
+ margin-top: 10px;
+}
+
+.save-button {
+ background-color: #007bff;
+ color: #fff;
+ padding: 10px 15px;
+ border: none;
+ border-radius: 3px;
+ cursor: pointer;
+ margin-top: 20px;
+ display: block;
+ width: 100%;
+}
+
+.delete-skill-button {
+ color: #fff;
+ padding: 5px 8px;
+ border: none;
+ cursor: pointer;
+ margin-left: 4px;
+ margin-right: 4px;
+ border-radius: 3px;
+}
+
+.delete-skill-button img {
+ width: 15px;
+ height: 15px;
+}
+
+.add-employee-section {
+ margin-top: 15px;
+}
+
+.add-employee-section label {
+ display: block;
+ margin-bottom: 5px;
+ font-weight: bold;
+}
+
+.add-employee-section input[type="text"] {
+ width: 100%;
+ padding: 10px;
+ border: 1px solid #ddd;
+ border-radius: 3px;
+}
+
+.employee-container {
+ border: 1px solid #ccc;
+ padding: 20px;
+ border-radius: 1px;
+ margin-bottom: 20px;
+}
diff --git a/src/app/components/qualifikation-form/qualifikation-form.component.html b/src/app/components/qualifikation-form/qualifikation-form.component.html
new file mode 100644
index 0000000..a881a16
--- /dev/null
+++ b/src/app/components/qualifikation-form/qualifikation-form.component.html
@@ -0,0 +1,41 @@
+
diff --git a/src/app/components/qualifikation-form/qualifikation-form.component.spec.ts b/src/app/components/qualifikation-form/qualifikation-form.component.spec.ts
new file mode 100644
index 0000000..3571e98
--- /dev/null
+++ b/src/app/components/qualifikation-form/qualifikation-form.component.spec.ts
@@ -0,0 +1,23 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { QualifikationFormComponent } from './qualifikation-form.component';
+
+describe('QualifikationFormComponent', () => {
+ let component: QualifikationFormComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ imports: [QualifikationFormComponent]
+ })
+ .compileComponents();
+
+ fixture = TestBed.createComponent(QualifikationFormComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/app/components/qualifikation-form/qualifikation-form.component.ts b/src/app/components/qualifikation-form/qualifikation-form.component.ts
new file mode 100644
index 0000000..608ac05
--- /dev/null
+++ b/src/app/components/qualifikation-form/qualifikation-form.component.ts
@@ -0,0 +1,126 @@
+import { Component, EventEmitter, Input, Output } from '@angular/core';
+import { EmployeesForAQualificationDTO, QualificationGetDTO } from '../../models/skill';
+import { FormControl, FormGroup, ReactiveFormsModule, Validators } from '@angular/forms';
+import { SkillService } from '../../service/skill.service';
+import { EmployeeService } from '../../service/employee.service';
+import { concatMap, every, from, lastValueFrom, Observable, of, switchMap, take, tap } from 'rxjs';
+import { EmployeeNameDataDTO, EmployeeResponseDTO } from '../../models/mitarbeiter';
+import { AsyncPipe } from '@angular/common';
+import { Router } from '@angular/router';
+
+@Component({
+ selector: 'app-qualifikation-form',
+ standalone: true,
+ imports: [ReactiveFormsModule, AsyncPipe],
+ templateUrl: './qualifikation-form.component.html',
+ styleUrl: './qualifikation-form.component.css'
+})
+export class QualifikationFormComponent {
+ @Input() skill!: QualificationGetDTO;
+ @Output() skillChange = new EventEmitter();
+
+ public skillForm!: FormGroup;
+ public addableEmployees: Array = [];
+ public addedEmployees: Array = [];
+ errorMessages: Record = {};
+
+
+ constructor(private skillService: SkillService, private employeeService: EmployeeService, private router: Router) { }
+
+ private validationErrorMessages: Record = {
+ required: "This field is required",
+ };
+
+ updateErrorMessages(): void {
+ this.errorMessages = {};
+
+ Object.keys(this.skillForm.controls).forEach(field => {
+ const control = this.skillForm.get(field);
+
+ if (control && control.errors) {
+ this.errorMessages[field] = Object.keys(control.errors)
+ .map(errorKey => this.validationErrorMessages[errorKey] || `Unknown error: ${errorKey}`)
+ .join(' ');
+ }
+ });
+ }
+
+ setUpForm() {
+ this.skillForm = new FormGroup({
+ name: new FormControl(this.skill.skill, Validators.required),
+ newEmployee: new FormControl(),
+ });
+ }
+
+
+ addEmployee() {
+ const employeeId = Number(this.skillForm.get("newEmployee")?.value);
+ const employee = this.addableEmployees.find(emp => emp.id === employeeId);
+
+ if (employee) {
+ this.addableEmployees = this.addableEmployees.filter(emp => emp.id !== employeeId);
+
+ this.addedEmployees.push(employee);
+ }
+ }
+
+ removeEmployee(employeeId: number) {
+ const employee = this.addedEmployees.find(emp => emp.id === employeeId);
+
+ if (employee) {
+ this.addedEmployees = this.addedEmployees.filter(emp => emp.id !== employeeId);
+
+ this.employeeService.getEmployeeById(employee.id).subscribe(employeeDto => {
+ this.addableEmployees.push(employeeDto);
+ });
+ }
+ }
+
+ updateEmployeeLists() {
+ if (this.skill.id != -1) {
+ this.employeeService.getAllEmployees().subscribe(employees => {
+ this.addableEmployees = employees;
+
+ this.skillService.getEmployeesBySkill(this.skill.id).subscribe(addedEmployeesResponse => {
+ this.addedEmployees = addedEmployeesResponse.employees;
+
+ this.addableEmployees = this.addableEmployees.filter(employee => {
+ return !this.addedEmployees.some(added => added.id === employee.id);
+ });
+ });
+ });
+ }
+ }
+
+ submit() {
+ this.updateErrorMessages();
+ if (!this.skillForm.valid) {
+ return;
+ }
+
+ for (const employee of this.addedEmployees) {
+ this.employeeService.getEmployeeById(employee.id).subscribe(employeeResponse => {
+ this.employeeService.addSkillToEmployee(this.skill.id, employeeResponse);
+ });
+ }
+
+ for (const employee of this.addableEmployees) {
+ this.employeeService.removeSkillFromEmployee(this.skill.id, employee);
+ }
+
+ this.skill.skill = this.skillForm.get("name")?.value;
+ this.skillChange.emit(this.skill);
+
+ this.router.navigate(["/qualifikationen"]);
+ }
+
+ ngOnChanges(): void {
+ this.setUpForm();
+ this.updateEmployeeLists();
+ }
+
+ ngOnInit() {
+ this.setUpForm();
+ this.updateEmployeeLists();
+ }
+}
diff --git a/src/app/components/qualifikaton-bearbeiten-view/qualifikaton-bearbeiten-view.component.css b/src/app/components/qualifikaton-bearbeiten-view/qualifikaton-bearbeiten-view.component.css
index 886cc52..e69de29 100644
--- a/src/app/components/qualifikaton-bearbeiten-view/qualifikaton-bearbeiten-view.component.css
+++ b/src/app/components/qualifikaton-bearbeiten-view/qualifikaton-bearbeiten-view.component.css
@@ -1,131 +0,0 @@
-body {
- font-family: sans-serif;
- margin: 0;
- padding: 20px;
- background-color: #f0f0f0;
-}
-
-.container {
- width: 100%;
- max-width: 800px;
- margin: 0 auto;
- padding: 20px;
- background-color: #fff;
-}
-
-h1, h2 {
- font-size: 1.8rem;
- margin-bottom: 15px;
-}
-
-.back-button {
- background-color: #ccc;
- color: #333;
- border: none;
- padding: 8px 12px;
- border-radius: 3px;
- margin-bottom: 15px;
-}
-
-.form-group {
- margin-bottom: 15px;
-}
-
-label {
- display: block;
- margin-bottom: 5px;
-}
-
-input[type="text"] {
- width: 100%;
- padding: 10px;
- border: 1px solid #ccc;
- border-radius: 1px;
-}
-
-.employee-list {
- list-style: none;
- padding: 0;
-}
-
-.employee-list li {
- display: flex;
- align-items: center;
- margin-bottom: 5px;
-}
-
-.employee-icon {
- margin-right: 5px;
-}
-
-.add-employee-section {
- margin-top: 15px;
-}
-
-.add-employee-section select {
- padding: 10px;
- border: 1px solid #ddd;
- border-radius: 3px;
- margin-right: 10px;
-}
-
-.add-employee-button {
- background-color: #06a63b;
- color: #fff;
- padding: 10px 15px;
- border: none;
- border-radius: 3px;
- cursor: pointer;
- margin-top: 10px;
-}
-
-.save-button {
- background-color: #007bff;
- color: #fff;
- padding: 10px 15px;
- border: none;
- border-radius: 3px;
- cursor: pointer;
- margin-top: 20px;
- display: block;
- width: 100%;
-}
-
-.delete-skill-button {
- color: #fff;
- padding: 5px 8px;
- border: none;
- cursor: pointer;
- margin-left: 4px;
- margin-right: 4px;
- border-radius: 3px;
-}
-
-.delete-skill-button img {
- width: 15px;
- height: 15px;
-}
-
-.add-employee-section {
- margin-top: 15px;
-}
-
-.add-employee-section label {
- display: block;
- margin-bottom: 5px;
- font-weight: bold;
-}
-
-.add-employee-section input[type="text"] {
- width: 100%;
- padding: 10px;
- border: 1px solid #ddd;
- border-radius: 3px;
-}
-
-.employee-container {
- border: 1px solid #ccc;
- padding: 20px;
- border-radius: 1px;
- margin-bottom: 20px;
-}
diff --git a/src/app/components/qualifikaton-bearbeiten-view/qualifikaton-bearbeiten-view.component.html b/src/app/components/qualifikaton-bearbeiten-view/qualifikaton-bearbeiten-view.component.html
index 2370e98..adfe33c 100644
--- a/src/app/components/qualifikaton-bearbeiten-view/qualifikaton-bearbeiten-view.component.html
+++ b/src/app/components/qualifikaton-bearbeiten-view/qualifikaton-bearbeiten-view.component.html
@@ -1,36 +1 @@
-
-
-
-
-
-
-
-
-
-
Employees possessing the qualification
-
-
- -
-
- Max Mustermann
-
- -
-
- Mehdi Boudjoudi
-
-
-
-
-
-
-
-
-
-
-
-
-
+
diff --git a/src/app/components/qualifikaton-bearbeiten-view/qualifikaton-bearbeiten-view.component.ts b/src/app/components/qualifikaton-bearbeiten-view/qualifikaton-bearbeiten-view.component.ts
index ed93e94..791b8ec 100644
--- a/src/app/components/qualifikaton-bearbeiten-view/qualifikaton-bearbeiten-view.component.ts
+++ b/src/app/components/qualifikaton-bearbeiten-view/qualifikaton-bearbeiten-view.component.ts
@@ -1,12 +1,38 @@
import { Component } from '@angular/core';
+import { QualifikationFormComponent } from '../qualifikation-form/qualifikation-form.component';
+import { SkillService } from '../../service/skill.service';
+import { FormGroup } from '@angular/forms';
+import { QualificationGetDTO } from '../../models/skill';
+import { ActivatedRoute } from '@angular/router';
@Component({
selector: 'app-qualifikaton-bearbeiten-view',
standalone: true,
- imports: [],
+ imports: [QualifikationFormComponent],
templateUrl: './qualifikaton-bearbeiten-view.component.html',
styleUrl: './qualifikaton-bearbeiten-view.component.css'
})
export class QualifikatonBearbeitenViewComponent {
+ public skill!: QualificationGetDTO;
+ constructor(private skillService: SkillService, private route: ActivatedRoute) {}
+
+ submitted(skill: QualificationGetDTO) {
+ this.skillService.updateSkill(skill);
+ }
+
+ ngOnInit(): void {
+ this.skill = {
+ id: -1,
+ skill: '',
+ };
+
+ this.skillService.getAllSkills().subscribe(skills => {
+ for (const skill of skills) {
+ if (skill.id == Number(this.route.snapshot.params['id'])) {
+ this.skill = skill;
+ }
+ }
+ });
+ }
}
diff --git a/src/app/service/employee.service.ts b/src/app/service/employee.service.ts
index 17062f7..caaf5e1 100644
--- a/src/app/service/employee.service.ts
+++ b/src/app/service/employee.service.ts
@@ -54,10 +54,20 @@ 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);
+ }
+
+ this.http.put(`${SkillService.BASE_URL}/employees/${employee.id}`, employeePut).subscribe();
+ }
addSkillToEmployee(skillId: number, employee: EmployeeResponseDTO) {
let employeePut = this.responseDtoToPutDto(employee);
- employeePut.skillSet.push(skillId);
+ if (employeePut.skillSet.indexOf(skillId) == -1) {
+ employeePut.skillSet.push(skillId);
+ }
this.http.put(`${SkillService.BASE_URL}/employees/${employee.id}`, employeePut).subscribe();
}
diff --git a/src/app/service/skill.service.ts b/src/app/service/skill.service.ts
index 9f6764b..9e0beb1 100644
--- a/src/app/service/skill.service.ts
+++ b/src/app/service/skill.service.ts
@@ -1,7 +1,8 @@
import { HttpClient } from "@angular/common/http";
import { Injectable } from "@angular/core";
-import { QualificationGetDTO } from "../models/skill";
+import { EmployeesForAQualificationDTO, QualificationGetDTO, QualificationPostDTO } from "../models/skill";
import { Observable } from "rxjs";
+import { EmployeeNameDataDTO } from "../models/mitarbeiter";
@Injectable({
providedIn: 'root'
@@ -10,11 +11,25 @@ export class SkillService {
public static readonly BASE_URL = "http://localhost:8089";
+ getToPutDto(skill: QualificationGetDTO): QualificationPostDTO {
+ return {
+ skill: skill.skill,
+ }
+ }
+
constructor(private http: HttpClient) {
}
+ updateSkill(skill: QualificationGetDTO) {
+ this.http.put(`${SkillService.BASE_URL}/qualifications/${skill.id}`, this.getToPutDto(skill)).subscribe();
+ }
+
getAllSkills(): Observable> {
return this.http.get>(`${SkillService.BASE_URL}/qualifications`);
}
+
+ getEmployeesBySkill(id: number): Observable {
+ return this.http.get(`${SkillService.BASE_URL}/qualifications/${id}/employees`);
+ }
}