diff --git a/pom.xml b/pom.xml
index e4af5cb..d3de326 100644
--- a/pom.xml
+++ b/pom.xml
@@ -52,6 +52,12 @@
com.vaadin
vaadin-spring-boot-starter
+
+
+ org.apache.commons
+ commons-csv
+ 1.11.0
+
org.vaadin.klaudeta
grid-pagination
@@ -101,6 +107,11 @@
vaadin-testbench-junit5
test
+
+ org.apache.commons
+ commons-csv
+ 1.10.0
+
diff --git a/src/main/java/com/application/munera/views/expenses/ExpensesView.java b/src/main/java/com/application/munera/views/expenses/ExpensesView.java
index 98f505d..544c2aa 100644
--- a/src/main/java/com/application/munera/views/expenses/ExpensesView.java
+++ b/src/main/java/com/application/munera/views/expenses/ExpensesView.java
@@ -1,7 +1,7 @@
package com.application.munera.views.expenses;
-import com.application.munera.security.SecurityUtils;
import com.application.munera.data.*;
+import com.application.munera.security.SecurityUtils;
import com.application.munera.services.*;
import com.application.munera.views.MainLayout;
import com.vaadin.flow.component.UI;
@@ -13,6 +13,7 @@ import com.vaadin.flow.component.datepicker.DatePicker;
import com.vaadin.flow.component.dependency.Uses;
import com.vaadin.flow.component.formlayout.FormLayout;
import com.vaadin.flow.component.grid.GridVariant;
+import com.vaadin.flow.component.html.Anchor;
import com.vaadin.flow.component.html.Div;
import com.vaadin.flow.component.icon.Icon;
import com.vaadin.flow.component.notification.Notification;
@@ -27,13 +28,22 @@ import com.vaadin.flow.data.binder.ValidationException;
import com.vaadin.flow.data.converter.StringToBigDecimalConverter;
import com.vaadin.flow.data.renderer.ComponentRenderer;
import com.vaadin.flow.router.*;
+import com.vaadin.flow.server.StreamResource;
import jakarta.annotation.security.PermitAll;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.orm.ObjectOptimisticLockingFailureException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
+import org.apache.commons.csv.CSVPrinter;
+import org.apache.commons.csv.CSVFormat;
+
import org.vaadin.klaudeta.PaginatedGrid;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.OutputStreamWriter;
+import java.nio.charset.StandardCharsets;
+import java.util.List;
import java.util.Objects;
import java.util.Optional;
@@ -52,6 +62,7 @@ public class ExpensesView extends Div implements BeforeEnterObserver {
private final Button cancel = new Button("Cancel");
private final Button save = new Button("Save");
private final Button delete = new Button("Delete");
+ private final Button exportToCSVButton = new Button("Export to CSV");
private final BeanValidationBinder binder;
private Expense expense;
@@ -109,6 +120,15 @@ public class ExpensesView extends Div implements BeforeEnterObserver {
grid.setPageSize(22); // setting page size
grid.addThemeVariants(GridVariant.LUMO_NO_BORDER);
+ // Export to CSV button
+ exportToCSVButton.addClickListener(event -> {
+ StreamResource resource = createCSVResource(expenseService.findAll());
+ Anchor downloadLink = new Anchor(resource, "Download CSV");
+ downloadLink.getElement().setAttribute("download", true);
+ add(downloadLink);
+ });
+ add(exportToCSVButton);
+
// when a row is selected or deselected, populate form
grid.asSingleSelect().addValueChangeListener(event -> {
if (event.getValue() != null) UI.getCurrent().navigate(String.format(EXPENSE_EDIT_ROUTE_TEMPLATE, event.getValue().getId()));
@@ -329,4 +349,29 @@ public class ExpensesView extends Div implements BeforeEnterObserver {
}
}
}
+
+ private StreamResource createCSVResource(List expenses) {
+ return new StreamResource("expenses.csv", () -> {
+ ByteArrayOutputStream stream = new ByteArrayOutputStream();
+ try (OutputStreamWriter writer = new OutputStreamWriter(stream, StandardCharsets.UTF_8);
+ CSVPrinter csvPrinter = new CSVPrinter(writer, CSVFormat.DEFAULT.withHeader("Name", "Cost", "Category", "Period Interval", "Period Unit", "Date", "Status"))) {
+
+ for (Expense expense : expenses) {
+ csvPrinter.printRecord(
+ expense.getName(),
+ expense.getCost(),
+ expense.getCategory() != null ? expense.getCategory().getName() : "",
+ expense.getPeriodInterval(),
+ expense.getPeriodUnit(),
+ expense.getDate(),
+ expense.getIsPaid() ? "Paid" : "Unpaid"
+ );
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ return new ByteArrayInputStream(stream.toByteArray());
+ });
+ }
}
\ No newline at end of file