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