diff --git a/src/main/java/com/primefactorsolutions/views/DocumentView.java b/src/main/java/com/primefactorsolutions/views/DocumentView.java index e78a8a5..de4457e 100644 --- a/src/main/java/com/primefactorsolutions/views/DocumentView.java +++ b/src/main/java/com/primefactorsolutions/views/DocumentView.java @@ -8,13 +8,14 @@ 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.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.server.StreamRegistration; +import com.vaadin.flow.server.StreamResource; import com.vaadin.flow.spring.annotation.SpringComponent; import elemental.json.Json; import elemental.json.JsonArray; @@ -25,10 +26,12 @@ import org.springframework.security.core.userdetails.UserDetails; import org.vaadin.firitin.form.BeanValidationForm; import com.vaadin.flow.spring.security.AuthenticationContext; +import java.io.ByteArrayInputStream; import java.io.IOException; import java.util.Base64; import java.util.List; import java.util.UUID; +import java.io.InputStream; @SpringComponent @PermitAll @@ -36,8 +39,6 @@ import java.util.UUID; @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"); @@ -46,11 +47,11 @@ 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, final AuthenticationContext authContext) { @@ -66,34 +67,6 @@ public class DocumentView extends BeanValidationForm implements HasUrl configureUploadButton(); } - private void configureComponents() { - setFileNameProperties(); - setDocumentTypeProperties(); - setEmployeeComboBoxProperties(); - } - - private void setFileNameProperties() { - fileName.setWidthFull(); - } - - private void setDocumentTypeProperties() { - documentType.setItems(DocumentType.values()); - documentType.setWidthFull(); - } - - private void setEmployeeComboBoxProperties() { - List employees = employeeService.findAllEmployees(); - employeeComboBox.setItems(employees); - employeeComboBox.setItemLabelGenerator(employee -> employee.getFirstName() + " " + employee.getLastName()); - employeeComboBox.setWidthFull(); - } - - private void configureUploadButton() { - uploadButton.setMaxFiles(1); - uploadButton.setAcceptedFileTypes(".pdf"); - uploadButton.addSucceededListener(event -> handleUploadSuccess()); - } - protected Button createSaveButton() { saveButton = new Button("Save"); saveButton.addClickListener(event -> saveDocument()); @@ -113,43 +86,58 @@ public class DocumentView extends BeanValidationForm implements HasUrl return viewDocumentButton; } + private void setFileNameProperties() { + fileName.setWidthFull(); + } + + private void setDocumentTypeProperties() { + documentType.setItems(DocumentType.values()); + documentType.setWidthFull(); + } + + private void setEmployeeComboBoxProperties() { + List employees = employeeService.findAllEmployees(); + employeeComboBox.setItems(employees); + employeeComboBox.setItemLabelGenerator(employee -> employee.getFirstName() + " " + employee.getLastName()); + employeeComboBox.setWidthFull(); + } + + private void setDocumentCreator(final Document document) { + authContext.getAuthenticatedUser(UserDetails.class).ifPresent(user -> { + document.setCreator(user.getUsername()); + }); + } + + private void setFieldsReadOnly(final boolean option) { + fileName.setReadOnly(option); + documentType.setReadOnly(option); + employeeComboBox.setReadOnly(option); + } + 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."); + StreamResource resource; + try { + InputStream inputStream = buffer.getInputStream(); + if (inputStream != null && inputStream.available() > 0) { + resource = new StreamResource(fileName.getValue(), () -> new ByteArrayInputStream(readFileData())); + } else { + byte[] fileData = getEntity().getFileData(); + resource = new StreamResource(fileName.getValue(), () -> new ByteArrayInputStream(fileData)); + } + resource.setContentType("application/pdf"); + getUI().ifPresent(ui -> { + StreamRegistration registration = ui.getSession().getResourceRegistry().registerResource(resource); + ui.getPage().open(registration.getResourceUri().toString()); + }); + } catch (IOException e) { + Notification.show("Error reading file."); } } - 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(); - } - private void navigateToDocumentsListView() { getUI().ifPresent(ui -> ui.navigate(DocumentsListView.class)); } - private void handleUploadSuccess() { - fileUploaded = true; - Notification.show("File uploaded successfully."); - viewDocumentButton.setEnabled(true); - } - private void saveDocument() { if (isFormValid()) { Document document = getEntity(); @@ -167,10 +155,8 @@ public class DocumentView extends BeanValidationForm implements HasUrl } } - private void setDocumentCreator(final Document document) { - authContext.getAuthenticatedUser(UserDetails.class).ifPresent(user -> { - document.setCreator(user.getUsername()); - }); + private void closeForm() { + navigateToDocumentsListView(); } private boolean isFormValid() { @@ -180,15 +166,6 @@ public class DocumentView extends BeanValidationForm implements HasUrl && fileUploaded; } - private byte[] readFileData() { - try { - return buffer.getInputStream().readAllBytes(); - } catch (IOException e) { - Notification.show("Error reading file data."); - return new byte[0]; - } - } - private void clearForm() { fileName.clear(); documentType.clear(); @@ -198,10 +175,13 @@ public class DocumentView extends BeanValidationForm implements HasUrl viewDocumentButton.setEnabled(false); } - private void setFieldsReadOnly(final boolean option) { - fileName.setReadOnly(option); - documentType.setReadOnly(option); - employeeComboBox.setReadOnly(option); + private byte[] readFileData() { + try { + return buffer.getInputStream().readAllBytes(); + } catch (IOException e) { + Notification.show("Error reading file data."); + return new byte[0]; + } } private void preLoadFile(final Document document) { @@ -210,8 +190,55 @@ public class DocumentView extends BeanValidationForm implements HasUrl jsonObject.put("name", document.getFileName()); jsonObject.put("progress", 100); jsonObject.put("complete", true); + jsonObject.put("fileData", Base64.getEncoder().encodeToString(document.getFileData())); jsonArray.set(0, jsonObject); uploadButton.getElement().setPropertyJson("files", jsonArray); + fileUploaded = true; + } + + private void updateSaveButtonState() { + boolean isModified = !fileName.getValue().equals(getEntity().getFileName()) + || documentType.getValue() != getEntity().getDocumentType() + || employeeComboBox.getValue() != getEntity().getEmployee() + || fileUploaded; + saveButton.setEnabled(isModified); + } + + private void configureComponents() { + setFileNameProperties(); + setDocumentTypeProperties(); + setEmployeeComboBoxProperties(); + fileName.addValueChangeListener(e -> updateSaveButtonState()); + documentType.addValueChangeListener(e -> updateSaveButtonState()); + employeeComboBox.addValueChangeListener(e -> updateSaveButtonState()); + uploadButton.addSucceededListener(e -> updateSaveButtonState()); + uploadButton.getElement().addEventListener("file-remove", event -> updateSaveButtonState()); + } + + private void configureUploadButton() { + uploadButton.setMaxFiles(1); + uploadButton.setAcceptedFileTypes(".pdf"); + uploadButton.addSucceededListener(event -> { + fileUploaded = true; + updateSaveButtonState(); + }); + uploadButton.getElement().addEventListener("file-remove", event -> { + fileUploaded = false; + updateSaveButtonState(); + }); + } + + private void configureViewOrEditAction(final String action, final String documentIdString) { + if ("edit".equals(action) && !documentIdString.isEmpty()) { + setFieldsReadOnly(false); + preLoadFile(getEntity()); + viewDocumentButton.setEnabled(true); + } else if ("view".equals(action) && !documentIdString.isEmpty()) { + setFieldsReadOnly(true); + preLoadFile(getEntity()); + saveButton.setEnabled(false); + viewDocumentButton.setEnabled(true); + } } @Override @@ -222,6 +249,7 @@ public class DocumentView extends BeanValidationForm implements HasUrl if ("new".equals(action)) { setEntityWithEnabledSave(new Document()); } else { + assert documentIdString != null; UUID documentId = UUID.fromString(documentIdString); Document document = documentService.getDocument(documentId); setEntity(document); @@ -231,22 +259,11 @@ public class DocumentView extends BeanValidationForm implements HasUrl } } - 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() { HorizontalLayout buttonLayout = new HorizontalLayout(); buttonLayout.add(uploadButton, createViewDocumentButton()); buttonLayout.setSpacing(true); - return List.of(title, fileName, documentType, employeeComboBox, buttonLayout, createCloseButton()); + return List.of(fileName, documentType, employeeComboBox, buttonLayout, createCloseButton()); } }