Rama-Ricardo #14
5
pom.xml
5
pom.xml
@ -110,6 +110,11 @@
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-beanutils</groupId>
|
||||
<artifactId>commons-beanutils</artifactId>
|
||||
<version>1.9.4</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-core</artifactId>
|
||||
|
@ -1,51 +1,59 @@
|
||||
package com.primefactorsolutions.model;
|
||||
|
||||
import io.hypersistence.utils.hibernate.type.json.JsonType;
|
||||
import jakarta.persistence.*;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.hibernate.annotations.Type;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@Entity
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class Employee extends BaseEntity {
|
||||
private String firstName;
|
||||
private String lastName;
|
||||
private LocalDate birthday;
|
||||
private String birthCity;
|
||||
|
||||
@Enumerated(EnumType.STRING)
|
||||
private MaritalStatus maritalStatus;
|
||||
|
||||
private String residenceAddress;
|
||||
private String phoneNumber;
|
||||
private String personalEmail;
|
||||
|
||||
private String emergencyCName;
|
||||
private String emergencyCAddress;
|
||||
private String emergencyCPhone;
|
||||
private String emergencyCEmail;
|
||||
|
||||
@Enumerated(EnumType.STRING)
|
||||
private Status status;
|
||||
|
||||
public enum Status {
|
||||
ACTIVE,
|
||||
INACTIVE
|
||||
package com.primefactorsolutions.model;
|
||||
|
||||
|
||||
import io.hypersistence.utils.hibernate.type.json.JsonType;
|
||||
import jakarta.persistence.*;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.hibernate.annotations.Type;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@Entity
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class Employee extends BaseEntity {
|
||||
private String firstName;
|
||||
private String lastName;
|
||||
private LocalDate birthday;
|
||||
private String birthCity;
|
||||
|
||||
@Enumerated(EnumType.STRING)
|
||||
private MaritalStatus maritalStatus;
|
||||
|
||||
private String residenceAddress;
|
||||
private String phoneNumber;
|
||||
private String personalEmail;
|
||||
|
||||
private String emergencyCName;
|
||||
private String emergencyCAddress;
|
||||
private String emergencyCPhone;
|
||||
private String emergencyCEmail;
|
||||
|
||||
@Enumerated(EnumType.STRING)
|
||||
private Status status;
|
||||
|
||||
public enum Status {
|
||||
ACTIVE,
|
||||
INACTIVE
|
||||
}
|
||||
|
||||
public enum MaritalStatus {
|
||||
SINGLE,
|
||||
MARRIED,
|
||||
WIDOWED,
|
||||
DIVORCED
|
||||
}
|
||||
|
||||
public Status getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public void setStatus(Status status) {
|
||||
this.status = status;
|
||||
}
|
||||
}
|
||||
|
||||
public enum MaritalStatus {
|
||||
SINGLE,
|
||||
MARRIED,
|
||||
WIDOWED,
|
||||
DIVORCED
|
||||
}
|
||||
}
|
||||
|
@ -1,49 +1,65 @@
|
||||
package com.primefactorsolutions.service;
|
||||
|
||||
import com.primefactorsolutions.model.Employee;
|
||||
import org.apache.commons.beanutils.BeanComparator;
|
||||
import com.primefactorsolutions.repositories.EmployeeRepository;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import lombok.Data;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.Optional;
|
||||
import java.util.Collections;
|
||||
|
||||
|
||||
@Service
|
||||
@Data
|
||||
public class EmployeeService {
|
||||
private final EmployeeRepository employeeRepository;
|
||||
private List<Employee> pagedBase;
|
||||
|
||||
public EmployeeService(EmployeeRepository employeeRepository) {
|
||||
this.employeeRepository = employeeRepository;
|
||||
}
|
||||
|
||||
private void initializePagedBase() {
|
||||
if (pagedBase == null) {
|
||||
alex
commented
no se puede guardar en un campo de la clase porque la clase es un singleton (si hay varios llamados van a haber problemas de concurrencia). solucion: no usar un campo en la clase y simplemente retornar toda la lista cada vez sin guardar en un campo. no se puede guardar en un campo de la clase porque la clase es un singleton (si hay varios llamados van a haber problemas de concurrencia). solucion: no usar un campo en la clase y simplemente retornar toda la lista cada vez sin guardar en un campo.
|
||||
this.pagedBase = employeeRepository.findAll();
|
||||
}
|
||||
}
|
||||
|
||||
public List<Employee> findEmployees(int start, int pageSize, String sortProperty, boolean asc) {
|
||||
initializePagedBase(); // Asegurarse de que pagedBase esté inicializada
|
||||
System.err.println("findAll " + start + " " + pageSize + " sort " + sortProperty + " asc:" + asc );
|
||||
alex
commented
usar logger en vez de system println. ver lombok @Slf4j https://projectlombok.org/features/log usar logger en vez de system println. ver lombok @Slf4j https://projectlombok.org/features/log
|
||||
int end = (int) (start + pageSize);
|
||||
if (end > pagedBase.size()) {
|
||||
end = pagedBase.size();
|
||||
}
|
||||
Collections.sort(pagedBase, new BeanComparator<Employee>(sortProperty));
|
||||
|
||||
if(!asc) {
|
||||
Collections.reverse(pagedBase);
|
||||
}
|
||||
return pagedBase.subList((int) start, end);
|
||||
}
|
||||
|
||||
public List<Employee> findEmployees(int start, int pageSize) {
|
||||
initializePagedBase(); // Asegurarse de que pagedBase esté inicializada
|
||||
System.err.println("findAll " + start + " " + pageSize);
|
||||
int end = (int) (start + pageSize);
|
||||
if (end > pagedBase.size()) {
|
||||
end = pagedBase.size();
|
||||
}
|
||||
return pagedBase.subList((int) start, end);
|
||||
}
|
||||
|
||||
public Employee createOrUpdate(final Employee employee) {
|
||||
final Employee saved = employeeRepository.save(employee);
|
||||
return saved;
|
||||
}
|
||||
|
||||
public List<Employee> getEmployees() {
|
||||
return employeeRepository.findAll();
|
||||
}
|
||||
|
||||
public Employee getEmployee(final UUID id) {
|
||||
Optional<Employee> employee = employeeRepository.findById(id);
|
||||
return employee.orElse(null);
|
||||
}
|
||||
|
||||
public Page<Employee> getEmployeesPaginated(int pageNo, int pageSize, String sortField, boolean ascending) {
|
||||
Sort sort = ascending ? Sort.by(sortField).ascending() : Sort.by(sortField).descending();
|
||||
Pageable pageable = PageRequest.of(pageNo - 1, pageSize, sort);
|
||||
return employeeRepository.findAll(pageable);
|
||||
}
|
||||
|
||||
public boolean hasNextPage(int currentPage, int pageSize, String sortField, boolean ascending) {
|
||||
return getEmployeesPaginated(currentPage, pageSize, sortField, ascending).hasNext();
|
||||
}
|
||||
}
|
||||
|
@ -3,18 +3,20 @@ package com.primefactorsolutions.views;
|
||||
import com.primefactorsolutions.model.Employee;
|
||||
import com.primefactorsolutions.service.EmployeeService;
|
||||
import com.vaadin.flow.component.button.Button;
|
||||
import com.vaadin.flow.component.combobox.ComboBox;
|
||||
import com.vaadin.flow.component.checkbox.Checkbox;
|
||||
import com.vaadin.flow.component.html.H2;
|
||||
import com.vaadin.flow.component.html.Main;
|
||||
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
|
||||
import com.vaadin.flow.component.notification.Notification;
|
||||
import com.vaadin.flow.router.PageTitle;
|
||||
import com.vaadin.flow.router.Route;
|
||||
import com.vaadin.flow.spring.annotation.SpringComponent;
|
||||
import org.vaadin.firitin.components.grid.PagingGrid;
|
||||
import com.vaadin.flow.component.grid.GridSortOrder;
|
||||
import com.vaadin.flow.data.provider.SortDirection;
|
||||
import jakarta.annotation.security.PermitAll;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
import org.vaadin.firitin.components.grid.VGrid;
|
||||
import org.springframework.data.domain.Page;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
@SpringComponent
|
||||
@Scope("prototype")
|
||||
@ -24,111 +26,99 @@ import org.springframework.data.domain.Page;
|
||||
public class EmployeesListView extends Main {
|
||||
|
||||
private final EmployeeService employeeService;
|
||||
private final int pageSize = 5;
|
||||
private int currentPage = 1;
|
||||
private String sortField = "firstName";
|
||||
private boolean ascending = true;
|
||||
private VGrid<Employee> grid;
|
||||
private Button previous;
|
||||
private Button next;
|
||||
private final PagingGrid<Employee> table = new PagingGrid<>(Employee.class);
|
||||
|
||||
public EmployeesListView(EmployeeService employeeService) {
|
||||
this.employeeService = employeeService;
|
||||
addComponents();
|
||||
updateGrid();
|
||||
setupView();
|
||||
refreshGrid();
|
||||
}
|
||||
|
||||
private void addComponents() {
|
||||
addTitle();
|
||||
addOrderButtons();
|
||||
configureGrid();
|
||||
addNavigationButtons();
|
||||
private void setupView() {
|
||||
add(new H2("Employee List"));
|
||||
configureTable();
|
||||
add(createAddEmployeeButton());
|
||||
add(table);
|
||||
}
|
||||
|
||||
private void addTitle() {
|
||||
final H2 title = new H2("Employees list");
|
||||
add(title);
|
||||
private void configureTable() {
|
||||
table.setColumns("firstName", "lastName", "status");
|
||||
addStatusColumn();
|
||||
addEditButtonColumn("Edit", this::navigateToEditView);
|
||||
addEditButtonColumn("Save", this::navigateToSaveChangeStatus);
|
||||
setupPagingGrid();
|
||||
}
|
||||
|
||||
private void addOrderButtons() {
|
||||
final HorizontalLayout hl = new HorizontalLayout();
|
||||
hl.add(createOrderButton("Employee List in Ascending Order", true));
|
||||
hl.add(createOrderButton("Employee List in Descending Order", false));
|
||||
add(hl);
|
||||
private void addStatusColumn() {
|
||||
table.addComponentColumn(this::createStatusCheckbox)
|
||||
.setHeader("Change Status");
|
||||
}
|
||||
|
||||
private Button createOrderButton(String label, boolean isAscending) {
|
||||
private Checkbox createStatusCheckbox(Employee employee) {
|
||||
Checkbox statusCheckbox = new Checkbox( employee.getStatus() == Employee.Status.ACTIVE);
|
||||
return statusCheckbox;
|
||||
}
|
||||
|
||||
private void updateEmployeeStatus(Employee employee, boolean isActive) {
|
||||
employee.setStatus(isActive ? Employee.Status.ACTIVE : Employee.Status.INACTIVE);
|
||||
employeeService.createOrUpdate(employee);
|
||||
refreshGrid();
|
||||
}
|
||||
|
||||
private void addEditButtonColumn(String label, ButtonClickHandler handler) {
|
||||
table.addComponentColumn(employee -> createButton(label, () -> handler.handle(employee)));
|
||||
}
|
||||
alex
commented
podemos usar el componente PagingGrid de la llibreria Viritin (ya esta incluida). Ejemplo: https://addons.dokku1.parttio.org/paginggrid y codigo https://github.com/parttio/addon-demos/blob/main/src/main/java/org/example/views/PagingGridView.java asi ya no necesitamos crear los botones y navegacion manualmente. podemos usar el componente PagingGrid de la llibreria Viritin (ya esta incluida). Ejemplo: https://addons.dokku1.parttio.org/paginggrid y codigo https://github.com/parttio/addon-demos/blob/main/src/main/java/org/example/views/PagingGridView.java
asi ya no necesitamos crear los botones y navegacion manualmente.
|
||||
|
||||
private Button createButton(String label, Runnable onClickAction) {
|
||||
Button button = new Button(label);
|
||||
button.addClickListener(event -> {
|
||||
sortField = "firstName";
|
||||
ascending = isAscending;
|
||||
updateGrid();
|
||||
});
|
||||
button.addClickListener(event -> onClickAction.run());
|
||||
return button;
|
||||
}
|
||||
private void configureGrid() {
|
||||
grid = new VGrid<>(Employee.class);
|
||||
grid.setColumns("firstName", "lastName", "status");
|
||||
grid.setAllRowsVisible(true);
|
||||
grid.addComponentColumn(employee -> createStatusComboBox()).setHeader("Change Status");
|
||||
grid.addComponentColumn(employee -> createEditButton());
|
||||
grid.addComponentColumn(employee -> createSaveButton());
|
||||
add(grid);
|
||||
}
|
||||
|
||||
private ComboBox<String> createStatusComboBox() {
|
||||
ComboBox<String> statusComboBox = new ComboBox<>();
|
||||
statusComboBox.setItems("Active", "Inactive");
|
||||
return statusComboBox;
|
||||
}
|
||||
|
||||
private Button createEditButton() {
|
||||
return new Button("Edit");
|
||||
}
|
||||
private Button createSaveButton() {
|
||||
return new Button("Save");
|
||||
}
|
||||
|
||||
private void addNavigationButtons() {
|
||||
final HorizontalLayout hf = new HorizontalLayout();
|
||||
previous = createNavigationButton("Previous", -1);
|
||||
next = createNavigationButton("Next", 1);
|
||||
hf.add(previous, next, createAddEmployeeButton());
|
||||
add(hf);
|
||||
}
|
||||
|
||||
private Button createNavigationButton(String label, int increment) {
|
||||
Button button = new Button(label);
|
||||
button.addClickListener(event -> handlePageChange(increment));
|
||||
return button;
|
||||
}
|
||||
private void handlePageChange(int increment) {
|
||||
if (isPageChangeValid(increment)) {
|
||||
currentPage += increment;
|
||||
updateGrid();
|
||||
} else {
|
||||
showNotification("No existen más datos en lista.");
|
||||
}
|
||||
}
|
||||
private boolean isPageChangeValid(int increment) {
|
||||
if (increment < 0) {
|
||||
return currentPage > 1;
|
||||
} else if (increment > 0) {
|
||||
return employeeService.hasNextPage(currentPage, pageSize, sortField, ascending);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
private void showNotification(String message) {
|
||||
Notification notification = new Notification(message, 3000, Notification.Position.BOTTOM_END);
|
||||
notification.open();
|
||||
}
|
||||
private Button createAddEmployeeButton() {
|
||||
return new Button("Add Employee", event ->
|
||||
getUI().flatMap(ui -> ui.navigate(EmployeeView.class, "new"))
|
||||
);
|
||||
return createButton("Add Employee", this::navigateToAddEmployeeView);
|
||||
}
|
||||
private void updateGrid() {
|
||||
Page<Employee> page = employeeService.getEmployeesPaginated(currentPage, pageSize, sortField, ascending);
|
||||
grid.setItems(page.getContent());
|
||||
|
||||
private void navigateToEditView(Employee employee) {
|
||||
getUI().ifPresent(ui -> ui.navigate(EmployeeView.class, employee.getId().toString()));
|
||||
}
|
||||
}
|
||||
|
||||
private void navigateToAddEmployeeView() {
|
||||
getUI().ifPresent(ui -> ui.navigate(EmployeeView.class, "new"));
|
||||
}
|
||||
|
||||
private void navigateToSaveChangeStatus(Employee employee) {
|
||||
// no-op
|
||||
}
|
||||
|
||||
private void setupPagingGrid() {
|
||||
table.setPaginationBarMode(PagingGrid.PaginationBarMode.BOTTOM);
|
||||
table.setPageSize(5);
|
||||
}
|
||||
|
||||
private void refreshGrid() {
|
||||
table.setPagingDataProvider((page, pageSize) -> fetchEmployees((int) page, pageSize));
|
||||
}
|
||||
|
||||
private List<Employee> fetchEmployees(int page, int pageSize) {
|
||||
int start = page * pageSize;
|
||||
if (hasSortOrder()) {
|
||||
return fetchSortedEmployees(start, pageSize);
|
||||
}
|
||||
return employeeService.findEmployees(start, pageSize);
|
||||
}
|
||||
|
||||
private boolean hasSortOrder() {
|
||||
return !table.getSortOrder().isEmpty();
|
||||
}
|
||||
|
||||
private List<Employee> fetchSortedEmployees(int start, int pageSize) {
|
||||
GridSortOrder<Employee> sortOrder = table.getSortOrder().getFirst();
|
||||
return employeeService.findEmployees(start, pageSize, sortOrder.getSorted().getKey(), sortOrder.getDirection() == SortDirection.ASCENDING);
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
private interface ButtonClickHandler {
|
||||
void handle(Employee employee);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user
quitar espacios blancos al inicio de cada linea