diff --git a/src/main/bundles/prod.bundle b/src/main/bundles/prod.bundle index 2b19afd..a9302b7 100644 Binary files a/src/main/bundles/prod.bundle and b/src/main/bundles/prod.bundle differ diff --git a/src/main/java/com/primefactorsolutions/model/Candidate.java b/src/main/java/com/primefactorsolutions/model/Candidate.java index 976b9b4..a8ee05f 100644 --- a/src/main/java/com/primefactorsolutions/model/Candidate.java +++ b/src/main/java/com/primefactorsolutions/model/Candidate.java @@ -11,7 +11,12 @@ import lombok.NoArgsConstructor; @AllArgsConstructor @NoArgsConstructor @EqualsAndHashCode(callSuper = true) -public class Candidate extends BaseEntity { +public class Candidate extends BaseEntity implements HasLabel { @Column(unique = true) private String email; + + @Override + public String getLabel() { + return email; + } } diff --git a/src/main/java/com/primefactorsolutions/model/Employee.java b/src/main/java/com/primefactorsolutions/model/Employee.java index 4eeaf34..3a896aa 100644 --- a/src/main/java/com/primefactorsolutions/model/Employee.java +++ b/src/main/java/com/primefactorsolutions/model/Employee.java @@ -21,7 +21,7 @@ import java.util.List; @AllArgsConstructor @NoArgsConstructor @EqualsAndHashCode(callSuper = true) -public class Employee extends BaseEntity implements UserDetails { +public class Employee extends BaseEntity implements UserDetails, HasLabel { private String username; @NotNull(message = "El nombre no puede estar vacĂ­o") @@ -159,6 +159,11 @@ public class Employee extends BaseEntity implements UserDetails { @Enumerated(EnumType.STRING) private Role role = Role.USER; + @Override + public String getLabel() { + return String.format("%s %s", firstName, lastName); + } + public enum Status { ACTIVE, INACTIVE diff --git a/src/main/java/com/primefactorsolutions/model/Evaluation.java b/src/main/java/com/primefactorsolutions/model/Evaluation.java index bb7102f..26152f5 100644 --- a/src/main/java/com/primefactorsolutions/model/Evaluation.java +++ b/src/main/java/com/primefactorsolutions/model/Evaluation.java @@ -18,13 +18,13 @@ import java.util.List; public class Evaluation extends BaseEntity { @ManyToOne private Candidate candidate; + private Integer points; private EmployeePosition candidatePosition; private Employee interviewer; @Type(JsonType.class) @Column(columnDefinition = "json") @ColumnDefault("JSON_ARRAY()") private List skillEvaluations = Lists.newArrayList(); - private Integer points; @OneToMany(fetch = FetchType.EAGER, mappedBy = "evaluation") private List exams; } diff --git a/src/main/java/com/primefactorsolutions/model/HasLabel.java b/src/main/java/com/primefactorsolutions/model/HasLabel.java new file mode 100644 index 0000000..1e42b8b --- /dev/null +++ b/src/main/java/com/primefactorsolutions/model/HasLabel.java @@ -0,0 +1,5 @@ +package com.primefactorsolutions.model; + +public interface HasLabel { + String getLabel(); +} diff --git a/src/main/java/com/primefactorsolutions/repositories/EvaluationRepository.java b/src/main/java/com/primefactorsolutions/repositories/EvaluationRepository.java new file mode 100644 index 0000000..fad583f --- /dev/null +++ b/src/main/java/com/primefactorsolutions/repositories/EvaluationRepository.java @@ -0,0 +1,9 @@ +package com.primefactorsolutions.repositories; + +import com.primefactorsolutions.model.Evaluation; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.UUID; + +public interface EvaluationRepository extends JpaRepository { +} diff --git a/src/main/java/com/primefactorsolutions/service/EmployeeService.java b/src/main/java/com/primefactorsolutions/service/EmployeeService.java index 7a4f4de..bfe552e 100644 --- a/src/main/java/com/primefactorsolutions/service/EmployeeService.java +++ b/src/main/java/com/primefactorsolutions/service/EmployeeService.java @@ -38,6 +38,10 @@ public class EmployeeService { .build(); } + public List getEmployees() { + return employeeRepository.findAll(); + } + public Employee getDetachedEmployeeByUsername(final String username) { final Employee employee = employeeRepository.findByUsername(username).orElse(null); diff --git a/src/main/java/com/primefactorsolutions/service/EvaluationService.java b/src/main/java/com/primefactorsolutions/service/EvaluationService.java new file mode 100644 index 0000000..5a53207 --- /dev/null +++ b/src/main/java/com/primefactorsolutions/service/EvaluationService.java @@ -0,0 +1,27 @@ +package com.primefactorsolutions.service; + +import com.primefactorsolutions.model.Evaluation; +import com.primefactorsolutions.repositories.EvaluationRepository; +import lombok.AllArgsConstructor; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.UUID; + +@Service +@AllArgsConstructor +public class EvaluationService { + private final EvaluationRepository evaluationRepository; + + public Evaluation createOrUpdate(final Evaluation candidate) { + return evaluationRepository.save(candidate); + } + + public List getEvaluations() { + return evaluationRepository.findAll(); + } + + public Evaluation getEvaluation(final UUID id) { + return evaluationRepository.findById(id).orElse(null); + } +} diff --git a/src/main/java/com/primefactorsolutions/views/MainLayout.java b/src/main/java/com/primefactorsolutions/views/MainLayout.java index a759368..2941e6d 100644 --- a/src/main/java/com/primefactorsolutions/views/MainLayout.java +++ b/src/main/java/com/primefactorsolutions/views/MainLayout.java @@ -1,6 +1,7 @@ package com.primefactorsolutions.views; import com.primefactorsolutions.model.Employee; +import com.primefactorsolutions.views.assessment.EvaluationsListView; import com.primefactorsolutions.views.employee.DocumentsListView; import com.primefactorsolutions.views.employee.EmployeesListView; import com.primefactorsolutions.views.admin.TimeOffListView; @@ -149,10 +150,12 @@ public class MainLayout extends AppLayout { SideNavItem recruiting = new SideNavItem("Recruiting"); recruiting.setPrefixComponent(LineAwesomeIcon.BUSINESS_TIME_SOLID.create()); - recruiting.addItem(new SideNavItem("Exams", ExamsListView.class, - LineAwesomeIcon.RIBBON_SOLID.create())); recruiting.addItem(new SideNavItem("Candidates", CandidatesListView.class, LineAwesomeIcon.USER.create())); + recruiting.addItem(new SideNavItem("Evaluations", EvaluationsListView.class, + LineAwesomeIcon.BOOK_READER_SOLID.create())); + recruiting.addItem(new SideNavItem("Exams", ExamsListView.class, + LineAwesomeIcon.PEN_NIB_SOLID.create())); recruiting.addItem(new SideNavItem("Questions", QuestionsListView.class, LineAwesomeIcon.QUESTION_SOLID.create())); nav.addItem(recruiting); diff --git a/src/main/java/com/primefactorsolutions/views/MainView.java b/src/main/java/com/primefactorsolutions/views/MainView.java index 1a55317..8f524e1 100644 --- a/src/main/java/com/primefactorsolutions/views/MainView.java +++ b/src/main/java/com/primefactorsolutions/views/MainView.java @@ -2,6 +2,7 @@ package com.primefactorsolutions.views; import com.vaadin.flow.component.Text; import com.vaadin.flow.component.html.Main; +import com.vaadin.flow.component.orderedlayout.VerticalLayout; import com.vaadin.flow.router.PageTitle; import com.vaadin.flow.router.Route; import jakarta.annotation.security.PermitAll; @@ -12,6 +13,6 @@ import jakarta.annotation.security.PermitAll; public class MainView extends Main { public MainView() { - add(new Text("Welcome")); + add(new VerticalLayout(new Text("Welcome to PFS!"))); } } diff --git a/src/main/java/com/primefactorsolutions/views/assessment/EvaluationView.java b/src/main/java/com/primefactorsolutions/views/assessment/EvaluationView.java new file mode 100644 index 0000000..9c94c20 --- /dev/null +++ b/src/main/java/com/primefactorsolutions/views/assessment/EvaluationView.java @@ -0,0 +1,88 @@ +package com.primefactorsolutions.views.assessment; + +import com.primefactorsolutions.model.*; +import com.primefactorsolutions.service.CandidateService; +import com.primefactorsolutions.service.EmployeeService; +import com.primefactorsolutions.service.EvaluationService; +import com.primefactorsolutions.views.BaseEntityForm; +import com.primefactorsolutions.views.MainLayout; +import com.primefactorsolutions.views.util.EntityComboBox; +import com.vaadin.flow.component.Component; +import com.vaadin.flow.component.Text; +import com.vaadin.flow.component.textfield.IntegerField; +import com.vaadin.flow.router.BeforeEvent; +import com.vaadin.flow.router.HasUrlParameter; +import com.vaadin.flow.router.PageTitle; +import com.vaadin.flow.router.Route; +import com.vaadin.flow.spring.annotation.SpringComponent; +import com.vaadin.flow.spring.security.AuthenticationContext; +import jakarta.annotation.security.RolesAllowed; +import org.apache.commons.lang3.StringUtils; +import org.springframework.context.annotation.Scope; +import org.vaadin.firitin.fields.ElementCollectionField; +import org.vaadin.firitin.fields.EnumSelect; + +import java.util.List; +import java.util.UUID; + +@SpringComponent +@Scope("prototype") +@PageTitle("Evaluations") +@Route(value = "/evaluations", layout = MainLayout.class) +@RolesAllowed("ROLE_ADMIN") +public class EvaluationView extends BaseEntityForm implements HasUrlParameter { + private final CandidateService candidateService; + private final EvaluationService evaluationService; + private final EmployeeService employeeService; + + private final EntityComboBox candidate = new EntityComboBox<>("Candidate"); + private final EntityComboBox interviewer = new EntityComboBox<>("Interviewer"); + private final EnumSelect candidatePosition = + new EnumSelect<>("Position", EmployeePosition.class); + private final IntegerField points = new IntegerField("Points"); + private final Text skillLabel = new Text("Skills"); + private final ElementCollectionField skillEvaluations = + new ElementCollectionField<>(SkillEvaluation.class); + + public EvaluationView(final AuthenticationContext authenticationContext, + final CandidateService candidateService, + final EmployeeService employeeService, + final EvaluationService evaluationService) { + super(authenticationContext, Evaluation.class); + this.employeeService = employeeService; + this.evaluationService = evaluationService; + this.candidateService = candidateService; + + this.candidate.setWidthFull(); + this.interviewer.setWidthFull(); + this.points.setWidthFull(); + this.skillEvaluations.setWidthFull(); + this.candidatePosition.setWidthFull(); + this.candidate.setItems(this.candidateService.getCandidates()); + this.interviewer.setItems(this.employeeService.getEmployees()); + + setSavedHandler(evaluation -> goTo(EvaluationsListView.class)); + } + + @Override + public void setParameter(final BeforeEvent beforeEvent, final String s) { + if (StringUtils.isNotBlank(s) && !"new".equals(s)) { + var evaluation = evaluationService.getEvaluation(UUID.fromString(s)); + setEntityWithEnabledSave(evaluation); + } else { + setEntityWithEnabledSave(new Evaluation()); + } + } + + @Override + protected List getFormComponents() { + return List.of( + candidate, + points, + candidatePosition, + skillLabel, + skillEvaluations, + interviewer + ); + } +} diff --git a/src/main/java/com/primefactorsolutions/views/assessment/EvaluationsListView.java b/src/main/java/com/primefactorsolutions/views/assessment/EvaluationsListView.java new file mode 100644 index 0000000..2501514 --- /dev/null +++ b/src/main/java/com/primefactorsolutions/views/assessment/EvaluationsListView.java @@ -0,0 +1,52 @@ +package com.primefactorsolutions.views.assessment; + +import com.primefactorsolutions.model.Evaluation; +import com.primefactorsolutions.service.EvaluationService; +import com.primefactorsolutions.views.BaseView; +import com.primefactorsolutions.views.MainLayout; +import com.primefactorsolutions.views.util.MenuBarUtils; +import com.vaadin.flow.component.button.Button; +import com.vaadin.flow.component.button.ButtonVariant; +import com.vaadin.flow.component.icon.VaadinIcon; +import com.vaadin.flow.component.orderedlayout.HorizontalLayout; +import com.vaadin.flow.data.provider.ListDataProvider; +import com.vaadin.flow.router.PageTitle; +import com.vaadin.flow.router.Route; +import com.vaadin.flow.spring.annotation.SpringComponent; +import com.vaadin.flow.spring.security.AuthenticationContext; +import jakarta.annotation.security.RolesAllowed; +import org.apache.commons.lang3.tuple.Pair; +import org.springframework.context.annotation.Scope; +import org.vaadin.firitin.components.grid.VGrid; + +import java.util.Map; + +@SpringComponent +@Scope("prototype") +@PageTitle("Evaluations") +@Route(value = "/evaluations", layout = MainLayout.class) +@RolesAllowed("ROLE_ADMIN") +public class EvaluationsListView extends BaseView { + + public EvaluationsListView(final AuthenticationContext authenticationContext, + final EvaluationService evaluationService) { + super(authenticationContext); + final HorizontalLayout hl = new HorizontalLayout(); + final Button addEvaluation = new Button("Add Evaluation"); + addEvaluation.addThemeVariants(ButtonVariant.LUMO_PRIMARY); + addEvaluation.addClickListener(buttonClickEvent -> { + this.getUI().flatMap(ui -> ui.navigate(EvaluationView.class, "new")); + }); + hl.add(addEvaluation); + + final VGrid grid = new VGrid<>(Evaluation.class); + grid.setColumns("candidate.email"); + grid.setAllRowsVisible(true); + grid.addComponentColumn(evaluation -> + MenuBarUtils.menuBar(Map.of(Pair.of("Edit", VaadinIcon.PENCIL), menuItemClickEvent -> + getUI().flatMap(ui -> ui.navigate(EvaluationView.class, evaluation.getId().toString()))))); + grid.setDataProvider(new ListDataProvider<>(evaluationService.getEvaluations())); + + getCurrentPageLayout().add(hl, grid); + } +} diff --git a/src/main/java/com/primefactorsolutions/views/util/EntityComboBox.java b/src/main/java/com/primefactorsolutions/views/util/EntityComboBox.java new file mode 100644 index 0000000..376c4b2 --- /dev/null +++ b/src/main/java/com/primefactorsolutions/views/util/EntityComboBox.java @@ -0,0 +1,18 @@ +package com.primefactorsolutions.views.util; + +import com.primefactorsolutions.model.HasLabel; +import org.vaadin.firitin.components.combobox.VComboBox; + +import java.util.List; + +public class EntityComboBox extends VComboBox { + public EntityComboBox(final String label) { + super(label); + this.setItemLabelGenerator(HasLabel::getLabel); + } + + public EntityComboBox(final String label, final List items) { + super(label, items); + this.setItemLabelGenerator(HasLabel::getLabel); + } +}