Rama-Ricardo #14

Merged
alex merged 8 commits from Rama-Ricardo into main 2024-09-04 17:53:01 +00:00
4 changed files with 182 additions and 163 deletions
Showing only changes of commit 4eebdf6f01 - Show all commits

View File

@ -110,6 +110,11 @@
<artifactId>spring-boot-starter-test</artifactId> <artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
<version>1.9.4</version>
</dependency>
<dependency> <dependency>
<groupId>org.mockito</groupId> <groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId> <artifactId>mockito-core</artifactId>

View File

@ -1,51 +1,59 @@
package com.primefactorsolutions.model; package com.primefactorsolutions.model;
Review

quitar espacios blancos al inicio de cada linea

quitar espacios blancos al inicio de cada linea
import io.hypersistence.utils.hibernate.type.json.JsonType; import io.hypersistence.utils.hibernate.type.json.JsonType;
import jakarta.persistence.*; import jakarta.persistence.*;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import org.hibernate.annotations.Type; import org.hibernate.annotations.Type;
import java.time.LocalDate; import java.time.LocalDate;
import java.util.List; import java.util.List;
@Data @Data
@Entity @Entity
@AllArgsConstructor @AllArgsConstructor
@NoArgsConstructor @NoArgsConstructor
@EqualsAndHashCode(callSuper = true) @EqualsAndHashCode(callSuper = true)
public class Employee extends BaseEntity { public class Employee extends BaseEntity {
private String firstName; private String firstName;
private String lastName; private String lastName;
private LocalDate birthday; private LocalDate birthday;
private String birthCity; private String birthCity;
@Enumerated(EnumType.STRING) @Enumerated(EnumType.STRING)
private MaritalStatus maritalStatus; private MaritalStatus maritalStatus;
private String residenceAddress; private String residenceAddress;
private String phoneNumber; private String phoneNumber;
private String personalEmail; private String personalEmail;
private String emergencyCName; private String emergencyCName;
private String emergencyCAddress; private String emergencyCAddress;
private String emergencyCPhone; private String emergencyCPhone;
private String emergencyCEmail; private String emergencyCEmail;
@Enumerated(EnumType.STRING) @Enumerated(EnumType.STRING)
private Status status; private Status status;
public enum Status { public enum Status {
ACTIVE, ACTIVE,
INACTIVE 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
}
}

View File

@ -1,49 +1,65 @@
package com.primefactorsolutions.service; package com.primefactorsolutions.service;
import com.primefactorsolutions.model.Employee; import com.primefactorsolutions.model.Employee;
import org.apache.commons.beanutils.BeanComparator;
import com.primefactorsolutions.repositories.EmployeeRepository; 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 lombok.Data;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
import java.util.Optional; import java.util.Optional;
import java.util.Collections;
@Service @Service
@Data @Data
public class EmployeeService { public class EmployeeService {
private final EmployeeRepository employeeRepository; private final EmployeeRepository employeeRepository;
private List<Employee> pagedBase;
public EmployeeService(EmployeeRepository employeeRepository) { public EmployeeService(EmployeeRepository employeeRepository) {
this.employeeRepository = employeeRepository; this.employeeRepository = employeeRepository;
} }
private void initializePagedBase() {
if (pagedBase == null) {
Outdated
Review

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 );
Outdated
Review

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) { public Employee createOrUpdate(final Employee employee) {
final Employee saved = employeeRepository.save(employee); final Employee saved = employeeRepository.save(employee);
return saved; return saved;
} }
public List<Employee> getEmployees() {
return employeeRepository.findAll();
}
public Employee getEmployee(final UUID id) { public Employee getEmployee(final UUID id) {
Optional<Employee> employee = employeeRepository.findById(id); Optional<Employee> employee = employeeRepository.findById(id);
return employee.orElse(null); 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();
}
} }

View File

@ -3,18 +3,20 @@ package com.primefactorsolutions.views;
import com.primefactorsolutions.model.Employee; import com.primefactorsolutions.model.Employee;
import com.primefactorsolutions.service.EmployeeService; import com.primefactorsolutions.service.EmployeeService;
import com.vaadin.flow.component.button.Button; 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.H2;
import com.vaadin.flow.component.html.Main; 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.PageTitle;
import com.vaadin.flow.router.Route; import com.vaadin.flow.router.Route;
import com.vaadin.flow.spring.annotation.SpringComponent; 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 jakarta.annotation.security.PermitAll;
import org.springframework.context.annotation.Scope; import org.springframework.context.annotation.Scope;
import org.vaadin.firitin.components.grid.VGrid;
import org.springframework.data.domain.Page; import java.util.List;
@SpringComponent @SpringComponent
@Scope("prototype") @Scope("prototype")
@ -24,111 +26,99 @@ import org.springframework.data.domain.Page;
public class EmployeesListView extends Main { public class EmployeesListView extends Main {
private final EmployeeService employeeService; private final EmployeeService employeeService;
private final int pageSize = 5; private final PagingGrid<Employee> table = new PagingGrid<>(Employee.class);
private int currentPage = 1;
private String sortField = "firstName";
private boolean ascending = true;
private VGrid<Employee> grid;
private Button previous;
private Button next;
public EmployeesListView(EmployeeService employeeService) { public EmployeesListView(EmployeeService employeeService) {
this.employeeService = employeeService; this.employeeService = employeeService;
addComponents(); setupView();
updateGrid(); refreshGrid();
} }
private void addComponents() { private void setupView() {
addTitle(); add(new H2("Employee List"));
addOrderButtons(); configureTable();
configureGrid(); add(createAddEmployeeButton());
addNavigationButtons(); add(table);
} }
private void addTitle() { private void configureTable() {
final H2 title = new H2("Employees list"); table.setColumns("firstName", "lastName", "status");
add(title); addStatusColumn();
addEditButtonColumn("Edit", this::navigateToEditView);
addEditButtonColumn("Save", this::navigateToSaveChangeStatus);
setupPagingGrid();
} }
private void addOrderButtons() { private void addStatusColumn() {
final HorizontalLayout hl = new HorizontalLayout(); table.addComponentColumn(this::createStatusCheckbox)
hl.add(createOrderButton("Employee List in Ascending Order", true)); .setHeader("Change Status");
hl.add(createOrderButton("Employee List in Descending Order", false));
add(hl);
} }
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)));
}
Outdated
Review

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 button = new Button(label);
button.addClickListener(event -> { button.addClickListener(event -> onClickAction.run());
sortField = "firstName";
ascending = isAscending;
updateGrid();
});
return button; 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() { private Button createAddEmployeeButton() {
return new Button("Add Employee", event -> return createButton("Add Employee", this::navigateToAddEmployeeView);
getUI().flatMap(ui -> ui.navigate(EmployeeView.class, "new"))
);
} }
private void updateGrid() {
Page<Employee> page = employeeService.getEmployeesPaginated(currentPage, pageSize, sortField, ascending); private void navigateToEditView(Employee employee) {
grid.setItems(page.getContent()); 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);
}
}