diff --git a/src/app/app.component.html b/src/app/app.component.html index 0680b43..86ddd42 100644 --- a/src/app/app.component.html +++ b/src/app/app.component.html @@ -1 +1 @@ - + diff --git a/src/app/app.component.ts b/src/app/app.component.ts index 04ea690..79dce0a 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -1,10 +1,26 @@ -import { Component } from '@angular/core'; -import { RouterOutlet } from '@angular/router'; +import {Component} from '@angular/core'; +import {RouterOutlet} from '@angular/router'; +import {LoginViewComponent} from "./components/login-view/login-view.component"; +import { + MitarbeiterverwaltungViewComponent +} from "./components/mitarbeiterverwaltung-view/mitarbeiterverwaltung-view.component"; + +import {NavigationBarComponent} from './components/navigation-bar/navigation-bar.component'; +import {EmployeeDetailComponent} from './components/employee-detail/employee-detail.component'; +import { + MitarbeiterBearbeitenViewComponent +} from "./components/mitarbeiter-bearbeiten-view/mitarbeiter-bearbeiten-view.component"; +import { + QualifikatonBearbeitenViewComponent +} from "./components/qualifikaton-bearbeiten-view/qualifikaton-bearbeiten-view.component"; +import {QualifikatonDetailComponent} from "./components/qualifikaton-detail/qualifikaton-detail.component"; +import {EmployeeListComponent} from "./components/employee-list/employee-list.component"; + @Component({ selector: 'app-root', standalone: true, - imports: [RouterOutlet], + imports: [RouterOutlet, NavigationBarComponent, EmployeeDetailComponent, LoginViewComponent, MitarbeiterverwaltungViewComponent, MitarbeiterBearbeitenViewComponent, QualifikatonBearbeitenViewComponent, QualifikatonDetailComponent, EmployeeListComponent], templateUrl: './app.component.html', styleUrl: './app.component.css' }) diff --git a/src/app/app.config.ts b/src/app/app.config.ts index bd19328..b047b4b 100644 --- a/src/app/app.config.ts +++ b/src/app/app.config.ts @@ -2,7 +2,7 @@ import { APP_INITIALIZER, ApplicationConfig, provideZoneChangeDetection } from ' import { provideRouter } from '@angular/router'; import { routes } from './app.routes'; -import { KeycloakAngularModule, KeycloakBearerInterceptor, KeycloakService } from "keycloak-angular"; +import {KeycloakAngularModule, KeycloakBearerInterceptor, KeycloakService} from "keycloak-angular"; import { HTTP_INTERCEPTORS, provideHttpClient, withInterceptorsFromDi } from '@angular/common/http'; export const initializeKeycloak = (keycloak: KeycloakService) => async () => @@ -28,20 +28,20 @@ function initializeApp(keycloak: KeycloakService): () => Promise { export const appConfig: ApplicationConfig = { providers: [ - provideRouter(routes), - KeycloakAngularModule, - { - provide: APP_INITIALIZER, - useFactory: initializeApp, - multi: true, - deps: [KeycloakService] - }, - KeycloakService, - provideHttpClient(withInterceptorsFromDi()), - { - provide: HTTP_INTERCEPTORS, - useClass: KeycloakBearerInterceptor, - multi: true - } - ] + provideRouter(routes), + KeycloakAngularModule, + { + provide: APP_INITIALIZER, + useFactory: initializeApp, + multi: true, + deps: [KeycloakService] + }, + KeycloakService, + provideHttpClient(withInterceptorsFromDi()), + { + provide: HTTP_INTERCEPTORS, + useClass: KeycloakBearerInterceptor, + multi: true + } + ] }; diff --git a/src/app/app.routes.ts b/src/app/app.routes.ts index d68355b..361a73b 100644 --- a/src/app/app.routes.ts +++ b/src/app/app.routes.ts @@ -3,8 +3,9 @@ import { LoginViewComponent } from "./components/login-view/login-view.component import { MitarbeiterverwaltungViewComponent } from "./components/mitarbeiterverwaltung-view/mitarbeiterverwaltung-view.component"; import { EmployeeDetailComponent } from "./components/employee-detail/employee-detail.component"; import { QualifikatonBearbeitenViewComponent } from "./components/qualifikaton-bearbeiten-view/qualifikaton-bearbeiten-view.component"; -import { AuthGuard } from "./data_layer/service/auth.service"; -import { MitarbeiterBearbeitenViewComponent } from "./components/mitarbeiter-bearbeiten-view/mitarbeiter-bearbeiten-view.component"; +import { KeycloakAuthGuard } from "keycloak-angular"; +import { AuthGuard } from "/Users/mehdiboudjoudi/WebstormProjects/employeeService/src/app/data_layer/service/auth.service"; +import {EmployeeListComponent} from "./components/employee-list/employee-list.component"; export const routes: Routes = [ { @@ -17,8 +18,8 @@ export const routes: Routes = [ canActivate: [AuthGuard], }, { - path: "mitarbeiterbearbeiten/:id", - component: MitarbeiterBearbeitenViewComponent, + path: "mitarbeiterHeidemann", + component: EmployeeListComponent, canActivate: [AuthGuard], }, { diff --git a/src/app/components/mitarbeiter-bearbeiten-view/mitarbeiter-bearbeiten-view.component.css b/src/app/components/mitarbeiter-bearbeiten-view/mitarbeiter-bearbeiten-view.component.css index e69de29..ac54d29 100644 --- a/src/app/components/mitarbeiter-bearbeiten-view/mitarbeiter-bearbeiten-view.component.css +++ b/src/app/components/mitarbeiter-bearbeiten-view/mitarbeiter-bearbeiten-view.component.css @@ -0,0 +1,120 @@ +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: 2rem; + margin-bottom: 20px; +} + +.back-button { + background-color: #ccc; + color: #333; + border: none; + padding: 8px 12px; + border-radius: 3px; + margin-bottom: 15px; +} + +.user-info { + display: grid; + grid-template-columns: 1fr 1fr; + grid-gap: 20px; + margin-bottom: 20px; +} + +.form-group { + display: flex; + flex-direction: column; +} + +label { + margin-bottom: 5px; +} + +input[type="text"] { + padding: 10px; + border: 1px solid #ddd; + border-radius: 3px; +} + +input[type="text"]::placeholder { + color: #999; +} + +.save-button { + background-color: #007bff; + color: #fff; + padding: 10px 15px; + border: none; + border-radius: 3px; + cursor: pointer; + margin-top: 10px; + width: 100%; +} + +.skills-container { + border: 1px solid #ccc; + padding: 20px; + border-radius: 3px; +} + +.skill-controls select { + padding: 10px 10px; + border: none; + border-radius: 3px; + background-color: #007bff; + color: #fff; + cursor: pointer; +} + +.skill-list { + list-style: none; + padding: 0; +} + +.skill-list li { + display: flex; + align-items: center; + margin-bottom: 5px; +} + +.skill-icon { + margin-right: 5px; +} + +.delete-skill-button { + color: #fff; + padding: 5px 8px; + border: none; + cursor: pointer; + margin-left: 10px; + border-radius: 3px; +} + +.delete-skill-button img { + width: 15px; + height: 15px; +} + +.add-skill-button{ + background-color: #06a63b; + color: #fff; + padding: 8px 10px; + border: none; + border-radius: 3px; + cursor: pointer; + margin-left: 10px; +} + diff --git a/src/app/components/mitarbeiter-bearbeiten-view/mitarbeiter-bearbeiten-view.component.html b/src/app/components/mitarbeiter-bearbeiten-view/mitarbeiter-bearbeiten-view.component.html index 682a986..4bc03b5 100644 --- a/src/app/components/mitarbeiter-bearbeiten-view/mitarbeiter-bearbeiten-view.component.html +++ b/src/app/components/mitarbeiter-bearbeiten-view/mitarbeiter-bearbeiten-view.component.html @@ -1 +1,49 @@ - + + Back + + + First Name + + + + Last Name + + + + Street + + + + Postcode + + + + City + + + + Phone Number + + + + + + Skills + + + Skill 1 + + + + + + + + Option 1 + Option 2 + + Add qualification + + + Save + diff --git a/src/app/components/mitarbeiter-bearbeiten-view/mitarbeiter-bearbeiten-view.component.ts b/src/app/components/mitarbeiter-bearbeiten-view/mitarbeiter-bearbeiten-view.component.ts index cc4c5f6..ccf171e 100644 --- a/src/app/components/mitarbeiter-bearbeiten-view/mitarbeiter-bearbeiten-view.component.ts +++ b/src/app/components/mitarbeiter-bearbeiten-view/mitarbeiter-bearbeiten-view.component.ts @@ -1,43 +1,12 @@ import { Component } from '@angular/core'; -import { MitarbeiterFormComponent } from '../mitarbeiter-form/mitarbeiter-form.component'; -import { EmployeeResponseDTO } from '../../models/mitarbeiter'; -import { ActivatedRoute, Router } from '@angular/router'; -import { EmployeeService } from '../../service/employee.service'; @Component({ selector: 'app-mitarbeiter-bearbeiten-view', standalone: true, - imports: [MitarbeiterFormComponent], + imports: [], templateUrl: './mitarbeiter-bearbeiten-view.component.html', styleUrl: './mitarbeiter-bearbeiten-view.component.css' }) export class MitarbeiterBearbeitenViewComponent { - public mitarbeiter!: EmployeeResponseDTO; - constructor(private employeeService: EmployeeService, private route: ActivatedRoute, private router: Router) { } - - submitted(mitarbeiter: EmployeeResponseDTO) { - this.employeeService.updateEmployee(mitarbeiter); - this.returnToEmployeeOverview(); - } - - returnToEmployeeOverview() { - this.router.navigate(["mitarbeiter"]); - } - - ngOnInit(): void { - this.mitarbeiter = { - id: 0, - firstName: '', - lastName: '', - street: '', - phone: '', - skillSet: [], - postcode: '', - city: '', - } - this.employeeService.getEmployeeById(this.route.snapshot.params['id']).subscribe(employee => { - this.mitarbeiter = employee; - }); - } } diff --git a/src/app/components/mitarbeiter-form/mitarbeiter-form.component.css b/src/app/components/mitarbeiter-form/mitarbeiter-form.component.css deleted file mode 100644 index ac54d29..0000000 --- a/src/app/components/mitarbeiter-form/mitarbeiter-form.component.css +++ /dev/null @@ -1,120 +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: 2rem; - margin-bottom: 20px; -} - -.back-button { - background-color: #ccc; - color: #333; - border: none; - padding: 8px 12px; - border-radius: 3px; - margin-bottom: 15px; -} - -.user-info { - display: grid; - grid-template-columns: 1fr 1fr; - grid-gap: 20px; - margin-bottom: 20px; -} - -.form-group { - display: flex; - flex-direction: column; -} - -label { - margin-bottom: 5px; -} - -input[type="text"] { - padding: 10px; - border: 1px solid #ddd; - border-radius: 3px; -} - -input[type="text"]::placeholder { - color: #999; -} - -.save-button { - background-color: #007bff; - color: #fff; - padding: 10px 15px; - border: none; - border-radius: 3px; - cursor: pointer; - margin-top: 10px; - width: 100%; -} - -.skills-container { - border: 1px solid #ccc; - padding: 20px; - border-radius: 3px; -} - -.skill-controls select { - padding: 10px 10px; - border: none; - border-radius: 3px; - background-color: #007bff; - color: #fff; - cursor: pointer; -} - -.skill-list { - list-style: none; - padding: 0; -} - -.skill-list li { - display: flex; - align-items: center; - margin-bottom: 5px; -} - -.skill-icon { - margin-right: 5px; -} - -.delete-skill-button { - color: #fff; - padding: 5px 8px; - border: none; - cursor: pointer; - margin-left: 10px; - border-radius: 3px; -} - -.delete-skill-button img { - width: 15px; - height: 15px; -} - -.add-skill-button{ - background-color: #06a63b; - color: #fff; - padding: 8px 10px; - border: none; - border-radius: 3px; - cursor: pointer; - margin-left: 10px; -} - diff --git a/src/app/components/mitarbeiter-form/mitarbeiter-form.component.html b/src/app/components/mitarbeiter-form/mitarbeiter-form.component.html deleted file mode 100644 index 5fe664d..0000000 --- a/src/app/components/mitarbeiter-form/mitarbeiter-form.component.html +++ /dev/null @@ -1,78 +0,0 @@ - - - - Back - - - @if (errorMessages['firstName']) { - {{errorMessages['firstName']}} - } - First Name - - - - @if (errorMessages['lastName']) { - {{errorMessages['lastName']}} - } - Last Name - - - - @if (errorMessages['street']) { - {{errorMessages['street']}} - } - Street - - - - @if (errorMessages['postcode']) { - {{errorMessages['postcode']}} - } - Postcode - - - - @if (errorMessages['city']) { - {{errorMessages['city']}} - } - City - - - - @if (errorMessages['phone']) { - {{errorMessages['phone']}} - } - Phone Number - - - - - - Skills - - @for (skill of mitarbeiter.skillSet; track skill) { - - {{skill.skill}} - - - - - } - - @if (!hasAllSkills) { - - - @for (skill of allSkills | async; track skill) { - @if (!hasSkill(skill.id)) { - {{skill.skill}} - } - } - - Add qualification - - } - - Save - - - diff --git a/src/app/components/mitarbeiter-form/mitarbeiter-form.component.spec.ts b/src/app/components/mitarbeiter-form/mitarbeiter-form.component.spec.ts deleted file mode 100644 index 76b7600..0000000 --- a/src/app/components/mitarbeiter-form/mitarbeiter-form.component.spec.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { ComponentFixture, TestBed } from '@angular/core/testing'; - -import { MitarbeiterFormComponent } from './mitarbeiter-form.component'; - -describe('MitarbeiterFormComponent', () => { - let component: MitarbeiterFormComponent; - let fixture: ComponentFixture; - - beforeEach(async () => { - await TestBed.configureTestingModule({ - imports: [MitarbeiterFormComponent] - }) - .compileComponents(); - - fixture = TestBed.createComponent(MitarbeiterFormComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); -}); diff --git a/src/app/components/mitarbeiter-form/mitarbeiter-form.component.ts b/src/app/components/mitarbeiter-form/mitarbeiter-form.component.ts deleted file mode 100644 index 0e73354..0000000 --- a/src/app/components/mitarbeiter-form/mitarbeiter-form.component.ts +++ /dev/null @@ -1,131 +0,0 @@ -import { Component, EventEmitter, Input, Output } from '@angular/core'; -import { EmployeeNameAndSkillDataDTO, EmployeeRequestPutDTO, EmployeeResponseDTO } from '../../models/mitarbeiter'; -import { AbstractControl, FormControl, FormGroup, ReactiveFormsModule, Validators } from '@angular/forms'; -import { HttpClient } from '@angular/common/http'; -import { Router } from '@angular/router'; -import { AsyncPipe, NgFor } from '@angular/common'; -import { SkillService } from '../../service/skill.service'; -import { QualificationGetDTO } from '../../models/skill'; -import { Observable, of } from 'rxjs'; - -@Component({ - selector: 'app-mitarbeiter-form', - standalone: true, - imports: [MitarbeiterFormComponent, ReactiveFormsModule, NgFor, AsyncPipe], - templateUrl: './mitarbeiter-form.component.html', - styleUrl: './mitarbeiter-form.component.css' -}) -export class MitarbeiterFormComponent { - @Input() mitarbeiter!: EmployeeResponseDTO; - @Output() mitarbeiterChange = new EventEmitter(); - - public mitarbeiterForm!: FormGroup; - public allSkills: Observable> = of([]); - public hasAllSkills: boolean = false; - errorMessages: Record = {}; - - constructor(public http: HttpClient, public router: Router, private skillService: SkillService) { - - } - - returnToEmployeeOverview() { - this.router.navigate(["mitarbeiter"]); - } - - private setupForm() { - this.mitarbeiterForm = new FormGroup({ - lastName: new FormControl(this.mitarbeiter.lastName, Validators.required), - firstName: new FormControl(this.mitarbeiter.firstName, Validators.required), - street: new FormControl(this.mitarbeiter.street, Validators.required), - postcode: new FormControl(this.mitarbeiter.postcode, [Validators.required, Validators.minLength(5), Validators.maxLength(5)]), - city: new FormControl(this.mitarbeiter.city, Validators.required), - phone: new FormControl(this.mitarbeiter.phone, [Validators.required, Validators.pattern('^[- +()0-9]+$')]), - newSkill: new FormControl(), - }); - } - - ngOnChanges(): void { - this.setupForm(); - } - - skillsChanged() { - this.allSkills.subscribe(skills => { - this.hasAllSkills = this.checkAllSkills(skills); - }); - } - - ngOnInit(): void { - this.allSkills = this.skillService.getAllSkills(); - this.skillsChanged(); - this.setupForm(); - } - - removeSkill(id?: number) { - this.mitarbeiter.skillSet = this.mitarbeiter.skillSet?.filter(skill => skill.id !== id); - this.skillsChanged(); - } - - checkAllSkills(skills: Array): boolean { - const skillSet = this.mitarbeiter.skillSet || []; - - return skills.every(skill => - skillSet.some(givenSkill => skill.id === givenSkill.id) - ); - } - - hasSkill(id: number): boolean { - for (const skill of this.mitarbeiter.skillSet || []) { - if (skill.id == id) { - return true; - } - } - return false; - } - - addSkill() { - const id = Number(this.mitarbeiterForm.get("newSkill")?.value); - this.allSkills.subscribe(skills => { - const newSkill = skills.filter(skill => skill.id == id)[0]; - this.mitarbeiter.skillSet?.push(newSkill); - this.skillsChanged(); - }); - } - - private validationErrorMessages: Record = { - required: "This field is required", - minlength: "The value is too short", - maxlength: "The value is too long", - pattern: "This field must be a valid phone number", - }; - - updateErrorMessages(): void { - this.errorMessages = {}; - - Object.keys(this.mitarbeiterForm.controls).forEach(field => { - const control = this.mitarbeiterForm.get(field); - - if (control && control.errors && control.touched) { - this.errorMessages[field] = Object.keys(control.errors) - .map(errorKey => this.validationErrorMessages[errorKey] || `Unknown error: ${errorKey}`) - .join(' '); - } - }); - } - - - submit() { - this.updateErrorMessages(); - if (!this.mitarbeiterForm.valid) { - return; - } - - this.mitarbeiter.firstName = this.mitarbeiterForm.get("firstName")?.value; - this.mitarbeiter.lastName = this.mitarbeiterForm.get("lastName")?.value; - this.mitarbeiter.street = this.mitarbeiterForm.get("street")?.value; - this.mitarbeiter.postcode = this.mitarbeiterForm.get("postcode")?.value; - this.mitarbeiter.city = this.mitarbeiterForm.get("city")?.value; - this.mitarbeiter.phone = this.mitarbeiterForm.get("phone")?.value; - - this.mitarbeiterChange.emit(this.mitarbeiter); - } -} diff --git a/src/app/models/mitarbeiter.ts b/src/app/models/mitarbeiter.ts deleted file mode 100644 index 9b67f85..0000000 --- a/src/app/models/mitarbeiter.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { QualificationGetDTO, QualificationPostDTO } from "./skill"; - -export interface EmployeeRequestPutDTO { - lastName: string, - firstName: string, - street: string, - postcode: string, - city: string, - phone: string, - skillSet: Array, -} - -export interface EmployeeResponseDTO { - id: number, - lastName: string, - firstName: string, - street: string, - postcode: string, - city: string, - phone: string, - skillSet?: Array, -} - -export interface EmployeeRequestDTO { - lastName: string, - firstName: string, - street: string, - postcode: string, - city: string, - phone: string, - skillSet?: Array, -} - -export interface EmployeeNameAndSkillDataDTO { - id: number, - lastName: string, - firstName: string, - skillSet: Array, -} - -export interface EmployeeNameDataDTO { - id: number, - lastName: string, - firstName: string, -} - - diff --git a/src/app/models/skill.ts b/src/app/models/skill.ts deleted file mode 100644 index 43b4411..0000000 --- a/src/app/models/skill.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { EmployeeNameDataDTO } from "./mitarbeiter"; - -export interface QualificationGetDTO { - id: number, - skill: string, -} - -export interface QualificationPostDTO { - skill: string, -} - -export interface EmployeesForAQualificationDTO { - qualification: QualificationGetDTO, - employees: Array, -} diff --git a/src/app/service/employee.service.ts b/src/app/service/employee.service.ts deleted file mode 100644 index a8a4d38..0000000 --- a/src/app/service/employee.service.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { Injectable } from "@angular/core"; -import { EmployeeRequestPutDTO, EmployeeResponseDTO } from "../models/mitarbeiter"; -import { HttpClient } from "@angular/common/http"; -import { Observable } from "rxjs"; -import { SkillService } from "./skill.service"; - -@Injectable({ - providedIn: 'root' -}) -export class EmployeeService { - constructor(private http: HttpClient) { } - - - responseDtoToPutDto(employee: EmployeeResponseDTO): EmployeeRequestPutDTO { - return { - firstName: employee.firstName, - lastName: employee.lastName, - street: employee.street, - postcode: employee.postcode, - city: employee.city, - phone: employee.phone, - skillSet: employee.skillSet?.map(skill => skill.id) || [], - } - } - - updateEmployee(employee: EmployeeResponseDTO) { - this.http.put(`${SkillService.BASE_URL}/employees/${employee.id}`, this.responseDtoToPutDto(employee)).subscribe(); - } - - getAllEmployees(): Observable> { - return this.http.get>(`${SkillService.BASE_URL}/employees`); - } - - - getEmployeeById(id: number): Observable { - return this.http.get(`${SkillService.BASE_URL}/employees/${id}`); - } - - - addSkillToEmployee(skillId: number, employee: EmployeeResponseDTO) { - let employeePut = this.responseDtoToPutDto(employee); - 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 deleted file mode 100644 index 9f6764b..0000000 --- a/src/app/service/skill.service.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { HttpClient } from "@angular/common/http"; -import { Injectable } from "@angular/core"; -import { QualificationGetDTO } from "../models/skill"; -import { Observable } from "rxjs"; - -@Injectable({ - providedIn: 'root' -}) -export class SkillService { - - public static readonly BASE_URL = "http://localhost:8089"; - - constructor(private http: HttpClient) { - - } - - getAllSkills(): Observable> { - return this.http.get>(`${SkillService.BASE_URL}/qualifications`); - } -}