diff --git a/src/main/java/de/deadlocker8/budgetmaster/settings/AutoBackupTime.java b/src/main/java/de/deadlocker8/budgetmaster/settings/AutoBackupTime.java new file mode 100644 index 0000000000000000000000000000000000000000..1234859af72771cb3546e996703a42f5fbab8364 --- /dev/null +++ b/src/main/java/de/deadlocker8/budgetmaster/settings/AutoBackupTime.java @@ -0,0 +1,6 @@ +package de.deadlocker8.budgetmaster.settings; + +public enum AutoBackupTime +{ + DEFAULT +} diff --git a/src/main/java/de/deadlocker8/budgetmaster/settings/Settings.java b/src/main/java/de/deadlocker8/budgetmaster/settings/Settings.java index 80c4342ebfa22e17d681b70ced67cb95d53adeaf..9b79844e6e93dc9bc9b8b943391ffdd3fda59fc3 100644 --- a/src/main/java/de/deadlocker8/budgetmaster/settings/Settings.java +++ b/src/main/java/de/deadlocker8/budgetmaster/settings/Settings.java @@ -25,6 +25,8 @@ public class Settings private Integer searchItemsPerPage; private Boolean autoBackupActivated; + private Integer autoBackupDays; + private AutoBackupTime autoBackupTime; public Settings() { @@ -42,6 +44,8 @@ public class Settings defaultSettings.setLastBackupReminderDate(DateTime.now().minusMonths(1)); defaultSettings.setSearchItemsPerPage(10); defaultSettings.setAutoBackupActivated(false); + defaultSettings.setAutoBackupDays(1); + defaultSettings.setAutoBackupTime(AutoBackupTime.DEFAULT); return defaultSettings; } @@ -150,6 +154,26 @@ public class Settings this.autoBackupActivated = autoBackupActivated; } + public Integer getAutoBackupDays() + { + return autoBackupDays; + } + + public void setAutoBackupDays(Integer autoBackupDays) + { + this.autoBackupDays = autoBackupDays; + } + + public AutoBackupTime getAutoBackupTime() + { + return autoBackupTime; + } + + public void setAutoBackupTime(AutoBackupTime autoBackupTime) + { + this.autoBackupTime = autoBackupTime; + } + @Override public String toString() { @@ -164,6 +188,8 @@ public class Settings ", lastBackupReminderDate=" + lastBackupReminderDate + ", searchItemsPerPage=" + searchItemsPerPage + ", autoBackupActivated=" + autoBackupActivated + + ", autoBackupDays=" + autoBackupDays + + ", autoBackupTime=" + autoBackupTime + '}'; } } \ No newline at end of file diff --git a/src/main/java/de/deadlocker8/budgetmaster/settings/SettingsController.java b/src/main/java/de/deadlocker8/budgetmaster/settings/SettingsController.java index bad3156e9f5ec2b532054218e5fd2a5a87bd5ed6..722505a2219b3c7e7f8c3ece2b58719030ff852b 100644 --- a/src/main/java/de/deadlocker8/budgetmaster/settings/SettingsController.java +++ b/src/main/java/de/deadlocker8/budgetmaster/settings/SettingsController.java @@ -2,6 +2,7 @@ package de.deadlocker8.budgetmaster.settings; import de.deadlocker8.budgetmaster.Build; import de.deadlocker8.budgetmaster.accounts.AccountService; +import de.deadlocker8.budgetmaster.accounts.AccountValidator; import de.deadlocker8.budgetmaster.authentication.User; import de.deadlocker8.budgetmaster.authentication.UserRepository; import de.deadlocker8.budgetmaster.categories.CategoryService; @@ -42,6 +43,7 @@ import java.io.IOException; import java.nio.charset.StandardCharsets; import java.util.Arrays; import java.util.List; +import java.util.Optional; @Controller @@ -86,12 +88,15 @@ public class SettingsController extends BaseController { settings.setLanguage(LanguageType.fromName(languageType)); - FieldError error = validatePassword(password, passwordConfirmation); - if(error != null) + Optional<FieldError> passwordErrorOptional = validatePassword(password, passwordConfirmation); + if(passwordErrorOptional.isPresent()) { - bindingResult.addError(error); + bindingResult.addError(passwordErrorOptional.get()); } + SettingsValidator settingsValidator = new SettingsValidator(); + settingsValidator.validate(settings, bindingResult); + if(settings.getBackupReminderActivated() == null) { settings.setBackupReminderActivated(false); @@ -102,6 +107,13 @@ public class SettingsController extends BaseController settings.setAutoBackupActivated(false); } + if(!settings.getAutoBackupActivated()) + { + final Settings defaultSettings = Settings.getDefault(); + settings.setAutoBackupDays(defaultSettings.getAutoBackupDays()); + settings.setAutoBackupTime(defaultSettings.getAutoBackupTime()); + } + if(bindingResult.hasErrors()) { model.addAttribute("error", bindingResult); @@ -109,48 +121,46 @@ public class SettingsController extends BaseController model.addAttribute("searchResultsPerPageOptions", SEARCH_RESULTS_PER_PAGE_OPTIONS); return "settings/settings"; } - else + + if(!password.equals("•••••")) { - if(!password.equals("•••••")) - { - BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder(); - String encryptedPassword = bCryptPasswordEncoder.encode(password); - User user = userRepository.findByName("Default"); - user.setPassword(encryptedPassword); - userRepository.save(user); - } - - settingsService.getRepository().deleteById(0); - settingsService.getRepository().save(settings); - - Localization.load(); + BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder(); + String encryptedPassword = bCryptPasswordEncoder.encode(password); + User user = userRepository.findByName("Default"); + user.setPassword(encryptedPassword); + userRepository.save(user); } + settingsService.getRepository().deleteById(0); + settingsService.getRepository().save(settings); + + Localization.load(); + return "redirect:/settings"; } - private FieldError validatePassword(String password, String passwordConfirmation) + private Optional<FieldError> validatePassword(String password, String passwordConfirmation) { if(password == null || password.equals("")) { - return new FieldError("Settings", "password", password, false, new String[]{Strings.WARNING_SETTINGS_PASSWORD_EMPTY}, null, Strings.WARNING_SETTINGS_PASSWORD_EMPTY); + return Optional.of(new FieldError("Settings", "password", password, false, new String[]{Strings.WARNING_SETTINGS_PASSWORD_EMPTY}, null, Strings.WARNING_SETTINGS_PASSWORD_EMPTY)); } else if(password.length() < 3) { - return new FieldError("Settings", "password", password, false, new String[]{Strings.WARNING_SETTINGS_PASSWORD_LENGTH}, null, Strings.WARNING_SETTINGS_PASSWORD_LENGTH); + return Optional.of(new FieldError("Settings", "password", password, false, new String[]{Strings.WARNING_SETTINGS_PASSWORD_LENGTH}, null, Strings.WARNING_SETTINGS_PASSWORD_LENGTH)); } if(passwordConfirmation == null || passwordConfirmation.equals("")) { - return new FieldError("Settings", "passwordConfirmation", passwordConfirmation, false, new String[]{Strings.WARNING_SETTINGS_PASSWORD_CONFIRMATION_EMPTY}, null, Strings.WARNING_SETTINGS_PASSWORD_CONFIRMATION_EMPTY); + return Optional.of(new FieldError("Settings", "passwordConfirmation", passwordConfirmation, false, new String[]{Strings.WARNING_SETTINGS_PASSWORD_CONFIRMATION_EMPTY}, null, Strings.WARNING_SETTINGS_PASSWORD_CONFIRMATION_EMPTY)); } if(!password.equals(passwordConfirmation)) { - return new FieldError("Settings", "passwordConfirmation", passwordConfirmation, false, new String[]{Strings.WARNING_SETTINGS_PASSWORD_CONFIRMATION_WRONG}, null, Strings.WARNING_SETTINGS_PASSWORD_CONFIRMATION_WRONG); + return Optional.of(new FieldError("Settings", "passwordConfirmation", passwordConfirmation, false, new String[]{Strings.WARNING_SETTINGS_PASSWORD_CONFIRMATION_WRONG}, null, Strings.WARNING_SETTINGS_PASSWORD_CONFIRMATION_WRONG)); } - return null; + return Optional.empty(); } @RequestMapping("/settings/database/requestExport") diff --git a/src/main/java/de/deadlocker8/budgetmaster/settings/SettingsService.java b/src/main/java/de/deadlocker8/budgetmaster/settings/SettingsService.java index bb868c396c456e3978decae5a7f07269647099e0..51ac3e58a574c3042864f7825a1b8bcdd3ba1b18 100644 --- a/src/main/java/de/deadlocker8/budgetmaster/settings/SettingsService.java +++ b/src/main/java/de/deadlocker8/budgetmaster/settings/SettingsService.java @@ -53,6 +53,15 @@ public class SettingsService { settings.setAutoBackupActivated(defaultSettings.getAutoBackupActivated()); } + if(settings.getAutoBackupDays() == null) + { + settings.setAutoBackupDays(defaultSettings.getAutoBackupDays()); + } + if(settings.getAutoBackupTime() == null) + { + settings.setAutoBackupTime(defaultSettings.getAutoBackupTime()); + } + settingsRepository.deleteById(0); settingsRepository.save(settings); } diff --git a/src/main/java/de/deadlocker8/budgetmaster/settings/SettingsValidator.java b/src/main/java/de/deadlocker8/budgetmaster/settings/SettingsValidator.java new file mode 100644 index 0000000000000000000000000000000000000000..31efe6b18219944e1f9d60a15c9d435717be3a0c --- /dev/null +++ b/src/main/java/de/deadlocker8/budgetmaster/settings/SettingsValidator.java @@ -0,0 +1,20 @@ +package de.deadlocker8.budgetmaster.settings; + +import de.deadlocker8.budgetmaster.utils.Strings; +import org.springframework.validation.Errors; +import org.springframework.validation.ValidationUtils; +import org.springframework.validation.Validator; + + +public class SettingsValidator implements Validator +{ + public boolean supports(Class clazz) + { + return Settings.class.equals(clazz); + } + + public void validate(Object obj, Errors errors) + { + ValidationUtils.rejectIfEmptyOrWhitespace(errors, "autoBackupDays", Strings.WARNING_SETTINGS_EMPTY_SETTINGS_AUTO_BACKUP_DAYS); + } +} \ No newline at end of file diff --git a/src/main/java/de/deadlocker8/budgetmaster/utils/Strings.java b/src/main/java/de/deadlocker8/budgetmaster/utils/Strings.java index 4dea4a64317fa4963e6f246a4adb73005eb70082..550b5ba93df092773840720ba45d2e625a2a73f3 100644 --- a/src/main/java/de/deadlocker8/budgetmaster/utils/Strings.java +++ b/src/main/java/de/deadlocker8/budgetmaster/utils/Strings.java @@ -38,6 +38,7 @@ public class Strings public static final String WARNING_SETTINGS_PASSWORD_LENGTH = "warning.settings.password.length"; public static final String WARNING_SETTINGS_PASSWORD_CONFIRMATION_EMPTY = "warning.settings.password.confirmation.empty"; public static final String WARNING_SETTINGS_PASSWORD_CONFIRMATION_WRONG = "warning.settings.password.confirmation.wrong"; + public static final String WARNING_SETTINGS_EMPTY_SETTINGS_AUTO_BACKUP_DAYS = "warning.settings.empty.auto.backup.days"; public static final String WARNING_EMPTY_CHART_NAME = "warning.empty.chart.name"; public static final String WARNING_EMPTY_CHART_SCRIPT = "warning.empty.chart.script"; diff --git a/src/main/resources/languages/_de.properties b/src/main/resources/languages/_de.properties index b594a4b0f7032b62236552b38e198f767c34aab5..e4d6009ae765feed65d5f3fb9648836bbfdaeb69 100644 --- a/src/main/resources/languages/_de.properties +++ b/src/main/resources/languages/_de.properties @@ -129,6 +129,7 @@ warning.settings.password.empty=Bitte gib ein Passwort ein. warning.settings.password.length=Das Passwort muss mindestens drei Zeichen lang sein. warning.settings.password.confirmation.empty=Bitte gib dein Passwort zur Best�tigung erneut ein. warning.settings.password.confirmation.wrong=Passwort und Passwort Wiederholung stimmen nicht �berein. +warning.settings.empty.auto.backup.days=Gib eine g�ltige Zahl gr��er 0 ein. warning.empty.chart.name=Bitte gib einen Namen ein. warning.empty.chart.script=Bitte gib ein Script ein. @@ -176,6 +177,8 @@ settings.backup=Backup settings.backup.auto=Automatisches Backup settings.backup.auto.deactivated=Aus settings.backup.auto.activated=An +settings.backup.auto.days=Intervall in Tagen +settings.backup.auto.time=Uhrzeit settings.database.import=Importieren settings.database.export=Exportieren diff --git a/src/main/resources/languages/_en.properties b/src/main/resources/languages/_en.properties index 1ae80fb1391223016f96efc140e64114f0cf064b..0fbd729b119a523a2733011bfbc13a73c839d2ad 100644 --- a/src/main/resources/languages/_en.properties +++ b/src/main/resources/languages/_en.properties @@ -111,7 +111,7 @@ info.database.import.or=or info.title.update=Update available info.text.update=An update for BudgetMaster is available<br><br>Installed: v{0}<br>Available: {1}<br><br>Would you like to update now?<br><br>Note: The update may take a while depending on your internet connection. The BudgetMaster server will be restarted automatically. Please do not make any changes to accounts, transactions, categories, etc. after starting the update. info.title.backup.reminder=Time for a backup -info.text.backup.reminder=Have you ever thought about a backup?<br>You should back up your BudgetMaster database regularly.<br>This can be donee on the settings page.<br><br>(You don''t want to see this reminder every month? Disable the backup reminder in the settings.) +info.text.backup.reminder=Have you ever thought about a backup?<br>You should back up your BudgetMaster database regularly.<br>This can be done on the settings page.<br><br>(You don''t want to see this reminder every month? Disable the backup reminder in the settings.) info.button.backup.reminder=To the settings # WARNING @@ -129,6 +129,7 @@ warning.settings.password.empty=Please enter a password. warning.settings.password.length=The password must be at least three characters long. warning.settings.password.confirmation.empty=Please enter your password again for confirmation. warning.settings.password.confirmation.wrong=Password and password confirmation do not match. +warning.settings.empty.auto.backup.days=Please enter a valid number greater than 0. warning.empty.chart.name=Please insert a name. warning.empty.chart.script=Please insert a script. @@ -176,6 +177,8 @@ settings.backup=Backup settings.backup.auto=Automatic Backup settings.backup.auto.deactivated=Off settings.backup.auto.activated=On +settings.backup.auto.days=Interval in days +settings.backup.auto.time=Time of day settings.database.import=Import settings.database.export=Export diff --git a/src/main/resources/static/js/helpers.js b/src/main/resources/static/js/helpers.js new file mode 100644 index 0000000000000000000000000000000000000000..a64d9700dafad3905b9b23d19e1317047e44b371 --- /dev/null +++ b/src/main/resources/static/js/helpers.js @@ -0,0 +1,52 @@ +NUMBER_REGEX = new RegExp("^\\d+$"); + +function validateNumber(text, ID, hiddenID, message) +{ + if(text.match(NUMBER_REGEX) == null) + { + addTooltip(ID, message); + if(hiddenID != null) + { + document.getElementById(hiddenID).value = ""; + } + return false; + } + else + { + removeTooltip(ID); + if(hiddenID != null) + { + document.getElementById(hiddenID).value = parseInt(text); + } + return true; + } +} + +function addTooltip(id, message) +{ + var element = document.getElementById(id); + + removeClass(element, "validate"); + removeClass(element, "valid"); + addClass(element, "tooltipped"); + addClass(element, "invalid"); + element.dataset.tooltip = message; + element.dataset.position = "bottom"; + element.dataset.delay = "50"; + M.Tooltip.init(element); +} + +function removeTooltip(id) +{ + var element = document.getElementById(id); + + removeClass(element, "validate"); + removeClass(element, "invalid"); + removeClass(element, "tooltipped"); + addClass(element, "valid"); + var tooltip = M.Tooltip.getInstance(element); + if(tooltip !== undefined) + { + tooltip.destroy(); + } +} \ No newline at end of file diff --git a/src/main/resources/static/js/settings.js b/src/main/resources/static/js/settings.js index 4e82347bffc0813095fa08def1c2e751986ab974..3970e855c1cda67e15f0de96c63f8fffb135a628 100644 --- a/src/main/resources/static/js/settings.js +++ b/src/main/resources/static/js/settings.js @@ -11,4 +11,33 @@ $(document).ready(function() { document.getElementById("form-database-import").submit(); }); -}); \ No newline at end of file + + $('input[name="autoBackupActivated"]').click(function() + { + $('#settings-auto-backup').toggle($(this).prop("checked")); + }); + + let autoBackupDays = $('#settings-backup-auto-days'); + if(autoBackupDays.length) + { + autoBackupDays.on('change keydown paste input', function() + { + validateNumber(autoBackupDays.val(), 'settings-backup-auto-days', "hidden-settings-backup-auto-days", numberValidationMessage); + }); + } + + // on initial page load + let autoBackupCheckbox = document.getElementsByName("autoBackupActivated")[0]; + $('#settings-auto-backup').toggle(autoBackupCheckbox.checked); +}); + +function validateForm() +{ + let autoBackupCheckbox = document.getElementsByName("autoBackupActivated")[0]; + if(autoBackupCheckbox.checked) + { + return validateNumber($('#settings-backup-auto-days').val(), 'settings-backup-auto-days', "hidden-settings-backup-auto-days", numberValidationMessage); + } + + return true; +} \ No newline at end of file diff --git a/src/main/resources/static/js/transactions.js b/src/main/resources/static/js/transactions.js index bd5290fc5102d77fdde481336802929aa37b70d9..38fa6509fd23b93b43bc02582c044227f47758f5 100644 --- a/src/main/resources/static/js/transactions.js +++ b/src/main/resources/static/js/transactions.js @@ -240,7 +240,6 @@ var transactionRepeatingModifierID = "#transaction-repeating-modifier"; var transactionRepeatingEndAfterXTimesInputID = "#transaction-repeating-end-after-x-times-input"; AMOUNT_REGEX = new RegExp("^-?\\d+(,\\d+)?(\\.\\d+)?$"); -NUMBER_REGEX = new RegExp("^\\d+$"); ALLOWED_CHARACTERS = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", ",", "."]; function validateAmount(text) @@ -260,57 +259,6 @@ function validateAmount(text) } } -function validateNumber(text, ID, hiddenID, message) -{ - if(text.match(NUMBER_REGEX) == null) - { - addTooltip(ID, message); - if(hiddenID != null) - { - document.getElementById(hiddenID).value = ""; - } - return false; - } - else - { - removeTooltip(ID); - if(hiddenID != null) - { - document.getElementById(hiddenID).value = parseInt(text); - } - return true; - } -} - -function addTooltip(id, message) -{ - var element = document.getElementById(id); - - removeClass(element, "validate"); - removeClass(element, "valid"); - addClass(element, "tooltipped"); - addClass(element, "invalid"); - element.dataset.tooltip = message; - element.dataset.position = "bottom"; - element.dataset.delay = "50"; - M.Tooltip.init(element); -} - -function removeTooltip(id) -{ - var element = document.getElementById(id); - - removeClass(element, "validate"); - removeClass(element, "invalid"); - removeClass(element, "tooltipped"); - addClass(element, "valid"); - var tooltip = M.Tooltip.getInstance(element); - if(tooltip !== undefined) - { - tooltip.destroy(); - } -} - function validateForm() { // amount diff --git a/src/main/resources/templates/settings/settings.ftl b/src/main/resources/templates/settings/settings.ftl index 64bf3c8664f205d549de8043ac28b344664d106b..3d677210ca1a6e7757b2c75624a54a07360d0ad5 100644 --- a/src/main/resources/templates/settings/settings.ftl +++ b/src/main/resources/templates/settings/settings.ftl @@ -20,7 +20,7 @@ </div> <div class="container"> <#import "../helpers/validation.ftl" as validation> - <form name="Settings" action="<@s.url '/settings/save'/>" method="post"> + <form name="Settings" action="<@s.url '/settings/save'/>" method="post" onsubmit="return validateForm()"> <input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/> <input type="hidden" name="ID" value="${settings.getID()?c}"> <input type="hidden" name="lastBackupReminderDate" value="${dateService.getLongDateString(settings.getLastBackupReminderDate())}"> @@ -107,6 +107,23 @@ </div> </div> + <div class="row" id="settings-auto-backup"> + <div class="input-field col s12 m12 l8 offset-l2"> + <input id="settings-backup-auto-days" type="text" <@validation.validation "autoBackupDays"/> value="<#if settings.getAutoBackupActivated()??>${settings.getAutoBackupDays()}</#if>"> + <label for="settings-backup-auto-days">${locale.getString("settings.backup.auto.days")}</label> + </div> + <input type="hidden" id="hidden-settings-backup-auto-days" name="autoBackupDays" value="<#if settings.getAutoBackupActivated()??>${settings.getAutoBackupDays()}</#if>"> + + <script> + numberValidationMessage = "${locale.getString("warning.transaction.number")}"; + </script> + + <div class="input-field col s12 m12 l8 offset-l2"> + <input id="settings-backup-auto-time" type="text" name="autoBackupTime" <@validation.validation "autoBackupTime"/> value="<#if settings.getAutoBackupActivated()??>${settings.getAutoBackupTime().name()}</#if>"> + <label for="settings-backup-auto-time">${locale.getString("settings.backup.auto.time")}</label> + </div> + </div> + <br> <#-- buttons --> @@ -183,6 +200,7 @@ <#import "../helpers/scripts.ftl" as scripts> <@scripts.scripts/> <script src="<@s.url '/js/libs/spectrum.js'/>"></script> + <script src="<@s.url '/js/helpers.js'/>"></script> <script src="<@s.url '/js/settings.js'/>"></script> </body> </html> diff --git a/src/main/resources/templates/transactions/newTransactionNormal.ftl b/src/main/resources/templates/transactions/newTransactionNormal.ftl index 52dc18d8b4f21e851d6ce10988274011f530161a..d90a0f7fdb3b1d3cf2a99396f3c4a0fbbb248bfd 100644 --- a/src/main/resources/templates/transactions/newTransactionNormal.ftl +++ b/src/main/resources/templates/transactions/newTransactionNormal.ftl @@ -71,6 +71,7 @@ <#import "../helpers/scripts.ftl" as scripts> <@scripts.scripts/> <script src="<@s.url '/js/libs/spectrum.js'/>"></script> + <script src="<@s.url '/js/helpers.js'/>"></script> <script src="<@s.url '/js/transactions.js'/>"></script> <script src="<@s.url '/js/categorySelect.js'/>"></script> </body> diff --git a/src/main/resources/templates/transactions/newTransactionRepeating.ftl b/src/main/resources/templates/transactions/newTransactionRepeating.ftl index c7885207b70697dc0bcb95125610c680d20615fa..9bce67028c5c7e92f1ff31424962fdd8b6f0c0fb 100644 --- a/src/main/resources/templates/transactions/newTransactionRepeating.ftl +++ b/src/main/resources/templates/transactions/newTransactionRepeating.ftl @@ -74,6 +74,7 @@ <#import "../helpers/scripts.ftl" as scripts> <@scripts.scripts/> <script src="<@s.url '/js/libs/spectrum.js'/>"></script> + <script src="<@s.url '/js/helpers.js'/>"></script> <script src="<@s.url '/js/transactions.js'/>"></script> <script src="<@s.url '/js/categorySelect.js'/>"></script> </body> diff --git a/src/main/resources/templates/transactions/newTransactionTransfer.ftl b/src/main/resources/templates/transactions/newTransactionTransfer.ftl index eb457253aa50f6ec75b5f67d093668c260d1c13b..f2a42f81914346b69aaeda161db4a2b52cd03eb4 100644 --- a/src/main/resources/templates/transactions/newTransactionTransfer.ftl +++ b/src/main/resources/templates/transactions/newTransactionTransfer.ftl @@ -76,6 +76,7 @@ <#import "../helpers/scripts.ftl" as scripts> <@scripts.scripts/> <script src="<@s.url '/js/libs/spectrum.js'/>"></script> + <script src="<@s.url '/js/helpers.js'/>"></script> <script src="<@s.url '/js/transactions.js'/>"></script> <script src="<@s.url '/js/categorySelect.js'/>"></script> </body> diff --git a/src/main/resources/templates/transactions/transactions.ftl b/src/main/resources/templates/transactions/transactions.ftl index 9f4c522670d08649d49fc55ece6e520c5d5e993c..2e473e0bc7f05b64e4c0e8c8e94e1a9c98de2f93 100644 --- a/src/main/resources/templates/transactions/transactions.ftl +++ b/src/main/resources/templates/transactions/transactions.ftl @@ -96,6 +96,7 @@ <!-- Scripts--> <#import "../helpers/scripts.ftl" as scripts> <@scripts.scripts/> + <script src="<@s.url '/js/helpers.js'/>"></script> <script src="<@s.url '/js/transactions.js'/>"></script> <script src="<@s.url '/js/globalDatePicker.js'/>"></script> <script src="<@s.url '/js/filter.js'/>"></script>