Skip to content

Commit

Permalink
#724 - new input to configure the separator
Browse files Browse the repository at this point in the history
  • Loading branch information
deadlocker8 committed Jan 8, 2023
1 parent 6546f4c commit f794725
Show file tree
Hide file tree
Showing 5 changed files with 87 additions and 21 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,21 @@

import de.deadlocker8.budgetmaster.controller.BaseController;
import de.deadlocker8.budgetmaster.services.HelpersService;
import de.deadlocker8.budgetmaster.transactions.csvImport.CsvImport;
import de.deadlocker8.budgetmaster.transactions.csvImport.CsvParser;
import de.deadlocker8.budgetmaster.transactions.csvImport.CsvRow;
import de.deadlocker8.budgetmaster.utils.Mappings;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.nio.charset.StandardCharsets;
Expand All @@ -26,19 +28,20 @@ public class TransactionImportController extends BaseController
{
private static class ModelAttributes
{
public static final String ERROR = "error";
public static final String ERROR_UPLOAD = "errorUpload";
}

private static class ReturnValues
{
public static final String TRANSACTION_IMPORT = "transactions/transactionImport";
public static final String REDIRECT_IMPORT = "redirect:/transactionImport";
public static final String REDIRECT_CANCEL = "redirect:/transactionImport/cancel";

}

private static class RequestAttributeNames
{
public static final String IMPORTED_FILE = "importedFile";
public static final String CSV_IMPORT = "csvImport";
public static final String CSV_ROWS = "csvRows";
}

Expand All @@ -55,35 +58,46 @@ public TransactionImportController(TransactionService transactionService, Helper
@GetMapping
public String transactionImport(HttpServletRequest request, Model model)
{
model.addAttribute(RequestAttributeNames.CSV_IMPORT, new CsvImport(null, ";"));
return ReturnValues.TRANSACTION_IMPORT;
}

@PostMapping("/upload")
public String upload(WebRequest request, Model model, @RequestParam("file") MultipartFile file)
public String upload(WebRequest request,
Model model,
@ModelAttribute("CsvImport") CsvImport csvImport,
BindingResult bindingResult)
{
if(file.isEmpty())
if(csvImport.file().isEmpty())
{
return ReturnValues.REDIRECT_CANCEL;
}

try
if(!csvImport.isValidSeparator())
{
final String csvString = new String(file.getBytes(), StandardCharsets.UTF_8);
final List<CsvRow> csvRows = CsvParser.parseCsv(csvString, ';');
bindingResult.addError(new FieldError("CsvImport", "separator", "", false, new String[]{"warning.transaction.import.separator"}, null, null));
}

String fileName = file.getOriginalFilename();
if(fileName == null)
{
fileName = file.getName();
}
if(bindingResult.hasErrors())
{
model.addAttribute(ModelAttributes.ERROR, bindingResult);
request.setAttribute(RequestAttributeNames.CSV_IMPORT, csvImport, RequestAttributes.SCOPE_SESSION);
return ReturnValues.TRANSACTION_IMPORT;
}

request.setAttribute(RequestAttributeNames.IMPORTED_FILE, fileName, RequestAttributes.SCOPE_SESSION);
try
{
final String csvString = new String(csvImport.file().getBytes(), StandardCharsets.UTF_8);
final List<CsvRow> csvRows = CsvParser.parseCsv(csvString, csvImport.separator().charAt(0));

request.setAttribute(RequestAttributeNames.CSV_IMPORT, csvImport, RequestAttributes.SCOPE_SESSION);
request.setAttribute(RequestAttributeNames.CSV_ROWS, csvRows, RequestAttributes.SCOPE_SESSION);
}
catch(Exception e)
{
LOGGER.error("CSV upload failed", e);

// TODO: show in html
model.addAttribute(ModelAttributes.ERROR_UPLOAD, e.getMessage());
}

Expand All @@ -93,9 +107,9 @@ public String upload(WebRequest request, Model model, @RequestParam("file") Mult
@GetMapping("/cancel")
public String cancel(WebRequest request)
{
request.removeAttribute(RequestAttributeNames.IMPORTED_FILE, RequestAttributes.SCOPE_SESSION);
request.removeAttribute(RequestAttributeNames.CSV_IMPORT, RequestAttributes.SCOPE_SESSION);
request.removeAttribute(RequestAttributeNames.CSV_ROWS, RequestAttributes.SCOPE_SESSION);

return ReturnValues.TRANSACTION_IMPORT;
return ReturnValues.REDIRECT_IMPORT;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package de.deadlocker8.budgetmaster.transactions.csvImport;

import org.springframework.web.multipart.MultipartFile;

public record CsvImport(MultipartFile file, String separator)
{
@Override
public String toString()
{
return "CsvImport{" +
"file=" + file +
", separator='" + separator + '\'' +
'}';
}

public boolean isValidSeparator()
{
if(separator == null)
{
return false;
}

return separator.strip().length() == 1;
}

public String getFileName()
{
if(file == null)
{
return null;
}

final String fileName = file.getOriginalFilename();
if(fileName == null)
{
return file.getName();
}

return fileName;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,7 @@ warning.empty.git.url=Bitte gib die URL zum git-Server ein.
warning.empty.git.branch.name=Bitte gib den Namen des git-Branches ein.
warning.empty.git.user.name=Bitte gib deinen git-Nutzernamen ein.
warning.empty.git.token=Bitte gib dein git-Zugriffstoken ein.
warning.transaction.import.separator=Ungültiges Trennzeichen. Bitte genau ein Zeichen eingeben.


# UI
Expand Down Expand Up @@ -370,6 +371,7 @@ transactions.recurring.headline=Aktive wiederholende Buchungen
transactions.recurring.placeholder=Keine aktiven wiederholenden Buchungen
transactions.import.overview=Übersicht
transactions.import.column=Spalte
transactions.import.separator=Trennzeichen

repeating.button.add=Wiederholung hinzufügen
repeating.button.remove=Wiederholung entfernen
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ error.database.import.invalid.json=The uploaded JSON File is invalid.
error.database.import.unknown.version=The uploaded JSON File does not contain a valid BudgetMaster database definition.
error.database.import.version.too.old=The uploaded JSON File is too old. Version: {0} Minimum version: {1}


# TITLE
title.incomes=Incomes
title.income=Income
Expand Down Expand Up @@ -233,6 +232,7 @@ warning.empty.git.url=Please insert the git server's URL.
warning.empty.git.branch.name=Please insert the git branch name.
warning.empty.git.user.name=Please insert your git username.
warning.empty.git.token=Please insert your git access token.
warning.transaction.import.separator=Invalid separator. Please enter exactly one character.


# UI
Expand Down Expand Up @@ -370,6 +370,7 @@ transactions.recurring.headline=Active Recurring Transactions
transactions.recurring.placeholder=No active recurring transactions
transactions.import.overview=Overview
transactions.import.column=Column
transactions.import.separator=Separator

repeating.button.add=Add repetition
repeating.button.remove=Remove repetition
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<html>
<head>
<#import "../helpers/header.ftl" as header>
<#import "../helpers/validation.ftl" as validation>
<@header.globals/>
<@header.header "BudgetMaster - ${locale.getString('menu.transactions.import')}"/>
<#import "/spring.ftl" as s>
Expand All @@ -21,10 +22,10 @@

<@header.content>
<div class="container">
<#if importedFile??>
<#if !error?? && csvImport.getFileName()??>
<div class="row center-align">
<div class="col s12 m12 l8 offset-l2 headline-small text-green">
<i class="fas fa-file-csv"></i> ${importedFile}
<i class="fas fa-file-csv"></i> ${csvImport.getFileName()}
</div>
</div>

Expand Down Expand Up @@ -52,7 +53,7 @@
</html>

<#macro csvUpload>
<form id="form-csv-import" method="POST" action="<@s.url '/transactionImport/upload'/>" enctype="multipart/form-data" accept-charset="UTF-8">
<form id="form-csv-import" name="CsvImport" method="POST" action="<@s.url '/transactionImport/upload'/>" enctype="multipart/form-data" accept-charset="UTF-8">
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>

<div class="row">
Expand All @@ -67,6 +68,13 @@
</div>
</div>

<div class="row">
<div class="input-field col s2 offset-s5">
<input id="separator" type="text" name="separator" <@validation.validation "separator" "center-align"/> value="<#if csvImport??>${csvImport.separator()}</#if>">
<label class="input-label" for="separator">${locale.getString("transactions.import.separator")}</label>
</div>
</div>

<div class="row">
<div class="col s12 center-align">
<@header.buttonSubmit name='action' icon='cloud_upload' localizationKey='settings.database.import' id='button-confirm-csv-import' classes='text-white'/>
Expand Down

0 comments on commit f794725

Please sign in to comment.