Erweiterungen
This commit is contained in:
@@ -2,21 +2,53 @@ package de.assecutor.votianlt.model;
|
||||
|
||||
import lombok.Data;
|
||||
import org.bson.types.ObjectId;
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.mongodb.core.mapping.Document;
|
||||
import org.springframework.data.mongodb.core.mapping.Field;
|
||||
|
||||
@Data
|
||||
@Document(collection = "customers")
|
||||
public class Customer
|
||||
{
|
||||
@Id
|
||||
private ObjectId id;
|
||||
|
||||
@Field("title")
|
||||
private String title;
|
||||
|
||||
@Field("company_name")
|
||||
private String companyName;
|
||||
|
||||
@Field("firstname")
|
||||
private String firstname;
|
||||
|
||||
@Field("last_name")
|
||||
private String lastName;
|
||||
|
||||
@Field("telephone")
|
||||
private String telephone;
|
||||
|
||||
@Field("fax")
|
||||
private String fax;
|
||||
|
||||
@Field("mail")
|
||||
private String mail;
|
||||
|
||||
@Field("street")
|
||||
private String street;
|
||||
|
||||
@Field("house_number")
|
||||
private String houseNumber;
|
||||
|
||||
@Field("address_addition")
|
||||
private String addressAddition;
|
||||
|
||||
@Field("zip")
|
||||
private String zip;
|
||||
|
||||
@Field("city")
|
||||
private String city;
|
||||
|
||||
@Field("created_by")
|
||||
private ObjectId createdBy;
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package de.assecutor.votianlt.model;
|
||||
|
||||
import lombok.Data;
|
||||
import org.bson.types.ObjectId;
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.mongodb.core.mapping.Document;
|
||||
import org.springframework.data.mongodb.core.index.Indexed;
|
||||
@@ -14,7 +15,7 @@ import java.util.Set;
|
||||
public class User {
|
||||
|
||||
@Id
|
||||
private String id;
|
||||
private ObjectId id;
|
||||
|
||||
private int usrId;
|
||||
private int hqId;
|
||||
|
||||
@@ -1,98 +0,0 @@
|
||||
package de.assecutor.votianlt.pages.add_customer.ui.view;
|
||||
|
||||
import com.vaadin.flow.component.button.Button;
|
||||
import com.vaadin.flow.component.button.ButtonVariant;
|
||||
import com.vaadin.flow.component.html.Main;
|
||||
import com.vaadin.flow.component.orderedlayout.FlexComponent;
|
||||
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
|
||||
import com.vaadin.flow.component.textfield.TextField;
|
||||
import com.vaadin.flow.data.binder.Binder;
|
||||
import com.vaadin.flow.data.binder.ValidationException;
|
||||
import com.vaadin.flow.router.Menu;
|
||||
import com.vaadin.flow.router.PageTitle;
|
||||
import com.vaadin.flow.router.Route;
|
||||
import com.vaadin.flow.theme.lumo.LumoUtility;
|
||||
import de.assecutor.votianlt.model.Customer;
|
||||
import de.assecutor.votianlt.pages.add_customer.service.AddCustomerService;
|
||||
import de.assecutor.votianlt.pages.base.ui.component.ViewToolbar;
|
||||
|
||||
import jakarta.annotation.security.RolesAllowed;
|
||||
import java.time.Clock;
|
||||
|
||||
@Route(value = "add_customer", layout = de.assecutor.votianlt.pages.base.ui.view.MainLayout.class)
|
||||
@PageTitle("Neuen Kunden anlegen")
|
||||
//@Menu(order = 0, icon = "vaadin:clipboard-check", title = "Neuen Kunden anlegen")
|
||||
@RolesAllowed("USER")
|
||||
public class AddCustomerView extends Main {
|
||||
private final AddCustomerService addCustomerService;
|
||||
|
||||
TextField companyName;
|
||||
TextField firstName;
|
||||
TextField lastName;
|
||||
TextField telephone;
|
||||
TextField fax;
|
||||
TextField mail;
|
||||
TextField street;
|
||||
TextField houseNumber;
|
||||
TextField addressAddition;
|
||||
TextField zip;
|
||||
TextField city;
|
||||
final Button submitButton;
|
||||
|
||||
private final Binder<Customer> binder = new Binder<>(Customer.class); // Binder f
|
||||
|
||||
public AddCustomerView(AddCustomerService todoService, Clock clock) {
|
||||
this.addCustomerService = todoService;
|
||||
|
||||
companyName = new TextField("Firmenname");
|
||||
companyName.setRequiredIndicatorVisible(true);
|
||||
binder.forField(companyName)
|
||||
.asRequired("Firmenname ist ein Pflichtfeld") // Pflichtfeldmeldung
|
||||
.bind(Customer::getCompanyName, Customer::setCompanyName);
|
||||
|
||||
firstName = new TextField("Vorname");
|
||||
lastName = new TextField("Nachname");
|
||||
telephone = new TextField("Telefonnummer");
|
||||
fax = new TextField("Faxnummer");
|
||||
mail = new TextField("E-Mail-Adresse");
|
||||
street = new TextField("Straße");
|
||||
houseNumber = new TextField("Hausnummer");
|
||||
addressAddition = new TextField("Adresszusatz");
|
||||
zip = new TextField("Postleitzahl");
|
||||
city = new TextField("Stadt");
|
||||
|
||||
// Setze den Button als primär
|
||||
submitButton = new Button("Kunden anlegen", event -> submit());
|
||||
submitButton.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
|
||||
|
||||
// Erstelle ein Div als Container (oder direkt ein Layout)
|
||||
VerticalLayout formLayout = new VerticalLayout();
|
||||
formLayout.add(companyName, /*firstName, lastName, telephone, fax, mail, street, houseNumber, addressAddition, zip, city,*/ submitButton);
|
||||
|
||||
// Zentriere die Inhalte vertikal und horizontal
|
||||
formLayout.setDefaultHorizontalComponentAlignment(FlexComponent.Alignment.CENTER);
|
||||
formLayout.setSpacing(true);
|
||||
formLayout.setSizeUndefined(); // Inhalt eng setzen
|
||||
|
||||
setSizeFull();
|
||||
addClassNames(LumoUtility.BoxSizing.BORDER, LumoUtility.Display.FLEX, LumoUtility.FlexDirection.COLUMN,
|
||||
LumoUtility.Padding.MEDIUM, LumoUtility.Gap.SMALL);
|
||||
|
||||
add(new ViewToolbar("Neuen Kunden anlegen"));
|
||||
add(formLayout);
|
||||
}
|
||||
|
||||
private void submit() {
|
||||
Customer customer = new Customer();
|
||||
customer.setCompanyName(companyName.getValue());
|
||||
|
||||
try {
|
||||
binder.writeBean(customer);
|
||||
|
||||
addCustomerService.addCustomer(customer);
|
||||
|
||||
} catch (ValidationException e) {
|
||||
System.err.println("Validierungsfehler: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -74,7 +74,7 @@ public final class MainLayout extends AppLayout {
|
||||
|
||||
// Create navigation items for the collapsible list
|
||||
SideNavItem jobs = new SideNavItem("Aufträge", "jobs", new Icon(VaadinIcon.LIST));
|
||||
SideNavItem customers = new SideNavItem("Kunden", "2", new Icon(VaadinIcon.COG));
|
||||
SideNavItem customers = new SideNavItem("Kunden", "customers", new Icon(VaadinIcon.USERS));
|
||||
SideNavItem appUsers = new SideNavItem("App-Nutzer", "3", new Icon(VaadinIcon.COG));
|
||||
SideNavItem devices = new SideNavItem("Endgeräte", "4", new Icon(VaadinIcon.COG));
|
||||
SideNavItem invoices = new SideNavItem("Rechnungen", "5", new Icon(VaadinIcon.COG));
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package de.assecutor.votianlt.pages.add_company.domain;
|
||||
package de.assecutor.votianlt.pages.domain;
|
||||
|
||||
import de.assecutor.votianlt.model.Company;
|
||||
import de.assecutor.votianlt.model.Customer;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Slice;
|
||||
import org.springframework.data.mongodb.repository.MongoRepository;
|
||||
@@ -1,11 +1,12 @@
|
||||
package de.assecutor.votianlt.pages.add_customer.domain;
|
||||
package de.assecutor.votianlt.pages.domain;
|
||||
|
||||
import de.assecutor.votianlt.model.Customer;
|
||||
import org.bson.types.ObjectId;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Slice;
|
||||
import org.springframework.data.mongodb.repository.MongoRepository;
|
||||
|
||||
public interface AddCustomerRepository extends MongoRepository<Customer, String> {
|
||||
public interface AddCustomerRepository extends MongoRepository<Customer, ObjectId> {
|
||||
|
||||
// If you don't need a total row count, Slice is better than Page.
|
||||
Slice<Customer> findAllBy(Pageable pageable);
|
||||
@@ -1,11 +1,12 @@
|
||||
package de.assecutor.votianlt.pages.customers.domain;
|
||||
package de.assecutor.votianlt.pages.domain;
|
||||
|
||||
import de.assecutor.votianlt.model.Customer;
|
||||
import org.bson.types.ObjectId;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Slice;
|
||||
import org.springframework.data.mongodb.repository.MongoRepository;
|
||||
|
||||
public interface CustomerRepository extends MongoRepository<Customer, String> {
|
||||
public interface CustomerRepository extends MongoRepository<Customer, ObjectId> {
|
||||
|
||||
// If you don't need a total row count, Slice is better than Page.
|
||||
Slice<Customer> findAllBy(Pageable pageable);
|
||||
@@ -1,4 +1,4 @@
|
||||
package de.assecutor.votianlt.pages.login.domain;
|
||||
package de.assecutor.votianlt.pages.domain;
|
||||
|
||||
import de.assecutor.votianlt.model.User;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
@@ -1,8 +1,6 @@
|
||||
package de.assecutor.votianlt.pages.register.domain;
|
||||
package de.assecutor.votianlt.pages.domain;
|
||||
|
||||
import jakarta.validation.constraints.Size;
|
||||
import lombok.Data;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import org.springframework.data.mongodb.core.mapping.Document;
|
||||
|
||||
import java.time.Instant;
|
||||
@@ -1,4 +1,4 @@
|
||||
package de.assecutor.votianlt.pages.register.domain;
|
||||
package de.assecutor.votianlt.pages.domain;
|
||||
|
||||
import de.assecutor.votianlt.repository.UserRepository;
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
package de.assecutor.votianlt.pages.add_company.service;
|
||||
package de.assecutor.votianlt.pages.service;
|
||||
|
||||
import de.assecutor.votianlt.model.Company;
|
||||
import de.assecutor.votianlt.model.Customer;
|
||||
import de.assecutor.votianlt.pages.add_company.domain.AddCompanyRepository;
|
||||
import de.assecutor.votianlt.pages.domain.AddCompanyRepository;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Propagation;
|
||||
@@ -1,8 +1,10 @@
|
||||
package de.assecutor.votianlt.pages.add_customer.service;
|
||||
package de.assecutor.votianlt.pages.service;
|
||||
|
||||
import de.assecutor.votianlt.model.Customer;
|
||||
import de.assecutor.votianlt.pages.add_customer.domain.AddCustomerRepository;
|
||||
import de.assecutor.votianlt.pages.domain.AddCustomerRepository;
|
||||
import de.assecutor.votianlt.security.SecurityService;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Propagation;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
@@ -13,9 +15,11 @@ import java.util.List;
|
||||
@Transactional(propagation = Propagation.REQUIRES_NEW)
|
||||
public class AddCustomerService {
|
||||
private final AddCustomerRepository addCustomerRepository;
|
||||
private final SecurityService securityService;
|
||||
|
||||
AddCustomerService(AddCustomerRepository addCustomerRepository) {
|
||||
AddCustomerService(AddCustomerRepository addCustomerRepository, SecurityService securityService) {
|
||||
this.addCustomerRepository = addCustomerRepository;
|
||||
this.securityService = securityService;
|
||||
}
|
||||
|
||||
public List<Customer> list(Pageable pageable) {
|
||||
@@ -23,6 +27,10 @@ public class AddCustomerService {
|
||||
}
|
||||
|
||||
public void addCustomer(Customer customer) {
|
||||
// Setze den aktuellen Benutzer als Ersteller - jetzt direkt aus der Session
|
||||
de.assecutor.votianlt.model.User currentUser = securityService.getCurrentDatabaseUser();
|
||||
customer.setCreatedBy(currentUser.getId());
|
||||
|
||||
addCustomerRepository.save(customer);
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package de.assecutor.votianlt.pages.add_job.service;
|
||||
package de.assecutor.votianlt.pages.service;
|
||||
|
||||
import de.assecutor.votianlt.model.CargoItem;
|
||||
import de.assecutor.votianlt.model.Job;
|
||||
@@ -1,7 +1,7 @@
|
||||
package de.assecutor.votianlt.pages.customers.service;
|
||||
package de.assecutor.votianlt.pages.service;
|
||||
|
||||
import de.assecutor.votianlt.model.Customer;
|
||||
import de.assecutor.votianlt.pages.customers.domain.CustomerRepository;
|
||||
import de.assecutor.votianlt.pages.domain.CustomerRepository;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.stereotype.Service;
|
||||
@@ -37,4 +37,8 @@ public class CustomerService {
|
||||
return todoRepository.findAllBy(pageable).toList();
|
||||
}
|
||||
|
||||
public List<Customer> findAll() {
|
||||
return todoRepository.findAll();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,8 +1,8 @@
|
||||
package de.assecutor.votianlt.pages.login.service;
|
||||
package de.assecutor.votianlt.pages.service;
|
||||
|
||||
import com.vaadin.flow.component.notification.Notification;
|
||||
import de.assecutor.votianlt.model.User;
|
||||
import de.assecutor.votianlt.pages.login.domain.LoginRepository;
|
||||
import de.assecutor.votianlt.pages.domain.LoginRepository;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Propagation;
|
||||
@@ -1,13 +1,11 @@
|
||||
package de.assecutor.votianlt.pages.register.service;
|
||||
package de.assecutor.votianlt.pages.service;
|
||||
|
||||
import de.assecutor.votianlt.model.User;
|
||||
import de.assecutor.votianlt.pages.register.domain.RegisterRepository;
|
||||
import de.assecutor.votianlt.pages.domain.RegisterRepository;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Propagation;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.time.Clock;
|
||||
|
||||
@Service
|
||||
@Transactional(propagation = Propagation.REQUIRES_NEW)
|
||||
public class RegisterService {
|
||||
@@ -1,4 +1,4 @@
|
||||
package de.assecutor.votianlt.pages.register.service;
|
||||
package de.assecutor.votianlt.pages.service;
|
||||
|
||||
import de.assecutor.votianlt.model.User;
|
||||
import de.assecutor.votianlt.repository.UserRepository;
|
||||
@@ -1,4 +1,4 @@
|
||||
package de.assecutor.votianlt.pages.add_company.ui.view;
|
||||
package de.assecutor.votianlt.pages.view;
|
||||
|
||||
import com.vaadin.flow.component.button.Button;
|
||||
import com.vaadin.flow.component.button.ButtonVariant;
|
||||
@@ -8,12 +8,11 @@ import com.vaadin.flow.component.orderedlayout.VerticalLayout;
|
||||
import com.vaadin.flow.component.textfield.TextField;
|
||||
import com.vaadin.flow.data.binder.Binder;
|
||||
import com.vaadin.flow.data.binder.ValidationException;
|
||||
import com.vaadin.flow.router.Menu;
|
||||
import com.vaadin.flow.router.PageTitle;
|
||||
import com.vaadin.flow.router.Route;
|
||||
import com.vaadin.flow.theme.lumo.LumoUtility;
|
||||
import de.assecutor.votianlt.model.Company;
|
||||
import de.assecutor.votianlt.pages.add_company.service.AddCompanyService;
|
||||
import de.assecutor.votianlt.pages.service.AddCompanyService;
|
||||
import de.assecutor.votianlt.pages.base.ui.component.ViewToolbar;
|
||||
|
||||
import jakarta.annotation.security.RolesAllowed;
|
||||
@@ -0,0 +1,240 @@
|
||||
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.combobox.ComboBox;
|
||||
import com.vaadin.flow.component.formlayout.FormLayout;
|
||||
import com.vaadin.flow.component.html.Main;
|
||||
import com.vaadin.flow.component.orderedlayout.FlexComponent;
|
||||
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
|
||||
import com.vaadin.flow.component.textfield.TextField;
|
||||
import com.vaadin.flow.data.binder.Binder;
|
||||
import com.vaadin.flow.data.binder.ValidationException;
|
||||
import com.vaadin.flow.router.PageTitle;
|
||||
import com.vaadin.flow.router.Route;
|
||||
import com.vaadin.flow.theme.lumo.LumoUtility;
|
||||
import de.assecutor.votianlt.model.Customer;
|
||||
import de.assecutor.votianlt.pages.service.AddCustomerService;
|
||||
import de.assecutor.votianlt.pages.base.ui.component.ViewToolbar;
|
||||
|
||||
import jakarta.annotation.security.RolesAllowed;
|
||||
import java.time.Clock;
|
||||
|
||||
@Route(value = "add-customer", layout = de.assecutor.votianlt.pages.base.ui.view.MainLayout.class)
|
||||
@PageTitle("Neuen Kunden anlegen")
|
||||
//@Menu(order = 0, icon = "vaadin:clipboard-check", title = "Neuen Kunden anlegen")
|
||||
@RolesAllowed("USER")
|
||||
public class AddCustomerView extends Main {
|
||||
private final AddCustomerService addCustomerService;
|
||||
|
||||
TextField companyName;
|
||||
ComboBox<String> title;
|
||||
TextField firstName;
|
||||
TextField lastName;
|
||||
TextField telephone;
|
||||
TextField fax;
|
||||
TextField mail;
|
||||
TextField street;
|
||||
TextField houseNumber;
|
||||
TextField addressAddition;
|
||||
TextField zip;
|
||||
TextField city;
|
||||
final Button submitButton;
|
||||
|
||||
private final Binder<Customer> binder = new Binder<>(Customer.class); // Binder f
|
||||
|
||||
public AddCustomerView(AddCustomerService todoService, Clock clock) {
|
||||
this.addCustomerService = todoService;
|
||||
|
||||
// Firma (Pflichtfeld)
|
||||
companyName = new TextField("Firma");
|
||||
companyName.setRequiredIndicatorVisible(true);
|
||||
companyName.setWidthFull();
|
||||
|
||||
// Anrede (Dropdown)
|
||||
title = new ComboBox<>("Anrede");
|
||||
title.setItems("Herr", "Frau", "Divers");
|
||||
title.setPlaceholder("Anrede");
|
||||
title.setWidthFull();
|
||||
|
||||
// Vorname (Pflichtfeld)
|
||||
firstName = new TextField("Vorname");
|
||||
firstName.setRequiredIndicatorVisible(true);
|
||||
firstName.setWidthFull();
|
||||
|
||||
// Nachname (Pflichtfeld)
|
||||
lastName = new TextField("Nachname");
|
||||
lastName.setRequiredIndicatorVisible(true);
|
||||
lastName.setWidthFull();
|
||||
|
||||
// Telefonnummer (Pflichtfeld)
|
||||
telephone = new TextField("Telefonnummer");
|
||||
telephone.setRequiredIndicatorVisible(true);
|
||||
telephone.setWidthFull();
|
||||
|
||||
// Fax (optional)
|
||||
fax = new TextField("Fax");
|
||||
fax.setWidthFull();
|
||||
|
||||
// E-Mail (Pflichtfeld)
|
||||
mail = new TextField("E-Mail-Adresse");
|
||||
mail.setRequiredIndicatorVisible(true);
|
||||
mail.setWidthFull();
|
||||
|
||||
// Straße (Pflichtfeld)
|
||||
street = new TextField("Straße");
|
||||
street.setRequiredIndicatorVisible(true);
|
||||
|
||||
// Hausnummer (Pflichtfeld)
|
||||
houseNumber = new TextField("Hausnr.");
|
||||
houseNumber.setRequiredIndicatorVisible(true);
|
||||
|
||||
// Adresszusatz (optional)
|
||||
addressAddition = new TextField("Adresszusatz");
|
||||
addressAddition.setWidthFull();
|
||||
|
||||
// PLZ (Pflichtfeld)
|
||||
zip = new TextField("Postleitzahl");
|
||||
zip.setRequiredIndicatorVisible(true);
|
||||
|
||||
// Ort (Pflichtfeld)
|
||||
city = new TextField("Ort");
|
||||
city.setRequiredIndicatorVisible(true);
|
||||
|
||||
// Binder-Konfiguration
|
||||
configureBinder();
|
||||
|
||||
// Testdaten setzen
|
||||
setTestData();
|
||||
|
||||
// Setze den Button als primär
|
||||
submitButton = new Button("Kunden anlegen", event -> submit());
|
||||
submitButton.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
|
||||
submitButton.setWidthFull();
|
||||
|
||||
// Erstelle FormLayout wie im Bild
|
||||
FormLayout formLayout = new FormLayout();
|
||||
formLayout.setMaxWidth("600px");
|
||||
formLayout.getStyle().set("margin", "0 auto");
|
||||
|
||||
// Felder hinzufügen (einzeln pro Zeile, außer Straße/Hausnr und PLZ/Ort)
|
||||
formLayout.add(companyName);
|
||||
formLayout.add(title);
|
||||
formLayout.add(firstName);
|
||||
formLayout.add(lastName);
|
||||
formLayout.add(telephone);
|
||||
formLayout.add(fax);
|
||||
formLayout.add(mail);
|
||||
|
||||
// Straße und Hausnummer nebeneinander
|
||||
formLayout.add(street, houseNumber);
|
||||
|
||||
formLayout.add(addressAddition);
|
||||
|
||||
// PLZ und Ort nebeneinander
|
||||
formLayout.add(zip, city);
|
||||
|
||||
formLayout.add(submitButton);
|
||||
|
||||
// Container für zentrierte Darstellung
|
||||
VerticalLayout container = new VerticalLayout();
|
||||
container.setDefaultHorizontalComponentAlignment(FlexComponent.Alignment.CENTER);
|
||||
container.setSpacing(true);
|
||||
container.add(formLayout);
|
||||
|
||||
setSizeFull();
|
||||
addClassNames(LumoUtility.BoxSizing.BORDER, LumoUtility.Display.FLEX, LumoUtility.FlexDirection.COLUMN,
|
||||
LumoUtility.Padding.MEDIUM, LumoUtility.Gap.SMALL);
|
||||
|
||||
add(new ViewToolbar("Neuen Kunden anlegen"));
|
||||
add(container);
|
||||
}
|
||||
|
||||
private void configureBinder() {
|
||||
binder.forField(companyName)
|
||||
.asRequired("Firma ist ein Pflichtfeld")
|
||||
.bind(Customer::getCompanyName, Customer::setCompanyName);
|
||||
|
||||
binder.forField(title)
|
||||
.bind(Customer::getTitle, Customer::setTitle);
|
||||
|
||||
binder.forField(firstName)
|
||||
.asRequired("Vorname ist ein Pflichtfeld")
|
||||
.bind(Customer::getFirstname, Customer::setFirstname);
|
||||
|
||||
binder.forField(lastName)
|
||||
.asRequired("Nachname ist ein Pflichtfeld")
|
||||
.bind(Customer::getLastName, Customer::setLastName);
|
||||
|
||||
binder.forField(telephone)
|
||||
.asRequired("Telefonnummer ist ein Pflichtfeld")
|
||||
.bind(Customer::getTelephone, Customer::setTelephone);
|
||||
|
||||
binder.forField(fax)
|
||||
.bind(Customer::getFax, Customer::setFax);
|
||||
|
||||
binder.forField(mail)
|
||||
.asRequired("E-Mail-Adresse ist ein Pflichtfeld")
|
||||
.withValidator(email -> email.contains("@"), "Bitte geben Sie eine gültige E-Mail-Adresse ein")
|
||||
.bind(Customer::getMail, Customer::setMail);
|
||||
|
||||
binder.forField(street)
|
||||
.asRequired("Straße ist ein Pflichtfeld")
|
||||
.bind(Customer::getStreet, Customer::setStreet);
|
||||
|
||||
binder.forField(houseNumber)
|
||||
.asRequired("Hausnummer ist ein Pflichtfeld")
|
||||
.bind(Customer::getHouseNumber, Customer::setHouseNumber);
|
||||
|
||||
binder.forField(addressAddition)
|
||||
.bind(Customer::getAddressAddition, Customer::setAddressAddition);
|
||||
|
||||
binder.forField(zip)
|
||||
.asRequired("Postleitzahl ist ein Pflichtfeld")
|
||||
.bind(Customer::getZip, Customer::setZip);
|
||||
|
||||
binder.forField(city)
|
||||
.asRequired("Ort ist ein Pflichtfeld")
|
||||
.bind(Customer::getCity, Customer::setCity);
|
||||
}
|
||||
|
||||
|
||||
private void setTestData() {
|
||||
companyName.setValue("Mustermann Transport GmbH");
|
||||
title.setValue("Herr");
|
||||
firstName.setValue("Max");
|
||||
lastName.setValue("Mustermann");
|
||||
telephone.setValue("+49 40 123456789");
|
||||
fax.setValue("+49 40 123456790");
|
||||
mail.setValue("max.mustermann@mustermann-transport.de");
|
||||
street.setValue("Musterstraße");
|
||||
houseNumber.setValue("123");
|
||||
addressAddition.setValue("2. OG");
|
||||
zip.setValue("20095");
|
||||
city.setValue("Hamburg");
|
||||
}
|
||||
private void submit() {
|
||||
try {
|
||||
Customer customer = new Customer();
|
||||
binder.writeBean(customer);
|
||||
|
||||
addCustomerService.addCustomer(customer);
|
||||
|
||||
// Erfolg anzeigen und zur Kundenliste navigieren
|
||||
com.vaadin.flow.component.notification.Notification.show(
|
||||
"Kunde erfolgreich angelegt", 3000,
|
||||
com.vaadin.flow.component.notification.Notification.Position.TOP_CENTER);
|
||||
|
||||
getUI().ifPresent(ui -> ui.navigate("customers"));
|
||||
|
||||
} catch (ValidationException e) {
|
||||
com.vaadin.flow.component.notification.Notification.show(
|
||||
"Bitte überprüfen Sie Ihre Eingaben", 3000,
|
||||
com.vaadin.flow.component.notification.Notification.Position.TOP_CENTER);
|
||||
} catch (Exception e) {
|
||||
com.vaadin.flow.component.notification.Notification.show(
|
||||
"Fehler beim Speichern: " + e.getMessage(), 5000,
|
||||
com.vaadin.flow.component.notification.Notification.Position.TOP_CENTER);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package de.assecutor.votianlt.pages.add_job.ui.view;
|
||||
package de.assecutor.votianlt.pages.view;
|
||||
|
||||
import com.vaadin.flow.component.button.Button;
|
||||
import com.vaadin.flow.component.button.ButtonVariant;
|
||||
@@ -34,7 +34,7 @@ import com.vaadin.flow.router.Route;
|
||||
import com.vaadin.flow.theme.lumo.LumoUtility;
|
||||
import de.assecutor.votianlt.model.Job;
|
||||
import de.assecutor.votianlt.model.TaskEntry;
|
||||
import de.assecutor.votianlt.pages.add_job.service.AddJobService;
|
||||
import de.assecutor.votianlt.pages.service.AddJobService;
|
||||
import de.assecutor.votianlt.pages.base.ui.component.ViewToolbar;
|
||||
|
||||
import jakarta.annotation.security.RolesAllowed;
|
||||
@@ -42,7 +42,6 @@ import lombok.extern.slf4j.Slf4j;
|
||||
import de.assecutor.votianlt.model.CargoItem;
|
||||
import java.util.*;
|
||||
import java.util.Objects;
|
||||
import de.assecutor.votianlt.model.TaskEntry;
|
||||
import java.util.Optional;
|
||||
|
||||
@Route(value = "add_job", layout = de.assecutor.votianlt.pages.base.ui.view.MainLayout.class)
|
||||
@@ -1,4 +1,4 @@
|
||||
package de.assecutor.votianlt.pages.start.ui.view;
|
||||
package de.assecutor.votianlt.pages.view;
|
||||
|
||||
import com.vaadin.flow.component.Component;
|
||||
import com.vaadin.flow.component.html.*;
|
||||
@@ -1,4 +1,4 @@
|
||||
package de.assecutor.votianlt.pages.customers.ui.view;
|
||||
package de.assecutor.votianlt.pages.view;
|
||||
|
||||
import com.vaadin.flow.component.UI;
|
||||
import com.vaadin.flow.component.button.Button;
|
||||
@@ -12,7 +12,7 @@ import com.vaadin.flow.router.Route;
|
||||
import com.vaadin.flow.theme.lumo.LumoUtility;
|
||||
import de.assecutor.votianlt.model.Customer;
|
||||
import de.assecutor.votianlt.pages.base.ui.component.ViewToolbar;
|
||||
import de.assecutor.votianlt.pages.customers.service.CustomerService;
|
||||
import de.assecutor.votianlt.pages.service.CustomerService;
|
||||
|
||||
import java.time.Clock;
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
package de.assecutor.votianlt.pages.login.ui.view;
|
||||
package de.assecutor.votianlt.pages.view;
|
||||
|
||||
import com.vaadin.flow.component.UI;
|
||||
import com.vaadin.flow.component.button.Button;
|
||||
import com.vaadin.flow.component.button.ButtonVariant;
|
||||
import com.vaadin.flow.component.html.Anchor;
|
||||
import com.vaadin.flow.component.html.H1;
|
||||
import com.vaadin.flow.component.html.Main;
|
||||
import com.vaadin.flow.component.login.LoginForm;
|
||||
import com.vaadin.flow.component.orderedlayout.FlexComponent;
|
||||
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
|
||||
@@ -1,4 +1,4 @@
|
||||
package de.assecutor.votianlt.pages.register.ui.view;
|
||||
package de.assecutor.votianlt.pages.view;
|
||||
|
||||
import com.vaadin.flow.component.button.Button;
|
||||
import com.vaadin.flow.component.button.ButtonVariant;
|
||||
@@ -12,8 +12,8 @@ import com.vaadin.flow.component.textfield.TextField;
|
||||
import com.vaadin.flow.router.PageTitle;
|
||||
import com.vaadin.flow.router.Route;
|
||||
import com.vaadin.flow.server.auth.AnonymousAllowed;
|
||||
import de.assecutor.votianlt.pages.register.service.RegisterService;
|
||||
import de.assecutor.votianlt.pages.register.service.UserService;
|
||||
import de.assecutor.votianlt.pages.service.RegisterService;
|
||||
import de.assecutor.votianlt.pages.service.UserService;
|
||||
|
||||
import java.time.Clock;
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
package de.assecutor.votianlt.pages.view;
|
||||
|
||||
import com.vaadin.flow.component.button.Button;
|
||||
import com.vaadin.flow.component.grid.Grid;
|
||||
import com.vaadin.flow.component.html.H2;
|
||||
import com.vaadin.flow.component.icon.Icon;
|
||||
import com.vaadin.flow.component.icon.VaadinIcon;
|
||||
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
|
||||
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
|
||||
import com.vaadin.flow.router.PageTitle;
|
||||
import com.vaadin.flow.router.Route;
|
||||
import de.assecutor.votianlt.model.Customer;
|
||||
import de.assecutor.votianlt.pages.service.CustomerService;
|
||||
import jakarta.annotation.security.RolesAllowed;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
@PageTitle("Kunden")
|
||||
@Route(value = "customers", layout = de.assecutor.votianlt.pages.base.ui.view.MainLayout.class)
|
||||
@RolesAllowed({"USER","ADMIN"})
|
||||
public class ShowCustomersView extends VerticalLayout {
|
||||
|
||||
private final CustomerService customerService;
|
||||
private final Grid<Customer> grid = new Grid<>(Customer.class, false);
|
||||
|
||||
@Autowired
|
||||
public ShowCustomersView(CustomerService customerService) {
|
||||
this.customerService = customerService;
|
||||
setSizeFull();
|
||||
setPadding(true);
|
||||
setSpacing(true);
|
||||
|
||||
// Header with title and add button
|
||||
HorizontalLayout header = new HorizontalLayout();
|
||||
header.setWidthFull();
|
||||
header.add(new H2("Kunden"));
|
||||
Button addCustomerButton = new Button("Kunde hinzufügen", new Icon(VaadinIcon.PLUS));
|
||||
header.add(addCustomerButton);
|
||||
header.setJustifyContentMode(JustifyContentMode.BETWEEN);
|
||||
header.setAlignItems(Alignment.CENTER);
|
||||
add(header);
|
||||
|
||||
// Configure grid columns
|
||||
grid.addColumn(Customer::getCompanyName).setHeader("Firma").setAutoWidth(true).setFlexGrow(1).setSortable(true);
|
||||
grid.addColumn(customer -> (customer.getFirstname() != null ? customer.getFirstname() : "") + " " +
|
||||
(customer.getLastName() != null ? customer.getLastName() : ""))
|
||||
.setHeader("Name").setAutoWidth(true).setFlexGrow(1).setSortable(true);
|
||||
grid.addColumn(Customer::getMail).setHeader("E-Mail").setAutoWidth(true).setFlexGrow(1).setSortable(true);
|
||||
grid.addColumn(Customer::getTelephone).setHeader("Telefon").setAutoWidth(true).setSortable(true);
|
||||
grid.addColumn(customer -> (customer.getStreet() != null ? customer.getStreet() : "") + " " +
|
||||
(customer.getHouseNumber() != null ? customer.getHouseNumber() : ""))
|
||||
.setHeader("Straße").setAutoWidth(true).setFlexGrow(1).setSortable(true);
|
||||
grid.addColumn(customer -> (customer.getZip() != null ? customer.getZip() : "") + " " +
|
||||
(customer.getCity() != null ? customer.getCity() : ""))
|
||||
.setHeader("Ort").setAutoWidth(true).setFlexGrow(1).setSortable(true);
|
||||
|
||||
grid.setMultiSort(true);
|
||||
grid.setSizeFull();
|
||||
add(grid);
|
||||
|
||||
// Button action
|
||||
addCustomerButton.addClickListener(e ->
|
||||
getUI().ifPresent(ui -> ui.navigate("add-customer"))
|
||||
);
|
||||
|
||||
loadData();
|
||||
}
|
||||
|
||||
private void loadData() {
|
||||
var customers = customerService.findAll();
|
||||
grid.setItems(customers);
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package de.assecutor.votianlt.pages.jobs.ui.view;
|
||||
package de.assecutor.votianlt.pages.view;
|
||||
|
||||
import com.vaadin.flow.component.datepicker.DatePicker;
|
||||
import com.vaadin.flow.component.button.Button;
|
||||
@@ -1,4 +1,4 @@
|
||||
package de.assecutor.votianlt.pages.start.ui.view;
|
||||
package de.assecutor.votianlt.pages.view;
|
||||
|
||||
import com.vaadin.flow.component.Component;
|
||||
import com.vaadin.flow.component.UI;
|
||||
@@ -13,12 +13,10 @@ import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
|
||||
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
|
||||
import com.vaadin.flow.router.PageTitle;
|
||||
import com.vaadin.flow.router.Route;
|
||||
import com.vaadin.flow.router.RouterLayout;
|
||||
import com.vaadin.flow.router.BeforeEnterEvent;
|
||||
import com.vaadin.flow.router.BeforeEnterObserver;
|
||||
import com.vaadin.flow.server.auth.AnonymousAllowed;
|
||||
import de.assecutor.votianlt.security.SecurityService;
|
||||
import de.assecutor.votianlt.pages.base.ui.view.MainLayout;
|
||||
|
||||
@Route("")
|
||||
@PageTitle("VotianLT - Willkommen")
|
||||
@@ -1,4 +1,4 @@
|
||||
package de.assecutor.votianlt.pages.verwaltung.ui.view;
|
||||
package de.assecutor.votianlt.pages.view;
|
||||
|
||||
import com.vaadin.flow.component.html.H1;
|
||||
import com.vaadin.flow.component.html.Main;
|
||||
@@ -0,0 +1,73 @@
|
||||
package de.assecutor.votianlt.security;
|
||||
|
||||
import de.assecutor.votianlt.model.User;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Custom UserDetails implementation that holds a reference to the MongoDB User entity.
|
||||
* This allows access to the complete User object from the session without additional database queries.
|
||||
*/
|
||||
public class CustomUserPrincipal implements UserDetails {
|
||||
|
||||
private final User user; // MongoDB User entity
|
||||
|
||||
public CustomUserPrincipal(User user) {
|
||||
this.user = user;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the complete MongoDB User entity
|
||||
*/
|
||||
public User getUser() {
|
||||
return user;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUsername() {
|
||||
return user.getEmail();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPassword() {
|
||||
return user.getPassword();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
return user.getIsActivated() == 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<? extends GrantedAuthority> getAuthorities() {
|
||||
Set<String> roles = user.getRoles();
|
||||
if (roles != null && !roles.isEmpty()) {
|
||||
return roles.stream()
|
||||
.map(role -> new SimpleGrantedAuthority("ROLE_" + role))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
// Default role if no roles are set
|
||||
return Collections.singletonList(new SimpleGrantedAuthority("ROLE_USER"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAccountNonExpired() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAccountNonLocked() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCredentialsNonExpired() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -9,8 +9,6 @@ import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
||||
|
||||
import de.assecutor.votianlt.pages.login.ui.view.LoginView;
|
||||
|
||||
@EnableWebSecurity
|
||||
@Configuration
|
||||
public class SecurityConfig extends VaadinWebSecurity {
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package de.assecutor.votianlt.security;
|
||||
|
||||
import com.vaadin.flow.spring.security.AuthenticationContext;
|
||||
import org.bson.types.ObjectId;
|
||||
import org.springframework.security.core.userdetails.User;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@@ -25,8 +27,44 @@ public class SecurityService {
|
||||
|
||||
public String getCurrentUsername() {
|
||||
return getAuthenticatedUser()
|
||||
.map(UserDetails::getUsername)
|
||||
.orElse("Anonymous");
|
||||
.map(UserDetails::getUsername)
|
||||
.orElse("Anonymous");
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the complete MongoDB User entity from the session
|
||||
*/
|
||||
public de.assecutor.votianlt.model.User getCurrentDatabaseUser() {
|
||||
return getAuthenticatedUser()
|
||||
.filter(userDetails -> userDetails instanceof CustomUserPrincipal)
|
||||
.map(userDetails -> ((CustomUserPrincipal) userDetails).getUser())
|
||||
.orElseThrow(() -> new RuntimeException("No user logged in"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the MongoDB User ID from the session
|
||||
*/
|
||||
public ObjectId getCurrentUserId() {
|
||||
return getCurrentDatabaseUser().getId();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the usrId from the session
|
||||
*/
|
||||
public int getCurrentUsrId() {
|
||||
return getCurrentDatabaseUser().getUsrId();
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use getCurrentDatabaseUser() instead
|
||||
*/
|
||||
@Deprecated
|
||||
public User getCurrentUser() {
|
||||
if (getAuthenticatedUser().isPresent()) {
|
||||
return (User) getAuthenticatedUser().get();
|
||||
} else {
|
||||
throw new RuntimeException("No user logged in");
|
||||
}
|
||||
}
|
||||
|
||||
public void logout() {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package de.assecutor.votianlt.security;
|
||||
|
||||
import de.assecutor.votianlt.model.User;
|
||||
import de.assecutor.votianlt.pages.register.service.UserService;
|
||||
import de.assecutor.votianlt.pages.service.UserService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
@@ -26,19 +26,9 @@ public class UserDetailsServiceImpl implements UserDetailsService {
|
||||
throw new UsernameNotFoundException("User not found with email: " + email);
|
||||
}
|
||||
|
||||
return new org.springframework.security.core.userdetails.User(
|
||||
user.getEmail(),
|
||||
user.getPassword(),
|
||||
user.getIsActivated() == 1, // enabled
|
||||
true, // accountNonExpired
|
||||
true, // credentialsNonExpired
|
||||
true, // accountNonLocked
|
||||
getAuthorities(user)
|
||||
);
|
||||
// Use CustomUserPrincipal to store the complete User entity in the session
|
||||
return new CustomUserPrincipal(user);
|
||||
}
|
||||
|
||||
private Collection<? extends GrantedAuthority> getAuthorities(User user) {
|
||||
// Basis-Rolle für alle Benutzer
|
||||
return Collections.singletonList(new SimpleGrantedAuthority("ROLE_USER"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user