Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision
Loading items

Target

Select target project
  • deadlocker8/BudgetMaster
1 result
Select Git revision
Loading items
Show changes
Commits on Source (28)
Showing
with 4154 additions and 122 deletions
......@@ -5,7 +5,7 @@
<parent>
<artifactId>BudgetMaster</artifactId>
<groupId>de.deadlocker8</groupId>
<version>2.17.2</version>
<version>2.18.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
......@@ -26,23 +26,23 @@
<properties>
<jlibs.version>3.2.0</jlibs.version>
<versionizer.version>3.0.1</versionizer.version>
<webjars-locator.version>0.52</webjars-locator.version>
<webjars-locator.version>1.1.0</webjars-locator.version>
<jquery.version>3.7.1</jquery.version>
<materializecss.version>1.0.0</materializecss.version>
<fontawesome.version>6.5.2</fontawesome.version>
<sortablejs.version>1.15.3</sortablejs.version>
<fontawesome.version>6.7.2</fontawesome.version>
<sortablejs.version>1.15.6</sortablejs.version>
<mousetrap.version>1.6.5</mousetrap.version>
<codemirror.version>5.62.2</codemirror.version>
<selenium.version>4.26.0</selenium.version>
<jgit.version>7.0.0.202409031743-r</jgit.version>
<selenium.version>4.31.0</selenium.version>
<jgit.version>7.2.0.202503040940-r</jgit.version>
<natorder.version>1.1.3</natorder.version>
<itextpdf.version>5.5.13.4</itextpdf.version>
<vanilla-picker.version>2.12.3</vanilla-picker.version>
<jacoco-maven-plugin.version>0.8.12</jacoco-maven-plugin.version>
<opencsv.version>5.9</opencsv.version>
<datatables.version>2.1.0</datatables.version>
<opencsv.version>5.10</opencsv.version>
<datatables.version>2.1.8</datatables.version>
<jakarta.xml.bind-api.version>4.0.2</jakarta.xml.bind-api.version>
<junit-jupiter-engine.version>5.11.3</junit-jupiter-engine.version>
<junit-jupiter-engine.version>5.12.1</junit-jupiter-engine.version>
<project.outputDirectory>${project.build.directory}/../build/${project.version}</project.outputDirectory>
<project.artifactName>${project.artifactId}-v${project.version}</project.artifactName>
......@@ -149,7 +149,7 @@
<!--Webjars-->
<dependency>
<groupId>org.webjars</groupId>
<artifactId>webjars-locator</artifactId>
<artifactId>webjars-locator-lite</artifactId>
<version>${webjars-locator.version}</version>
</dependency>
<dependency>
......@@ -192,7 +192,11 @@
<artifactId>datatables</artifactId>
<version>${datatables.version}</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
</dependency>
<!-- selenium -->
<dependency>
......
......@@ -11,16 +11,16 @@ import de.deadlocker8.budgetmaster.utils.notification.Notification;
import de.deadlocker8.budgetmaster.utils.notification.NotificationLinkBuilder;
import de.deadlocker8.budgetmaster.utils.notification.NotificationType;
import de.thecodelabs.utils.util.Localization;
import jakarta.servlet.http.HttpServletRequest;
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.*;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.WebRequest;
import jakarta.servlet.http.HttpServletRequest;
import java.text.MessageFormat;
import java.time.LocalDate;
import java.util.List;
......@@ -43,6 +43,7 @@ public class AccountController extends BaseController
public static final String ERROR = "error";
public static final String NOTIFICATIONS = "notifications";
public static final String TODAY = "today";
public static final String FILTER_CONFIGURATION = "accountsFilterConfiguration";
}
private static class ReturnValues
......@@ -115,22 +116,24 @@ public class AccountController extends BaseController
}
@GetMapping
public String accounts(Model model)
public String accounts(Model model, HttpServletRequest request)
{
model.addAttribute(ModelAttributes.ALL_ENTITIES, accountService.getAllEntitiesAsc());
final AccountsFilterConfiguration accountsFilterConfiguration = getAccountsFilterConfiguration(request);
model.addAttribute(ModelAttributes.ALL_ENTITIES, accountService.getFilteredEntitiesAsc(accountsFilterConfiguration));
return ReturnValues.SHOW_ALL;
}
@GetMapping("/{ID}/requestDelete")
public String requestDeleteAccount(Model model, @PathVariable("ID") Integer ID)
public String requestDeleteAccount(Model model, @PathVariable("ID") Integer ID, HttpServletRequest request)
{
model.addAttribute(ModelAttributes.ALL_ENTITIES, accountService.getAllEntitiesAsc());
final AccountsFilterConfiguration accountsFilterConfiguration = getAccountsFilterConfiguration(request);
model.addAttribute(ModelAttributes.ALL_ENTITIES, accountService.getFilteredEntitiesAsc(accountsFilterConfiguration));
model.addAttribute(ModelAttributes.ENTITY_TO_DELETE, accountService.getRepository().getReferenceById(ID));
return ReturnValues.DELETE_ENTITY;
}
@GetMapping("/{ID}/delete")
public String deleteAccountAndReferringTransactions(WebRequest request, Model model, @PathVariable("ID") Integer ID)
public String deleteAccountAndReferringTransactions(HttpServletRequest servletRequest, WebRequest request, Model model, @PathVariable("ID") Integer ID)
{
// at least one account is required (to delete a sole account another one has to be created first)
final Account accountToDelete = accountService.getRepository().getReferenceById(ID);
......@@ -141,7 +144,8 @@ public class AccountController extends BaseController
return ReturnValues.REDIRECT_SHOW_ALL;
}
model.addAttribute(ModelAttributes.ALL_ENTITIES, accountService.getAllEntitiesAsc());
final AccountsFilterConfiguration accountsFilterConfiguration = getAccountsFilterConfiguration(servletRequest);
model.addAttribute(ModelAttributes.ALL_ENTITIES, accountService.getFilteredEntitiesAsc(accountsFilterConfiguration));
model.addAttribute(ModelAttributes.CURRENT_ACCOUNT, accountToDelete);
model.addAttribute(ModelAttributes.ACCOUNT_NOT_DELETABLE, true);
return ReturnValues.SHOW_ALL;
......@@ -272,4 +276,23 @@ public class AccountController extends BaseController
settingsService.updateLastAccountEndDateReminderDate();
return "redirect:" + request.getHeader("Referer");
}
@PostMapping(value = "/applyFilter")
public String applyFilter(WebRequest request,
@ModelAttribute("AccountsFilter") AccountsFilterConfiguration accountsFilterConfiguration)
{
request.setAttribute(ModelAttributes.FILTER_CONFIGURATION, accountsFilterConfiguration, RequestAttributes.SCOPE_SESSION);
return ReturnValues.REDIRECT_SHOW_ALL;
}
private AccountsFilterConfiguration getAccountsFilterConfiguration(HttpServletRequest request)
{
Object sessionAccountsFilterConfiguration = request.getSession().getAttribute(ModelAttributes.FILTER_CONFIGURATION);
if(sessionAccountsFilterConfiguration == null)
{
request.getSession().setAttribute(ModelAttributes.FILTER_CONFIGURATION, AccountsFilterConfiguration.DEFAULT);
return AccountsFilterConfiguration.DEFAULT;
}
return (AccountsFilterConfiguration) sessionAccountsFilterConfiguration;
}
}
\ No newline at end of file
......@@ -79,6 +79,17 @@ public class AccountService implements Resettable, AccessAllEntities<Account>, A
return accounts;
}
public List<Account> getFilteredEntitiesAsc(AccountsFilterConfiguration accountsFilterConfiguration)
{
return accountRepository.findAllByTypeOrderByNameAsc(AccountType.CUSTOM).stream()
.filter(a -> accountsFilterConfiguration.getIncludedStates().contains(a.getAccountState()))
.filter(a -> (accountsFilterConfiguration.isIncludeWithEndDate() && a.getEndDate() != null) || (accountsFilterConfiguration.isIncludeWithoutEndDate() && a.getEndDate() == null))
.filter(a -> (!accountsFilterConfiguration.hasName() || (accountsFilterConfiguration.hasName() && a.getName().toLowerCase().contains(accountsFilterConfiguration.getName().toLowerCase()))))
.filter(a -> (!accountsFilterConfiguration.hasDescription() || (accountsFilterConfiguration.hasDescription() && a.getDescription().toLowerCase().contains(accountsFilterConfiguration.getDescription().toLowerCase()))))
.sorted((a1, a2) -> new NaturalOrderComparator().compare(a1.getName(), a2.getName()))
.toList();
}
@Override
public Optional<Account> findById(Integer ID)
{
......
package de.deadlocker8.budgetmaster.accounts;
import lombok.*;
import java.util.ArrayList;
import java.util.List;
@Getter
@Setter
@ToString
@AllArgsConstructor
@NoArgsConstructor
@EqualsAndHashCode
public class AccountsFilterConfiguration
{
private boolean includeFullAccess;
private boolean includeReadOnly;
private boolean includeHidden;
private boolean includeWithEndDate;
private boolean includeWithoutEndDate;
private String name;
private String description;
public static final AccountsFilterConfiguration DEFAULT = new AccountsFilterConfiguration(true, true, false, true, true, "", "");
public List<AccountState> getIncludedStates()
{
final List<AccountState> includedStates = new ArrayList<>();
if(includeFullAccess)
{
includedStates.add(AccountState.FULL_ACCESS);
}
if(includeReadOnly)
{
includedStates.add(AccountState.READ_ONLY);
}
if(includeHidden)
{
includedStates.add(AccountState.HIDDEN);
}
return includedStates;
}
public boolean hasName()
{
return name != null && !name.isEmpty();
}
public boolean hasDescription()
{
return description != null && !description.isEmpty();
}
}
\ No newline at end of file
......@@ -119,7 +119,7 @@ public class ChartController extends BaseController
throw new ResourceNotFoundException();
}
List<Transaction> transactions = transactionService.getTransactionsForAccount(helpers.getCurrentAccount(), chartSettings.getStartDate(), chartSettings.getEndDate(), chartSettings.getFilterConfiguration());
List<Transaction> transactions = transactionService.getTransactionsForAccount(helpers.getCurrentAccount(), chartSettings.getStartDate(), chartSettings.getEndDate(), chartSettings.getFilterConfiguration(), false);
List<Transaction> convertedTransactions = convertTransferAmounts(transactions);
String transactionJson = GSON.toJson(convertedTransactions);
......@@ -298,7 +298,7 @@ public class ChartController extends BaseController
}
}
final List<Transaction> transactions = transactionService.getTransactionsForAccount(helpers.getCurrentAccount(), chartSettings.getStartDate(), chartSettings.getEndDate(), chartSettings.getFilterConfiguration());
final List<Transaction> transactions = transactionService.getTransactionsForAccount(helpers.getCurrentAccount(), chartSettings.getStartDate(), chartSettings.getEndDate(), chartSettings.getFilterConfiguration(), false);
final List<Transaction> convertedTransactions = convertTransferAmounts(transactions);
model.addAttribute(ModelAttributes.MATCHING_TRANSACTIONS, convertedTransactions);
model.addAttribute(ModelAttributes.MATCHING_TRANSACTIONS_TITLE, title);
......
......@@ -47,11 +47,9 @@ public class AboutController extends BaseController
public String whatsNewModal(Model model)
{
final List<NewsEntry> newsEntries = new ArrayList<>();
newsEntries.add(NewsEntry.createWithLocalizationKey("accountEndDate"));
newsEntries.add(NewsEntry.createWithLocalizationKey("accountDescription"));
newsEntries.add(NewsEntry.createWithLocalizationKey("transactionNameSuggestionsSort"));
newsEntries.add(NewsEntry.createWithLocalizationKey("bugfixCsvImport"));
newsEntries.add(NewsEntry.createWithLocalizationKey("bugfixEndDateReminder"));
newsEntries.add(NewsEntry.createWithLocalizationKey("accountFilter"));
newsEntries.add(NewsEntry.createWithLocalizationKey("java21"));
newsEntries.add(NewsEntry.createWithLocalizationKey("bugfixAllAccountsSum"));
model.addAttribute(ModelAttributes.NEWS_ENTRIES, newsEntries);
return ReturnValues.WHATS_NEW;
......
......@@ -194,7 +194,7 @@ public class HelpersService
private int getBudgetForAccount(Account account)
{
final LocalDate endDate = DateHelper.getCurrentDate();
List<Transaction> transactions = transactionService.getTransactionsForAccountUntilDate(account, endDate, FilterConfiguration.DEFAULT);
List<Transaction> transactions = transactionService.getTransactionsForAccountUntilDate(account, endDate, FilterConfiguration.DEFAULT, account.getType().equals(AccountType.ALL));
int sum = 0;
for(Transaction transaction : transactions)
......
......@@ -96,16 +96,16 @@ public class TransactionService implements Resettable
final LocalDate startDate = LocalDate.of(year, month, 1);
final LocalDate endDate = LocalDate.of(year, month, 1).with(lastDayOfMonth());
return getTransactionsForAccount(account, startDate, endDate, filterConfiguration);
return getTransactionsForAccount(account, startDate, endDate, filterConfiguration, false);
}
public List<Transaction> getTransactionsForAccountUntilDate(Account account, LocalDate date, FilterConfiguration filterConfiguration)
public List<Transaction> getTransactionsForAccountUntilDate(Account account, LocalDate date, FilterConfiguration filterConfiguration, boolean includeHidden)
{
LocalDate startDate = LocalDate.of(1900, 1, 1);
return getTransactionsForAccount(account, startDate, date, filterConfiguration);
return getTransactionsForAccount(account, startDate, date, filterConfiguration, includeHidden);
}
public List<Transaction> getTransactionsForAccount(Account account, LocalDate startDate, LocalDate endDate, FilterConfiguration filterConfiguration)
public List<Transaction> getTransactionsForAccount(Account account, LocalDate startDate, LocalDate endDate, FilterConfiguration filterConfiguration, boolean includeHidden)
{
if(filterConfiguration == null)
{
......@@ -114,11 +114,11 @@ public class TransactionService implements Resettable
if(account.getType().equals(AccountType.ALL))
{
Specification<Transaction> spec = TransactionSpecifications.withDynamicQuery(startDate, endDate, null, filterConfiguration.isIncludeIncome(), filterConfiguration.isIncludeExpenditure(), false, filterConfiguration.isIncludeRepeatingAndNotRepeating(), filterConfiguration.getIncludedCategoryIDs(), filterConfiguration.getIncludedTagIDs(), filterConfiguration.getName());
Specification<Transaction> spec = TransactionSpecifications.withDynamicQuery(startDate, endDate, null, filterConfiguration.isIncludeIncome(), filterConfiguration.isIncludeExpenditure(), false, filterConfiguration.isIncludeRepeatingAndNotRepeating(), filterConfiguration.getIncludedCategoryIDs(), filterConfiguration.getIncludedTagIDs(), filterConfiguration.getName(), includeHidden);
return transactionRepository.findAll(spec);
}
Specification<Transaction> spec = TransactionSpecifications.withDynamicQuery(startDate, endDate, account, filterConfiguration.isIncludeIncome(), filterConfiguration.isIncludeExpenditure(), filterConfiguration.isIncludeTransfer(), filterConfiguration.isIncludeRepeatingAndNotRepeating(), filterConfiguration.getIncludedCategoryIDs(), filterConfiguration.getIncludedTagIDs(), filterConfiguration.getName());
Specification<Transaction> spec = TransactionSpecifications.withDynamicQuery(startDate, endDate, account, filterConfiguration.isIncludeIncome(), filterConfiguration.isIncludeExpenditure(), filterConfiguration.isIncludeTransfer(), filterConfiguration.isIncludeRepeatingAndNotRepeating(), filterConfiguration.getIncludedCategoryIDs(), filterConfiguration.getIncludedTagIDs(), filterConfiguration.getName(), includeHidden);
return transactionRepository.findAll(spec);
}
......
......@@ -27,7 +27,8 @@ public class TransactionSpecifications
final Boolean isRepeating,
final List<Integer> categoryIDs,
final List<Integer> tagIDs,
final String name)
final String name,
final boolean isIncludeHidden)
{
return (transaction, query, builder) -> {
List<Predicate> predicates = new ArrayList<>();
......@@ -126,7 +127,12 @@ public class TransactionSpecifications
Predicate generalPredicates = builder.and(dateConstraint, predicatesCombined);
if(account == null)
{
Predicate accountPredicate = transaction.get(Transaction_.account).get("accountState").in(List.of(AccountState.FULL_ACCESS, AccountState.READ_ONLY));
final List<AccountState> accountStates = new ArrayList<>(List.of(AccountState.FULL_ACCESS, AccountState.READ_ONLY));
if(isIncludeHidden)
{
accountStates.add(AccountState.HIDDEN);
}
Predicate accountPredicate = transaction.get(Transaction_.account).get("accountState").in(accountStates);
generalPredicates = builder.and(generalPredicates, accountPredicate);
}
else
......
locale=de
# DEFAULT
credits=Verwendete Schriftarten: Roboto<br>Verwendete Bibliotheken:<br>spring-boot-starter-parent 3.3.5<br>spring-boot-devtools 3.3.5<br>spring-boot-starter-web 3.3.5<br>spring-boot-starter-test 3.3.5<br>spring-boot-starter-security 3.3.5<br>spring-boot-starter-freemarker 3.3.5<br>spring-boot-starter-validation 3.3.5<br>spring-boot-starter-data-jpa 3.3.5<br>hibernate-jpamodelgen 6.1.7.Final<br>jakarta.xml.bind-api 4.0.2<br>maven-surefire-plugin 2.22.2<br>launch4j-maven-plugin 1.7.25<br>jquery 3.7.1<br>materialize 1.0.0<br>fontawesome 6.5.2<br>Google Material Icons<br>Vanilla-picker 2.12.3<br>SortableJS 1.15.3<br>jlibs 3.2.0<br>itextpdf 5.5.13.4<br>mousetrap 1.6.5<br>plotly 2.35.2<br>momentjs 2.30.1<br>codemirror 5.62.2<br>webjars-locator 0.52<br>libUtils 3.2.7<br>libStorage 3.2.3<br>natorder 1.1.3<br>jgit 7.0.0.202409031743-r<br>opencsv 5.9<br>datatables 2.1.0<br>
credits=Verwendete Schriftarten: Roboto<br>Verwendete Bibliotheken:<br>spring-boot-starter-parent 3.3.5<br>spring-boot-devtools 3.3.5<br>spring-boot-starter-web 3.3.5<br>spring-boot-starter-test 3.3.5<br>spring-boot-starter-security 3.3.5<br>spring-boot-starter-freemarker 3.3.5<br>spring-boot-starter-validation 3.3.5<br>spring-boot-starter-data-jpa 3.3.5<br>hibernate-jpamodelgen 6.1.7.Final<br>jakarta.xml.bind-api 4.0.2<br>maven-surefire-plugin 2.22.2<br>launch4j-maven-plugin 1.7.25<br>jquery 3.7.1<br>materialize 1.0.0<br>fontawesome 6.7.2<br>Google Material Icons<br>Vanilla-picker 2.12.3<br>SortableJS 1.15.6<br>jlibs 3.2.0<br>itextpdf 5.5.13.4<br>mousetrap 1.6.5<br>plotly 2.35.2<br>momentjs 2.30.1<br>codemirror 5.62.2<br>webjars-locator 0.52<br>libUtils 3.2.7<br>libStorage 3.2.3<br>natorder 1.1.3<br>jgit 7.2.0.202503040940-r<br>opencsv 5.10<br>datatables 2.1.8<br>
folder=Deadlocker/BudgetMaster
roadmap.url=https://roadmaps.thecodelabs.de/roadmap/1
github.url=https://github.com/deadlocker8/BudgetMaster
......@@ -371,6 +371,8 @@ account.all=Alle Konten
account.tooltip.default=Als Standardkonto festlegen
account.tooltip.endDate.soon=Das Enddatum für dieses Konto wird in {0} Tagen erreicht!
account.tooltip.endDate.done=Das Enddatum für dieses Konto wurde vor {0} Tagen erreicht!
account.label.endDate.with=mit
account.label.endDate.without=ohne
account.state.full.access=Vollzugriff
account.state.read.only=Lesezugriff
......@@ -624,22 +626,22 @@ chart.matching.transactions.title.category=Buchungen in der Kategorie "{0}"
charts.default.accountSumPerDay=Kontostand pro Tag
charts.default.accountSumPerDay.localization='{"axisY": "Summe in "'}
charts.default.categories=Eingaben/Ausgaben pro Kategorie
charts.default.incomesAndExpendituresPerMonthBar=Eingaben/Ausgaben
charts.default.categories=Einnahmen/Ausgaben pro Kategorie
charts.default.incomesAndExpendituresPerMonthBar=Einnahmen/Ausgaben
charts.default.incomesAndExpendituresPerMonthBar.localization='{"axisY": "Summe in ", "traceName1": "Einnahmen", "traceName2": "Ausgaben"'}
charts.default.incomesAndExpendituresPerMonthLine=Eingaben/Ausgaben
charts.default.incomesAndExpendituresPerMonthLine=Einnahmen/Ausgaben
charts.default.incomesAndExpendituresPerMonthLine.localization='{"axisY": "Summe in ", "traceName1": "Einnahmen", "traceName2": "Ausgaben"'}
charts.default.incomesAndExpendituresByCategoryBar=Eingaben/Ausgaben pro Kategorie
charts.default.incomesAndExpendituresByCategoryBar=Einnahmen/Ausgaben pro Kategorie
charts.default.incomesAndExpendituresByCategoryBar.localization='{"label1": "Ausgaben", "label2": "Einnahmen"'}
charts.default.incomesAndExpendituresByCategoryPie=Eingaben/Ausgaben pro Kategorie
charts.default.incomesAndExpendituresByCategoryPie=Einnahmen/Ausgaben pro Kategorie
charts.default.incomesAndExpendituresByCategoryPie.localization='{"label1": "Ausgaben", "label2": "Einnahmen"'}
charts.default.incomesAndExpendituresPerMonthByCategories=Eingaben/Ausgaben pro Kategorie
charts.default.incomesAndExpendituresPerMonthByCategories=Einnahmen/Ausgaben pro Kategorie
charts.default.incomesAndExpendituresPerMonthByCategories.localization='{"label1": "Ausgaben", "label2": "Einnahmen"'}
charts.default.restPerMonth=Rest
charts.default.restPerMonth.localization='{"label1": "Rest in "'}
charts.default.incomesAndExpendituresPerYearBar=Eingaben/Ausgaben
charts.default.incomesAndExpendituresPerYearBar=Einnahmen/Ausgaben
charts.default.incomesAndExpendituresPerYearBar.localization='{"axisY": "Summe in ", "traceName1": "Einnahmen", "traceName2": "Ausgaben"'}
charts.default.incomesAndExpendituresPerYearByCategories=Eingaben/Ausgaben pro Kategorie
charts.default.incomesAndExpendituresPerYearByCategories=Einnahmen/Ausgaben pro Kategorie
charts.default.incomesAndExpendituresPerYearByCategories.localization='{"label1": "Ausgaben", "label2": "Einnahmen"'}
charts.default.averageTransactionAmountPerCategory=Durchschnittlicher Transaktionsbetrag pro Kategorie
charts.default.averageTransactionAmountPerCategory.localization='{"label1": "Durchschnittlicher Transaktionsbetrag in"'}
......
locale=en
# DEFAULT
credits=Fonts used: Roboto<br>Libraries used:<br>spring-boot-starter-parent 3.3.5<br>spring-boot-devtools 3.3.5<br>spring-boot-starter-web 3.3.5<br>spring-boot-starter-test 3.3.5<br>spring-boot-starter-security 3.3.5<br>pring-boot-starter-freemarker 3.3.5<br>spring-boot-starter-validation 3.3.5<br>spring-boot-starter-data-jpa 3.3.5<br>hibernate-jpamodelgen 6.1.7.Final<br>jakarta.xml.bind-api 4.0.2<br>maven-surefire-plugin 2.22.2<br>launch4j-maven-plugin 1.7.25<br>jquery 3.7.1<br>materialize 1.0.0<br>fontawesome 6.5.2<br>Google Material Icons<br>Vanilla-picker 2.12.3<br>SortableJS 1.15.3<br>jlibs 3.2.0<br>itextpdf 5.5.13.4<br>mousetrap 1.6.5<br>plotly 2.35.2<br>momentjs 2.30.1<br>codemirror 5.62.2<br>webjars-locator 0.52<br>libUtils 3.2.7<br>libStorage 3.2.3<br>natorder 1.1.3<br>jgit 7.0.0.202409031743-r<br>opencsv 5.9<br>datatables 2.1.0<br>
credits=Fonts used: Roboto<br>Libraries used:<br>spring-boot-starter-parent 3.3.5<br>spring-boot-devtools 3.3.5<br>spring-boot-starter-web 3.3.5<br>spring-boot-starter-test 3.3.5<br>spring-boot-starter-security 3.3.5<br>pring-boot-starter-freemarker 3.3.5<br>spring-boot-starter-validation 3.3.5<br>spring-boot-starter-data-jpa 3.3.5<br>hibernate-jpamodelgen 6.1.7.Final<br>jakarta.xml.bind-api 4.0.2<br>maven-surefire-plugin 2.22.2<br>launch4j-maven-plugin 1.7.25<br>jquery 3.7.1<br>materialize 1.0.0<br>fontawesome 6.7.2<br>Google Material Icons<br>Vanilla-picker 2.12.3<br>SortableJS 1.15.6<br>jlibs 3.2.0<br>itextpdf 5.5.13.4<br>mousetrap 1.6.5<br>plotly 2.35.2<br>momentjs 2.30.1<br>codemirror 5.62.2<br>webjars-locator 0.52<br>libUtils 3.2.7<br>libStorage 3.2.3<br>natorder 1.1.3<br>jgit 7.2.0.202503040940-r<br>opencsv 5.10<br>datatables 2.1.8<br>
folder=Deadlocker/BudgetMaster
roadmap.url=https://roadmaps.thecodelabs.de/roadmap/2
github.url=https://github.com/deadlocker8/BudgetMaster
......@@ -370,6 +370,8 @@ account.all=All Accounts
account.tooltip.default=Set as default account
account.tooltip.endDate.soon=The end date for this account will be reached in {0} days!
account.tooltip.endDate.done=The end date for this account was reached {0} days ago!
account.label.endDate.with=with
account.label.endDate.without=without
account.state.full.access=Full access
account.state.read.only=Read-only
......
......@@ -2,17 +2,11 @@ news.further.information=Weitere Informationen
news.all.releases=Alle veröffentlichten und geplanten Versionen:
news.detailed=Ausführliches Changelog (nur auf Englisch):
news.accountEndDate.headline=Konten: neues optionales Feld "Enddatum"
news.accountEndDate.description=Konten können jetzt mit einem Enddatum versehen werden. Kurz vor Erreichen des Enddatums wird nach dem Login eine Warnung angezeigt.
news.accountFilter.headline=Konten filtern
news.accountFilter.description=Auf der Kontoübersichtsseite können die aufgelisteten Konten nun gefiltert werden.
news.accountDescription.headline=Konten: neues optionales Feld "Beschreibung"
news.accountDescription.description=Konten können jetzt mit einer Beschreibung versehen werden.
news.java21.headline=Java 21
news.java21.description=Update auf Java 21.
news.transactionNameSuggestionsSort.headline=Einstellungsoption für die Sortierung der Buchungsnamensvorschläge
news.transactionNameSuggestionsSort.description=Neue Einstellungsoption hinzugefügt, um festzulegen, wie die Vorschläge für Transaktionsnamen sortiert werden (alphabetisch oder nach Häufigkeit der Verwendung).
news.bugfixCsvImport.headline=Bugfix: CSV Import
news.bugfixCsvImport.description=Fehler behoben, der verhinderte, dass beim csv-Import die richtigen Spalten ausgewählt wurden, wenn die csv-Datei weniger Zeilen als Spalten hat.
news.bugfixEndDateReminder.headline=Bugfix: Enddatumserinnerung
news.bugfixEndDateReminder.description=Fehler behoben, der dazu führte, dass die Enddatumserinnerung für Konten auch angezeigt wurde, wenn keine Konten ihr Enddatum bald erreichen.
\ No newline at end of file
news.bugfixAllAccountsSum.headline=Bugfix: Transaktionen aus versteckten Konten
news.bugfixAllAccountsSum.description=Transaktionen aus versteckten Konten werden nun korrekt in der Summe aller Konten berücksichtigt.
\ No newline at end of file
......@@ -2,17 +2,11 @@ news.further.information=Further information
news.all.releases=All published and planned releases:
news.detailed=Detailed changelog (english only):
news.accountEndDate.headline=Accounts: new optional field "end date"
news.accountEndDate.description=Accounts can now have an end date. A warning is displayed after login if the end date of an account will soon be reached.
news.accountFilter.headline=Account Filter
news.accountFilter.description=The account overview page now allows to filter the listed accounts.
news.accountDescription.headline=Accounts: new optional field "description"
news.accountDescription.description=Accounts can now be given a description.
news.java21.headline=Java 21
news.java21.description=Update to Java 21.
news.transactionNameSuggestionsSort.headline=Settings option for transaction name suggestion ordering
news.transactionNameSuggestionsSort.description=Add new settings option to define how transaction name suggestions are ordered (alphabetically or by frequency of use).
news.bugfixCsvImport.headline=Bugfix: CSV import
news.bugfixCsvImport.description=Fixed a bug that prevented to select the correct columns during csv import if the csv has fewer rows than columns.
news.bugfixEndDateReminder.headline=Bugfix: End date reminder
news.bugfixEndDateReminder.description=Fixed a bug that caused the end date reminder for accounts to be displayed even if no accounts are about to reach their end date.
\ No newline at end of file
news.bugfixAllAccountsSum.headline=Bugfix: Transactions from hidden accounts
news.bugfixAllAccountsSum.description=Transactions from hidden accounts are now correctly included in all accounts sum.
......@@ -31,3 +31,11 @@
border: 3px solid var(--color-text);
line-height: 32px !important;
}
.account-container th {
vertical-align: top;
}
.account-container th.vertical-align-middle {
vertical-align: middle;
}
\ No newline at end of file
......@@ -24,10 +24,72 @@
<div class="center-align"><@header.buttonLink url='/accounts/newAccount' icon='add' localizationKey='title.account.new' id='button-new-account'/></div>
<br>
<div class="container account-container">
<form name="AccountsFilter" action="<@s.url '/accounts/applyFilter'/>" method="post">
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" />
<table class="bordered">
<thead class="hide-on-med-and-down">
<tr>
<th></th>
<th>
<div>${locale.getString("account.new.label.state")}</div>
<div>
<label>
<input type="checkbox" name="includeFullAccess" <#if accountsFilterConfiguration?? && accountsFilterConfiguration.includeFullAccess>checked</#if>/>
<span><i class="fas fa-edit placeholder-icon-right"></i>${locale.getString("account.state.full.access")}</span>
</label>
</div>
<div>
<label>
<input type="checkbox" name="includeReadOnly" <#if accountsFilterConfiguration?? && accountsFilterConfiguration.includeReadOnly>checked</#if>/>
<span><i class="fas fa-lock placeholder-icon-right"></i>${locale.getString("account.state.read.only")}</span>
</label>
</div>
<div>
<label>
<input type="checkbox" name="includeHidden" <#if accountsFilterConfiguration?? && accountsFilterConfiguration.includeHidden>checked</#if>/>
<span id="includeHidden"><i class="far fa-eye-slash placeholder-icon-right"></i>${locale.getString("account.state.hidden")}</span>
</label>
</div>
</th>
<th>
<div>${locale.getString("account.new.label.endDate")}</div>
<div>
<label>
<input type="checkbox" name="includeWithEndDate" <#if accountsFilterConfiguration?? && accountsFilterConfiguration.includeWithEndDate>checked</#if>/>
<span><i class="fas fa-bell placeholder-icon-right"></i>${locale.getString("account.label.endDate.with")}</span>
</label>
</div>
<div>
<label>
<input type="checkbox" name="includeWithoutEndDate" <#if accountsFilterConfiguration?? && accountsFilterConfiguration.includeWithoutEndDate>checked</#if>/>
<span><i class="fas fa-bell-slash placeholder-icon-right"></i>${locale.getString("account.label.endDate.without")}</span>
</label>
</div>
</th>
<th>
<div>${locale.getString("account.new.label.name")}</div>
<div class="input-field">
<input type="text" name="name" value="<#if accountsFilterConfiguration??>${accountsFilterConfiguration.name}</#if>"/>
</div>
</th>
<th>
<div>${locale.getString("transaction.new.label.description")}</div>
<div class="input-field">
<input type="text" name="description" value="<#if accountsFilterConfiguration??>${accountsFilterConfiguration.description}</#if>"/>
</div>
</th>
<th class="vertical-align-middle">
<button class="btn waves-effect waves-light background-green" type="submit" id="accounts-filter-button">
<i class="fas fa-filter left"></i>${locale.getString("filter.apply")}
</button>
</th>
</tr>
</thead>
<#list accounts as account>
<#if (account.getType().name() == "CUSTOM")>
<tr class="account-overview-row">
<td><@customSelectMacros.accountIcon account account.getName() "text-blue"/></td>
<td>
<#if account.getAccountState().name() == "READ_ONLY">
<div class="placeholder-icon placeholder-icon-right"></div>
......@@ -39,14 +101,14 @@
<a href="<@s.url '/accounts/${account.getID()?c}/setAsDefault'/>" class="btn-flat no-padding text-default tooltipped" data-position="left" data-tooltip="${locale.getString("account.tooltip.default")}"><i class="material-icons left"><#if account.isDefault()>star<#else>star_border</#if></i></a>
<i class="fas fa-edit placeholder-icon-right"></i>
</#if>
</td>
<td>
<#if account.getEndDate()??>
<i class="fas fa-bell"></i>
<i class="fas fa-bell placeholder-icon-right"></i> ${dateService.getDateStringNormal(account.getEndDate())}
<#else>
<div class="placeholder-icon"></div>
</#if>
</td>
<td><@customSelectMacros.accountIcon account account.getName() "text-blue"/></td>
<td>${account.getName()}</td>
<td>
<div class="truncate account-description">
......@@ -61,6 +123,7 @@
</#if>
</#list>
</table>
</form>
<#if accounts?size == 0>
<div class="headline center-align">${locale.getString("placeholder")}</div>
</#if>
......
......@@ -138,7 +138,7 @@
<!-- Scripts-->
<#import "../helpers/scripts.ftl" as scripts>
<@scripts.scripts/>
<script src="<@s.url '/webjars/vanilla-picker/2.12.3/dist/vanilla-picker.min.js'/>"></script>
<script src="<@s.url '/webjars/vanilla-picker/dist/vanilla-picker.min.js'/>"></script>
<script src="<@s.url '/js/accounts.js'/>"></script>
<script src="<@s.url '/js/iconSelect.js'/>"></script>
<script src="<@s.url '/js/fontColorPicker.js'/>"></script>
......
......@@ -118,7 +118,7 @@
<!-- Scripts-->
<#import "../helpers/scripts.ftl" as scripts>
<@scripts.scripts/>
<script src="<@s.url '/webjars/vanilla-picker/2.12.3/dist/vanilla-picker.min.js'/>"></script>
<script src="<@s.url '/webjars/vanilla-picker/dist/vanilla-picker.min.js'/>"></script>
<script src="<@s.url '/js/categories.js'/>"></script>
<script src="<@s.url '/js/iconSelect.js'/>"></script>
<script src="<@s.url '/js/fontColorPicker.js'/>"></script>
......
......@@ -11,7 +11,7 @@
<@header.header "BudgetMaster - ${title}"/>
<#import "/spring.ftl" as s>
<link rel="stylesheet" href="<@s.url "/webjars/codemirror/5.62.2/lib/codemirror.css"/>">
<link rel="stylesheet" href="<@s.url "/webjars/codemirror/lib/codemirror.css"/>">
<@header.style "charts"/>
</head>
<@header.body>
......@@ -102,8 +102,8 @@
<!-- Scripts-->
<#import "../helpers/scripts.ftl" as scripts>
<@scripts.scripts/>
<script src="<@s.url '/webjars/codemirror/5.62.2/lib/codemirror.js'/>"></script>
<script src="<@s.url '/webjars/codemirror/5.62.2/mode/javascript/javascript.js'/>"></script>
<script src="<@s.url '/webjars/codemirror/lib/codemirror.js'/>"></script>
<script src="<@s.url '/webjars/codemirror/mode/javascript/javascript.js'/>"></script>
<script src="<@s.url '/js/charts.js'/>"></script>
</@header.body>
</html>
\ No newline at end of file
......@@ -21,9 +21,9 @@
<#import "/spring.ftl" as s>
<title>${title}</title>
<meta charset="UTF-8"/>
<link rel="stylesheet" href="<@s.url '/webjars/font-awesome/6.5.2/css/all.min.css'/>">
<link rel="stylesheet" href="<@s.url '/webjars/font-awesome/css/all.min.css'/>">
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<link rel="stylesheet" href="<@s.url "/webjars/materializecss/1.0.0/css/materialize.min.css"/>">
<link rel="stylesheet" href="<@s.url "/webjars/materializecss/css/materialize.min.css"/>">
<@style "colors"/>
<@style "style"/>
<@style "navbar"/>
......