Merge pull request 'chore: Update branch' (#4) from Maradona/Backend:restfull into main

Reviewed-on: 2210970/Backend#4
pull/1/head
Mohammad Hawrami 2024-11-08 10:41:28 +01:00
commit 261025bdda
46 changed files with 1557 additions and 3445 deletions

Binary file not shown.

File diff suppressed because it is too large Load Diff

11
pom.xml
View File

@ -90,7 +90,18 @@
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<classifier>exec</classifier>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.4.1</version>
<configuration>
<destDir>${project.build.directory}/docs</destDir>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,113 @@
package com.maradona.backend;
import com.maradona.backend.entities.Employee;
import com.maradona.backend.entities.EmployeeSecondarySkill;
import com.maradona.backend.entities.FormOfAddress;
import com.maradona.backend.entities.PrimarySkill;
import com.maradona.backend.entities.SecondarySkill;
import com.maradona.backend.repositories.EmployeeRepository;
import com.maradona.backend.repositories.FormOfAddressRepository;
import com.maradona.backend.repositories.PrimarySkillRepository;
import com.maradona.backend.repositories.SecondarySkillRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
import java.time.LocalTime;
import java.util.ArrayList;
import java.util.List;
@Component
public class DefaultValueLoader implements CommandLineRunner {
@Autowired
private PrimarySkillRepository primarySkillRepository;
@Autowired
private SecondarySkillRepository secondarySkillRepository;
@Autowired
private EmployeeRepository employeeRepository;
@Autowired
private FormOfAddressRepository formOfAddressRepository;
@Override
public void run(String... args) throws Exception {
// Clear all tables
// formOfAddressRepository.deleteAll();
// employeeRepository.deleteAll();
// secondarySkillRepository.deleteAll();
// primarySkillRepository.deleteAll();
// Create form of addresses
FormOfAddress formOfAddress1 = new FormOfAddress();
formOfAddress1.setDescription("Herr");
FormOfAddress formOfAddress2 = new FormOfAddress();
formOfAddress2.setDescription("Frau");
FormOfAddress formOfAddress3 = new FormOfAddress();
formOfAddress3.setDescription("Einkaufstüte");
formOfAddress1 = formOfAddressRepository.save(formOfAddress1);
formOfAddress2 = formOfAddressRepository.save(formOfAddress2);
// Create primary skills
PrimarySkill primarySkill1 = new PrimarySkill();
primarySkill1.setDescription("Software Development");
PrimarySkill primarySkill2 = new PrimarySkill();
primarySkill2.setDescription("Project Management");
primarySkillRepository.save(primarySkill1);
primarySkillRepository.save(primarySkill2);
// Create secondary skills
SecondarySkill secondarySkill1 = new SecondarySkill();
secondarySkill1.setDescription("Java");
secondarySkill1.setPrimarySkill(primarySkill1);
SecondarySkill secondarySkill2 = new SecondarySkill();
secondarySkill2.setDescription("Agile Methodology");
secondarySkill2.setPrimarySkill(primarySkill2);
SecondarySkill secondarySkill3 = new SecondarySkill();
secondarySkill3.setDescription("Risk Management");
secondarySkill3.setPrimarySkill(primarySkill2);
secondarySkillRepository.save(secondarySkill1);
secondarySkillRepository.save(secondarySkill2);
secondarySkillRepository.save(secondarySkill3);
// Create employees
Employee employee1 = new Employee();
employee1.setEmployeeNr(1);
employee1.setFirstName("Jane");
employee1.setLastName("Smith");
employee1.setDStart(LocalTime.of(9, 0));
employee1.setDEnd(LocalTime.of(17, 0));
employee1.setFormOfAddress(formOfAddress2);
employeeRepository.save(employee1);
// Assign secondary skills to employees
EmployeeSecondarySkill employeeSecondarySkill1 = new EmployeeSecondarySkill();
employeeSecondarySkill1.setEmployee(employee1);
employeeSecondarySkill1.setSecondarySkill(secondarySkill1);
employeeSecondarySkill1.setLevel(4);
EmployeeSecondarySkill employeeSecondarySkill2 = new EmployeeSecondarySkill();
employeeSecondarySkill2.setEmployee(employee1);
employeeSecondarySkill2.setSecondarySkill(secondarySkill2);
employeeSecondarySkill2.setLevel(3);
List<EmployeeSecondarySkill> employee1Skills = new ArrayList<>();
employee1Skills.add(employeeSecondarySkill1);
employee1Skills.add(employeeSecondarySkill2);
employee1.setSecondarySkills(employee1Skills);
employeeRepository.save(employee1);
}
}

View File

@ -1,45 +0,0 @@
package com.maradona.backend.controllers;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import org.springframework.beans.factory.annotation.Autowired;
import com.maradona.backend.entities.Project;
import com.maradona.backend.services.ProjectService;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
@Controller
@RequestMapping("/projects")
public class ProjectController {
@Autowired
private ProjectService projectService;
@GetMapping({ "/", "" })
public String projects(Model model) {
var projectData = projectService.getAllProjects();
model.addAttribute("projectData", projectData);
return "projects";
}
@GetMapping("/create")
public String create(Model model) {
model.addAttribute("project", new Project());
return "project-create";
}
@PostMapping("/save")
public String save(@ModelAttribute Project project) {
projectService.saveProject(project);
return "redirect:/projects";
}
@PostMapping("/delete")
public String delete(@RequestParam Long id) {
projectService.deleteProject(id);
return "redirect:/projects";
}
}

View File

@ -1,31 +0,0 @@
package com.maradona.backend.controllers;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import com.maradona.backend.services.EmployeeService;
import com.maradona.backend.services.SkillService;
@Controller
@RequestMapping("/skills")
public class SkillsController {
@Autowired
private EmployeeService employeeService;
@Autowired
private SkillService skillService;
@GetMapping({ "/", "" })
public String profile(Model model) {
var employeeData = employeeService.getEmployeeById(Long.valueOf(1));
model.addAttribute("employee", employeeData.orElse(null));
var skillData = skillService.getAllSkills();
model.addAttribute("skillData", skillData);
return "skills";
}
}

View File

@ -0,0 +1,125 @@
package com.maradona.backend.controllers.api;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.maradona.backend.dto.SkillPrototype;
import com.maradona.backend.entities.Employee;
import com.maradona.backend.services.EmployeeService;
/**
* Controller for handling employee related requests.
*
* Endpoints:
* - GET /api/employee
* - GET /api/employee/all
* - GET /api/employee/from-skill
* - GET /api/employee/skill/all
* - POST /api/employee/skill/protoype
* - PUT /api/employee/skill/level
* - DELETE /api/employee/skill
*
* @see com.maradona.backend.entities.Employee
*/
@RestController
@RequestMapping("/api/employee")
public class EmployeeController {
@Autowired
private EmployeeService employeeService;
Long user = Long.valueOf(1);
/**
* Returns a specific employee from the database.
*
* @param id The ID of the requested employee.
* @return The employee with the requested ID.
* @see com.maradona.backend.entities.Employee
*/
@GetMapping({ "/", "" })
public ResponseEntity<Employee> get(@RequestParam Long id) {
return employeeService.getEmployeeById(id)
.map(ResponseEntity::ok)
.orElse(ResponseEntity.notFound().build());
}
/**
* Returns all employees from the database.
*
* @return list of employees
* @see com.maradona.backend.entities.Employee
*/
@GetMapping("/all")
public ResponseEntity<Iterable<Employee>> getAll() {
return ResponseEntity.ok(employeeService.getAllEmployees());
}
/**
* Returns a list of employees for a given secondary skill and level.
*
* @param skillId ID of the secondary skill
* @param level Level of the secondary skill
* @return list of employees
* @see com.maradona.backend.entities.Employee
* @see com.maradona.backend.entities.SecondarySkill
*/
@GetMapping("/from-skill")
public ResponseEntity<Iterable<Employee>> getFromSkill(@RequestParam Long skillId, @RequestParam Integer level) {
return ResponseEntity.ok(employeeService.getEmployeesBySecondarySkill(skillId, level));
}
/**
* Adds a secondary skill based on a skillPrototype object to the user profile.
*
* @param skillPrototype The skillPrototype object containing the secondary
* skill ID and level
* @return HTTP status indicating the outcome of the operation
* @see com.maradona.backend.entities.Employee
* @see com.maradona.backend.entities.SecondarySkill
*/
@PostMapping("/skill/protoype")
public ResponseEntity<Void> postSkillProtoype(@RequestBody SkillPrototype skillPrototype) {
employeeService.addSecondarySkillToEmployee(user, skillPrototype);
return ResponseEntity.status(HttpStatus.CREATED).build();
}
/**
* Updates the level of a secondary skill in the user profile.
*
* @param skillId ID of the secondary skill
* @param level Level of the secondary skill
* @return HTTP status indicating the outcome of the operation
* @see com.maradona.backend.entities.Employee
* @see com.maradona.backend.entities.SecondarySkill
* @see com.maradona.backend.entities.EmployeeSecondarySkill
*/
@PutMapping("/skill/level")
public ResponseEntity<Void> putSkillLevel(@RequestParam Long skillId, @RequestParam Integer level) {
employeeService.updateSecondarySkillLevel(user, skillId, level);
return ResponseEntity.ok().build();
}
/**
* Removes a secondary skill from the user profile.
*
* @param id The ID of the secondary skill to be removed
* @return HTTP status indicating the outcome of the operation
* @see com.maradona.backend.entities.Employee
* @see com.maradona.backend.entities.SecondarySkill
*/
@DeleteMapping("/skill")
public ResponseEntity<Void> delete(@RequestParam Long id) {
employeeService.deleteSecondarySkillFromEmployee(user, id);
return ResponseEntity.noContent().build();
}
}

View File

@ -0,0 +1,116 @@
package com.maradona.backend.controllers.api;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.maradona.backend.entities.PrimarySkill;
import com.maradona.backend.entities.SecondarySkill;
import com.maradona.backend.services.PrimarySkillService;
import com.maradona.backend.services.SecondarySkillService;
/**
* Controller for handling primary skill data.
*
* List of endpoints:
* - GET /api/primary-skill
* - GET /api/primary-skill/all
* - POST /api/primary-skill
* - PUT /api/primary-skill
* - DELETE /api/primary-skill
*
* @see com.maradona.backend.entities.PrimarySkill
*/
@RestController
@RequestMapping("/api/primary-skill")
public class PrimarySkillController {
@Autowired
private PrimarySkillService primarySkillService;
@Autowired
private SecondarySkillService secondarySkillService;
/**
* Returns a specific primary skill from the database.
*
* @param id The ID of the requested primary skill.
* @return The primary skill with the requested ID.
* @see com.maradona.backend.entities.PrimarySkill
*/
@GetMapping({ "/", "" })
public ResponseEntity<PrimarySkill> get(@RequestParam Long id) {
return primarySkillService.getPrimarySkillById(id)
.map(ResponseEntity::ok)
.orElse(ResponseEntity.notFound().build());
}
/**
* Returns all primary skills from the database.
*
* @return list of primary skills
* @see com.maradona.backend.entities.PrimarySkill
*/
@GetMapping("/all")
public ResponseEntity<Iterable<PrimarySkill>> getAll() {
return ResponseEntity.ok(primarySkillService.getAllPrimarySkills());
}
/**
* Adds a new primary skill to the database.
*
* @param primarySkill The primary skill to be added
* @return The added primary skill
* @see com.maradona.backend.entities.PrimarySkill
*/
@PostMapping({ "/", "" })
public ResponseEntity<PrimarySkill> post(@RequestBody PrimarySkill primarySkill) {
PrimarySkill savedPrimarySkill = primarySkillService.savePrimarySkill(primarySkill);
return ResponseEntity.status(HttpStatus.CREATED).body(savedPrimarySkill);
}
/**
* Modifies an existing primary skill in the database.
*
* @param primarySkill The primary skill to be modified
* @return The modified primary skill
* @see com.maradona.backend.entities.PrimarySkill
*/
@PutMapping({ "/", "" })
public ResponseEntity<PrimarySkill> put(@RequestBody PrimarySkill primarySkill) {
PrimarySkill updatedPrimarySkill = primarySkillService.savePrimarySkill(primarySkill);
return ResponseEntity.ok(updatedPrimarySkill);
}
/**
* Deletes a primary skill from the database.
*
* @param id The ID of the primary skill to be deleted
* @return HTTP status indicating the outcome of the operation
* @see com.maradona.backend.entities.PrimarySkill
*/
@DeleteMapping({ "/", "" })
public ResponseEntity<Void> delete(@RequestParam Long id) {
var primarySkill = primarySkillService.getPrimarySkillById(id);
if (primarySkill.isPresent()) {
var secondarySkills = secondarySkillService.getAllSecondarySkills();
for (SecondarySkill secondarySkill : secondarySkills) {
if (secondarySkill.getPrimarySkill().getPsid().equals(id)) {
secondarySkillService.deleteSecondarySkill(secondarySkill.getSsid());
}
}
primarySkillService.deletePrimarySkill(id);
return ResponseEntity.noContent().build();
} else {
return ResponseEntity.notFound().build();
}
}
}

View File

@ -0,0 +1,116 @@
package com.maradona.backend.controllers.api;
import java.util.Optional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.maradona.backend.entities.Project;
import com.maradona.backend.services.ProjectService;
/**
* Controller for handling project data.
*
* List of endpoints:
* - GET /api/project
* - GET /api/project/all
* - GET /api/project/from-user
* - POST /api/project
* - PUT /api/project
* - DELETE /api/project
*
* @warning The ProjectService is not accounting for the user yet.
* @see com.maradona.backend.entities.Project
* @see com.maradona.backend.services.ProjectService
*/
@RestController
@RequestMapping("/api/project")
public class ProjectController {
@Autowired
private ProjectService projectService;
/**
* Returns a specific project from the database.
*
* @param id The ID of the requested project.
* @return The project with the requested ID.
* @see com.maradona.backend.entities.Project
*/
@GetMapping({ "/", "" })
public ResponseEntity<Project> get(@RequestParam Long id) {
Optional<Project> project = projectService.getProjectById(id);
return project.map(ResponseEntity::ok).orElseGet(() -> ResponseEntity.notFound().build());
}
/**
* Returns all projects from the database.
*
* @return list of projects
* @see com.maradona.backend.entities.Project
*/
@GetMapping("/all")
public ResponseEntity<Iterable<Project>> getAll() {
return ResponseEntity.ok(projectService.getAllProjects());
}
/**
* Returns a list of projects for a given user.
*
* @param userId ID of the user
* @return list of projects
* @see com.maradona.backend.entities.Project
*/
@GetMapping("/from-user")
public ResponseEntity<Iterable<Project>> getFromUser(@RequestParam Long userId) {
return ResponseEntity.ok(projectService.getProjectsByUserId(userId));
}
/**
* Adds a new project to the database.
*
* @param project The project to be added
* @return The added project
* @see com.maradona.backend.entities.Project
*/
@PostMapping({ "/", "" })
public ResponseEntity<Project> post(@RequestBody Project project) {
Project savedProject = projectService.saveProject(project);
return ResponseEntity.status(HttpStatus.CREATED).body(savedProject);
}
/**
* Modifies an existing project in the database.
*
* @param project The project to be modified
* @return The modified project
* @see com.maradona.backend.entities.Project
*/
@PutMapping({ "/", "" })
public ResponseEntity<Project> put(@RequestBody Project project) {
Project updatedProject = projectService.saveProject(project);
return ResponseEntity.ok(updatedProject);
}
/**
* Deletes a project from the database.
*
* @param id The ID of the project to be deleted
* @return HTTP status indicating the outcome of the operation
* @see com.maradona.backend.entities.Project
*/
@DeleteMapping({ "/", "" })
public ResponseEntity<Void> delete(@RequestParam Long id) {
projectService.deleteProject(id);
return ResponseEntity.noContent().build();
}
}

View File

@ -0,0 +1,115 @@
package com.maradona.backend.controllers.api;
import java.util.Optional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.maradona.backend.entities.SecondarySkill;
import com.maradona.backend.services.SecondarySkillService;
/**
* Controller for handling secondary skill data.
*
* List of endpoints:
* - GET /api/secondary-skill
* - GET /api/secondary-skill/all
* - GET /api/secondary-skill/from-primary-skill
* - POST /api/secondary-skill
* - PUT /api/secondary-skill
* - DELETE /api/secondary-skill
*
* @see com.maradona.backend.entities.SecondarySkill
*/
@RestController
@RequestMapping("/api/secondary-skill")
public class SecondarySkillController {
@Autowired
private SecondarySkillService secondarySkillService;
/**
* Returns a specific secondary skill from the database.
*
* @param id The ID of the requested secondary skill.
* @return The secondary skill with the requested ID.
* @see com.maradona.backend.entities.SecondarySkill
*/
@GetMapping({ "/", "" })
public ResponseEntity<SecondarySkill> get(@RequestParam Long id) {
Optional<SecondarySkill> secondarySkill = secondarySkillService.getSecondarySkillById(id);
return secondarySkill.map(ResponseEntity::ok).orElseGet(() -> ResponseEntity.notFound().build());
}
/**
* Returns all secondary skills from the database.
*
* @return list of secondary skills
* @see com.maradona.backend.entities.SecondarySkill
*/
@GetMapping("/all")
public ResponseEntity<Iterable<SecondarySkill>> getAll() {
return ResponseEntity.ok(secondarySkillService.getAllSecondarySkills());
}
/**
* Returns a list of secondary skills for a given primary skill.
*
* @param primarySkillId ID of the primary skill
* @return list of secondary skills
* @see com.maradona.backend.entities.SecondarySkill
* @see com.maradona.backend.entities.PrimarySkill
*/
@GetMapping("/from-primary-skill")
public ResponseEntity<Iterable<SecondarySkill>> getSecondarySkills(@RequestParam Long primarySkillId) {
return ResponseEntity.ok(secondarySkillService.getSecondarySkillsByPrimarySkillId(primarySkillId));
}
/**
* Adds a new secondary skill to the database.
*
* @param secondarySkill The secondary skill to be added
* @return The added secondary skill
* @see com.maradona.backend.entities.SecondarySkill
*/
@PostMapping({ "/", "" })
public ResponseEntity<SecondarySkill> post(@RequestBody SecondarySkill secondarySkill) {
SecondarySkill savedSecondarySkill = secondarySkillService.saveSecondarySkill(secondarySkill);
return ResponseEntity.status(HttpStatus.CREATED).body(savedSecondarySkill);
}
/**
* Modifies an existing secondary skill in the database.
*
* @param secondarySkill The secondary skill to be modified
* @return The modified secondary skill
* @see com.maradona.backend.entities.SecondarySkill
*/
@PutMapping({ "/", "" })
public ResponseEntity<SecondarySkill> put(@RequestBody SecondarySkill secondarySkill) {
SecondarySkill updatedSecondarySkill = secondarySkillService.saveSecondarySkill(secondarySkill);
return ResponseEntity.ok(updatedSecondarySkill);
}
/**
* Deletes a secondary skill from the database.
*
* @param id The ID of the secondary skill to be deleted
* @return HTTP status indicating the outcome of the operation
* @see com.maradona.backend.entities.SecondarySkill
*/
@DeleteMapping({ "/", "" })
public ResponseEntity<Void> delete(@RequestParam Long id) {
secondarySkillService.deleteSecondarySkill(id);
return ResponseEntity.noContent().build();
}
}

View File

@ -1,11 +1,11 @@
package com.maradona.backend.controllers;
package com.maradona.backend.controllers.page;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class PageController {
public class Page {
@GetMapping({ "/", "" })
public String home(Model model) {
@ -14,11 +14,16 @@ public class PageController {
@GetMapping("/impressum")
public String impressum() {
return "impressum";
return "core/impressum";
}
@GetMapping("/datenschutz")
public String datenschutz() {
return "datenschutz";
return "core/datenschutz";
}
@GetMapping("/notes")
public String notes() {
return "notes/notes";
}
}

View File

@ -0,0 +1,56 @@
package com.maradona.backend.controllers.page;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import org.springframework.beans.factory.annotation.Autowired;
import com.maradona.backend.entities.Project;
import com.maradona.backend.services.ProjectService;
/**
* Controller for routing to project related pages.
*
* List of endpoints:
* - GET /projects
* - GET /projects/create
*
* @see Project
*/
@Controller
@RequestMapping("/projects")
public class ProjectPage {
@Autowired
private ProjectService projectService;
/**
* Returns the projects overview page.
* Collects the project list and adds it to the model for the frontend.
*
* Attributes that can be used by the frontend are a List of Project objects
* "projects".
*
* @param model The model with the data to be displayed.
* @return The projects overview page template
* @see Project
*/
@GetMapping({ "/", "" })
public String projects(Model model) {
var projects = projectService.getAllProjects();
model.addAttribute("projects", projects);
return "projects/projects";
}
/**
* Returns the project creation page.
*
* @param model The model with the data to be displayed.
* @return The project creation page template
* @see Project
*/
@GetMapping("/create")
public String create(Model model) {
model.addAttribute("project", new Project());
return "projects/projects-create";
}
}

View File

@ -0,0 +1,102 @@
package com.maradona.backend.controllers.page;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.stereotype.Controller;
import com.maradona.backend.entities.SecondarySkill;
import com.maradona.backend.entities.Employee;
import com.maradona.backend.entities.PrimarySkill;
import com.maradona.backend.services.EmployeeService;
import com.maradona.backend.services.SkillService;
import com.maradona.backend.services.PrimarySkillService;
import com.maradona.backend.dto.SkillPrototype;
/**
* Controller for routing to the skills related pages.
*
* List of endpoints:
* - GET /skills
* - GET /skills/create
* - GET /skills/add
*
*/
@Controller
@RequestMapping("/skills")
public class SkillsPage {
@Autowired
private EmployeeService employeeService;
@Autowired
private SkillService skillService;
@Autowired
private PrimarySkillService primarySkillService;
// Hardcoded placeholder user ID for now
Long user = Long.valueOf(1);
/**
* Returns the skills overview page.
* Collects the employee and skills data and adds it to the model for the
* frontend.
*
* Attributes that can be used by the frontend are a Employee object
* "employee" and a SkillsDto object "skills".
*
* @param model The model with the data to be displayed.
* @return The skills overview page template
* @see Employee
* @see SkillsDto
*/
@GetMapping({ "/", "" })
public String profile(Model model) {
model.addAttribute("employee", employeeService.getEmployeeById(user).orElse(null));
model.addAttribute("skills", skillService.getUserSkills(user));
return "skills/skills";
}
/**
* Returns the create skill page.
*
* Attributes that can be used by the frontend are a SecondarySkill object
* "secondarySkill".
*
* @param model The model with the data to be displayed
* @return The create skill page template
* @see SecondarySkill
*/
@GetMapping("/create")
public String createSkill(Model model) {
model.addAttribute("secondarySkill", new SecondarySkill());
return "skills/skills-create";
}
/**
* Returns the page used to add a skill to the user profile.
*
* Attributes that can be used by the frontend are a PrimarySkill object
* "primarySkill", a SecondarySkill object "secondarySkill" and a
* SkillProtoype object "skillProtoype".
*
* The skillProtoype object contains the data needed to add a skill to the user
* profile.
* To add it to a user profile, POST to /api/employee/skill/protoype.
*
* @param model The model with the data to be displayed
* @return The add skill page template
* @see PrimarySkill
* @see SecondarySkill
* @see SkillPrototype
*/
@GetMapping("/add")
public String addSkill(Model model) {
// TODO: Make sure it returns the correct initail data for secondary skills
model.addAttribute("primarySkills", primarySkillService.getAllPrimarySkills());
model.addAttribute("skillProtoype", new SkillPrototype());
return "skills/skills-add";
}
}

View File

@ -2,13 +2,14 @@ package com.maradona.backend.dto;
import com.maradona.backend.entities.PrimarySkill;
import com.maradona.backend.entities.SecondarySkill;
import org.springframework.data.util.Pair;
import java.util.List;
public class Skill {
public class SkillList {
private PrimarySkill primarySkill;
private List<SecondarySkill> secondarySkills;
private List<Pair<SecondarySkill, Integer>> secondarySkills;
public Skill(PrimarySkill primarySkill, List<SecondarySkill> secondarySkills) {
public SkillList(PrimarySkill primarySkill, List<Pair<SecondarySkill, Integer>> secondarySkills) {
this.primarySkill = primarySkill;
this.secondarySkills = secondarySkills;
}
@ -21,11 +22,11 @@ public class Skill {
this.primarySkill = primarySkill;
}
public List<SecondarySkill> getSecondarySkills() {
public List<Pair<SecondarySkill, Integer>> getSecondarySkills() {
return secondarySkills;
}
public void setSecondarySkills(List<SecondarySkill> secondarySkills) {
public void setSecondarySkills(List<Pair<SecondarySkill, Integer>> secondarySkills) {
this.secondarySkills = secondarySkills;
}
}

View File

@ -0,0 +1,31 @@
package com.maradona.backend.dto;
public class SkillPrototype {
private Long primarySkillId;
private Long secondarySkillId;
private Integer level;
public Long getPrimarySkillId() {
return primarySkillId;
}
public void setPrimarySkillId(Long primarySkillId) {
this.primarySkillId = primarySkillId;
}
public Long getSecondarySkillId() {
return secondarySkillId;
}
public void setSecondarySkillId(Long secondarySkillId) {
this.secondarySkillId = secondarySkillId;
}
public Integer getLevel() {
return level;
}
public void setLevel(Integer level) {
this.level = level;
}
}

View File

@ -3,6 +3,9 @@ package com.maradona.backend.entities;
import jakarta.persistence.*;
import lombok.Data;
import java.time.LocalTime;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@Entity
@Data
@ -24,12 +27,12 @@ public class Employee {
@JoinColumn(name = "AID")
private FormOfAddress formOfAddress;
@Column(length = 150)
private String mail;
private LocalTime dStart;
private LocalTime dEnd;
@OneToMany(mappedBy = "employee", cascade = CascadeType.ALL, orphanRemoval = true)
private List<EmployeeSecondarySkill> secondarySkills;
public void setEmployeeNr(Integer employeeNr) {
this.employeeNr = employeeNr;
}
@ -62,14 +65,6 @@ public class Employee {
return formOfAddress;
}
public void setMail(String mail) {
this.mail = mail;
}
public String getMail() {
return mail;
}
public void setDStart(LocalTime dStart) {
this.dStart = dStart;
}
@ -85,4 +80,17 @@ public class Employee {
public LocalTime getDEnd() {
return dEnd;
}
}
public void setSecondarySkills(List<EmployeeSecondarySkill> secondarySkills) {
this.secondarySkills = secondarySkills;
}
public List<EmployeeSecondarySkill> getSecondarySkills() {
return secondarySkills;
}
public Map<SecondarySkill, Integer> getSecondarySkillLevels() {
return secondarySkills.stream()
.collect(Collectors.toMap(EmployeeSecondarySkill::getSecondarySkill, EmployeeSecondarySkill::getLevel));
}
}

View File

@ -0,0 +1,59 @@
package com.maradona.backend.entities;
import jakarta.persistence.*;
import com.fasterxml.jackson.annotation.JsonBackReference;
import lombok.Data;
@Entity
@Data
public class EmployeeSecondarySkill {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ManyToOne
@JoinColumn(name = "employee_id", nullable = false)
@JsonBackReference
private Employee employee;
@ManyToOne
@JoinColumn(name = "secondary_skill_id", nullable = false)
@JsonBackReference
private SecondarySkill secondarySkill;
@Column(nullable = false)
private Integer level;
public void setId(Long id) {
this.id = id;
}
public Long getId() {
return id;
}
public void setEmployee(Employee employee) {
this.employee = employee;
}
public Employee getEmployee() {
return employee;
}
public void setSecondarySkill(SecondarySkill secondarySkill) {
this.secondarySkill = secondarySkill;
}
public SecondarySkill getSecondarySkill() {
return secondarySkill;
}
public void setLevel(Integer level) {
this.level = level;
}
public Integer getLevel() {
return level;
}
}

View File

@ -1,11 +1,13 @@
package com.maradona.backend.entities;
import jakarta.persistence.*;
import com.fasterxml.jackson.annotation.JsonManagedReference;
import lombok.Data;
import java.util.List;
@Entity
@Data
public class PrimarySkill {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long psid;
@ -14,6 +16,7 @@ public class PrimarySkill {
private String description;
@OneToMany(mappedBy = "primarySkill", cascade = CascadeType.ALL, orphanRemoval = true)
@JsonManagedReference
private List<SecondarySkill> secondarySkills;
public void setPsid(Long psid) {

View File

@ -1,10 +1,14 @@
package com.maradona.backend.entities;
import jakarta.persistence.*;
import com.fasterxml.jackson.annotation.JsonBackReference;
import com.fasterxml.jackson.annotation.JsonManagedReference;
import lombok.Data;
import java.util.List;
@Entity
@Data
public class SecondarySkill {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long ssid;
@ -14,8 +18,13 @@ public class SecondarySkill {
@ManyToOne
@JoinColumn(name = "psid", nullable = false)
@JsonBackReference
private PrimarySkill primarySkill;
@OneToMany(mappedBy = "secondarySkill", cascade = CascadeType.ALL, orphanRemoval = true)
@JsonManagedReference
private List<EmployeeSecondarySkill> employeeSecondarySkills;
public void setSsid(Long ssid) {
this.ssid = ssid;
}
@ -39,4 +48,12 @@ public class SecondarySkill {
public PrimarySkill getPrimarySkill() {
return primarySkill;
}
public void setEmployeeSecondarySkills(List<EmployeeSecondarySkill> employeeSecondarySkills) {
this.employeeSecondarySkills = employeeSecondarySkills;
}
public List<EmployeeSecondarySkill> getEmployeeSecondarySkills() {
return employeeSecondarySkills;
}
}

View File

@ -0,0 +1,9 @@
package com.maradona.backend.repositories;
import org.springframework.data.repository.CrudRepository;
import com.maradona.backend.entities.EmployeeSecondarySkill;
import java.util.List;
public interface EmployeeSecondarySkillRepository extends CrudRepository<EmployeeSecondarySkill, Long> {
List<EmployeeSecondarySkill> findByEmployeeId(Long employeeId);
}

View File

@ -3,16 +3,20 @@ package com.maradona.backend.services;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.maradona.backend.entities.Employee;
import com.maradona.backend.entities.EmployeeSecondarySkill;
import com.maradona.backend.repositories.EmployeeRepository;
import com.maradona.backend.dto.SkillPrototype;
import java.util.Optional;
@Service
public class EmployeeService {
@Autowired
private EmployeeRepository employeeRepository;
@Autowired
private SecondarySkillService secondarySkillService;
public Employee saveEmployee(Employee employee) {
return employeeRepository.save(employee);
}
@ -28,4 +32,53 @@ public class EmployeeService {
public Iterable<Employee> getAllEmployees() {
return employeeRepository.findAll();
}
}
public void addSecondarySkillToEmployee(Long userId, SkillPrototype skillPrototype) {
var employee = getEmployeeById(userId).orElseThrow(() -> new RuntimeException("Employee not found"));
var secondarySkill = secondarySkillService.getSecondarySkillById(skillPrototype.getSecondarySkillId())
.orElseThrow(() -> new RuntimeException("Secondary Skill not found"));
for (EmployeeSecondarySkill skill : employee.getSecondarySkills()) {
if (skill.getSecondarySkill().getSsid().equals(skillPrototype.getSecondarySkillId())) {
return;
}
}
EmployeeSecondarySkill employeeSecondarySkill = new EmployeeSecondarySkill();
employeeSecondarySkill.setEmployee(employee);
employeeSecondarySkill.setSecondarySkill(secondarySkill);
employeeSecondarySkill.setLevel(skillPrototype.getLevel());
employee.getSecondarySkills().add(employeeSecondarySkill);
saveEmployee(employee);
}
public void updateSecondarySkillLevel(Long userId, Long skillId, Integer level) {
var employee = getEmployeeById(userId).orElseThrow(() -> new RuntimeException("Employee not found"));
secondarySkillService.getSecondarySkillById(skillId)
.orElseThrow(() -> new RuntimeException("Secondary Skill not found"));
for (EmployeeSecondarySkill skill : employee.getSecondarySkills()) {
if (skill.getSecondarySkill().getSsid().equals(skillId)) {
skill.setLevel(level);
break;
}
}
saveEmployee(employee);
}
public void deleteSecondarySkillFromEmployee(Long userId, Long skillId) {
var employee = getEmployeeById(userId).orElseThrow(() -> new RuntimeException("Employee not found"));
secondarySkillService.getSecondarySkillById(skillId)
.orElseThrow(() -> new RuntimeException("Secondary Skill not found"));
employee.getSecondarySkills().removeIf(skill -> skill.getSecondarySkill().getSsid().equals(skillId));
saveEmployee(employee);
}
public Iterable<Employee> getEmployeesBySecondarySkill(Long skillId, Integer level) {
// Implement logic to fetch employees by secondary skill and level
// This is a placeholder implementation
return employeeRepository.findAll();
}
}

View File

@ -28,4 +28,14 @@ public class PrimarySkillService {
public Iterable<PrimarySkill> getAllPrimarySkills() {
return primarySkillRepository.findAll();
}
public Optional<PrimarySkill> findByDescription(String description) {
var allPrimarySkills = primarySkillRepository.findAll();
for (PrimarySkill primarySkill : allPrimarySkills) {
if (primarySkill.getDescription().equals(description)) {
return Optional.of(primarySkill);
}
}
return Optional.empty();
}
}

View File

@ -28,4 +28,9 @@ public class ProjectService {
public Iterable<Project> getAllProjects() {
return projectRepository.findAll();
}
public Iterable<Project> getProjectsByUserId(Long userId) {
// TODO: Actually filter by user
return projectRepository.findAll();
}
}

View File

@ -9,11 +9,22 @@ import java.util.Optional;
@Service
public class SecondarySkillService {
@Autowired
private SecondarySkillRepository secondarySkillRepository;
@Autowired
private PrimarySkillService primarySkillService;
public SecondarySkill saveSecondarySkill(SecondarySkill secondarySkill) {
var primarySkillDescription = secondarySkill.getPrimarySkill().getDescription();
var existingPrimarySkill = primarySkillService.findByDescription(primarySkillDescription);
if (existingPrimarySkill.isPresent()) {
secondarySkill.setPrimarySkill(existingPrimarySkill.get());
} else {
primarySkillService.savePrimarySkill(secondarySkill.getPrimarySkill());
}
return secondarySkillRepository.save(secondarySkill);
}
@ -28,4 +39,16 @@ public class SecondarySkillService {
public Iterable<SecondarySkill> getAllSecondarySkills() {
return secondarySkillRepository.findAll();
}
}
public Iterable<SecondarySkill> getSecondarySkillsByPrimarySkillId(Long primarySkillId) {
var skills = secondarySkillRepository.findAll();
var result = new java.util.ArrayList<SecondarySkill>();
for (SecondarySkill skill : skills) {
if (skill.getPrimarySkill().getPsid().equals(primarySkillId)) {
result.add(skill);
System.out.println(skill.getDescription());
}
}
return result;
}
}

View File

@ -1,15 +1,19 @@
package com.maradona.backend.services;
import com.maradona.backend.dto.Skill;
import com.maradona.backend.dto.SkillList;
import com.maradona.backend.entities.Employee;
import com.maradona.backend.entities.PrimarySkill;
import com.maradona.backend.entities.SecondarySkill;
import com.maradona.backend.repositories.EmployeeRepository;
import com.maradona.backend.repositories.PrimarySkillRepository;
import com.maradona.backend.repositories.SecondarySkillRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.data.util.Pair;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@Service
public class SkillService {
@ -20,22 +24,51 @@ public class SkillService {
@Autowired
private SecondarySkillRepository secondarySkillRepository;
public Iterable<Skill> getAllSkills() {
@Autowired
private EmployeeRepository employeeRepository;
public Iterable<SkillList> getAllSkills() {
Iterable<PrimarySkill> primarySkills = primarySkillRepository.findAll();
Iterable<SecondarySkill> secondarySkills = secondarySkillRepository.findAll();
List<Skill> skills = new ArrayList<>();
List<SkillList> skills = new ArrayList<>();
for (PrimarySkill primarySkill : primarySkills) {
List<SecondarySkill> secondarySkillList = new ArrayList<>();
List<Pair<SecondarySkill, Integer>> secondarySkillList = new ArrayList<>();
for (SecondarySkill secondarySkill : secondarySkills) {
var currentSecondarySkillID = secondarySkill.getPrimarySkill().getPsid();
var currentPrimarySkillID = primarySkill.getPsid();
if (currentSecondarySkillID.equals(currentPrimarySkillID)) {
secondarySkillList.add(secondarySkill);
if (secondarySkill.getPrimarySkill().getPsid().equals(primarySkill.getPsid())) {
secondarySkillList.add(Pair.of(secondarySkill, 3)); // Placeholder level
}
}
skills.add(new Skill(primarySkill, secondarySkillList));
skills.add(new SkillList(primarySkill, secondarySkillList));
}
return skills;
}
public Iterable<SkillList> getUserSkills(Long userId) {
if (userId == null) {
return new ArrayList<>();
}
Employee employee = employeeRepository.findById(userId).orElse(null);
if (employee == null) {
return new ArrayList<>();
}
Map<SecondarySkill, Integer> secondarySkillLevels = employee.getSecondarySkillLevels();
List<SkillList> skills = new ArrayList<>();
for (PrimarySkill primarySkill : primarySkillRepository.findAll()) {
List<Pair<SecondarySkill, Integer>> secondarySkillList = new ArrayList<>();
for (Map.Entry<SecondarySkill, Integer> entry : secondarySkillLevels.entrySet()) {
if (entry.getKey().getPrimarySkill().getPsid().equals(primarySkill.getPsid())) {
secondarySkillList.add(Pair.of(entry.getKey(), entry.getValue()));
}
}
if (!secondarySkillList.isEmpty()) {
skills.add(new SkillList(primarySkill, secondarySkillList));
}
secondarySkillList.sort((a, b) -> a.getFirst().getDescription().compareTo(b.getFirst().getDescription()));
}
skills.sort((a, b) -> a.getPrimarySkill().getDescription().compareTo(b.getPrimarySkill().getDescription()));
return skills;
}
}

View File

@ -0,0 +1,183 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 27.1.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="INTER_x5F_flat_x5F_Logo_x5F_white_-_sRGB"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 283.46457 113.38583" style="enable-background:new 0 0 283.46457 113.38583;" xml:space="preserve">
<path style="fill-rule:evenodd;clip-rule:evenodd;fill:#FFFFFF;" d="M6.80021,113.05209L1.56688,98.16647h2.12632l4.25355,12.90562
H7.9884l4.29514-12.90562h2.06368l-5.29546,14.88562H6.80021z M17.18262,98.16647v14.88562h10.34107v-1.66776h-8.36057v-5.14914
h7.73518v-1.66875h-7.73518v-4.73216h8.29793v-1.66781H17.18262z M38.17726,98.16647c1.4182,0,2.5232,0.34747,3.31546,1.04237
c0.80599,0.69489,1.20924,1.64721,1.20924,2.85595c0,0.9034-0.20846,1.69617-0.62539,2.37738
c-0.40279,0.68021-1.05655,1.1461-1.95995,1.39665v0.04109c0.43116,0.08418,0.77813,0.22314,1.04237,0.41792
c0.27797,0.19479,0.4938,0.43066,0.64643,0.70863c0.16692,0.26424,0.28484,0.56275,0.35434,0.89649
c0.08368,0.33374,0.14632,0.68121,0.18792,1.04237c0.02786,0.36115,0.04891,0.73013,0.06214,1.105
c0.01418,0.37483,0.04896,0.7438,0.10473,1.10496c0.05527,0.3612,0.13214,0.70863,0.22951,1.04237
c0.1106,0.32006,0.2706,0.60489,0.47886,0.85445h-2.20976c-0.13946-0.15269-0.23587-0.36115-0.29165-0.62539
c-0.04164-0.26328-0.07-0.55499-0.08323-0.87499c-0.01468-0.33379-0.02836-0.68808-0.04204-1.06391
c-0.01423-0.37484-0.05582-0.74285-0.12528-1.10501c-0.05532-0.36115-0.12483-0.70176-0.20852-1.02081
c-0.08318-0.33374-0.21528-0.61852-0.39588-0.8554c-0.18055-0.25056-0.41743-0.44434-0.70908-0.58335
c-0.29215-0.15364-0.68121-0.22996-1.16714-0.22996H33.1529v6.35883h-1.98045V98.16647H38.17726z M38.59418,104.92072
c0.41743-0.0685,0.77908-0.20059,1.08446-0.39538c0.32006-0.20847,0.56961-0.47961,0.75067-0.81335
c0.19428-0.34743,0.2922-0.79176,0.2922-1.33401c0-0.75067-0.20896-1.36237-0.62544-1.83513
c-0.41743-0.4727-1.09177-0.70857-2.02254-0.70857H33.1529v5.19118h4.12832
C37.73979,105.02546,38.17726,104.99123,38.59418,104.92072z M55.31568,102.5238h1.87622
c-0.02786-0.82017-0.18742-1.52193-0.47956-2.10622c-0.27797-0.59703-0.66748-1.09032-1.16764-1.47984
c-0.48643-0.38956-1.05655-0.67435-1.70935-0.85445c-0.6533-0.18105-1.36193-0.2711-2.12677-0.2711
c-0.68071,0-1.34824,0.09005-2.00205,0.2711c-0.63912,0.16637-1.21555,0.43066-1.72989,0.79181
c-0.50061,0.34743-0.90336,0.79863-1.20924,1.35556c-0.30588,0.54221-0.45852,1.18819-0.45852,1.93886
c0,0.68121,0.13164,1.25083,0.39538,1.70985c0.27847,0.44434,0.64012,0.81236,1.08446,1.104
c0.45902,0.27897,0.97336,0.50798,1.54348,0.68903c0.56911,0.16642,1.1461,0.31911,1.72989,0.45807
c0.59753,0.12527,1.18183,0.25056,1.75144,0.37488c0.57012,0.12528,1.07709,0.2926,1.52193,0.50111
c0.45907,0.19473,0.82022,0.45116,1.08396,0.77122c0.27847,0.32006,0.41698,0.73698,0.41698,1.25082
c0,0.54221-0.1106,0.9866-0.33329,1.33401c-0.22264,0.34843-0.51434,0.62544-0.8755,0.83485
c-0.3616,0.19383-0.77171,0.33279-1.23023,0.41698c-0.44484,0.08318-0.88968,0.12527-1.33401,0.12527
c-0.55643,0-1.09864-0.0705-1.62666-0.20947c-0.52802-0.13895-0.99391-0.35429-1.39665-0.64598
c-0.38956-0.29165-0.70912-0.66062-0.95918-1.10496c-0.23637-0.45807-0.35429-1.00027-0.35429-1.62571H45.8498
c0,0.9024,0.16006,1.68835,0.48012,2.35583c0.33274,0.6528,0.77758,1.19505,1.33351,1.62566
c0.57011,0.41698,1.22342,0.73018,1.9599,0.93764c0.75072,0.20847,1.54348,0.31319,2.37688,0.31319
c0.68121,0,1.36238-0.08318,2.04359-0.24956c0.6949-0.15269,1.32034-0.40324,1.87622-0.75072
c0.55593-0.3621,1.00814-0.82017,1.35556-1.37611c0.36115-0.56961,0.54226-1.25082,0.54226-2.04359
c0-0.73598-0.13951-1.34769-0.41748-1.83412c-0.26424-0.48648-0.62539-0.88968-1.08441-1.20974
c-0.44434-0.32006-0.95181-0.56962-1.52143-0.75072c-0.57011-0.19473-1.15396-0.36115-1.75194-0.50011
c-0.58384-0.13895-1.16032-0.26424-1.72994-0.37583c-0.57062-0.12433-1.08446-0.27696-1.54348-0.45807
c-0.44434-0.18105-0.80599-0.41006-1.08396-0.68803c-0.26374-0.29165-0.39588-0.66748-0.39588-1.12555
c0-0.48643,0.09055-0.88968,0.2711-1.20974c0.19428-0.33374,0.44434-0.59798,0.75072-0.79276
c0.31906-0.19378,0.68071-0.33279,1.08396-0.41597c0.4032-0.08414,0.81331-0.12528,1.23023-0.12528
c1.02819,0,1.8689,0.24274,2.52271,0.72917C54.81552,100.68185,55.20458,101.45307,55.31568,102.5238z M61.54922,98.16647v14.88562
h1.981V98.16647H61.54922z M78.58246,102.64908h1.98095c-0.11109-0.79276-0.34747-1.48766-0.70862-2.08569
c-0.36161-0.61171-0.81331-1.11868-1.35551-1.52193c-0.54176-0.40325-1.16083-0.70858-1.85522-0.91709
c-0.69489-0.20846-1.43238-0.31219-2.21001-0.31219c-1.14018,0-2.15469,0.20847-3.04431,0.62539
c-0.876,0.4023-1.61248,0.95823-2.21001,1.66781c-0.58335,0.70857-1.02864,1.54247-1.33452,2.50166
c-0.30582,0.94545-0.45852,1.9594-0.45852,3.04386c0,1.08441,0.13846,2.09937,0.41693,3.04386
c0.29214,0.94545,0.7228,1.76562,1.29292,2.46052c0.56961,0.69494,1.28555,1.24401,2.14732,1.64725
c0.86182,0.38852,1.8694,0.5833,3.02287,0.5833c1.90458,0,3.40552-0.52065,4.50365-1.56302s1.74458-2.50166,1.93935-4.37888
h-1.98095c-0.04209,0.6117-0.16687,1.18132-0.37583,1.70985c-0.20802,0.52852-0.50016,0.98659-0.87499,1.37611
c-0.36166,0.37483-0.79963,0.67435-1.31397,0.89654c-0.50016,0.20847-1.0771,0.31319-1.72994,0.31319
c-0.88963,0-1.65402-0.16737-2.29365-0.50111c-0.63962-0.33379-1.16764-0.77813-1.58456-1.33401
c-0.40324-0.56966-0.70176-1.23029-0.89654-1.981c-0.19474-0.7644-0.29215-1.56989-0.29215-2.41842
c0-0.77813,0.09741-1.5288,0.29215-2.25111c0.19478-0.7233,0.49329-1.36243,0.89654-1.91931
c0.41692-0.56961,0.93813-1.02081,1.56352-1.35456c0.63962-0.33374,1.40402-0.50016,2.29369-0.50016
c1.04231,0,1.93886,0.26429,2.68952,0.79181C77.86697,100.80027,78.36027,101.59208,78.58246,102.64908z M84.42013,98.16647
v14.88562h1.98019v-6.81689h7.84022v6.81689h1.98045V98.16647h-1.98045v6.39997h-7.84022v-6.39997H84.42013z M100.72369,98.16647
v14.88562h10.34158v-1.66776h-8.36063v-5.14914h7.73468v-1.66875h-7.73468v-4.73216h8.29798v-1.66781H100.72369z
M121.71878,98.16647c1.41769,0,2.52271,0.34747,3.31546,1.04237c0.80599,0.69489,1.20874,1.64721,1.20874,2.85595
c0,0.9034-0.20847,1.69617-0.62489,2.37738c-0.40325,0.68021-1.05655,1.1461-1.96041,1.39665v0.04109
c0.43111,0.08418,0.77858,0.22314,1.04232,0.41792c0.27847,0.19479,0.4938,0.43066,0.64699,0.70863
c0.16687,0.26424,0.28428,0.56275,0.35429,0.89649c0.08318,0.33374,0.14632,0.68121,0.18792,1.04237
c0.0274,0.36115,0.04845,0.73013,0.06213,1.105c0.01418,0.37483,0.04845,0.7438,0.10423,1.10496
c0.05577,0.3612,0.13214,0.70863,0.22951,1.04237c0.1106,0.32006,0.27065,0.60489,0.47911,0.85445h-2.21001
c-0.13895-0.15269-0.23587-0.36115-0.29165-0.62539c-0.04159-0.26328-0.07001-0.55499-0.08318-0.87499
c-0.01418-0.33379-0.02791-0.68808-0.04209-1.06391c-0.01368-0.37484-0.05532-0.74285-0.12528-1.10501
c-0.05532-0.36115-0.12477-0.70176-0.20846-1.02081c-0.08319-0.33374-0.21483-0.61852-0.39594-0.8554
c-0.18055-0.25056-0.41692-0.44434-0.70857-0.58335c-0.29214-0.15364-0.68121-0.22996-1.16764-0.22996h-4.8369v6.35883h-1.98145
V98.16647H121.71878z M122.13576,104.92072c0.41743-0.0685,0.77858-0.20059,1.08391-0.39538
c0.32006-0.20847,0.57011-0.47961,0.75072-0.81335c0.19478-0.34743,0.29214-0.79176,0.29214-1.33401
c0-0.75067-0.20896-1.36237-0.62543-1.83513c-0.41743-0.4727-1.09128-0.70857-2.02254-0.70857h-4.92008v5.19118h4.12782
C121.28081,105.02546,121.71878,104.99123,122.13576,104.92072z M142.12987,107.67294v-9.50647h-1.98v9.50647
c0,1.33501-0.33374,2.34997-1.00128,3.04386c-0.6528,0.68121-1.61192,1.02282-2.87744,1.02282
c-1.33426,0-2.35558-0.34161-3.0647-1.02282c-0.70908-0.69389-1.06337-1.70885-1.06337-3.04386v-9.50647h-1.9805v9.50647
c0,1.98782,0.5349,3.44125,1.60562,4.35833c1.08395,0.90336,2.58534,1.35456,4.50294,1.35456
c1.87622,0,3.32184-0.47175,4.33679-1.4172C141.62285,111.00945,142.12987,109.57757,142.12987,107.67294z M146.52954,98.16647
v14.88562h1.87622v-11.94643h0.04208l7.77608,11.94643h2.16837V98.16647h-1.87622v12.07177h-0.04208l-7.83922-12.07177H146.52954z
M173.98749,111.19736l0.52115,1.85472h1.25084v-7.83871h-6.5257v1.66781h4.75371c0.02791,0.68116-0.06264,1.32028-0.2711,1.91831
c-0.20847,0.58329-0.52121,1.09814-0.93864,1.54247c-0.40274,0.43066-0.90285,0.77222-1.50089,1.02182
c-0.59752,0.25056-1.28555,0.37583-2.06413,0.37583c-0.83389,0-1.57039-0.1605-2.21001-0.48056
c-0.62538-0.33279-1.15341-0.77126-1.58456-1.31252c-0.43066-0.55688-0.75754-1.18914-0.97974-1.89776
c-0.22264-0.72326-0.33374-1.47298-0.33374-2.25205c0-0.79181,0.09743-1.56307,0.29216-2.31374
c0.19478-0.7644,0.49329-1.43874,0.89653-2.02304c0.41693-0.59703,0.94496-1.07659,1.58458-1.43875
c0.6528-0.36115,1.43138-0.54125,2.33478-0.54125c0.55594,0,1.07761,0.0695,1.56403,0.20847
c0.50011,0.12433,0.94495,0.31911,1.33401,0.58334c0.38951,0.26424,0.71594,0.60484,0.97972,1.02182
c0.26474,0.4032,0.4453,0.88968,0.54221,1.4593h1.98096c-0.13896-0.876-0.40324-1.61885-0.79225-2.23056
c-0.3754-0.62539-0.8481-1.14023-1.41771-1.54348c-0.55594-0.40224-1.19556-0.69489-1.91837-0.87499
c-0.70857-0.19473-1.46609-0.29165-2.2726-0.29165c-1.18132,0-2.21681,0.2222-3.10649,0.66653
c-0.8755,0.4306-1.61249,1.01495-2.21001,1.75194c-0.5838,0.73598-1.02864,1.59825-1.33401,2.58485
c-0.29216,0.97286-0.43797,2.0015-0.43797,3.08595c0,0.97286,0.1595,1.91145,0.47955,2.81485
c0.31956,0.90336,0.78496,1.70198,1.39665,2.39788c0.61171,0.69394,1.35558,1.25082,2.23106,1.66776
c0.87544,0.40229,1.86935,0.60389,2.98122,0.60389c0.87544,0,1.74458-0.16637,2.6064-0.50011
C172.68088,112.53825,173.40369,111.97549,173.98749,111.19736z M188.53981,102.5238h1.87627
c-0.02791-0.82017-0.18791-1.52193-0.47961-2.10622c-0.27792-0.59703-0.66748-1.09032-1.16759-1.47984
c-0.48643-0.38956-1.05655-0.67435-1.70941-0.85445c-0.65379-0.18105-1.36237-0.2711-2.12677-0.2711
c-0.68121,0-1.34819,0.09005-2.0015,0.2711c-0.63911,0.16637-1.21559,0.43066-1.73044,0.79181
c-0.50011,0.34743-0.90337,0.79863-1.20874,1.35556c-0.30582,0.54221-0.45901,1.18819-0.45901,1.93886
c0,0.68121,0.13214,1.25083,0.39587,1.70985c0.27847,0.44434,0.63962,0.81236,1.08446,1.104
c0.45853,0.27897,0.97287,0.50798,1.54298,0.68903c0.56961,0.16642,1.14609,0.31911,1.72993,0.45807
c0.59749,0.12527,1.18134,0.25056,1.75095,0.37488c0.57062,0.12528,1.07759,0.2926,1.52243,0.50111
c0.45853,0.19473,0.81967,0.45116,1.08397,0.77122c0.27795,0.32006,0.41692,0.73698,0.41692,1.25082
c0,0.54221-0.1106,0.9866-0.33324,1.33401c-0.2227,0.34843-0.51434,0.62544-0.87601,0.83485
c-0.36115,0.19383-0.77121,0.33279-1.23027,0.41698c-0.44434,0.08318-0.88918,0.12527-1.33401,0.12527
c-0.5564,0-1.09814-0.0705-1.62616-0.20947c-0.52753-0.13895-0.99341-0.35429-1.39665-0.64598
c-0.38907-0.29165-0.70863-0.66062-0.95868-1.10496c-0.23639-0.45807-0.3548-1.00027-0.3548-1.62571h-1.87622
c0,0.9024,0.15952,1.68835,0.47957,2.35583c0.33324,0.6528,0.77809,1.19505,1.33401,1.62566
c0.57011,0.41698,1.22342,0.73018,1.9599,0.93764c0.75021,0.20847,1.54253,0.31319,2.37639,0.31319
c0.68121,0,1.36243-0.08318,2.04314-0.24956c0.69539-0.15269,1.32079-0.40324,1.87672-0.75072
c0.55592-0.3621,1.00758-0.82017,1.35506-1.37611c0.36165-0.56961,0.54221-1.25082,0.54221-2.04359
c0-0.73598-0.13896-1.34769-0.41693-1.83412c-0.26424-0.48648-0.62544-0.88968-1.08446-1.20974
c-0.44484-0.32006-0.95181-0.56962-1.52193-0.75072c-0.56963-0.19473-1.15341-0.36115-1.75145-0.50011
c-0.5838-0.13895-1.16028-0.26424-1.73039-0.37583c-0.56961-0.12433-1.08345-0.27696-1.54248-0.45807
c-0.44438-0.18105-0.80598-0.41006-1.08395-0.68803c-0.26428-0.29165-0.39638-0.66748-0.39638-1.12555
c0-0.48643,0.0905-0.88968,0.2711-1.20974c0.19473-0.33374,0.44484-0.59798,0.75067-0.79276
c0.31955-0.19378,0.68121-0.33279,1.08345-0.41597c0.40324-0.08414,0.81335-0.12528,1.23029-0.12528
c1.02863,0,1.8694,0.24274,2.52321,0.72917C188.0392,100.68185,188.42827,101.45307,188.53981,102.5238z M205.82381,111.19736
l0.52121,1.85472h1.25082v-7.83871h-6.52625v1.66781h4.75421c0.0274,0.68116-0.06264,1.32028-0.2711,1.91831
c-0.20897,0.58329-0.52167,1.09814-0.93858,1.54247c-0.40324,0.43066-0.90291,0.77222-1.50089,1.02182
c-0.59804,0.25056-1.28606,0.37583-2.06419,0.37583c-0.83385,0-1.57037-0.1605-2.20996-0.48056
c-0.62543-0.33279-1.15396-0.77126-1.58456-1.31252c-0.43115-0.55688-0.75758-1.18914-0.98022-1.89776
c-0.2222-0.72326-0.33374-1.47298-0.33374-2.25205c0-0.79181,0.09737-1.56307,0.29214-2.31374
c0.19478-0.7644,0.4938-1.43874,0.89655-2.02304c0.41692-0.59703,0.94545-1.07659,1.58456-1.43875
c0.65331-0.36115,1.43188-0.54125,2.33524-0.54125c0.55594,0,1.0771,0.0695,1.56352,0.20847
c0.50067,0.12433,0.94551,0.31911,1.33452,0.58334c0.38907,0.26424,0.71548,0.60484,0.97972,1.02182
c0.2643,0.4032,0.44534,0.88968,0.54221,1.4593h1.9805c-0.13901-0.876-0.40274-1.61885-0.79181-2.23056
c-0.37582-0.62539-0.84808-1.14023-1.41769-1.54348c-0.55638-0.40224-1.19551-0.69489-1.9183-0.87499
c-0.70914-0.19473-1.46666-0.29165-2.27266-0.29165c-1.18132,0-2.21732,0.2222-3.10649,0.66653
c-0.87595,0.4306-1.61249,1.01495-2.20996,1.75194c-0.58385,0.73598-1.02869,1.59825-1.33452,2.58485
c-0.29214,0.97286-0.43802,2.0015-0.43802,3.08595c0,0.97286,0.16005,1.91145,0.47961,2.81485
c0.32001,0.90336,0.78545,1.70198,1.39716,2.39788c0.61121,0.69394,1.35506,1.25082,2.2305,1.66776
c0.87599,0.40229,1.8699,0.60389,2.98172,0.60389c0.8755,0,1.74463-0.16637,2.6064-0.50011
C204.5172,112.53825,205.24001,111.97549,205.82381,111.19736z M218.77057,98.16647c1.4182,0,2.52269,0.34747,3.31546,1.04237
c0.80598,0.69489,1.20923,1.64721,1.20923,2.85595c0,0.9034-0.20895,1.69617-0.62543,2.37738
c-0.40326,0.68021-1.05655,1.1461-1.96042,1.39665v0.04109c0.43117,0.08418,0.77858,0.22314,1.04288,0.41792
c0.27797,0.19479,0.49329,0.43066,0.64644,0.70863c0.16687,0.26424,0.28482,0.56275,0.35432,0.89649
c0.08319,0.33374,0.14629,0.68121,0.18793,1.04237c0.02736,0.36115,0.04842,0.73013,0.06213,1.105
c0.01418,0.37483,0.04846,0.7438,0.10423,1.10496c0.05577,0.3612,0.13214,0.70863,0.22951,1.04237
c0.1111,0.32006,0.2711,0.60489,0.47957,0.85445h-2.21046c-0.13901-0.15269-0.23587-0.36115-0.29164-0.62539
c-0.0416-0.26328-0.0695-0.55499-0.08324-0.87499c-0.01419-0.33379-0.02786-0.68808-0.0416-1.06391
c-0.01418-0.37484-0.05577-0.74285-0.12527-1.10501c-0.05528-0.36115-0.12527-0.70176-0.20847-1.02081
c-0.08368-0.33374-0.21533-0.61852-0.39638-0.8554c-0.18056-0.25056-0.41693-0.44434-0.70863-0.58335
c-0.29214-0.15364-0.68115-0.22996-1.16759-0.22996h-4.83694v6.35883h-1.98096V98.16647H218.77057z M219.18748,104.92072
c0.41743-0.0685,0.77858-0.20059,1.08446-0.39538c0.31956-0.20847,0.56963-0.47961,0.75021-0.81335
c0.19473-0.34743,0.29216-0.79176,0.29216-1.33401c0-0.75067-0.20851-1.36237-0.62544-1.83513
c-0.41693-0.4727-1.09128-0.70857-2.02205-0.70857h-4.92062v5.19118h4.12782
C218.33304,105.02546,218.77057,104.99123,219.18748,104.92072z M239.18159,107.67294v-9.50647h-1.98044v9.50647
c0,1.33501-0.33374,2.34997-1.00078,3.04386c-0.65331,0.68121-1.61249,1.02282-2.87749,1.02282
c-1.33401,0-2.35579-0.34161-3.06491-1.02282c-0.70857-0.69389-1.06342-1.70885-1.06342-3.04386v-9.50647h-1.98045v9.50647
c0,1.98782,0.5349,3.44125,1.60512,4.35833c1.08446,0.90336,2.58585,1.35456,4.50366,1.35456
c1.87627,0,3.32233-0.47175,4.33678-1.4172C238.67412,111.00945,239.18159,109.57757,239.18159,107.67294z M249.46033,105.29655
c1.12601,0.01373,1.94572-0.21528,2.46002-0.68803c0.52802-0.47275,0.79231-1.15392,0.79231-2.04359
c0-0.88873-0.2643-1.56307-0.79231-2.02209c-0.5143-0.4727-1.33401-0.70857-2.46002-0.70857h-3.87825v5.46228H249.46033z
M250.12732,98.16647c1.50137,0,2.63379,0.38857,3.39819,1.16765c0.77858,0.7644,1.16759,1.84099,1.16759,3.23083
c0,1.39079-0.38901,2.47424-1.16759,3.25333c-0.7644,0.77808-1.89682,1.16077-3.39819,1.1461h-4.54524v6.08772h-1.98051V98.16647
H250.12732z M264.22162,105.29655c1.12555,0.01373,1.94574-0.21528,2.46008-0.68803
c0.52802-0.47275,0.79224-1.15392,0.79224-2.04359c0-0.88873-0.26422-1.56307-0.79224-2.02209
c-0.51434-0.4727-1.33453-0.70857-2.46008-0.70857h-3.87827v5.46228H264.22162z M264.88861,98.16647
c1.50137,0,2.63379,0.38857,3.39819,1.16765c0.77856,0.7644,1.16763,1.84099,1.16763,3.23083
c0,1.39079-0.38907,2.47424-1.16763,3.25333c-0.7644,0.77808-1.89682,1.16077-3.39819,1.1461h-4.54526v6.08772h-1.98096V98.16647
H264.88861z M273.12326,98.16647v14.88562h10.34131v-1.66776h-8.36038v-5.14914h7.73495v-1.66875h-7.73495v-4.73216h8.29819
v-1.66781H273.12326z M2.58373,86.21188h29.01948l-0.01562-46.90319H2.56857L2.58373,86.21188z M39.95358,39.30869l0.09973,46.90319
h28.92347V44.44587h9.45532v41.76601h29.03466V39.30869H39.95358z M78.4321,29.03514v5.13693h36.92667v52.03981h29.03561V34.17206
h69.5351v-5.13693h-69.5351V18.76083L115.35877,0v29.03514H78.4321z M221.82074,39.30869v46.90319h29.0349V44.44587h9.45534
v18.31516h23.15359V39.30869H221.82074z M190.77538,57.62341V44.44587h-9.45483v13.17754H190.77538z M181.32054,62.76103v18.31422
h32.60893v5.13663h-61.64433V39.30869h61.64433v23.45234H181.32054z M7.82649,17.08627c0-8.09053,5.78203-14.23438,5.79084-14.23633
C7.20117,4.40769,2.43656,10.19067,2.43656,17.08627H7.82649z M17.08576,34.17206c9.43655,0,17.08579-7.64954,17.08579-17.08629
C34.17155,7.64927,26.52231,0,17.08576,0C7.64901,0,0,7.64927,0,17.08577C0,26.52252,7.64901,34.17206,17.08576,34.17206z"/>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 17 KiB

View File

@ -4,6 +4,11 @@ header {
border-bottom: 1px solid var(--starlight-white-dark);
}
header .svg-logo {
width: 100px;
height: auto;
}
header h1 {
color: var(--starlight-white-lighter);
margin: 0;

View File

@ -0,0 +1 @@
/* Placeholder */

View File

@ -1,28 +1,15 @@
.project-card {
background-color: var(--cosmic-dark-dark);
color: var(--starlight-white-lighter);
border: 1px solid var(--cosmic-dark-medium);
border-radius: 8px;
padding: 20px;
border-radius: 5px;
padding: 10px;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
}
.project-card:hover {
transform: translateY(-5px);
}
.project-card .card-title {
color: var(--starlight-white-lighter);
margin-bottom: 15px;
}
.project-card .card-details {
display: flex;
justify-content: space-between;
align-items: center;
}
.project-card .card-text {
margin-bottom: 0;
margin-bottom: 10px;
}
.btn-create-project {
@ -36,7 +23,7 @@
background-color: var(--aurora-yellowgreen-lighter);
border: none;
border-radius: 4px;
margin-bottom: 20px;
margin-bottom: 10px;
}
.btn-create-project:hover {

View File

@ -1,32 +1,24 @@
.project-card {
background-color: var(--cosmic-dark-dark);
color: var(--starlight-white-lighter);
border: 1px solid var(--cosmic-dark-medium);
border-radius: 8px;
padding: 10px;
border-radius: 5px;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
transition: transform 0.2s;
}
.project-card:hover {
transform: translateY(-5px);
}
.project-card .card-title {
color: var(--starlight-white-lighter);
margin-bottom: 15px;
}
.project-card .card-details {
display: flex;
justify-content: space-between;
align-items: center;
}
.project-card .card-text {
margin-bottom: 0;
}
.project-card .card-text .star {
background-color: transparent;
border: none;
font-size: 25px;
}
.btn-create-project {
display: inline-block;
padding: 10px 20px;
@ -38,7 +30,6 @@
background-color: var(--aurora-yellowgreen-lighter);
border: none;
border-radius: 4px;
margin-bottom: 20px;
}
.btn-create-project:hover {
@ -47,7 +38,7 @@
.btn-delete {
display: inline-block;
padding: 10px 20px;
padding: 3px 10px;
font-size: 16px;
cursor: pointer;
text-align: center;
@ -63,8 +54,8 @@
}
.form-control {
background-color: var(--cosmic-dark-light);
color: var(--starlight-white-lighter);
background-color: var(--starlight-white-lighter);
color: var(--cosmic-dark-dark);
border: 1px solid var(--cosmic-dark-medium);
border-radius: 4px;
padding: 10px;
@ -72,5 +63,13 @@
}
.form-control::placeholder {
color: var(--starlight-white-darker);
color: var(--cosmic-dark-dark);
}
.star-filled {
color: var(--aurora-yellowgreen-lighter);
}
.star-empty {
color: var(--cosmic-dark-light) !important;
}

View File

@ -2,7 +2,7 @@
<div class="container">
<div class="row align-items-center">
<div class="col-md-6">
<h1>INTER</h1>
<img src="/assets/inter-brand.svg" alt="INTER Logo" class="svg-logo" />
</div>
<div class="col-md-6">
<nav>

View File

@ -12,7 +12,7 @@
href="https://fonts.googleapis.com/css2?family=Barlow:wght@400;700&display=swap"
rel="stylesheet"
/>
<link rel="stylesheet" href="/style.css" />
<link rel="stylesheet" href="/header.css" />
<link rel="stylesheet" href="/footer.css" />
<link rel="stylesheet" href="style/core/style.css" />
<link rel="stylesheet" href="style/core/header.css" />
<link rel="stylesheet" href="style/core/footer.css" />
</th:block>

View File

@ -1,11 +1,11 @@
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<div th:replace="~{_metadata :: metadata}"></div>
<div th:replace="~{/core/_metadata :: metadata}"></div>
<title>Impressum</title>
</head>
<body>
<div th:replace="~{_header :: header(activePage=${home})}"></div>
<div th:replace="~{/core/_header :: header(activePage=${home})}"></div>
<div>
<h1>Datenschutzerklärung</h1>
@ -100,6 +100,6 @@
[E-Mail-Adresse für Datenschutzanfragen]
</p>
</div>
<div th:replace="~{_footer :: footer}"></div>
<div th:replace="~{/core/_footer :: footer}"></div>
</body>
</html>

View File

@ -1,11 +1,11 @@
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<div th:replace="~{_metadata :: metadata}"></div>
<div th:replace="~{/core/_metadata :: metadata}"></div>
<title>Impressum</title>
</head>
<body>
<div th:replace="~{_header :: header(activePage=${home})}"></div>
<div th:replace="~{/core/_header :: header(activePage=${home})}"></div>
<div>
<h1>Impressum</h1>
<h2>Angaben gemäß § 5 TMG</h2>
@ -76,6 +76,6 @@
jeweiligen Autors bzw. Erstellers.
</p>
</div>
<div th:replace="~{_footer :: footer}"></div>
<div th:replace="~{/core/_footer :: footer}"></div>
</body>
</html>

View File

@ -0,0 +1,15 @@
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<div th:replace="~{/core/_metadata :: metadata}"></div>
<title>My Skill Management System</title>
<link rel="stylesheet" href="style/notes/notes.css" />
</head>
<body>
<div class="wrapper">
<div th:replace="~{/core/_header :: header(activePage=${notes})}"></div>
<div class="content container mt-4"></div>
<div th:replace="~{/core/_footer :: footer}"></div>
</div>
</body>
</html>

View File

@ -1,13 +1,18 @@
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<div th:replace="~{_metadata :: metadata}"></div>
<div th:replace="~{/core/_metadata :: metadata}"></div>
<title>Create Project</title>
<link rel="stylesheet" href="/projects.css" />
<link rel="stylesheet" href="/style/projects/projects.css" />
<link rel="stylesheet" href="/style/core/style.css" />
<link rel="stylesheet" href="/style/core/header.css" />
<link rel="stylesheet" href="/style/core/footer.css" />
</head>
<body>
<div class="wrapper">
<div th:replace="~{_header :: header(activePage=${createProject})}"></div>
<div
th:replace="~{/core/_header :: header(activePage=${createProject})}"
></div>
<div class="content container mt-4">
<h2 class="mb-4">Create Project</h2>
<form
@ -55,7 +60,7 @@
</div>
</form>
</div>
<div th:replace="~{_footer :: footer}"></div>
<div th:replace="~{/core/_footer :: footer}"></div>
</div>
</body>
</html>

View File

@ -1,13 +1,13 @@
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<div th:replace="~{_metadata :: metadata}"></div>
<title>My Skill Management System</title>
<link rel="stylesheet" href="/projects.css" />
<div th:replace="~{/core/_metadata :: metadata}"></div>
<title>Projects</title>
<link rel="stylesheet" href="/style/projects/projects.css" />
</head>
<body>
<div class="wrapper">
<div th:replace="~{_header :: header(activePage=${home})}"></div>
<div th:replace="~{/core/_header :: header(activePage=${home})}"></div>
<div class="content container mt-4">
<h2 class="mb-4">Projects</h2>
<a th:href="@{/projects/create}" class="btn-create-project"
@ -41,7 +41,7 @@
</div>
</div>
</div>
<div th:replace="~{_footer :: footer}"></div>
<div th:replace="~{/core/_footer :: footer}"></div>
</div>
</body>
</html>

View File

@ -1,56 +0,0 @@
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<div th:replace="~{_metadata :: metadata}"></div>
<title>My Skill Management System</title>
<link rel="stylesheet" href="/skills.css" />
</head>
<body>
<div class="wrapper">
<div th:replace="~{_header :: header(activePage=${skills})}"></div>
<div class="content container mt-4">
<h2 class="mb-4">Profile</h2>
<div class="project-card mb-4">
<div class="card-body">
<ul>
<li th:text="${employee.formOfAddress.description}">
Form of Address
</li>
<li th:text="${employee.firstName}">First Name</li>
<li th:text="${employee.lastName}">Last Name</li>
<li th:text="${employee.mail}">Email</li>
</ul>
</div>
</div>
<h2 class="mb-4">Skills</h2>
<div class="row">
<div class="col-12" th:each="skill : ${skillData}">
<div class="project-card mb-4">
<div class="card-body">
<h5
class="card-title"
th:text="${skill.primarySkill.description}"
>
Primary Skill
</h5>
<div class="card-details">
<div class="card-text">
<ul>
<li
th:each="secondarySkill : ${skill.secondarySkills}"
th:text="${secondarySkill.description}"
>
Secondary Skill
</li>
</ul>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div th:replace="~{_footer :: footer}"></div>
</div>
</body>
</html>

View File

@ -0,0 +1,98 @@
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<div th:replace="~{/core/_metadata :: metadata}"></div>
<title>Add Skill</title>
<link rel="stylesheet" href="/style/skills/skills.css" />
<link rel="stylesheet" href="/style/core/style.css" />
<link rel="stylesheet" href="/style/core/header.css" />
<link rel="stylesheet" href="/style/core/footer.css" />
</head>
<body>
<div class="wrapper">
<div th:replace="~{/core/_header :: header(activePage=${skills})}"></div>
<div class="content container mt-4">
<h2 class="mb-4">Add Skill</h2>
<form
th:action="@{/skills/add}"
th:object="${skillForm}"
method="post"
class="project-card"
>
<div class="card-body">
<div class="form-group">
<label for="primarySkill">Primary Skill</label>
<select
id="primarySkill"
name="primarySkillId"
class="form-control"
th:field="*{primarySkillId}"
>
<option
th:each="primarySkill : ${primarySkills}"
th:value="${primarySkill.psid}"
th:text="${primarySkill.description}"
></option>
</select>
</div>
<div class="form-group">
<label for="secondarySkill">Secondary Skill</label>
<select
id="secondarySkill"
name="secondarySkillId"
class="form-control"
th:field="*{secondarySkillId}"
>
<option value="" disabled selected>
Select a secondary skill
</option>
</select>
</div>
<div class="form-group">
<label for="level">Level</label>
<select
id="level"
name="level"
class="form-control"
th:field="*{level}"
>
<option
th:each="level : ${#numbers.sequence(1, 5)}"
th:value="${level}"
th:text="${level}"
></option>
</select>
</div>
<button type="submit" class="btn-create-project">Add Skill</button>
</div>
</form>
</div>
<div th:replace="~{/core/_footer :: footer}"></div>
</div>
<script>
document
.getElementById("primarySkill")
.addEventListener("change", function () {
var primarySkillId = this.value;
fetch("/skills/secondary-skills?primarySkillId=" + primarySkillId)
.then((response) => response.json())
.then((data) => {
console.log("Fetch response data:", data);
var secondarySkillSelect =
document.getElementById("secondarySkill");
secondarySkillSelect.innerHTML =
'<option value="" disabled selected>Select a secondary skill</option>';
data.forEach(function (secondarySkill) {
var option = document.createElement("option");
option.value = secondarySkill.ssid;
option.text = secondarySkill.description;
secondarySkillSelect.add(option);
});
})
.catch((error) =>
console.error("Error fetching secondary skills:", error)
);
});
</script>
</body>
</html>

View File

@ -0,0 +1,56 @@
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<div th:replace="~{/core/_metadata :: metadata}"></div>
<title>Create Skill</title>
<link rel="stylesheet" href="/style/skills/skills.css" />
<link rel="stylesheet" href="/style/core/style.css" />
<link rel="stylesheet" href="/style/core/header.css" />
<link rel="stylesheet" href="/style/core/footer.css" />
</head>
<body>
<div class="wrapper">
<div
th:replace="~{/core/_header :: header(activePage=${createSkill})}"
></div>
<div class="content container mt-4">
<h2 class="mb-4">Create Skill</h2>
<form
th:action="@{/skills/save}"
th:object="${secondarySkill}"
method="post"
class="project-card"
>
<div class="card-body">
<div class="form-group">
<label for="primarySkill">Primary Skill:</label>
<input
type="text"
id="primarySkill"
th:field="*{primarySkill.description}"
class="form-control"
required
/>
</div>
<div class="form-group">
<label for="secondarySkill">Secondary Skill:</label>
<input
type="text"
id="secondarySkill"
th:field="*{description}"
class="form-control"
required
/>
</div>
<div class="form-group">
<button type="submit" class="btn-create-project">
Save Skill
</button>
</div>
</div>
</form>
</div>
<div th:replace="~{/core/_footer :: footer}"></div>
</div>
</body>
</html>

View File

@ -0,0 +1,104 @@
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<div th:replace="~{/core/_metadata :: metadata}"></div>
<title>Skills</title>
<link rel="stylesheet" href="/style/skills/skills.css" />
<link rel="stylesheet" href="/style/core/style.css" />
</head>
<body>
<div class="wrapper">
<div th:replace="~{/core/_header :: header(activePage=${skills})}"></div>
<div class="content container mt-4">
<h2 class="mb-4">Profil</h2>
<div class="project-card mb-4">
<div class="card-body">
<p>
<span th:text="${employee.formOfAddress.description}"
>Form of Address</span
>
<span th:text="${employee.firstName}">First Name</span>
<span th:text="${employee.lastName}">Last Name</span>
</p>
</div>
</div>
<div class="d-flex justify-content-between align-items-center mb-4">
<h2 class="mb-0">Skills</h2>
<div>
<a th:href="@{/skills/add}" class="btn-create-project">Add Skill</a>
<a th:href="@{/skills/create}" class="btn-create-project"
>Create Skill</a
>
</div>
</div>
<div class="row">
<div class="col-12" th:each="skillDto : ${skillData}">
<div class="project-card mb-4">
<div class="card-body">
<h5
class="card-title"
th:text="${skillDto.primarySkill.description}"
>
Primary Skill
</h5>
<div class="card-details">
<div class="card-text">
<ul>
<li th:each="pair : ${skillDto.secondarySkills}">
<span th:text="${pair.first.description}"
>Secondary Skill</span
>
<span class="stars">
<span th:each="i : ${#numbers.sequence(1, 5)}">
<form
th:action="@{/skills/update-level}"
method="post"
class="d-inline"
>
<input
type="hidden"
name="skillId"
th:value="${pair.first.ssid}"
/>
<input
type="hidden"
name="level"
th:value="${i}"
/>
<button
type="submit"
th:classappend="${i <= pair.second} ? 'star-filled' : 'star-empty'"
class="star"
>
&#9733;
</button>
</form>
</span>
</span>
<form
th:action="@{/skills/remove}"
method="post"
class="d-inline"
>
<input
type="hidden"
name="id"
th:value="${pair.first.ssid}"
/>
<button type="submit" class="btn-delete">
Delete
</button>
</form>
</li>
</ul>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div th:replace="~{/core/_footer :: footer}"></div>
</div>
</body>
</html>