Merge pull request 'Qualifikationen Bearbeiten' (#67) from feature/edit-skills into main
Reviewed-on: #67
This commit is contained in:
		
				commit
				
					
						b7e1ec2d57
					
				
			
		
					 11 changed files with 379 additions and 172 deletions
				
			
		| 
						 | 
					@ -32,8 +32,9 @@ export const routes: Routes = [
 | 
				
			||||||
    component: EmployeeDetailComponent,
 | 
					    component: EmployeeDetailComponent,
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  {
 | 
					  {
 | 
				
			||||||
    path: "qualifikationbearbeiten",
 | 
					    path: "qualifikationbearbeiten/:id",
 | 
				
			||||||
    component: QualifikatonBearbeitenViewComponent,
 | 
					    component: QualifikatonBearbeitenViewComponent,
 | 
				
			||||||
 | 
					    canActivate: [AuthGuard],
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  {
 | 
					  {
 | 
				
			||||||
    path: "**",
 | 
					    path: "**",
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -104,7 +104,7 @@ export class MitarbeiterFormComponent {
 | 
				
			||||||
    Object.keys(this.mitarbeiterForm.controls).forEach(field => {
 | 
					    Object.keys(this.mitarbeiterForm.controls).forEach(field => {
 | 
				
			||||||
      const control = this.mitarbeiterForm.get(field);
 | 
					      const control = this.mitarbeiterForm.get(field);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      if (control && control.errors && control.touched) {
 | 
					      if (control && control.errors) {
 | 
				
			||||||
        this.errorMessages[field] = Object.keys(control.errors)
 | 
					        this.errorMessages[field] = Object.keys(control.errors)
 | 
				
			||||||
          .map(errorKey => this.validationErrorMessages[errorKey] || `Unknown error: ${errorKey}`)
 | 
					          .map(errorKey => this.validationErrorMessages[errorKey] || `Unknown error: ${errorKey}`)
 | 
				
			||||||
          .join(' ');
 | 
					          .join(' ');
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,41 @@
 | 
				
			||||||
 | 
					<div class="container">
 | 
				
			||||||
 | 
					  <form [formGroup]="skillForm">
 | 
				
			||||||
 | 
					    <button class="back-button">Back</button>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <div class="form-group">
 | 
				
			||||||
 | 
					      @if (errorMessages['name']) {
 | 
				
			||||||
 | 
					      <div class="alert alert-danger">{{errorMessages['name']}}</div>
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      <label for="name">Name</label>
 | 
				
			||||||
 | 
					      <input type="text" id="name" formControlName="name">
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <div class="employee-container">
 | 
				
			||||||
 | 
					      <h2>Employees possessing the qualification</h2>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      <ul class="employee-list">
 | 
				
			||||||
 | 
					        @for (employee of addedEmployees; track employee) {
 | 
				
			||||||
 | 
					        <li>
 | 
				
			||||||
 | 
					          <button (click)="removeEmployee(employee.id)" class="delete-skill-button">
 | 
				
			||||||
 | 
					            <img src="Delete-button.svg" alt="Delete">
 | 
				
			||||||
 | 
					          </button>
 | 
				
			||||||
 | 
					          <span class="employee-name">{{employee.firstName}} {{employee.lastName}}</span>
 | 
				
			||||||
 | 
					        </li>
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      </ul>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      @if (addableEmployees.length > 0) {
 | 
				
			||||||
 | 
					      <div class="add-employee-section">
 | 
				
			||||||
 | 
					        <select formControlName="newEmployee">
 | 
				
			||||||
 | 
					          @for (employee of addableEmployees; track employee) {
 | 
				
			||||||
 | 
					          <option value="{{employee.id}}">{{employee.firstName}} {{employee.lastName}}</option>
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        </select>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        <button (click)="addEmployee()" class="add-employee-button">Add employee</button>
 | 
				
			||||||
 | 
					      </div>
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					    <button (click)="submit()" class="save-button">Save</button>
 | 
				
			||||||
 | 
					  </form>
 | 
				
			||||||
 | 
					</div>
 | 
				
			||||||
| 
						 | 
					@ -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<QualifikationFormComponent>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  beforeEach(async () => {
 | 
				
			||||||
 | 
					    await TestBed.configureTestingModule({
 | 
				
			||||||
 | 
					      imports: [QualifikationFormComponent]
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					    .compileComponents();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fixture = TestBed.createComponent(QualifikationFormComponent);
 | 
				
			||||||
 | 
					    component = fixture.componentInstance;
 | 
				
			||||||
 | 
					    fixture.detectChanges();
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  it('should create', () => {
 | 
				
			||||||
 | 
					    expect(component).toBeTruthy();
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
| 
						 | 
					@ -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<QualificationGetDTO>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  public skillForm!: FormGroup;
 | 
				
			||||||
 | 
					  public addableEmployees: Array<EmployeeResponseDTO> = [];
 | 
				
			||||||
 | 
					  public addedEmployees: Array<EmployeeNameDataDTO> = [];
 | 
				
			||||||
 | 
					  errorMessages: Record<string, string> = {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  constructor(private skillService: SkillService, private employeeService: EmployeeService, private router: Router) { }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  private validationErrorMessages: Record<string, string> = {
 | 
				
			||||||
 | 
					    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();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -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;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,36 +1 @@
 | 
				
			||||||
<div class="container">
 | 
					<app-qualifikation-form [(skill)]="skill" (skillChange)="submitted($event)"></app-qualifikation-form>
 | 
				
			||||||
  <button class="back-button">Back</button>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  <div class="form-group">
 | 
					 | 
				
			||||||
    <label for="name">Name</label>
 | 
					 | 
				
			||||||
    <input type="text" id="name" value="(Hier kommt name der gewählten qualification hin)">
 | 
					 | 
				
			||||||
  </div>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  <div class="employee-container">
 | 
					 | 
				
			||||||
    <h2>Employees possessing the qualification</h2>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    <ul class="employee-list">
 | 
					 | 
				
			||||||
      <li>
 | 
					 | 
				
			||||||
        <button class="delete-skill-button">
 | 
					 | 
				
			||||||
          <img src="Delete-button.svg" alt="Delete">
 | 
					 | 
				
			||||||
        </button>
 | 
					 | 
				
			||||||
        <span class="employee-name">Max Mustermann</span>
 | 
					 | 
				
			||||||
      </li>
 | 
					 | 
				
			||||||
      <li>
 | 
					 | 
				
			||||||
        <button class="delete-skill-button">
 | 
					 | 
				
			||||||
          <img src="Delete-button.svg" alt="Delete">
 | 
					 | 
				
			||||||
        </button>
 | 
					 | 
				
			||||||
        <span class="employee-name">Mehdi Boudjoudi</span>
 | 
					 | 
				
			||||||
      </li>
 | 
					 | 
				
			||||||
    </ul>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    <div class="add-employee-section">
 | 
					 | 
				
			||||||
      <label for="employeeSearch">Search for employee</label>
 | 
					 | 
				
			||||||
      <input type="text" id="employeeSearch" placeholder="Last name of employee">
 | 
					 | 
				
			||||||
      <button class="add-employee-button">Add employee</button>
 | 
					 | 
				
			||||||
    </div>
 | 
					 | 
				
			||||||
  </div>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  <button class="save-button">Save</button>
 | 
					 | 
				
			||||||
</div>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,12 +1,38 @@
 | 
				
			||||||
import { Component } from '@angular/core';
 | 
					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({
 | 
					@Component({
 | 
				
			||||||
  selector: 'app-qualifikaton-bearbeiten-view',
 | 
					  selector: 'app-qualifikaton-bearbeiten-view',
 | 
				
			||||||
  standalone: true,
 | 
					  standalone: true,
 | 
				
			||||||
  imports: [],
 | 
					  imports: [QualifikationFormComponent],
 | 
				
			||||||
  templateUrl: './qualifikaton-bearbeiten-view.component.html',
 | 
					  templateUrl: './qualifikaton-bearbeiten-view.component.html',
 | 
				
			||||||
  styleUrl: './qualifikaton-bearbeiten-view.component.css'
 | 
					  styleUrl: './qualifikaton-bearbeiten-view.component.css'
 | 
				
			||||||
})
 | 
					})
 | 
				
			||||||
export class QualifikatonBearbeitenViewComponent {
 | 
					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;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -54,10 +54,20 @@ export class EmployeeService {
 | 
				
			||||||
    return this.http.get<EmployeeResponseDTO>(`${SkillService.BASE_URL}/employees/${id}`);
 | 
					    return this.http.get<EmployeeResponseDTO>(`${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) {
 | 
					  addSkillToEmployee(skillId: number, employee: EmployeeResponseDTO) {
 | 
				
			||||||
    let employeePut = this.responseDtoToPutDto(employee);
 | 
					    let employeePut = this.responseDtoToPutDto(employee);
 | 
				
			||||||
 | 
					    if (employeePut.skillSet.indexOf(skillId) == -1) {
 | 
				
			||||||
      employeePut.skillSet.push(skillId);
 | 
					      employeePut.skillSet.push(skillId);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    this.http.put(`${SkillService.BASE_URL}/employees/${employee.id}`, employeePut).subscribe();
 | 
					    this.http.put(`${SkillService.BASE_URL}/employees/${employee.id}`, employeePut).subscribe();
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,7 +1,8 @@
 | 
				
			||||||
import { HttpClient } from "@angular/common/http";
 | 
					import { HttpClient } from "@angular/common/http";
 | 
				
			||||||
import { Injectable } from "@angular/core";
 | 
					import { Injectable } from "@angular/core";
 | 
				
			||||||
import { QualificationGetDTO } from "../models/skill";
 | 
					import { EmployeesForAQualificationDTO, QualificationGetDTO, QualificationPostDTO } from "../models/skill";
 | 
				
			||||||
import { Observable } from "rxjs";
 | 
					import { Observable } from "rxjs";
 | 
				
			||||||
 | 
					import { EmployeeNameDataDTO } from "../models/mitarbeiter";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@Injectable({
 | 
					@Injectable({
 | 
				
			||||||
  providedIn: 'root'
 | 
					  providedIn: 'root'
 | 
				
			||||||
| 
						 | 
					@ -10,11 +11,25 @@ export class SkillService {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  public static readonly BASE_URL = "http://localhost:8089";
 | 
					  public static readonly BASE_URL = "http://localhost:8089";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  getToPutDto(skill: QualificationGetDTO): QualificationPostDTO {
 | 
				
			||||||
 | 
					    return {
 | 
				
			||||||
 | 
					      skill: skill.skill,
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  constructor(private http: HttpClient) {
 | 
					  constructor(private http: HttpClient) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  updateSkill(skill: QualificationGetDTO) {
 | 
				
			||||||
 | 
					    this.http.put(`${SkillService.BASE_URL}/qualifications/${skill.id}`, this.getToPutDto(skill)).subscribe();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  getAllSkills(): Observable<Array<QualificationGetDTO>> {
 | 
					  getAllSkills(): Observable<Array<QualificationGetDTO>> {
 | 
				
			||||||
    return this.http.get<Array<QualificationGetDTO>>(`${SkillService.BASE_URL}/qualifications`);
 | 
					    return this.http.get<Array<QualificationGetDTO>>(`${SkillService.BASE_URL}/qualifications`);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  getEmployeesBySkill(id: number): Observable<EmployeesForAQualificationDTO> {
 | 
				
			||||||
 | 
					    return this.http.get<EmployeesForAQualificationDTO>(`${SkillService.BASE_URL}/qualifications/${id}/employees`);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Reference in a new issue