Compare commits
10 commits
bcf121d659
...
212a6f8d26
Author | SHA1 | Date | |
---|---|---|---|
212a6f8d26 | |||
ebd4508743 | |||
5cc396f552 | |||
f3738ff631 | |||
fbec66debc | |||
4dc253b508 | |||
5f18aa207d | |||
2a337f3586 | |||
471a675117 | |||
9b80777fc3 |
15 changed files with 204 additions and 122 deletions
18
package-lock.json
generated
18
package-lock.json
generated
|
@ -5503,9 +5503,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/caniuse-lite": {
|
||||
"version": "1.0.30001692",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001692.tgz",
|
||||
"integrity": "sha512-A95VKan0kdtrsnMubMKxEKUKImOPSuCpYgxSQBo036P5YYgVIcOYJEgt/txJWqObiRQeISNCfef9nvlQ0vbV7A==",
|
||||
"version": "1.0.30001695",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001695.tgz",
|
||||
"integrity": "sha512-vHyLade6wTgI2u1ec3WQBxv+2BrTERV28UXQu9LO6lZ9pYeMk34vjXFLOxo1A4UBA8XTL4njRQZdno/yYaSmWw==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
|
@ -6430,9 +6430,9 @@
|
|||
"license": "MIT"
|
||||
},
|
||||
"node_modules/electron-to-chromium": {
|
||||
"version": "1.5.83",
|
||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.83.tgz",
|
||||
"integrity": "sha512-LcUDPqSt+V0QmI47XLzZrz5OqILSMGsPFkDYus22rIbgorSvBYEFqq854ltTmUdHkY92FSdAAvsh4jWEULMdfQ==",
|
||||
"version": "1.5.84",
|
||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.84.tgz",
|
||||
"integrity": "sha512-I+DQ8xgafao9Ha6y0qjHHvpZ9OfyA1qKlkHkjywxzniORU2awxyz7f/iVJcULmrF2yrM3nHQf+iDjJtbbexd/g==",
|
||||
"dev": true,
|
||||
"license": "ISC"
|
||||
},
|
||||
|
@ -7063,9 +7063,9 @@
|
|||
"license": "MIT"
|
||||
},
|
||||
"node_modules/fast-uri": {
|
||||
"version": "3.0.5",
|
||||
"resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.5.tgz",
|
||||
"integrity": "sha512-5JnBCWpFlMo0a3ciDy/JckMzzv1U9coZrIhedq+HXxxUfDTAiS0LA8OKVao4G9BxmCVck/jtA5r3KAtRWEyD8Q==",
|
||||
"version": "3.0.6",
|
||||
"resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.6.tgz",
|
||||
"integrity": "sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
|
|
|
@ -7,6 +7,7 @@ import { MitarbeiterBearbeitenViewComponent } from "./components/mitarbeiter-bea
|
|||
import { AuthGuard } from "./service/auth.service";
|
||||
import { MitarbeiterErstellenComponent } from "./components/mitarbeiter-erstellen/mitarbeiter-erstellen.component";
|
||||
import { QualifikationsverwaltungComponent } from "./components/qualifikationsverwaltung/qualifikationsverwaltung.component";
|
||||
import { QulifikationErstellenComponent } from "./components/qualifikation-erstellen/qualifikation-erstellen.component";
|
||||
|
||||
export const routes: Routes = [
|
||||
{
|
||||
|
@ -18,6 +19,11 @@ export const routes: Routes = [
|
|||
component: MitarbeiterverwaltungViewComponent,
|
||||
canActivate: [AuthGuard],
|
||||
},
|
||||
{
|
||||
path: "qualifikationerstellen",
|
||||
component: QulifikationErstellenComponent,
|
||||
canActivate: [AuthGuard],
|
||||
},
|
||||
{
|
||||
path: "mitarbeitererstellen",
|
||||
component: MitarbeiterErstellenComponent,
|
||||
|
|
|
@ -1,57 +1,52 @@
|
|||
<div class="container">
|
||||
<div class="header">
|
||||
<div class="dropdown position-absolute top-0 end-0 m-3">
|
||||
<button class="btn align-items-center d-flex" type="button" id="userDropdown" data-bs-toggle="dropdown"
|
||||
aria-expanded="false">
|
||||
<img src="user.svg" alt="User Icon" class="rounded-circle" style="width: 30px; height: 30px;">
|
||||
</button>
|
||||
<ul class="dropdown-menu dropdown-menu-end" aria-labelledby="userDropdown">
|
||||
<li><a class="dropdown-item" href="/logout">Log out</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<h1>Employees</h1>
|
||||
</div>
|
||||
|
||||
<div class="header-actions">
|
||||
<form [formGroup]="searchForm">
|
||||
<div class="search-bar">
|
||||
<input type="text" placeholder="Search employee" formControlName="search">
|
||||
<button (click)="submit()">Search</button>
|
||||
<div class="d-flex flex-row">
|
||||
<app-navigation-bar [route]="'employee'" class="row" style="height: 100vh;"></app-navigation-bar>
|
||||
<div class="container">
|
||||
<div class="header">
|
||||
<div class="dropdown position-absolute top-0 end-0 m-3">
|
||||
<button class="btn align-items-center d-flex" type="button" id="userDropdown" data-bs-toggle="dropdown"
|
||||
aria-expanded="false">
|
||||
<img src="user.svg" alt="User Icon" class="rounded-circle" style="width: 30px; height: 30px;">
|
||||
</button>
|
||||
<ul class="dropdown-menu dropdown-menu-end" aria-labelledby="userDropdown">
|
||||
<li><a class="dropdown-item" href="/logout">Log out</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<p class="text-body-tertiary">Search for a propertiy of an Employee. eg. First Name</p>
|
||||
</form>
|
||||
<button (click)="createEmployee()" class="add-button">Add employee</button>
|
||||
</div>
|
||||
<h1>Employees</h1>
|
||||
</div>
|
||||
|
||||
<table class="employee-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th><span class="sortable">First Name</span></th>
|
||||
<th><span class="sortable">Last Name</span></th>
|
||||
<th>Street</th>
|
||||
<th>Postcode</th>
|
||||
<th>City</th>
|
||||
<th>Phone</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@if (employees) {
|
||||
@for (employee of employees; track employee) {
|
||||
<tr>
|
||||
<td>{{ employee.firstName }}</td>
|
||||
<td>{{ employee.lastName }}</td>
|
||||
<td>{{ employee.street }}</td>
|
||||
<td>{{ employee.postcode }}</td>
|
||||
<td>{{ employee.city }}</td>
|
||||
<td>{{ employee.phone }}</td>
|
||||
<td>
|
||||
<button class="btn btn-primary me-2" (click)="editEmployee(employee.id)">Edit</button>
|
||||
<button class="btn btn-danger" (click)="deleteEmployee(employee.id)">Delete</button>
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="header-actions">
|
||||
<form [formGroup]="searchForm">
|
||||
<div class="search-bar">
|
||||
<input type="text" placeholder="Search employee" formControlName="search">
|
||||
<button (click)="submit()">Search</button>
|
||||
</div>
|
||||
<p class="text-body-tertiary">Search for a propertiy of an Employee. eg. First Name</p>
|
||||
</form>
|
||||
<button (click)="createEmployee()" class="add-button">Add employee</button>
|
||||
</div>
|
||||
|
||||
<table class="employee-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th><span class="sortable">First Name</span></th>
|
||||
<th><span class="sortable">Last Name</span></th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@if (employees) {
|
||||
@for (employee of employees; track employee) {
|
||||
<tr>
|
||||
<td>{{ employee.firstName }}</td>
|
||||
<td>{{ employee.lastName }}</td>
|
||||
<td>
|
||||
<button class="btn btn-primary me-2" (click)="editEmployee(employee.id)">Edit</button>
|
||||
<button class="btn btn-danger" (click)="deleteEmployee(employee.id)">Delete</button>
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -5,13 +5,14 @@ import { EmployeeResponseDTO } from '../../models/mitarbeiter';
|
|||
import { EmployeeService } from '../../service/employee.service';
|
||||
import { FormControl, FormGroup, ReactiveFormsModule, Validators } from '@angular/forms';
|
||||
import { Router } from '@angular/router';
|
||||
import { NavigationBarComponent } from '../navigation-bar/navigation-bar.component';
|
||||
|
||||
@Component({
|
||||
selector: 'app-mitarbeiterverwaltung-view',
|
||||
templateUrl: './mitarbeiterverwaltung-view.component.html',
|
||||
styleUrls: ['./mitarbeiterverwaltung-view.component.css'],
|
||||
standalone: true,
|
||||
imports: [CommonModule, ReactiveFormsModule]
|
||||
imports: [CommonModule, ReactiveFormsModule, NavigationBarComponent]
|
||||
})
|
||||
export class MitarbeiterverwaltungViewComponent implements OnInit {
|
||||
employees: Array<EmployeeResponseDTO> = [];
|
||||
|
|
|
@ -5,18 +5,13 @@
|
|||
</a>
|
||||
<hr>
|
||||
<ul class="nav nav-pills flex-column mb-auto">
|
||||
<li class="nav-item">
|
||||
<a href="#" class="nav-link active text-black" aria-current="page">
|
||||
Dashboard
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#" class="nav-link text-black">
|
||||
<a [routerLink]="['/mitarbeiter']" (click)="employees()" [class.active]="route == 'employee'" class="nav-link text-black" aria-current="page">
|
||||
Mitarbeiterverwaltung
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#" class="nav-link text-black">
|
||||
<a [routerLink]="['/qualifikationsverwaltung']" [class.active]="route == 'skill'" class="nav-link text-black">
|
||||
Qualifikationsverwaltung
|
||||
</a>
|
||||
</li>
|
||||
|
|
|
@ -1,12 +1,18 @@
|
|||
import { Component } from '@angular/core';
|
||||
import { Component, Input } from '@angular/core';
|
||||
import { ActivatedRoute, Router, RouterLink } from '@angular/router';
|
||||
|
||||
@Component({
|
||||
selector: 'app-navigation-bar',
|
||||
standalone: true,
|
||||
imports: [],
|
||||
imports: [RouterLink],
|
||||
templateUrl: './navigation-bar.component.html',
|
||||
styleUrl: './navigation-bar.component.css'
|
||||
})
|
||||
export class NavigationBarComponent {
|
||||
constructor(private router: Router) { }
|
||||
@Input() route: string = "";
|
||||
|
||||
employees() {
|
||||
this.router.navigate(['mitarbeiter']);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
<app-qualifikation-form [(skill)]="skill" (skillChange)="submitted($event)"></app-qualifikation-form>
|
|
@ -0,0 +1,23 @@
|
|||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { QulifikationErstellenComponent } from './qulifikation-erstellen.component';
|
||||
|
||||
describe('QulifikationErstellenComponent', () => {
|
||||
let component: QulifikationErstellenComponent;
|
||||
let fixture: ComponentFixture<QulifikationErstellenComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [QulifikationErstellenComponent]
|
||||
})
|
||||
.compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(QulifikationErstellenComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
|
@ -0,0 +1,29 @@
|
|||
import { Component } from '@angular/core';
|
||||
import { QualifikationFormComponent } from '../qualifikation-form/qualifikation-form.component';
|
||||
import { QualificationGetDTO } from '../../models/skill';
|
||||
import { SkillService } from '../../service/skill.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-qulifikation-erstellen',
|
||||
standalone: true,
|
||||
imports: [QualifikationFormComponent],
|
||||
templateUrl: './qualifikation-erstellen.component.html',
|
||||
styleUrl: './qualifikation-erstellen.component.css'
|
||||
})
|
||||
export class QulifikationErstellenComponent {
|
||||
public skill!: QualificationGetDTO;
|
||||
|
||||
constructor(private skillService: SkillService) { }
|
||||
|
||||
submitted(skill: QualificationGetDTO) {
|
||||
console.log(skill);
|
||||
this.skillService.createSkill(skill);
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.skill = {
|
||||
id: 0,
|
||||
skill: '',
|
||||
};
|
||||
}
|
||||
}
|
|
@ -115,7 +115,7 @@ export class QualifikationFormComponent {
|
|||
this.skill.skill = this.skillForm.get("name")?.value;
|
||||
this.skillChange.emit(this.skill);
|
||||
|
||||
this.router.navigate(["/qualifikationen"]);
|
||||
this.router.navigate(["/qualifikationsverwaltung"]);
|
||||
}
|
||||
|
||||
ngOnChanges(): void {
|
||||
|
|
|
@ -1,47 +1,60 @@
|
|||
<div class="container">
|
||||
<div class="header">
|
||||
<div class="dropdown position-absolute top-0 end-0 m-3">
|
||||
<button class="btn align-items-center d-flex" type="button" id="userDropdown" data-bs-toggle="dropdown"
|
||||
aria-expanded="false">
|
||||
<img src="user.svg" alt="User Icon" class="rounded-circle" style="width: 30px; height: 30px;">
|
||||
</button>
|
||||
<ul class="dropdown-menu dropdown-menu-end" aria-labelledby="userDropdown">
|
||||
<li><a class="dropdown-item" href="/logout">Log out</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<h1>Qualifications</h1>
|
||||
</div>
|
||||
|
||||
<div class="header-actions">
|
||||
<form [formGroup]="searchForm">
|
||||
<div class="search-bar">
|
||||
<input type="text" placeholder="Search employee" formControlName="search">
|
||||
<button (click)="submit()">Search</button>
|
||||
<div class="d-flex flex-row">
|
||||
<app-navigation-bar [route]="'skill'" class="row" style="height: 100vh;"></app-navigation-bar>
|
||||
<div class="container">
|
||||
<div class="header">
|
||||
<div class="dropdown position-absolute top-0 end-0 m-3">
|
||||
<button class="btn align-items-center d-flex" type="button" id="userDropdown" data-bs-toggle="dropdown"
|
||||
aria-expanded="false">
|
||||
<img src="user.svg" alt="User Icon" class="rounded-circle" style="width: 30px; height: 30px;">
|
||||
</button>
|
||||
<ul class="dropdown-menu dropdown-menu-end" aria-labelledby="userDropdown">
|
||||
<li><a class="dropdown-item" href="/logout">Log out</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<p class="text-body-tertiary">Search for a propertiy of a Qualification. eg. Name</p>
|
||||
</form>
|
||||
<button (click)="createSkill()" class="add-button">Add qualification</button>
|
||||
</div>
|
||||
<h1>Qualifications</h1>
|
||||
</div>
|
||||
|
||||
<table class="employee-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th><span class="sortable">Name</span></th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@if (skills) {
|
||||
@for (skill of skills; track skill) {
|
||||
<tr>
|
||||
<td>{{ skill.skill }}</td>
|
||||
<td>
|
||||
<button class="btn btn-primary me-2" (click)="editSkill(skill.id)">Edit</button>
|
||||
<button class="btn btn-danger" (click)="deleteSkill(skill.id)">Delete</button>
|
||||
</td>
|
||||
</tr>
|
||||
<div class="d-flex flex-column">
|
||||
<div class="row header-actions">
|
||||
<form [formGroup]="searchForm">
|
||||
<div class="search-bar">
|
||||
<input type="text" placeholder="Search employee" formControlName="search">
|
||||
<button (click)="submit()">Search</button>
|
||||
</div>
|
||||
<p class="text-body-tertiary">Search for a propertiy of a Qualification. eg. Name</p>
|
||||
</form>
|
||||
<div class="d-flex">
|
||||
<button (click)="createSkill()" class="add-button me-auto">Add qualification</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@if (errorDeletingSkill) {
|
||||
<div class="row">
|
||||
<p class="alert alert-danger">This Qualification can not be deleted because it still has employees.</p>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<table class="employee-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th><span class="sortable">Name</span></th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@if (skills) {
|
||||
@for (skill of skills; track skill) {
|
||||
<tr>
|
||||
<td>{{ skill.skill }}</td>
|
||||
<td>
|
||||
<button class="btn btn-primary me-2" (click)="editSkill(skill.id)">Edit</button>
|
||||
<button class="btn btn-danger" (click)="deleteSkill(skill.id)">Delete</button>
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -3,19 +3,21 @@ import { QualificationGetDTO } from '../../models/skill';
|
|||
import { FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms';
|
||||
import { SkillService } from '../../service/skill.service';
|
||||
import { Router } from '@angular/router';
|
||||
import { NavigationBarComponent } from '../navigation-bar/navigation-bar.component';
|
||||
|
||||
@Component({
|
||||
selector: 'app-qualifikationsverwaltung',
|
||||
standalone: true,
|
||||
imports: [ReactiveFormsModule],
|
||||
imports: [ReactiveFormsModule, NavigationBarComponent],
|
||||
templateUrl: './qualifikationsverwaltung.component.html',
|
||||
styleUrl: './qualifikationsverwaltung.component.css'
|
||||
})
|
||||
export class QualifikationsverwaltungComponent {
|
||||
skills: Array<QualificationGetDTO> = [];
|
||||
public searchForm!: FormGroup;
|
||||
public errorDeletingSkill = false;
|
||||
|
||||
constructor(private skillService: SkillService, private router: Router) {}
|
||||
constructor(private skillService: SkillService, private router: Router) { }
|
||||
|
||||
submit() {
|
||||
const searchTerm = this.searchForm.get("search")?.value || '';
|
||||
|
@ -44,8 +46,15 @@ export class QualifikationsverwaltungComponent {
|
|||
}
|
||||
|
||||
deleteSkill(id: number) {
|
||||
this.skillService.deleteSkill(id);
|
||||
this.skills = this.skills.filter(skill => skill.id != id);
|
||||
this.skillService.getEmployeesBySkill(id).subscribe(employees => {
|
||||
this.errorDeletingSkill = false;
|
||||
if (employees.employees.length == 0) {
|
||||
this.skillService.deleteSkill(id);
|
||||
this.skills = this.skills.filter(skill => skill.id != id);
|
||||
} else {
|
||||
this.errorDeletingSkill = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
|
|
|
@ -15,7 +15,7 @@ import { ActivatedRoute } from '@angular/router';
|
|||
export class QualifikatonBearbeitenViewComponent {
|
||||
public skill!: QualificationGetDTO;
|
||||
|
||||
constructor(private skillService: SkillService, private route: ActivatedRoute) {}
|
||||
constructor(private skillService: SkillService, private route: ActivatedRoute) { }
|
||||
|
||||
submitted(skill: QualificationGetDTO) {
|
||||
this.skillService.updateSkill(skill);
|
||||
|
|
|
@ -28,6 +28,10 @@ export class SkillService {
|
|||
}
|
||||
}
|
||||
|
||||
createSkill(skill: QualificationGetDTO) {
|
||||
this.http.post(`${SkillService.BASE_URL}/qualifications`, this.getToPutDto(skill)).subscribe();
|
||||
}
|
||||
|
||||
constructor(private http: HttpClient, private employeeService: EmployeeService) {
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue