From 2caa878c07399d38829f83a53f38e4921347b3c7 Mon Sep 17 00:00:00 2001 From: ricardo051199 Date: Tue, 24 Sep 2024 12:30:03 -0400 Subject: [PATCH 1/9] =?UTF-8?q?#30=20Perfil=20de=20Usuario=20Administrativ?= =?UTF-8?q?o=20-=20A=C3=B1adir=20NUEVO=20Documento?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/EmployeeService.java | 4 + .../views/DocumentsView.java | 201 ++++++++---------- .../views/MainLayout.java | 8 +- 3 files changed, 95 insertions(+), 118 deletions(-) diff --git a/src/main/java/com/primefactorsolutions/service/EmployeeService.java b/src/main/java/com/primefactorsolutions/service/EmployeeService.java index c30f9b8..45f3cd2 100644 --- a/src/main/java/com/primefactorsolutions/service/EmployeeService.java +++ b/src/main/java/com/primefactorsolutions/service/EmployeeService.java @@ -87,4 +87,8 @@ public class EmployeeService { ldapTemplate.modifyAttributes(buildDn(employee), new ModificationItem[] {item}); } + + public List findAllEmployees() { + return employeeRepository.findAll(); + } } \ No newline at end of file diff --git a/src/main/java/com/primefactorsolutions/views/DocumentsView.java b/src/main/java/com/primefactorsolutions/views/DocumentsView.java index 545472c..37b11b5 100644 --- a/src/main/java/com/primefactorsolutions/views/DocumentsView.java +++ b/src/main/java/com/primefactorsolutions/views/DocumentsView.java @@ -2,18 +2,16 @@ package com.primefactorsolutions.views; import com.primefactorsolutions.model.Document; import com.primefactorsolutions.model.DocumentType; +import com.primefactorsolutions.model.Employee; import com.primefactorsolutions.service.DocumentService; -import com.vaadin.flow.component.Component; +import com.primefactorsolutions.service.EmployeeService; import com.vaadin.flow.component.button.Button; -import com.vaadin.flow.component.dialog.Dialog; -import com.vaadin.flow.component.html.Div; +import com.vaadin.flow.component.combobox.ComboBox; import com.vaadin.flow.component.html.H2; -import com.vaadin.flow.component.html.IFrame; import com.vaadin.flow.component.html.Main; import com.vaadin.flow.component.notification.Notification; -import com.vaadin.flow.component.orderedlayout.FlexComponent; import com.vaadin.flow.component.orderedlayout.HorizontalLayout; -import com.vaadin.flow.component.orderedlayout.VerticalLayout; +import com.vaadin.flow.component.textfield.TextField; import com.vaadin.flow.component.upload.Upload; import com.vaadin.flow.component.upload.receivers.MemoryBuffer; import com.vaadin.flow.router.PageTitle; @@ -23,152 +21,129 @@ import jakarta.annotation.security.PermitAll; import org.springframework.context.annotation.Scope; import java.io.IOException; -import java.util.Base64; +import java.util.List; @SpringComponent @PermitAll @Scope("prototype") @PageTitle("Documents") -@Route(value = "/documents/me", layout = MainLayout.class) -public abstract class DocumentsView extends Main { - private final DocumentService documentService; +@Route(value = "/documents", layout = MainLayout.class) +public class DocumentsView extends Main { + + private final TextField fileName = new TextField("Document Name"); + private final ComboBox documentType = new ComboBox<>("Document Type"); + private final ComboBox employeeComboBox = new ComboBox<>("Employee"); private final MemoryBuffer buffer = new MemoryBuffer(); - private String lastUploadedFileName = null; + private final Upload uploadButton = new Upload(buffer); + private final DocumentService documentService; + private final EmployeeService employeeService; + private boolean fileUploaded = false; - public DocumentsView(final DocumentService documentService) { + public DocumentsView(final DocumentService documentService, final EmployeeService employeeService) { this.documentService = documentService; - initializeLayout(); + this.employeeService = employeeService; + initializeView(); + addComponents(); } - protected abstract void initializeLayout(); - - protected HorizontalLayout createRow( - final String title1, - final DocumentType type1, - final String title2, - final DocumentType type2) { - - HorizontalLayout row = new HorizontalLayout(); - row.add( - createDocumentSection(title1, type1), - createDocumentSection(title2, type2) - ); - return row; + private void initializeView() { + setFileNameProperties(); + setDocumentTypeProperties(); + setEmployeeComboBoxProperties(); + setUploadButtonProperties(); } - protected HorizontalLayout createRow(final String title1, final DocumentType type1) { - HorizontalLayout row = new HorizontalLayout(); - row.add(createDocumentSection(title1, type1)); - return row; + private void setFileNameProperties() { + fileName.setWidthFull(); } - private Div createDocumentSection(final String title, final DocumentType documentType) { - Div section = new Div(); - section.add(new H2(title)); - - Upload upload = createUploadComponent(); - Button viewButton = createViewButton(documentType); - Button saveButton = createSaveButton(viewButton, documentType); - - section.add(createLayout(upload), - createLayout(viewButton, new Button("Edit"), saveButton), - createAdditionalButtons()); - return section; + private void setDocumentTypeProperties() { + documentType.setItems(DocumentType.values()); + documentType.setWidthFull(); } - private Upload createUploadComponent() { - Upload upload = new Upload(buffer); - upload.setMaxFiles(1); - upload.setAcceptedFileTypes(".pdf"); - upload.addSucceededListener(event -> handleUploadSuccess(event.getFileName())); - return upload; + private void setEmployeeComboBoxProperties() { + List employees = employeeService.findAllEmployees(); + employeeComboBox.setItems(employees); + employeeComboBox.setItemLabelGenerator(employee -> employee.getFirstName() + " " + employee.getLastName()); + employeeComboBox.setWidthFull(); } - private Button createViewButton(final DocumentType documentType) { - Button viewButton = new Button("View"); - viewButton.setEnabled(documentExists(documentType)); - viewButton.addClickListener(event -> viewDocument(documentType)); - return viewButton; + private void setUploadButtonProperties() { + uploadButton.setMaxFiles(1); + uploadButton.setAcceptedFileTypes(".pdf"); + uploadButton.addSucceededListener(event -> handleUploadSuccess()); } - private Button createSaveButton(final Button viewButton, final DocumentType documentType) { + private void addComponents() { + H2 title = new H2("Edit Documents"); + Button saveButton = createSaveButton(); + Button closeButton = createCloseButton(); + HorizontalLayout buttonLayout = new HorizontalLayout(saveButton, closeButton); + + add(title, fileName, documentType, employeeComboBox, uploadButton, buttonLayout); + } + + private Button createSaveButton() { Button saveButton = new Button("Save"); - saveButton.addClickListener(event -> saveFile(documentType, viewButton)); + saveButton.addClickListener(event -> saveDocument()); return saveButton; } - private void handleUploadSuccess(final String fileName) { - lastUploadedFileName = fileName; - Notification.show("File uploaded successfully"); + private Button createCloseButton() { + Button closeButton = new Button("Close"); + closeButton.addClickListener(event -> closeForm()); + return closeButton; } - private HorizontalLayout createLayout(final Component... components) { - if (components.length != 1 && components.length != 3) { - throw new IllegalArgumentException("This method only accepts 1 or 3 components."); - } - HorizontalLayout layout = new HorizontalLayout(components); - layout.setJustifyContentMode(FlexComponent.JustifyContentMode.CENTER); - return layout; + private void handleUploadSuccess() { + fileUploaded = true; + Notification.show("File uploaded successfully."); } - private HorizontalLayout createAdditionalButtons() { - return createLayout(new Button("Print"), new Button("Download"), new Button("Delete")); - } - - private void saveFile(final DocumentType documentType, final Button viewButton) { - if (lastUploadedFileName == null) { - Notification.show("Please upload a file first."); - return; - } - try { - byte[] content = buffer.getInputStream().readAllBytes(); - documentService.saveDocument(new Document(lastUploadedFileName, documentType, content)); + private void saveDocument() { + if (isFormValid()) { + Document document = createDocument(); + documentService.saveDocument(document); Notification.show("File saved successfully."); - viewButton.setEnabled(true); - } catch (IOException e) { - Notification.show("Error saving file: " + e.getMessage()); + clearForm(); + } else { + Notification.show("Save failed: Please complete all fields and upload a file."); } } - private boolean documentExists(final DocumentType documentType) { - return documentService.getAllDocuments().stream() - .anyMatch(doc -> doc.getDocumentType() == documentType); + private boolean isFormValid() { + return !fileName.isEmpty() + && documentType.getValue() != null + && employeeComboBox.getValue() != null + && fileUploaded; } - private void viewDocument(final DocumentType documentType) { - documentService.getAllDocuments().stream() - .filter(doc -> doc.getDocumentType() == documentType) - .findFirst() - .ifPresentOrElse(this::showPdfDialog, () -> Notification.show("Document not found.")); + private Document createDocument() { + Document document = new Document(); + document.setFileName(fileName.getValue()); + document.setDocumentType(documentType.getValue()); + document.setFileData(readFileData()); + return document; } - private void showPdfDialog(final Document document) { - Dialog dialog = createDialog(document.getFileData()); - dialog.open(); + private byte[] readFileData() { + try { + return buffer.getInputStream().readAllBytes(); + } catch (IOException e) { + Notification.show("Error reading file data."); + return new byte[0]; + } } - private Dialog createDialog(final byte[] fileData) { - Dialog dialog = new Dialog(); - dialog.setModal(true); - dialog.setCloseOnEsc(true); - dialog.setCloseOnOutsideClick(true); - - IFrame pdfFrame = new IFrame(); - pdfFrame.setSrc(createPdfResource(fileData)); - pdfFrame.setWidth("800px"); - pdfFrame.setHeight("600px"); - - Button closeButton = new Button("Close", event -> dialog.close()); - VerticalLayout layout = new VerticalLayout(pdfFrame, closeButton); - layout.setAlignItems(FlexComponent.Alignment.CENTER); - - dialog.add(layout); - return dialog; + private void clearForm() { + fileName.clear(); + documentType.clear(); + employeeComboBox.clear(); + fileUploaded = false; } - private String createPdfResource(final byte[] fileData) { - return "data:application/pdf;base64," + Base64.getEncoder().encodeToString(fileData); + private void closeForm() { + clearForm(); } - } - diff --git a/src/main/java/com/primefactorsolutions/views/MainLayout.java b/src/main/java/com/primefactorsolutions/views/MainLayout.java index b5bbcf6..36aaa54 100644 --- a/src/main/java/com/primefactorsolutions/views/MainLayout.java +++ b/src/main/java/com/primefactorsolutions/views/MainLayout.java @@ -18,9 +18,7 @@ import com.vaadin.flow.theme.lumo.LumoUtility; import org.springframework.security.core.userdetails.UserDetails; import org.vaadin.lineawesome.LineAwesomeIcon; -/** - * The main view is a top-level placeholder for other views. - */ + public class MainLayout extends AppLayout { private final transient AuthenticationContext authContext; @@ -81,8 +79,8 @@ public class MainLayout extends AppLayout { SideNavItem admin = new SideNavItem("Admin", MainView.class, LineAwesomeIcon.SUPERSCRIPT_SOLID.create()); - admin.addItem(new SideNavItem("Employees", EmployeeView.class, - LineAwesomeIcon.USER_EDIT_SOLID.create())); +// admin.addItem(new SideNavItem("Employees", EmployeeView.class, +// LineAwesomeIcon.USER_EDIT_SOLID.create())); admin.addItem(new SideNavItem("Documents", DocumentsView.class, LineAwesomeIcon.FILE_ALT_SOLID.create())); From 514e4eaf4937a539fa72108f8f4706bd3b0d9e3e Mon Sep 17 00:00:00 2001 From: ricardo051199 Date: Tue, 24 Sep 2024 17:07:53 -0400 Subject: [PATCH 2/9] #29 Perfil de Empleado Administrativo - LISTAR Documentos --- .../primefactorsolutions/model/Document.java | 3 + .../service/DocumentService.java | 34 ++++- .../{DocumentsView.java => DocumentView.java} | 62 +++++--- .../views/DocumentsListView.java | 143 ++++++++++++++++++ .../views/MainLayout.java | 2 +- 5 files changed, 215 insertions(+), 29 deletions(-) rename src/main/java/com/primefactorsolutions/views/{DocumentsView.java => DocumentView.java} (73%) create mode 100644 src/main/java/com/primefactorsolutions/views/DocumentsListView.java diff --git a/src/main/java/com/primefactorsolutions/model/Document.java b/src/main/java/com/primefactorsolutions/model/Document.java index 3b8b200..2e3b222 100644 --- a/src/main/java/com/primefactorsolutions/model/Document.java +++ b/src/main/java/com/primefactorsolutions/model/Document.java @@ -13,6 +13,9 @@ public class Document extends BaseEntity { private String fileName; @Enumerated(EnumType.STRING) private DocumentType documentType; + @ManyToOne + @JoinColumn(name = "employee_id", nullable = false) + private Employee employee; @Lob @Column(columnDefinition = "BLOB") private byte[] fileData; diff --git a/src/main/java/com/primefactorsolutions/service/DocumentService.java b/src/main/java/com/primefactorsolutions/service/DocumentService.java index 838840f..efdf0cc 100644 --- a/src/main/java/com/primefactorsolutions/service/DocumentService.java +++ b/src/main/java/com/primefactorsolutions/service/DocumentService.java @@ -2,20 +2,20 @@ package com.primefactorsolutions.service; import com.primefactorsolutions.model.Document; import com.primefactorsolutions.repositories.DocumentRepository; +import lombok.AllArgsConstructor; +import org.apache.commons.beanutils.BeanComparator; import org.springframework.stereotype.Service; +import java.util.Collections; import java.util.List; import java.util.UUID; import java.util.Optional; @Service +@AllArgsConstructor public class DocumentService { private final DocumentRepository documentRepository; - public DocumentService(final DocumentRepository documentRepository) { - this.documentRepository = documentRepository; - } - public void saveDocument(final Document newDocument) { documentRepository.save(newDocument); } @@ -24,7 +24,29 @@ public class DocumentService { return documentRepository.findAll(); } - public Optional getDocumentById(final UUID id) { - return documentRepository.findById(id); + public Document getDocument(final UUID id) { + Optional employee = documentRepository.findById(id); + return employee.orElse(null); + } + + public List findDocuments( + final int start, final int pageSize, final String sortProperty, final boolean asc) { + List documents = documentRepository.findAll(); + + int end = Math.min(start + pageSize, documents.size()); + documents.sort(new BeanComparator<>(sortProperty)); + + if (!asc) { + Collections.reverse(documents); + } + + return documents.subList(start, end); + } + + public List findDocuments(final int start, final int pageSize) { + List employees = documentRepository.findAll(); + + int end = Math.min(start + pageSize, employees.size()); + return employees.subList(start, end); } } diff --git a/src/main/java/com/primefactorsolutions/views/DocumentsView.java b/src/main/java/com/primefactorsolutions/views/DocumentView.java similarity index 73% rename from src/main/java/com/primefactorsolutions/views/DocumentsView.java rename to src/main/java/com/primefactorsolutions/views/DocumentView.java index 37b11b5..4b9014f 100644 --- a/src/main/java/com/primefactorsolutions/views/DocumentsView.java +++ b/src/main/java/com/primefactorsolutions/views/DocumentView.java @@ -5,31 +5,32 @@ import com.primefactorsolutions.model.DocumentType; import com.primefactorsolutions.model.Employee; import com.primefactorsolutions.service.DocumentService; import com.primefactorsolutions.service.EmployeeService; +import com.vaadin.flow.component.Component; import com.vaadin.flow.component.button.Button; import com.vaadin.flow.component.combobox.ComboBox; import com.vaadin.flow.component.html.H2; -import com.vaadin.flow.component.html.Main; import com.vaadin.flow.component.notification.Notification; -import com.vaadin.flow.component.orderedlayout.HorizontalLayout; import com.vaadin.flow.component.textfield.TextField; import com.vaadin.flow.component.upload.Upload; import com.vaadin.flow.component.upload.receivers.MemoryBuffer; -import com.vaadin.flow.router.PageTitle; -import com.vaadin.flow.router.Route; +import com.vaadin.flow.router.*; import com.vaadin.flow.spring.annotation.SpringComponent; import jakarta.annotation.security.PermitAll; import org.springframework.context.annotation.Scope; +import org.vaadin.firitin.form.BeanValidationForm; import java.io.IOException; import java.util.List; +import java.util.UUID; @SpringComponent @PermitAll @Scope("prototype") -@PageTitle("Documents") -@Route(value = "/documents", layout = MainLayout.class) -public class DocumentsView extends Main { +@PageTitle("Document") +@Route(value = "/documents/:documentId?/:action?", layout = MainLayout.class) +public class DocumentView extends BeanValidationForm implements HasUrlParameter { + private final H2 title = new H2("Edit Documents"); private final TextField fileName = new TextField("Document Name"); private final ComboBox documentType = new ComboBox<>("Document Type"); private final ComboBox employeeComboBox = new ComboBox<>("Employee"); @@ -39,11 +40,11 @@ public class DocumentsView extends Main { private final EmployeeService employeeService; private boolean fileUploaded = false; - public DocumentsView(final DocumentService documentService, final EmployeeService employeeService) { + public DocumentView(final DocumentService documentService, final EmployeeService employeeService) { + super(Document.class); this.documentService = documentService; this.employeeService = employeeService; initializeView(); - addComponents(); } private void initializeView() { @@ -75,27 +76,27 @@ public class DocumentsView extends Main { uploadButton.addSucceededListener(event -> handleUploadSuccess()); } - private void addComponents() { - H2 title = new H2("Edit Documents"); - Button saveButton = createSaveButton(); - Button closeButton = createCloseButton(); - HorizontalLayout buttonLayout = new HorizontalLayout(saveButton, closeButton); - - add(title, fileName, documentType, employeeComboBox, uploadButton, buttonLayout); - } - - private Button createSaveButton() { + protected Button createSaveButton() { Button saveButton = new Button("Save"); saveButton.addClickListener(event -> saveDocument()); return saveButton; } - private Button createCloseButton() { + protected Button createCloseButton() { Button closeButton = new Button("Close"); closeButton.addClickListener(event -> closeForm()); return closeButton; } + + private void closeForm() { + navigateToDocumentsListView(); + } + + private void navigateToDocumentsListView() { + getUI().ifPresent(ui -> ui.navigate(DocumentsListView.class)); + } + private void handleUploadSuccess() { fileUploaded = true; Notification.show("File uploaded successfully."); @@ -104,6 +105,7 @@ public class DocumentsView extends Main { private void saveDocument() { if (isFormValid()) { Document document = createDocument(); + document.setEmployee(employeeComboBox.getValue()); documentService.saveDocument(document); Notification.show("File saved successfully."); clearForm(); @@ -143,7 +145,23 @@ public class DocumentsView extends Main { fileUploaded = false; } - private void closeForm() { - clearForm(); + + @Override + public void setParameter(final BeforeEvent beforeEvent, final String action) { + final RouteParameters params = beforeEvent.getRouteParameters(); + final String s = params.get("documentId").orElse(null); + + if ("new".equals(action)) { + setEntityWithEnabledSave(new Document()); + } else { + UUID documentId = UUID.fromString(s); + var document = documentService.getDocument(documentId); + setEntityWithEnabledSave(document); + } + } + + @Override + protected List getFormComponents() { + return List.of(title, fileName, documentType, employeeComboBox, uploadButton, createCloseButton()); } } diff --git a/src/main/java/com/primefactorsolutions/views/DocumentsListView.java b/src/main/java/com/primefactorsolutions/views/DocumentsListView.java new file mode 100644 index 0000000..0a311b1 --- /dev/null +++ b/src/main/java/com/primefactorsolutions/views/DocumentsListView.java @@ -0,0 +1,143 @@ +package com.primefactorsolutions.views; + +import com.primefactorsolutions.model.Document; +import com.primefactorsolutions.model.DocumentType; +import com.primefactorsolutions.model.Employee; +import com.primefactorsolutions.service.DocumentService; +import com.primefactorsolutions.service.EmployeeService; +import com.vaadin.flow.component.button.Button; +import com.vaadin.flow.component.combobox.ComboBox; +import com.vaadin.flow.component.html.Main; +import com.vaadin.flow.component.html.Span; +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 java.util.List; + + +@SpringComponent +@Scope("prototype") +@PageTitle("Documents") +@Route(value = "/documents", layout = MainLayout.class) +@PermitAll +public class DocumentsListView extends Main { + + private final DocumentService documentService; + private final EmployeeService employeeService; + private final PagingGrid documentGrid = new PagingGrid<>(Document.class); + + public DocumentsListView(final DocumentService documentService, final EmployeeService employeeService) { + this.documentService = documentService; + this.employeeService = employeeService; + initializeView(); + updateDocumentGrid(); + } + + private void initializeView() { + configureDocumentGrid(); + add(createActionButton("Add Document", this::navigateToAddDocumentView)); + add(createDocumentTypeFilter()); + add(createEmployeeFilter()); + add(documentGrid); + } + + private void configureDocumentGrid() { + documentGrid.setColumns("fileName", "documentType"); + documentGrid.addComponentColumn(this::createEmployeeSpan).setHeader("Employee"); + addDocumentActionColumn("View", this::navigateToDocumentView); + addDocumentActionColumn("Edit", this::navigateToEditDocumentView); + addDocumentActionColumn("Download", this::navigateToDownloadDocumentView); + configurePagination(); + } + + private Span createEmployeeSpan(final Document document) { + Employee employee = document.getEmployee(); + String employeeName = employee.getFirstName() + " " + employee.getLastName(); + return new Span(employeeName); + } + + + private void addDocumentActionColumn(final String label, final DocumentActionHandler handler) { + documentGrid.addComponentColumn(document -> createActionButton(label, () -> handler.handle(document))); + } + + private Button createActionButton(final String label, final Runnable onClickAction) { + Button actionButton = new Button(label); + actionButton.addClickListener(event -> onClickAction.run()); + return actionButton; + } + + private ComboBox createDocumentTypeFilter() { + ComboBox documentTypeFilter = new ComboBox<>("Document Type"); + documentTypeFilter.setItems(DocumentType.values()); + documentTypeFilter.addValueChangeListener(event -> updateDocumentGrid()); + return documentTypeFilter; + } + + private ComboBox createEmployeeFilter() { + ComboBox employeeFilter = new ComboBox<>("Employee"); + List employees = employeeService.findAllEmployees(); + employeeFilter.setItems(employees); + employeeFilter.setItemLabelGenerator(employee -> employee.getFirstName() + " " + employee.getLastName()); + employeeFilter.addValueChangeListener(event -> updateDocumentGrid()); + return employeeFilter; + } + + private void navigateToEditDocumentView(final Document document) { + navigateToDocumentView(document, "edit"); + } + + private void navigateToDocumentView(final Document document) { + navigateToDocumentView(document, "view"); + } + + private void navigateToDocumentView(final Document document, final String action) { + getUI().ifPresent(ui -> ui.navigate(DocumentView.class, document.getId().toString() + "/" + action)); + } + + private void navigateToDownloadDocumentView(final Document document) { + // No operation + } + + private void navigateToAddDocumentView() { + getUI().ifPresent(ui -> ui.navigate(DocumentView.class, "new")); + } + + private void configurePagination() { + documentGrid.setPaginationBarMode(PagingGrid.PaginationBarMode.BOTTOM); + documentGrid.setPageSize(5); + } + + private void updateDocumentGrid() { + documentGrid.setPagingDataProvider((page, pageSize) -> fetchDocuments((int) page, pageSize)); + } + + private List fetchDocuments(final int page, final int size) { + int startIndex = page * size; + return isSortOrderPresent() + ? fetchSortedDocuments(startIndex, size) + : documentService.findDocuments(startIndex, size); + } + + private boolean isSortOrderPresent() { + return !documentGrid.getSortOrder().isEmpty(); + } + + private List fetchSortedDocuments(final int start, final int pageSize) { + GridSortOrder sortOrder = documentGrid.getSortOrder().getFirst(); + return documentService.findDocuments(start, pageSize, + sortOrder.getSorted().getKey(), + sortOrder.getDirection() == SortDirection.ASCENDING); + } + + @FunctionalInterface + private interface DocumentActionHandler { + void handle(Document document); + } +} \ No newline at end of file diff --git a/src/main/java/com/primefactorsolutions/views/MainLayout.java b/src/main/java/com/primefactorsolutions/views/MainLayout.java index 36aaa54..42abb45 100644 --- a/src/main/java/com/primefactorsolutions/views/MainLayout.java +++ b/src/main/java/com/primefactorsolutions/views/MainLayout.java @@ -81,7 +81,7 @@ public class MainLayout extends AppLayout { LineAwesomeIcon.SUPERSCRIPT_SOLID.create()); // admin.addItem(new SideNavItem("Employees", EmployeeView.class, // LineAwesomeIcon.USER_EDIT_SOLID.create())); - admin.addItem(new SideNavItem("Documents", DocumentsView.class, + admin.addItem(new SideNavItem("Documents", DocumentsListView.class, LineAwesomeIcon.FILE_ALT_SOLID.create())); SideNavItem timeOff = new SideNavItem("My Time-off", TimeoffView.class, From 45987ccad989c939f004bb15a6bb88d1c5fb14dd Mon Sep 17 00:00:00 2001 From: ricardo051199 Date: Tue, 24 Sep 2024 17:25:43 -0400 Subject: [PATCH 3/9] #29 Perfil de Empleado Administrativo - LISTAR Documentos (correccionse) --- .../com/primefactorsolutions/views/DocumentsListView.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/primefactorsolutions/views/DocumentsListView.java b/src/main/java/com/primefactorsolutions/views/DocumentsListView.java index 0a311b1..101197d 100644 --- a/src/main/java/com/primefactorsolutions/views/DocumentsListView.java +++ b/src/main/java/com/primefactorsolutions/views/DocumentsListView.java @@ -7,16 +7,16 @@ import com.primefactorsolutions.service.DocumentService; import com.primefactorsolutions.service.EmployeeService; import com.vaadin.flow.component.button.Button; import com.vaadin.flow.component.combobox.ComboBox; +import com.vaadin.flow.component.grid.GridSortOrder; import com.vaadin.flow.component.html.Main; import com.vaadin.flow.component.html.Span; +import com.vaadin.flow.data.provider.SortDirection; 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.PagingGrid; import java.util.List; From f3bda474d0dad80474ff54654bd13fa00e888483 Mon Sep 17 00:00:00 2001 From: ricardo051199 Date: Tue, 24 Sep 2024 19:07:58 -0400 Subject: [PATCH 4/9] #32 Perfil de Personal Administrativo - VER Documento --- .../com/primefactorsolutions/views/DocumentView.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/main/java/com/primefactorsolutions/views/DocumentView.java b/src/main/java/com/primefactorsolutions/views/DocumentView.java index 4b9014f..b2b84ca 100644 --- a/src/main/java/com/primefactorsolutions/views/DocumentView.java +++ b/src/main/java/com/primefactorsolutions/views/DocumentView.java @@ -157,9 +157,21 @@ public class DocumentView extends BeanValidationForm implements HasUrl UUID documentId = UUID.fromString(s); var document = documentService.getDocument(documentId); setEntityWithEnabledSave(document); + + if ("edit".equals(action) && !s.isEmpty()) { + setFieldsReadOnly(false); + } else if ("view".equals(action) && !s.isEmpty()) { + setFieldsReadOnly(true); + } } } + private void setFieldsReadOnly(final boolean option) { + fileName.setReadOnly(option); + documentType.setReadOnly(option); + employeeComboBox.setReadOnly(option); + } + @Override protected List getFormComponents() { return List.of(title, fileName, documentType, employeeComboBox, uploadButton, createCloseButton()); From af3f13773bb06977a64fc5546089a9ca561410c4 Mon Sep 17 00:00:00 2001 From: ricardo051199 Date: Tue, 24 Sep 2024 19:26:18 -0400 Subject: [PATCH 5/9] #29 Perfil de Empleado Administrativo - LISTAR Documentos (implementacion de download) --- .../views/DocumentsListView.java | 23 ++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/primefactorsolutions/views/DocumentsListView.java b/src/main/java/com/primefactorsolutions/views/DocumentsListView.java index 101197d..229d333 100644 --- a/src/main/java/com/primefactorsolutions/views/DocumentsListView.java +++ b/src/main/java/com/primefactorsolutions/views/DocumentsListView.java @@ -18,6 +18,7 @@ import jakarta.annotation.security.PermitAll; import org.springframework.context.annotation.Scope; import org.vaadin.firitin.components.grid.PagingGrid; +import java.util.Base64; import java.util.List; @@ -52,7 +53,7 @@ public class DocumentsListView extends Main { documentGrid.addComponentColumn(this::createEmployeeSpan).setHeader("Employee"); addDocumentActionColumn("View", this::navigateToDocumentView); addDocumentActionColumn("Edit", this::navigateToEditDocumentView); - addDocumentActionColumn("Download", this::navigateToDownloadDocumentView); + addDocumentActionColumn("Download", this::downloadDocument); configurePagination(); } @@ -136,6 +137,26 @@ public class DocumentsListView extends Main { sortOrder.getDirection() == SortDirection.ASCENDING); } + private void downloadDocument(final Document document) { + String base64Data = Base64.getEncoder().encodeToString(document.getFileData()); + String jsCode = "var byteCharacters = atob('" + base64Data + "');" + + "var byteNumbers = new Array(byteCharacters.length);" + + "for (var i = 0; i < byteCharacters.length; i++) {" + + " byteNumbers[i] = byteCharacters.charCodeAt(i);" + + "}" + + "var byteArray = new Uint8Array(byteNumbers);" + + "var blob = new Blob([byteArray], { type: 'application/pdf' });" + + "var url = URL.createObjectURL(blob);" + + "var a = document.createElement('a');" + + "a.href = url;" + + "a.download = '" + document.getFileName() + "';" + + "document.body.appendChild(a);" + + "a.click();" + + "document.body.removeChild(a);" + + "URL.revokeObjectURL(url);"; + getElement().executeJs(jsCode); + } + @FunctionalInterface private interface DocumentActionHandler { void handle(Document document); From f0b41743c752f1689ff28fb39cd2982529ddf1f7 Mon Sep 17 00:00:00 2001 From: ricardo051199 Date: Tue, 24 Sep 2024 20:44:16 -0400 Subject: [PATCH 6/9] =?UTF-8?q?#30=20Perfil=20de=20Usuario=20Administrativ?= =?UTF-8?q?o=20-=20A=C3=B1adir=20NUEVO=20Documento=20(agregar=20creador=20?= =?UTF-8?q?del=20registro=20del=20doc)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../primefactorsolutions/model/Document.java | 1 + .../views/DocumentView.java | 12 ++++++- .../views/DocumentsListView.java | 32 +++++++++---------- 3 files changed, 28 insertions(+), 17 deletions(-) diff --git a/src/main/java/com/primefactorsolutions/model/Document.java b/src/main/java/com/primefactorsolutions/model/Document.java index 2e3b222..61620fa 100644 --- a/src/main/java/com/primefactorsolutions/model/Document.java +++ b/src/main/java/com/primefactorsolutions/model/Document.java @@ -19,4 +19,5 @@ public class Document extends BaseEntity { @Lob @Column(columnDefinition = "BLOB") private byte[] fileData; + private String creator; } diff --git a/src/main/java/com/primefactorsolutions/views/DocumentView.java b/src/main/java/com/primefactorsolutions/views/DocumentView.java index b2b84ca..fdf29d5 100644 --- a/src/main/java/com/primefactorsolutions/views/DocumentView.java +++ b/src/main/java/com/primefactorsolutions/views/DocumentView.java @@ -17,7 +17,9 @@ import com.vaadin.flow.router.*; import com.vaadin.flow.spring.annotation.SpringComponent; import jakarta.annotation.security.PermitAll; import org.springframework.context.annotation.Scope; +import org.springframework.security.core.userdetails.UserDetails; import org.vaadin.firitin.form.BeanValidationForm; +import com.vaadin.flow.spring.security.AuthenticationContext; import java.io.IOException; import java.util.List; @@ -38,12 +40,16 @@ public class DocumentView extends BeanValidationForm implements HasUrl private final Upload uploadButton = new Upload(buffer); private final DocumentService documentService; private final EmployeeService employeeService; + private final AuthenticationContext authContext; private boolean fileUploaded = false; - public DocumentView(final DocumentService documentService, final EmployeeService employeeService) { + public DocumentView(final DocumentService documentService, + final EmployeeService employeeService, + final AuthenticationContext authContext) { super(Document.class); this.documentService = documentService; this.employeeService = employeeService; + this.authContext = authContext; initializeView(); } @@ -106,6 +112,10 @@ public class DocumentView extends BeanValidationForm implements HasUrl if (isFormValid()) { Document document = createDocument(); document.setEmployee(employeeComboBox.getValue()); + authContext.getAuthenticatedUser(UserDetails.class).ifPresent(user -> { + String creator = user.getUsername(); + document.setCreator(creator); // Asignar el nombre del creador al documento + }); documentService.saveDocument(document); Notification.show("File saved successfully."); clearForm(); diff --git a/src/main/java/com/primefactorsolutions/views/DocumentsListView.java b/src/main/java/com/primefactorsolutions/views/DocumentsListView.java index 229d333..64c5f9f 100644 --- a/src/main/java/com/primefactorsolutions/views/DocumentsListView.java +++ b/src/main/java/com/primefactorsolutions/views/DocumentsListView.java @@ -49,7 +49,7 @@ public class DocumentsListView extends Main { } private void configureDocumentGrid() { - documentGrid.setColumns("fileName", "documentType"); + documentGrid.setColumns("fileName", "documentType", "creator"); documentGrid.addComponentColumn(this::createEmployeeSpan).setHeader("Employee"); addDocumentActionColumn("View", this::navigateToDocumentView); addDocumentActionColumn("Edit", this::navigateToEditDocumentView); @@ -139,21 +139,21 @@ public class DocumentsListView extends Main { private void downloadDocument(final Document document) { String base64Data = Base64.getEncoder().encodeToString(document.getFileData()); - String jsCode = "var byteCharacters = atob('" + base64Data + "');" + - "var byteNumbers = new Array(byteCharacters.length);" + - "for (var i = 0; i < byteCharacters.length; i++) {" + - " byteNumbers[i] = byteCharacters.charCodeAt(i);" + - "}" + - "var byteArray = new Uint8Array(byteNumbers);" + - "var blob = new Blob([byteArray], { type: 'application/pdf' });" + - "var url = URL.createObjectURL(blob);" + - "var a = document.createElement('a');" + - "a.href = url;" + - "a.download = '" + document.getFileName() + "';" + - "document.body.appendChild(a);" + - "a.click();" + - "document.body.removeChild(a);" + - "URL.revokeObjectURL(url);"; + String jsCode = "var byteCharacters = atob('" + base64Data + "');" + + "var byteNumbers = new Array(byteCharacters.length);" + + "for (var i = 0; i < byteCharacters.length; i++) {" + + " byteNumbers[i] = byteCharacters.charCodeAt(i);" + + "}" + + "var byteArray = new Uint8Array(byteNumbers);" + + "var blob = new Blob([byteArray], { type: 'application/pdf' });" + + "var url = URL.createObjectURL(blob);" + + "var a = document.createElement('a');" + + "a.href = url;" + + "a.download = '" + document.getFileName() + "';" + + "document.body.appendChild(a);" + + "a.click();" + + "document.body.removeChild(a);" + + "URL.revokeObjectURL(url);"; getElement().executeJs(jsCode); } From 4241e7b52b1d7f9958aa6b70d5d8c4f733dca0f5 Mon Sep 17 00:00:00 2001 From: ricardo051199 Date: Wed, 25 Sep 2024 18:50:59 -0400 Subject: [PATCH 7/9] #29 Perfil de Empleado Administrativo - LISTAR Documentos (correccion download, view, edit) --- .../views/DocumentView.java | 30 +++++++++++++++---- .../views/DocumentsListView.java | 29 ++++++++---------- 2 files changed, 37 insertions(+), 22 deletions(-) diff --git a/src/main/java/com/primefactorsolutions/views/DocumentView.java b/src/main/java/com/primefactorsolutions/views/DocumentView.java index fdf29d5..fe8d8a5 100644 --- a/src/main/java/com/primefactorsolutions/views/DocumentView.java +++ b/src/main/java/com/primefactorsolutions/views/DocumentView.java @@ -42,6 +42,7 @@ public class DocumentView extends BeanValidationForm implements HasUrl private final EmployeeService employeeService; private final AuthenticationContext authContext; private boolean fileUploaded = false; + private Button saveButton; public DocumentView(final DocumentService documentService, final EmployeeService employeeService, @@ -83,7 +84,7 @@ public class DocumentView extends BeanValidationForm implements HasUrl } protected Button createSaveButton() { - Button saveButton = new Button("Save"); + saveButton = new Button("Save"); saveButton.addClickListener(event -> saveDocument()); return saveButton; } @@ -110,13 +111,18 @@ public class DocumentView extends BeanValidationForm implements HasUrl private void saveDocument() { if (isFormValid()) { - Document document = createDocument(); + Document document = getEntity(); // Obtenemos el documento actual del formulario + document.setFileName(fileName.getValue()); + document.setDocumentType(documentType.getValue()); document.setEmployee(employeeComboBox.getValue()); + document.setFileData(readFileData()); // Actualizamos el archivo si es necesario + authContext.getAuthenticatedUser(UserDetails.class).ifPresent(user -> { String creator = user.getUsername(); - document.setCreator(creator); // Asignar el nombre del creador al documento + document.setCreator(creator); // Asignar el nombre del creador al documento si corresponde }); - documentService.saveDocument(document); + + documentService.saveDocument(document); // Guardamos el documento actualizado Notification.show("File saved successfully."); clearForm(); } else { @@ -155,6 +161,18 @@ public class DocumentView extends BeanValidationForm implements HasUrl fileUploaded = false; } + private void checkFormModifications() { + boolean hasModifications = !fileName.isEmpty() + && documentType.getValue() != null + && employeeComboBox.getValue() != null; + + if (hasModifications || fileUploaded) { + saveButton.setEnabled(true); + } else { + saveButton.setEnabled(false); + } + } + @Override public void setParameter(final BeforeEvent beforeEvent, final String action) { @@ -166,7 +184,8 @@ public class DocumentView extends BeanValidationForm implements HasUrl } else { UUID documentId = UUID.fromString(s); var document = documentService.getDocument(documentId); - setEntityWithEnabledSave(document); + setEntity(document); + employeeComboBox.setValue(document.getEmployee()); if ("edit".equals(action) && !s.isEmpty()) { setFieldsReadOnly(false); @@ -174,6 +193,7 @@ public class DocumentView extends BeanValidationForm implements HasUrl setFieldsReadOnly(true); } } + checkFormModifications(); } private void setFieldsReadOnly(final boolean option) { diff --git a/src/main/java/com/primefactorsolutions/views/DocumentsListView.java b/src/main/java/com/primefactorsolutions/views/DocumentsListView.java index 64c5f9f..7159229 100644 --- a/src/main/java/com/primefactorsolutions/views/DocumentsListView.java +++ b/src/main/java/com/primefactorsolutions/views/DocumentsListView.java @@ -8,16 +8,20 @@ import com.primefactorsolutions.service.EmployeeService; import com.vaadin.flow.component.button.Button; import com.vaadin.flow.component.combobox.ComboBox; import com.vaadin.flow.component.grid.GridSortOrder; +import com.vaadin.flow.component.html.Anchor; import com.vaadin.flow.component.html.Main; import com.vaadin.flow.component.html.Span; import com.vaadin.flow.data.provider.SortDirection; import com.vaadin.flow.router.PageTitle; import com.vaadin.flow.router.Route; +import com.vaadin.flow.server.StreamRegistration; +import com.vaadin.flow.server.StreamResource; import com.vaadin.flow.spring.annotation.SpringComponent; import jakarta.annotation.security.PermitAll; import org.springframework.context.annotation.Scope; import org.vaadin.firitin.components.grid.PagingGrid; +import java.io.ByteArrayInputStream; import java.util.Base64; import java.util.List; @@ -138,23 +142,14 @@ public class DocumentsListView extends Main { } private void downloadDocument(final Document document) { - String base64Data = Base64.getEncoder().encodeToString(document.getFileData()); - String jsCode = "var byteCharacters = atob('" + base64Data + "');" - + "var byteNumbers = new Array(byteCharacters.length);" - + "for (var i = 0; i < byteCharacters.length; i++) {" - + " byteNumbers[i] = byteCharacters.charCodeAt(i);" - + "}" - + "var byteArray = new Uint8Array(byteNumbers);" - + "var blob = new Blob([byteArray], { type: 'application/pdf' });" - + "var url = URL.createObjectURL(blob);" - + "var a = document.createElement('a');" - + "a.href = url;" - + "a.download = '" + document.getFileName() + "';" - + "document.body.appendChild(a);" - + "a.click();" - + "document.body.removeChild(a);" - + "URL.revokeObjectURL(url);"; - getElement().executeJs(jsCode); + StreamResource resource = new StreamResource(document.getFileName(), + () -> new ByteArrayInputStream(document.getFileData())); + resource.setContentType("application/pdf"); + resource.setHeader("Content-Disposition", "attachment; filename=\"" + document.getFileName() + ".pdf\""); + getUI().ifPresent(ui -> { + StreamRegistration registration = ui.getSession().getResourceRegistry().registerResource(resource); + ui.getPage().open(registration.getResourceUri().toString()); + }); } @FunctionalInterface From 1519d8299382a151db9ec9d846f1cdc8806e2300 Mon Sep 17 00:00:00 2001 From: ricardo051199 Date: Fri, 27 Sep 2024 00:07:27 -0400 Subject: [PATCH 8/9] #29 Perfil de Empleado Administrativo - LISTAR Documentos (filtar por tipo de documento y empleado) --- .../model/DocumentType.java | 1 + .../service/DocumentService.java | 19 ++++ .../views/DocumentsListView.java | 86 ++++++++++++++----- 3 files changed, 85 insertions(+), 21 deletions(-) diff --git a/src/main/java/com/primefactorsolutions/model/DocumentType.java b/src/main/java/com/primefactorsolutions/model/DocumentType.java index 138439e..96c8ce3 100644 --- a/src/main/java/com/primefactorsolutions/model/DocumentType.java +++ b/src/main/java/com/primefactorsolutions/model/DocumentType.java @@ -1,6 +1,7 @@ package com.primefactorsolutions.model; public enum DocumentType { + All, ID_CARD, PAY_STUB, PAY_SLIPS, diff --git a/src/main/java/com/primefactorsolutions/service/DocumentService.java b/src/main/java/com/primefactorsolutions/service/DocumentService.java index efdf0cc..78f5717 100644 --- a/src/main/java/com/primefactorsolutions/service/DocumentService.java +++ b/src/main/java/com/primefactorsolutions/service/DocumentService.java @@ -1,6 +1,8 @@ package com.primefactorsolutions.service; import com.primefactorsolutions.model.Document; +import com.primefactorsolutions.model.DocumentType; +import com.primefactorsolutions.model.Employee; import com.primefactorsolutions.repositories.DocumentRepository; import lombok.AllArgsConstructor; import org.apache.commons.beanutils.BeanComparator; @@ -10,6 +12,7 @@ import java.util.Collections; import java.util.List; import java.util.UUID; import java.util.Optional; +import java.util.stream.Collectors; @Service @AllArgsConstructor @@ -49,4 +52,20 @@ public class DocumentService { int end = Math.min(start + pageSize, employees.size()); return employees.subList(start, end); } + + public List findDocumentBy(DocumentType documentType, Employee employee, int start, int pageSize) { + List documents = documentRepository.findAll(); + if (documentType != null) { + documents = documents.stream() + .filter(doc -> doc.getDocumentType().equals(documentType)) + .collect(Collectors.toList()); + } + if (employee != null) { + documents = documents.stream() + .filter(doc -> doc.getEmployee().equals(employee)) + .collect(Collectors.toList()); + } + int end = Math.min(start + pageSize, documents.size()); + return documents.subList(start, end); + } } diff --git a/src/main/java/com/primefactorsolutions/views/DocumentsListView.java b/src/main/java/com/primefactorsolutions/views/DocumentsListView.java index 7159229..c786ca6 100644 --- a/src/main/java/com/primefactorsolutions/views/DocumentsListView.java +++ b/src/main/java/com/primefactorsolutions/views/DocumentsListView.java @@ -5,12 +5,13 @@ import com.primefactorsolutions.model.DocumentType; import com.primefactorsolutions.model.Employee; import com.primefactorsolutions.service.DocumentService; import com.primefactorsolutions.service.EmployeeService; +import com.vaadin.flow.component.UI; import com.vaadin.flow.component.button.Button; import com.vaadin.flow.component.combobox.ComboBox; import com.vaadin.flow.component.grid.GridSortOrder; -import com.vaadin.flow.component.html.Anchor; import com.vaadin.flow.component.html.Main; import com.vaadin.flow.component.html.Span; +import com.vaadin.flow.component.notification.Notification; import com.vaadin.flow.data.provider.SortDirection; import com.vaadin.flow.router.PageTitle; import com.vaadin.flow.router.Route; @@ -22,7 +23,6 @@ import org.springframework.context.annotation.Scope; import org.vaadin.firitin.components.grid.PagingGrid; import java.io.ByteArrayInputStream; -import java.util.Base64; import java.util.List; @@ -36,12 +36,14 @@ public class DocumentsListView extends Main { private final DocumentService documentService; private final EmployeeService employeeService; private final PagingGrid documentGrid = new PagingGrid<>(Document.class); + private ComboBox employeeFilter; + private ComboBox documentTypeFilter; public DocumentsListView(final DocumentService documentService, final EmployeeService employeeService) { this.documentService = documentService; this.employeeService = employeeService; initializeView(); - updateDocumentGrid(); + updateDocumentGrid(null, null); } private void initializeView() { @@ -55,9 +57,7 @@ public class DocumentsListView extends Main { private void configureDocumentGrid() { documentGrid.setColumns("fileName", "documentType", "creator"); documentGrid.addComponentColumn(this::createEmployeeSpan).setHeader("Employee"); - addDocumentActionColumn("View", this::navigateToDocumentView); - addDocumentActionColumn("Edit", this::navigateToEditDocumentView); - addDocumentActionColumn("Download", this::downloadDocument); + addActionColumns(); configurePagination(); } @@ -67,6 +67,11 @@ public class DocumentsListView extends Main { return new Span(employeeName); } + private void addActionColumns() { + addDocumentActionColumn("View", this::navigateToDocumentView); + addDocumentActionColumn("Edit", this::navigateToEditDocumentView); + addDocumentActionColumn("Download", this::downloadDocument); + } private void addDocumentActionColumn(final String label, final DocumentActionHandler handler) { documentGrid.addComponentColumn(document -> createActionButton(label, () -> handler.handle(document))); @@ -79,21 +84,38 @@ public class DocumentsListView extends Main { } private ComboBox createDocumentTypeFilter() { - ComboBox documentTypeFilter = new ComboBox<>("Document Type"); + documentTypeFilter = new ComboBox<>("Document Type"); documentTypeFilter.setItems(DocumentType.values()); - documentTypeFilter.addValueChangeListener(event -> updateDocumentGrid()); + documentTypeFilter.setValue(DocumentType.values()[0]); + documentTypeFilter.addValueChangeListener(event -> { + updateDocumentGrid(event.getValue(), employeeFilter.getValue()); + }); return documentTypeFilter; } private ComboBox createEmployeeFilter() { - ComboBox employeeFilter = new ComboBox<>("Employee"); + employeeFilter = new ComboBox<>("Employee"); List employees = employeeService.findAllEmployees(); + employees.addFirst(createAllEmployeesOption()); employeeFilter.setItems(employees); - employeeFilter.setItemLabelGenerator(employee -> employee.getFirstName() + " " + employee.getLastName()); - employeeFilter.addValueChangeListener(event -> updateDocumentGrid()); + employeeFilter.setItemLabelGenerator(this::getEmployeeLabel); + employeeFilter.setValue(employees.getFirst()); + employeeFilter.addValueChangeListener(event -> { + updateDocumentGrid(documentTypeFilter.getValue(), event.getValue()); + }); return employeeFilter; } + private Employee createAllEmployeesOption() { + Employee allEmployeesOption = new Employee(); + allEmployeesOption.setFirstName("All"); + return allEmployeesOption; + } + + private String getEmployeeLabel(Employee employee) { + return employee.getFirstName().equals("All") ? "All" : employee.getFirstName() + " " + employee.getLastName(); + } + private void navigateToEditDocumentView(final Document document) { navigateToDocumentView(document, "edit"); } @@ -106,10 +128,6 @@ public class DocumentsListView extends Main { getUI().ifPresent(ui -> ui.navigate(DocumentView.class, document.getId().toString() + "/" + action)); } - private void navigateToDownloadDocumentView(final Document document) { - // No operation - } - private void navigateToAddDocumentView() { getUI().ifPresent(ui -> ui.navigate(DocumentView.class, "new")); } @@ -119,8 +137,27 @@ public class DocumentsListView extends Main { documentGrid.setPageSize(5); } - private void updateDocumentGrid() { - documentGrid.setPagingDataProvider((page, pageSize) -> fetchDocuments((int) page, pageSize)); + private void updateDocumentGrid(DocumentType documentType, Employee employee) { + DocumentType finalDocumentType = isValidDocumentType(documentType) ? documentType : null; + Employee finalEmployee = isValidEmployee(employee) ? employee : null; + documentGrid.setPagingDataProvider((page, pageSize) -> + (finalDocumentType == null && finalEmployee == null) ? + fetchDocuments((int) page, pageSize) : + fetchFilteredDocuments((int) page, pageSize, finalDocumentType, finalEmployee) + ); + documentGrid.getDataProvider().refreshAll(); + } + + private boolean isValidDocumentType(DocumentType documentType) { + return documentType != null && !"All".equals(documentType.name()); + } + + private boolean isValidEmployee(Employee employee) { + return employee != null && !"All".equals(employee.getFirstName()); + } + + private List fetchFilteredDocuments(int page, int pageSize, final DocumentType documentType, final Employee employee) { + return documentService.findDocumentBy(documentType, employee, page, pageSize); } private List fetchDocuments(final int page, final int size) { @@ -142,14 +179,21 @@ public class DocumentsListView extends Main { } private void downloadDocument(final Document document) { + StreamResource resource = createDocumentStreamResource(document); + getUI().ifPresent(ui -> openDocumentStream(resource, ui)); + } + + private StreamResource createDocumentStreamResource(final Document document) { StreamResource resource = new StreamResource(document.getFileName(), () -> new ByteArrayInputStream(document.getFileData())); resource.setContentType("application/pdf"); resource.setHeader("Content-Disposition", "attachment; filename=\"" + document.getFileName() + ".pdf\""); - getUI().ifPresent(ui -> { - StreamRegistration registration = ui.getSession().getResourceRegistry().registerResource(resource); - ui.getPage().open(registration.getResourceUri().toString()); - }); + return resource; + } + + private void openDocumentStream(StreamResource resource, UI ui) { + StreamRegistration registration = ui.getSession().getResourceRegistry().registerResource(resource); + ui.getPage().open(registration.getResourceUri().toString()); } @FunctionalInterface From 6d9a2f65e5b67d6d3f361ceaff47d09b29eb2f3b Mon Sep 17 00:00:00 2001 From: ricardo051199 Date: Fri, 27 Sep 2024 03:29:26 -0400 Subject: [PATCH 9/9] #32 Perfil de Personal Administrativo - VER Documento (agregar boton ver documento) --- .../service/DocumentService.java | 9 +- .../views/DocumentView.java | 155 +++++++++++------- .../views/DocumentsListView.java | 22 +-- 3 files changed, 119 insertions(+), 67 deletions(-) diff --git a/src/main/java/com/primefactorsolutions/service/DocumentService.java b/src/main/java/com/primefactorsolutions/service/DocumentService.java index 78f5717..3e808b0 100644 --- a/src/main/java/com/primefactorsolutions/service/DocumentService.java +++ b/src/main/java/com/primefactorsolutions/service/DocumentService.java @@ -23,6 +23,10 @@ public class DocumentService { documentRepository.save(newDocument); } + public void deleteDocument(final UUID id) { + documentRepository.deleteById(id); + } + public List getAllDocuments() { return documentRepository.findAll(); } @@ -53,7 +57,10 @@ public class DocumentService { return employees.subList(start, end); } - public List findDocumentBy(DocumentType documentType, Employee employee, int start, int pageSize) { + public List findDocumentBy(final DocumentType documentType, + final Employee employee, + final int start, + final int pageSize) { List documents = documentRepository.findAll(); if (documentType != null) { documents = documents.stream() diff --git a/src/main/java/com/primefactorsolutions/views/DocumentView.java b/src/main/java/com/primefactorsolutions/views/DocumentView.java index fe8d8a5..e78a8a5 100644 --- a/src/main/java/com/primefactorsolutions/views/DocumentView.java +++ b/src/main/java/com/primefactorsolutions/views/DocumentView.java @@ -10,11 +10,15 @@ import com.vaadin.flow.component.button.Button; import com.vaadin.flow.component.combobox.ComboBox; import com.vaadin.flow.component.html.H2; import com.vaadin.flow.component.notification.Notification; +import com.vaadin.flow.component.orderedlayout.HorizontalLayout; import com.vaadin.flow.component.textfield.TextField; import com.vaadin.flow.component.upload.Upload; import com.vaadin.flow.component.upload.receivers.MemoryBuffer; import com.vaadin.flow.router.*; import com.vaadin.flow.spring.annotation.SpringComponent; +import elemental.json.Json; +import elemental.json.JsonArray; +import elemental.json.JsonObject; import jakarta.annotation.security.PermitAll; import org.springframework.context.annotation.Scope; import org.springframework.security.core.userdetails.UserDetails; @@ -22,6 +26,7 @@ import org.vaadin.firitin.form.BeanValidationForm; import com.vaadin.flow.spring.security.AuthenticationContext; import java.io.IOException; +import java.util.Base64; import java.util.List; import java.util.UUID; @@ -41,8 +46,10 @@ public class DocumentView extends BeanValidationForm implements HasUrl private final DocumentService documentService; private final EmployeeService employeeService; private final AuthenticationContext authContext; + private boolean fileUploaded = false; private Button saveButton; + private Button viewDocumentButton; public DocumentView(final DocumentService documentService, final EmployeeService employeeService, @@ -55,10 +62,14 @@ public class DocumentView extends BeanValidationForm implements HasUrl } private void initializeView() { + configureComponents(); + configureUploadButton(); + } + + private void configureComponents() { setFileNameProperties(); setDocumentTypeProperties(); setEmployeeComboBoxProperties(); - setUploadButtonProperties(); } private void setFileNameProperties() { @@ -77,24 +88,53 @@ public class DocumentView extends BeanValidationForm implements HasUrl employeeComboBox.setWidthFull(); } - private void setUploadButtonProperties() { + private void configureUploadButton() { uploadButton.setMaxFiles(1); uploadButton.setAcceptedFileTypes(".pdf"); uploadButton.addSucceededListener(event -> handleUploadSuccess()); } - protected Button createSaveButton() { + protected Button createSaveButton() { saveButton = new Button("Save"); saveButton.addClickListener(event -> saveDocument()); return saveButton; } - protected Button createCloseButton() { + protected Button createCloseButton() { Button closeButton = new Button("Close"); closeButton.addClickListener(event -> closeForm()); return closeButton; } + protected Button createViewDocumentButton() { + viewDocumentButton = new Button("View Document"); + viewDocumentButton.setEnabled(false); + viewDocumentButton.addClickListener(event -> viewDocument()); + return viewDocumentButton; + } + + private void viewDocument() { + Document document = getEntity(); + if (document.getFileData() != null && document.getFileData().length > 0) { + String base64Data = Base64.getEncoder().encodeToString(document.getFileData()); + String jsCode = createJsCodeForDocument(base64Data); + getElement().executeJs(jsCode); + } else { + Notification.show("No file data available to view."); + } + } + + private String createJsCodeForDocument(final String base64Data) { + return "var byteCharacters = atob('" + base64Data + "');" + + "var byteNumbers = new Array(byteCharacters.length);" + + "for (var i = 0; i < byteCharacters.length; i++) {" + + " byteNumbers[i] = byteCharacters.charCodeAt(i);" + + "}" + + "var byteArray = new Uint8Array(byteNumbers);" + + "var blob = new Blob([byteArray], { type: 'application/pdf' });" + + "var url = URL.createObjectURL(blob);" + + "window.open(url, '_blank');"; + } private void closeForm() { navigateToDocumentsListView(); @@ -107,22 +147,19 @@ public class DocumentView extends BeanValidationForm implements HasUrl private void handleUploadSuccess() { fileUploaded = true; Notification.show("File uploaded successfully."); + viewDocumentButton.setEnabled(true); } private void saveDocument() { if (isFormValid()) { - Document document = getEntity(); // Obtenemos el documento actual del formulario + Document document = getEntity(); document.setFileName(fileName.getValue()); document.setDocumentType(documentType.getValue()); document.setEmployee(employeeComboBox.getValue()); - document.setFileData(readFileData()); // Actualizamos el archivo si es necesario + document.setFileData(readFileData()); + setDocumentCreator(document); - authContext.getAuthenticatedUser(UserDetails.class).ifPresent(user -> { - String creator = user.getUsername(); - document.setCreator(creator); // Asignar el nombre del creador al documento si corresponde - }); - - documentService.saveDocument(document); // Guardamos el documento actualizado + documentService.saveDocument(document); Notification.show("File saved successfully."); clearForm(); } else { @@ -130,6 +167,12 @@ public class DocumentView extends BeanValidationForm implements HasUrl } } + private void setDocumentCreator(final Document document) { + authContext.getAuthenticatedUser(UserDetails.class).ifPresent(user -> { + document.setCreator(user.getUsername()); + }); + } + private boolean isFormValid() { return !fileName.isEmpty() && documentType.getValue() != null @@ -137,14 +180,6 @@ public class DocumentView extends BeanValidationForm implements HasUrl && fileUploaded; } - private Document createDocument() { - Document document = new Document(); - document.setFileName(fileName.getValue()); - document.setDocumentType(documentType.getValue()); - document.setFileData(readFileData()); - return document; - } - private byte[] readFileData() { try { return buffer.getInputStream().readAllBytes(); @@ -159,41 +194,8 @@ public class DocumentView extends BeanValidationForm implements HasUrl documentType.clear(); employeeComboBox.clear(); fileUploaded = false; - } - - private void checkFormModifications() { - boolean hasModifications = !fileName.isEmpty() - && documentType.getValue() != null - && employeeComboBox.getValue() != null; - - if (hasModifications || fileUploaded) { - saveButton.setEnabled(true); - } else { - saveButton.setEnabled(false); - } - } - - - @Override - public void setParameter(final BeforeEvent beforeEvent, final String action) { - final RouteParameters params = beforeEvent.getRouteParameters(); - final String s = params.get("documentId").orElse(null); - - if ("new".equals(action)) { - setEntityWithEnabledSave(new Document()); - } else { - UUID documentId = UUID.fromString(s); - var document = documentService.getDocument(documentId); - setEntity(document); - employeeComboBox.setValue(document.getEmployee()); - - if ("edit".equals(action) && !s.isEmpty()) { - setFieldsReadOnly(false); - } else if ("view".equals(action) && !s.isEmpty()) { - setFieldsReadOnly(true); - } - } - checkFormModifications(); + uploadButton.getElement().setPropertyJson("files", Json.createArray()); + viewDocumentButton.setEnabled(false); } private void setFieldsReadOnly(final boolean option) { @@ -202,8 +204,49 @@ public class DocumentView extends BeanValidationForm implements HasUrl employeeComboBox.setReadOnly(option); } + private void preLoadFile(final Document document) { + JsonArray jsonArray = Json.createArray(); + JsonObject jsonObject = Json.createObject(); + jsonObject.put("name", document.getFileName()); + jsonObject.put("progress", 100); + jsonObject.put("complete", true); + jsonArray.set(0, jsonObject); + uploadButton.getElement().setPropertyJson("files", jsonArray); + } + + @Override + public void setParameter(final BeforeEvent beforeEvent, final String action) { + final RouteParameters params = beforeEvent.getRouteParameters(); + final String documentIdString = params.get("documentId").orElse(null); + + if ("new".equals(action)) { + setEntityWithEnabledSave(new Document()); + } else { + UUID documentId = UUID.fromString(documentIdString); + Document document = documentService.getDocument(documentId); + setEntity(document); + employeeComboBox.setValue(document.getEmployee()); + preLoadFile(document); + configureViewOrEditAction(action, documentIdString); + } + } + + private void configureViewOrEditAction(final String action, final String documentIdString) { + if ("edit".equals(action) && !documentIdString.isEmpty()) { + setFieldsReadOnly(false); + preLoadFile(getEntity()); + } else if ("view".equals(action) && !documentIdString.isEmpty()) { + setFieldsReadOnly(true); + saveButton.setEnabled(false); + viewDocumentButton.setEnabled(true); + } + } + @Override protected List getFormComponents() { - return List.of(title, fileName, documentType, employeeComboBox, uploadButton, createCloseButton()); + HorizontalLayout buttonLayout = new HorizontalLayout(); + buttonLayout.add(uploadButton, createViewDocumentButton()); + buttonLayout.setSpacing(true); + return List.of(title, fileName, documentType, employeeComboBox, buttonLayout, createCloseButton()); } } diff --git a/src/main/java/com/primefactorsolutions/views/DocumentsListView.java b/src/main/java/com/primefactorsolutions/views/DocumentsListView.java index c786ca6..c95e917 100644 --- a/src/main/java/com/primefactorsolutions/views/DocumentsListView.java +++ b/src/main/java/com/primefactorsolutions/views/DocumentsListView.java @@ -11,7 +11,6 @@ import com.vaadin.flow.component.combobox.ComboBox; import com.vaadin.flow.component.grid.GridSortOrder; import com.vaadin.flow.component.html.Main; import com.vaadin.flow.component.html.Span; -import com.vaadin.flow.component.notification.Notification; import com.vaadin.flow.data.provider.SortDirection; import com.vaadin.flow.router.PageTitle; import com.vaadin.flow.router.Route; @@ -112,7 +111,7 @@ public class DocumentsListView extends Main { return allEmployeesOption; } - private String getEmployeeLabel(Employee employee) { + private String getEmployeeLabel(final Employee employee) { return employee.getFirstName().equals("All") ? "All" : employee.getFirstName() + " " + employee.getLastName(); } @@ -137,26 +136,29 @@ public class DocumentsListView extends Main { documentGrid.setPageSize(5); } - private void updateDocumentGrid(DocumentType documentType, Employee employee) { + private void updateDocumentGrid(final DocumentType documentType, final Employee employee) { DocumentType finalDocumentType = isValidDocumentType(documentType) ? documentType : null; Employee finalEmployee = isValidEmployee(employee) ? employee : null; documentGrid.setPagingDataProvider((page, pageSize) -> - (finalDocumentType == null && finalEmployee == null) ? - fetchDocuments((int) page, pageSize) : - fetchFilteredDocuments((int) page, pageSize, finalDocumentType, finalEmployee) + (finalDocumentType == null && finalEmployee == null) + ? fetchDocuments((int) page, pageSize) + : fetchFilteredDocuments((int) page, pageSize, finalDocumentType, finalEmployee) ); documentGrid.getDataProvider().refreshAll(); } - private boolean isValidDocumentType(DocumentType documentType) { + private boolean isValidDocumentType(final DocumentType documentType) { return documentType != null && !"All".equals(documentType.name()); } - private boolean isValidEmployee(Employee employee) { + private boolean isValidEmployee(final Employee employee) { return employee != null && !"All".equals(employee.getFirstName()); } - private List fetchFilteredDocuments(int page, int pageSize, final DocumentType documentType, final Employee employee) { + private List fetchFilteredDocuments(final int page, + final int pageSize, + final DocumentType documentType, + final Employee employee) { return documentService.findDocumentBy(documentType, employee, page, pageSize); } @@ -191,7 +193,7 @@ public class DocumentsListView extends Main { return resource; } - private void openDocumentStream(StreamResource resource, UI ui) { + private void openDocumentStream(final StreamResource resource, final UI ui) { StreamRegistration registration = ui.getSession().getResourceRegistry().registerResource(resource); ui.getPage().open(registration.getResourceUri().toString()); }