diff --git a/.claude/settings.local.json b/.claude/settings.local.json
index 74b6784..4f31da7 100644
--- a/.claude/settings.local.json
+++ b/.claude/settings.local.json
@@ -7,7 +7,8 @@
"Bash(./mvnw:*)",
"Bash(rm:*)",
"Bash(lsof:*)",
- "Bash(xargs kill:*)"
+ "Bash(xargs kill:*)",
+ "Bash(cat:*)"
],
"deny": [],
"ask": []
diff --git a/pom.xml b/pom.xml
index 6dff52a..9014927 100644
--- a/pom.xml
+++ b/pom.xml
@@ -6,7 +6,7 @@
de.assecutor.votianlt
votianlt
- 1.0-SNAPSHOT
+ 0.5
jar
@@ -217,6 +217,22 @@
3.3.2
+
+
+ src/main/resources
+ true
+
+ application.properties
+
+
+
+ src/main/resources
+ false
+
+ application.properties
+
+
+
diff --git a/src/main/bundles/prod.bundle b/src/main/bundles/prod.bundle
index 4ffda7b..876abda 100644
Binary files a/src/main/bundles/prod.bundle and b/src/main/bundles/prod.bundle differ
diff --git a/src/main/java/de/assecutor/votianlt/pages/view/AddJobView.java b/src/main/java/de/assecutor/votianlt/pages/view/AddJobView.java
index 03d5d3c..f8c5269 100644
--- a/src/main/java/de/assecutor/votianlt/pages/view/AddJobView.java
+++ b/src/main/java/de/assecutor/votianlt/pages/view/AddJobView.java
@@ -360,8 +360,29 @@ public class AddJobView extends Main {
// Date picker fields for appointments
pickupDate = new DatePicker("Datum");
pickupDate.setRequiredIndicatorVisible(true);
+ pickupDate.setLocale(java.util.Locale.GERMANY); // Monday as first day of week
+ pickupDate.setI18n(new DatePicker.DatePickerI18n()
+ .setFirstDayOfWeek(1) // 1 = Monday
+ .setMonthNames(java.util.Arrays.asList(
+ "Januar", "Februar", "März", "April", "Mai", "Juni",
+ "Juli", "August", "September", "Oktober", "November", "Dezember"))
+ .setWeekdays(java.util.Arrays.asList(
+ "Sonntag", "Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag"))
+ .setWeekdaysShort(java.util.Arrays.asList(
+ "So", "Mo", "Di", "Mi", "Do", "Fr", "Sa")));
+
deliveryDate = new DatePicker("Datum");
deliveryDate.setRequiredIndicatorVisible(true);
+ deliveryDate.setLocale(java.util.Locale.GERMANY); // Monday as first day of week
+ deliveryDate.setI18n(new DatePicker.DatePickerI18n()
+ .setFirstDayOfWeek(1) // 1 = Monday
+ .setMonthNames(java.util.Arrays.asList(
+ "Januar", "Februar", "März", "April", "Mai", "Juni",
+ "Juli", "August", "September", "Oktober", "November", "Dezember"))
+ .setWeekdays(java.util.Arrays.asList(
+ "Sonntag", "Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag"))
+ .setWeekdaysShort(java.util.Arrays.asList(
+ "So", "Mo", "Di", "Mi", "Do", "Fr", "Sa")));
// Submit button
submitButton = new Button("Auftrag anlegen", event -> submit());
diff --git a/src/main/java/de/assecutor/votianlt/pages/view/LoginView.java b/src/main/java/de/assecutor/votianlt/pages/view/LoginView.java
index 780ccd2..2f2062c 100644
--- a/src/main/java/de/assecutor/votianlt/pages/view/LoginView.java
+++ b/src/main/java/de/assecutor/votianlt/pages/view/LoginView.java
@@ -5,6 +5,7 @@ import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.button.ButtonVariant;
import com.vaadin.flow.component.html.Div;
import com.vaadin.flow.component.html.H1;
+import com.vaadin.flow.component.html.Span;
import com.vaadin.flow.component.login.LoginForm;
import com.vaadin.flow.component.textfield.TextField;
import com.vaadin.flow.component.notification.Notification;
@@ -26,6 +27,7 @@ import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.context.HttpSessionSecurityContextRepository;
import com.vaadin.flow.server.VaadinSession;
import org.springframework.beans.factory.annotation.Value;
+import jakarta.annotation.PostConstruct;
@Route("login")
@PageTitle("Bei VotianLT anmelden")
@@ -46,7 +48,11 @@ public class LoginView extends VerticalLayout implements BeforeEnterObserver, Af
@Value("${app.security.two-factor.enabled:false}")
private boolean twoFactorEnabled;
+ @Value("${app.version:unknown}")
+ private String appVersion;
+
private Authentication pendingAuth;
+ private Span versionSpan;
public LoginView() {
addClassName("login-view");
@@ -75,6 +81,12 @@ public class LoginView extends VerticalLayout implements BeforeEnterObserver, Af
Button registerButton = new Button("Noch kein Konto? Registrieren", e -> UI.getCurrent().navigate("register"));
registerButton.addThemeVariants(ButtonVariant.LUMO_TERTIARY);
+ // Version display - will be set in @PostConstruct
+ versionSpan = new Span("");
+ versionSpan.getStyle().set("color", "var(--lumo-secondary-text-color)")
+ .set("font-size", "var(--lumo-font-size-s)")
+ .set("margin-top", "var(--lumo-space-m)");
+
// Inline flash message box (hidden by default)
flashBox.getStyle().set("background", "var(--lumo-error-color-10pct)")
.set("color", "var(--lumo-error-text-color)").set("border", "1px solid var(--lumo-error-color)")
@@ -84,7 +96,7 @@ public class LoginView extends VerticalLayout implements BeforeEnterObserver, Af
VerticalLayout loginLayout = new VerticalLayout();
loginLayout.setAlignItems(FlexComponent.Alignment.CENTER);
- loginLayout.add(flashBox, title, loginForm, twoFaField, verify2faButton, registerButton);
+ loginLayout.add(flashBox, title, loginForm, twoFaField, verify2faButton, registerButton, versionSpan);
loginLayout.setMaxWidth("400px");
loginLayout.setPadding(true);
@@ -93,6 +105,12 @@ public class LoginView extends VerticalLayout implements BeforeEnterObserver, Af
loginForm.addLoginListener(e -> handlePasswordLogin(e.getUsername(), e.getPassword()));
}
+ @PostConstruct
+ private void init() {
+ // Set version after Spring injection
+ versionSpan.setText("Version " + appVersion);
+ }
+
private void handlePasswordLogin(String username, String password) {
try {
// Prüfe Benutzername/Passwort
diff --git a/src/main/java/de/assecutor/votianlt/service/CustomerInvoiceService.java b/src/main/java/de/assecutor/votianlt/service/CustomerInvoiceService.java
index 156e15d..4750f0f 100644
--- a/src/main/java/de/assecutor/votianlt/service/CustomerInvoiceService.java
+++ b/src/main/java/de/assecutor/votianlt/service/CustomerInvoiceService.java
@@ -148,9 +148,14 @@ public class CustomerInvoiceService {
}
private String readCustomerInvoiceHtmlTemplate() throws Exception {
- // Read the HTML template file
- java.nio.file.Path path = java.nio.file.Paths.get("src/main/resources/templates/customer_invoice.html");
- return java.nio.file.Files.readString(path);
+ // Read the HTML template file from classpath (works in Docker/production)
+ try (java.io.InputStream inputStream = getClass().getClassLoader()
+ .getResourceAsStream("templates/customer_invoice.html")) {
+ if (inputStream == null) {
+ throw new java.io.IOException("Template file not found: templates/customer_invoice.html");
+ }
+ return new String(inputStream.readAllBytes(), java.nio.charset.StandardCharsets.UTF_8);
+ }
}
private String fillCustomerInvoiceHtmlWithInvoiceData(String html, CustomerInvoiceData data) {
diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties
index b022eb6..aa699a7 100644
--- a/src/main/resources/application.properties
+++ b/src/main/resources/application.properties
@@ -59,4 +59,7 @@ app.mqtt.default-qos=2
app.mqtt.default-retained=false
# 2FA Configuration
-app.security.two-factor.enabled=false
\ No newline at end of file
+app.security.two-factor.enabled=false
+
+# Application Version - automatically set from pom.xml during build
+app.version=@project.version@
\ No newline at end of file