Erweiterungen
This commit is contained in:
5
pom.xml
5
pom.xml
@@ -87,6 +87,11 @@
|
||||
<artifactId>openpdf</artifactId>
|
||||
<version>1.3.30</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.sun.mail</groupId>
|
||||
<artifactId>jakarta.mail</artifactId>
|
||||
<version>2.0.1</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
|
||||
@@ -40,6 +40,9 @@ public class AppUser {
|
||||
@Field("app_device_id")
|
||||
private ObjectId appDeviceId;
|
||||
|
||||
@Field("owner")
|
||||
private ObjectId owner;
|
||||
|
||||
@Field("erstellt_am")
|
||||
private LocalDateTime erstelltAm;
|
||||
|
||||
|
||||
@@ -98,9 +98,9 @@ public final class MainLayout extends AppLayout {
|
||||
userContent.setSpacing(true);
|
||||
|
||||
// Create navigation items for the collapsible list
|
||||
SideNavItem profile = new SideNavItem("Mein Profil", "7", new Icon(VaadinIcon.COG));
|
||||
SideNavItem profile = new SideNavItem("Mein Profil", "edit-profile", new Icon(VaadinIcon.USER));
|
||||
SideNavItem myInvoices = new SideNavItem("Meine Rechnungen", "8", new Icon(VaadinIcon.COG));
|
||||
SideNavItem imprint = new SideNavItem("Impressum", "9", new Icon(VaadinIcon.COG));
|
||||
SideNavItem imprint = new SideNavItem("Impressum", "impressum", new Icon(VaadinIcon.INFO_CIRCLE));
|
||||
|
||||
userContent.add(profile, myInvoices, imprint);
|
||||
userDetails.add(userContent);
|
||||
|
||||
@@ -32,6 +32,7 @@ public class AppUserService {
|
||||
ObjectId currentUserId = securityService.getCurrentUserId();
|
||||
appUser.setErstelltVon(currentUserId);
|
||||
appUser.setAktualisiertVon(currentUserId);
|
||||
appUser.setOwner(currentUserId);
|
||||
|
||||
return appUserRepository.save(appUser);
|
||||
}
|
||||
|
||||
@@ -13,10 +13,7 @@ import com.vaadin.flow.router.PageTitle;
|
||||
import com.vaadin.flow.router.Route;
|
||||
import de.assecutor.votianlt.model.AppUser;
|
||||
import de.assecutor.votianlt.pages.service.AppUserService;
|
||||
import de.assecutor.votianlt.model.AppDevice;
|
||||
import de.assecutor.votianlt.pages.service.AppDeviceService;
|
||||
import jakarta.annotation.security.RolesAllowed;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
@PageTitle("App-Nutzer")
|
||||
@Route(value = "app-user", layout = de.assecutor.votianlt.pages.base.ui.view.MainLayout.class)
|
||||
@@ -25,12 +22,9 @@ public class AppUserView extends VerticalLayout {
|
||||
|
||||
private final AppUserService appUserService;
|
||||
private final Grid<AppUser> appUserGrid;
|
||||
private final AppDeviceService appDeviceService;
|
||||
|
||||
@Autowired
|
||||
public AppUserView(AppUserService appUserService, AppDeviceService appDeviceService) {
|
||||
public AppUserView(AppUserService appUserService) {
|
||||
this.appUserService = appUserService;
|
||||
this.appDeviceService = appDeviceService;
|
||||
|
||||
setSizeFull();
|
||||
setPadding(true);
|
||||
@@ -63,13 +57,7 @@ public class AppUserView extends VerticalLayout {
|
||||
appUserGrid.addColumn(AppUser::getTelefon).setHeader("Telefon").setAutoWidth(true);
|
||||
appUserGrid.addColumn(AppUser::getAppCode).setHeader("App-Code").setAutoWidth(true);
|
||||
appUserGrid.addColumn(AppUser::getEmail).setHeader("E-Mail").setAutoWidth(true);
|
||||
appUserGrid.addColumn(appUser -> {
|
||||
if (appUser.getAppDeviceId() != null) {
|
||||
AppDevice device = appDeviceService.findById(appUser.getAppDeviceId());
|
||||
return device != null ? device.getName() : "Unbekannt";
|
||||
}
|
||||
return "Nicht zugeordnet";
|
||||
}).setHeader("Gerät").setAutoWidth(true);
|
||||
appUserGrid.addColumn(AppUser::getGeraet).setHeader("Gerät").setAutoWidth(true);
|
||||
|
||||
// Make grid rows clickable
|
||||
appUserGrid.setSelectionMode(Grid.SelectionMode.SINGLE);
|
||||
|
||||
@@ -0,0 +1,170 @@
|
||||
package de.assecutor.votianlt.pages.view;
|
||||
|
||||
import com.vaadin.flow.component.button.Button;
|
||||
import com.vaadin.flow.component.button.ButtonVariant;
|
||||
import com.vaadin.flow.component.checkbox.Checkbox;
|
||||
import com.vaadin.flow.component.formlayout.FormLayout;
|
||||
import com.vaadin.flow.component.html.Div;
|
||||
import com.vaadin.flow.component.html.H2;
|
||||
import com.vaadin.flow.component.html.Label;
|
||||
import com.vaadin.flow.component.html.Paragraph;
|
||||
import com.vaadin.flow.component.icon.Icon;
|
||||
import com.vaadin.flow.component.icon.VaadinIcon;
|
||||
import com.vaadin.flow.component.notification.Notification;
|
||||
import com.vaadin.flow.component.orderedlayout.FlexComponent;
|
||||
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
|
||||
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
|
||||
import com.vaadin.flow.component.textfield.EmailField;
|
||||
import com.vaadin.flow.component.textfield.TextField;
|
||||
import com.vaadin.flow.component.textfield.NumberField;
|
||||
import com.vaadin.flow.router.PageTitle;
|
||||
import com.vaadin.flow.router.Route;
|
||||
import jakarta.annotation.security.RolesAllowed;
|
||||
|
||||
@PageTitle("Profil bearbeiten")
|
||||
@Route(value = "edit-profile", layout = de.assecutor.votianlt.pages.base.ui.view.MainLayout.class)
|
||||
@RolesAllowed({"USER","ADMIN"})
|
||||
public class EditProfileView extends HorizontalLayout {
|
||||
public EditProfileView() {
|
||||
setSizeFull();
|
||||
setPadding(true);
|
||||
setSpacing(true);
|
||||
setJustifyContentMode(JustifyContentMode.CENTER);
|
||||
setAlignItems(Alignment.START);
|
||||
|
||||
// Linke Spalte: Formular
|
||||
VerticalLayout formColumn = new VerticalLayout();
|
||||
formColumn.setWidth("500px");
|
||||
formColumn.setPadding(false);
|
||||
formColumn.setSpacing(false);
|
||||
|
||||
FormLayout form = new FormLayout();
|
||||
form.setWidthFull();
|
||||
form.setResponsiveSteps(new FormLayout.ResponsiveStep("0", 2));
|
||||
|
||||
// Firmenfelder
|
||||
TextField companyField = new TextField("Firma*");
|
||||
TextField companyAddField = new TextField("Firmenzusatz");
|
||||
TextField firstnameField = new TextField("Vorname*");
|
||||
TextField lastnameField = new TextField("Nachname*");
|
||||
TextField phoneField = new TextField("Telefonnummer*");
|
||||
TextField faxField = new TextField("Telefon (Fax)");
|
||||
TextField mobileField = new TextField("Telefon (Mobil)");
|
||||
EmailField emailField = new EmailField("E-Mail-Adresse (Login)*");
|
||||
TextField streetField = new TextField("Straße*");
|
||||
TextField houseNumberField = new TextField("Hausnr*");
|
||||
TextField addressAddField = new TextField("Adresszusatz");
|
||||
TextField zipField = new TextField("Postleitzahl*");
|
||||
TextField cityField = new TextField("Stadt*");
|
||||
|
||||
// Pflichtfeldhinweis
|
||||
Paragraph pflichtHinweis = new Paragraph("Die mit (*) gekennzeichneten Felder sind Pflichtfelder.");
|
||||
pflichtHinweis.getStyle().set("color", "#d32f2f").set("fontWeight", "bold");
|
||||
|
||||
// Abweichende Rechnungsadresse
|
||||
Checkbox diffInvoiceAddress = new Checkbox("Abweichende Rechnungsadresse");
|
||||
diffInvoiceAddress.getStyle().set("marginTop", "1em");
|
||||
// Rechnungsadresse Felder (disabled by default)
|
||||
TextField invCompanyField = new TextField("Firma*");
|
||||
TextField invCompanyAddField = new TextField("Firmenzusatz");
|
||||
TextField invFirstnameField = new TextField("Vorname*");
|
||||
TextField invLastnameField = new TextField("Nachname*");
|
||||
TextField invStreetField = new TextField("Straße*");
|
||||
TextField invHouseNumberField = new TextField("Hausnr*");
|
||||
TextField invAddressAddField = new TextField("Adresszusatz");
|
||||
TextField invZipField = new TextField("Postleitzahl*");
|
||||
TextField invCityField = new TextField("Stadt*");
|
||||
invCompanyField.setEnabled(false);
|
||||
invCompanyAddField.setEnabled(false);
|
||||
invFirstnameField.setEnabled(false);
|
||||
invLastnameField.setEnabled(false);
|
||||
invStreetField.setEnabled(false);
|
||||
invHouseNumberField.setEnabled(false);
|
||||
invAddressAddField.setEnabled(false);
|
||||
invZipField.setEnabled(false);
|
||||
invCityField.setEnabled(false);
|
||||
diffInvoiceAddress.addValueChangeListener(e -> {
|
||||
boolean enabled = e.getValue();
|
||||
invCompanyField.setEnabled(enabled);
|
||||
invCompanyAddField.setEnabled(enabled);
|
||||
invFirstnameField.setEnabled(enabled);
|
||||
invLastnameField.setEnabled(enabled);
|
||||
invStreetField.setEnabled(enabled);
|
||||
invHouseNumberField.setEnabled(enabled);
|
||||
invAddressAddField.setEnabled(enabled);
|
||||
invZipField.setEnabled(enabled);
|
||||
invCityField.setEnabled(enabled);
|
||||
});
|
||||
|
||||
// Formularfelder hinzufügen
|
||||
form.add(companyField, 2);
|
||||
form.add(companyAddField, 2);
|
||||
form.add(firstnameField, lastnameField);
|
||||
form.add(phoneField, faxField);
|
||||
form.add(mobileField, 2);
|
||||
form.add(emailField, 2);
|
||||
form.add(streetField, houseNumberField);
|
||||
form.add(addressAddField, 2);
|
||||
form.add(zipField, cityField);
|
||||
form.add(diffInvoiceAddress, 2);
|
||||
form.add(invCompanyField, 2);
|
||||
form.add(invCompanyAddField, 2);
|
||||
form.add(invFirstnameField, invLastnameField);
|
||||
form.add(invStreetField, invHouseNumberField);
|
||||
form.add(invAddressAddField, 2);
|
||||
form.add(invZipField, invCityField);
|
||||
|
||||
formColumn.add(form, pflichtHinweis);
|
||||
|
||||
// Schalter
|
||||
Checkbox locateAppUser = new Checkbox("App-Nutzer orten");
|
||||
Checkbox digitalProcess = new Checkbox("Digitale Abwicklung");
|
||||
Checkbox invoiceViaVotianlt = new Checkbox("Rechnungslegung über votianlt");
|
||||
formColumn.add(locateAppUser, digitalProcess, invoiceViaVotianlt);
|
||||
|
||||
// Rechte Spalte: Karte und Aktionen
|
||||
VerticalLayout rightColumn = new VerticalLayout();
|
||||
rightColumn.setWidth("100%");
|
||||
rightColumn.setAlignItems(Alignment.CENTER);
|
||||
rightColumn.setSpacing(true);
|
||||
rightColumn.setPadding(false);
|
||||
|
||||
// Koordinatenanzeige
|
||||
Label coordsLabel = new Label("53°36'25.1\"N 10°06'46.9\"E");
|
||||
coordsLabel.getStyle().set("fontWeight", "bold").set("marginTop", "1em");
|
||||
rightColumn.add(coordsLabel);
|
||||
|
||||
// Google Maps Platzhalter (iFrame)
|
||||
Div mapDiv = new Div();
|
||||
mapDiv.setWidth("400px");
|
||||
mapDiv.setHeight("400px");
|
||||
mapDiv.getElement().setProperty("innerHTML",
|
||||
"<iframe width='100%' height='100%' frameborder='0' style='border:0' " +
|
||||
"src='https://www.google.com/maps/embed/v1/place?key=AIzaSyDnbitL06iLp3elmj-WtPudCykX9xvXcVE&q=53.6070,10.1125' allowfullscreen></iframe>");
|
||||
rightColumn.add(mapDiv);
|
||||
|
||||
// 2-Faktor Auth
|
||||
Checkbox twoFactor = new Checkbox("2-Faktor-Authentifizierung");
|
||||
Icon twoFactorInfo = VaadinIcon.QUESTION_CIRCLE_O.create();
|
||||
twoFactorInfo.getStyle().set("marginLeft", "0.3em");
|
||||
HorizontalLayout twoFactorLayout = new HorizontalLayout(twoFactor, twoFactorInfo);
|
||||
twoFactorLayout.setAlignItems(Alignment.CENTER);
|
||||
rightColumn.add(twoFactorLayout);
|
||||
|
||||
// Passwort ändern Button
|
||||
Button changePassword = new Button("Passwort ändern");
|
||||
changePassword.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
|
||||
rightColumn.add(changePassword);
|
||||
|
||||
// Benutzerkonto löschen Button
|
||||
Button deleteAccount = new Button("Benutzerkonto löschen");
|
||||
deleteAccount.addThemeVariants(ButtonVariant.LUMO_ERROR);
|
||||
rightColumn.add(deleteAccount);
|
||||
|
||||
// Profil speichern Button (unten rechts)
|
||||
Button saveProfile = new Button("Profiländerungen speichern");
|
||||
saveProfile.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
|
||||
saveProfile.getStyle().set("position", "absolute").set("right", "2em").set("bottom", "2em");
|
||||
add(formColumn, rightColumn, saveProfile);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package de.assecutor.votianlt.pages.view;
|
||||
|
||||
import com.vaadin.flow.component.html.H2;
|
||||
import com.vaadin.flow.component.html.Paragraph;
|
||||
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
|
||||
import com.vaadin.flow.router.PageTitle;
|
||||
import com.vaadin.flow.router.Route;
|
||||
import jakarta.annotation.security.PermitAll;
|
||||
|
||||
@PageTitle("Impressum")
|
||||
@Route(value = "impressum", layout = de.assecutor.votianlt.pages.base.ui.view.MainLayout.class)
|
||||
@PermitAll
|
||||
public class ImprintView extends VerticalLayout {
|
||||
public ImprintView() {
|
||||
setSizeFull();
|
||||
setPadding(true);
|
||||
setSpacing(true);
|
||||
setAlignItems(Alignment.CENTER);
|
||||
|
||||
H2 title = new H2("Impressum");
|
||||
add(title);
|
||||
|
||||
Paragraph p1 = new Paragraph("Max Mustermann\nMusterstraße 1\n12345 Musterstadt\nDeutschland");
|
||||
Paragraph p2 = new Paragraph("Telefon: +49 123 456789\nE-Mail: info@example.com");
|
||||
Paragraph p3 = new Paragraph("Umsatzsteuer-ID: DE123456789\nHandelsregister: Amtsgericht Musterstadt, HRB 12345");
|
||||
Paragraph p4 = new Paragraph("Verantwortlich für den Inhalt nach § 55 Abs. 2 RStV: Max Mustermann");
|
||||
|
||||
add(p1, p2, p3, p4);
|
||||
}
|
||||
}
|
||||
41
src/main/java/de/assecutor/votianlt/util/MailUtil.java
Normal file
41
src/main/java/de/assecutor/votianlt/util/MailUtil.java
Normal file
@@ -0,0 +1,41 @@
|
||||
package de.assecutor.votianlt.util;
|
||||
|
||||
import jakarta.mail.Message;
|
||||
import jakarta.mail.MessagingException;
|
||||
import jakarta.mail.PasswordAuthentication;
|
||||
import jakarta.mail.Session;
|
||||
import jakarta.mail.Transport;
|
||||
import jakarta.mail.internet.InternetAddress;
|
||||
import jakarta.mail.internet.MimeMessage;
|
||||
import java.util.Properties;
|
||||
|
||||
public class MailUtil {
|
||||
public static void sendMail(String to, String subject, String body) throws MessagingException {
|
||||
// SMTP-Konfiguration (hier Beispiel für Gmail, anpassen für Produktivsystem!)
|
||||
final String username = "your-email@gmail.com"; // TODO: ersetzen
|
||||
final String password = "your-password"; // TODO: ersetzen
|
||||
final String host = "smtp.gmail.com";
|
||||
final int port = 587;
|
||||
|
||||
Properties props = new Properties();
|
||||
props.put("mail.smtp.auth", "true");
|
||||
props.put("mail.smtp.starttls.enable", "true");
|
||||
props.put("mail.smtp.host", host);
|
||||
props.put("mail.smtp.port", String.valueOf(port));
|
||||
|
||||
Session session = Session.getInstance(props, new jakarta.mail.Authenticator() {
|
||||
@Override
|
||||
protected PasswordAuthentication getPasswordAuthentication() {
|
||||
return new PasswordAuthentication(username, password);
|
||||
}
|
||||
});
|
||||
|
||||
Message message = new MimeMessage(session);
|
||||
message.setFrom(new InternetAddress(username));
|
||||
message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(to));
|
||||
message.setSubject(subject);
|
||||
message.setText(body);
|
||||
|
||||
Transport.send(message);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user