Erweiterungen
This commit is contained in:
56
src/main/java/de/assecutor/votianlt/model/AppUser.java
Normal file
56
src/main/java/de/assecutor/votianlt/model/AppUser.java
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
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;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@Document(collection = "app_user")
|
||||||
|
public class AppUser {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
private ObjectId id;
|
||||||
|
|
||||||
|
@Field("bezeichnung")
|
||||||
|
private String bezeichnung;
|
||||||
|
|
||||||
|
@Field("vorname")
|
||||||
|
private String vorname;
|
||||||
|
|
||||||
|
@Field("nachname")
|
||||||
|
private String nachname;
|
||||||
|
|
||||||
|
@Field("telefon")
|
||||||
|
private String telefon;
|
||||||
|
|
||||||
|
@Field("app_code")
|
||||||
|
private String appCode;
|
||||||
|
|
||||||
|
@Field("email")
|
||||||
|
@org.springframework.data.mongodb.core.index.Indexed(unique = true)
|
||||||
|
private String email;
|
||||||
|
|
||||||
|
@Field("geraet")
|
||||||
|
private String geraet;
|
||||||
|
|
||||||
|
@Field("erstellt_am")
|
||||||
|
private LocalDateTime erstelltAm;
|
||||||
|
|
||||||
|
@Field("erstellt_von")
|
||||||
|
private ObjectId erstelltVon;
|
||||||
|
|
||||||
|
@Field("aktualisiert_am")
|
||||||
|
private LocalDateTime aktualisiertAm;
|
||||||
|
|
||||||
|
@Field("aktualisiert_von")
|
||||||
|
private ObjectId aktualisiertVon;
|
||||||
|
|
||||||
|
public AppUser() {
|
||||||
|
this.erstelltAm = LocalDateTime.now();
|
||||||
|
this.aktualisiertAm = LocalDateTime.now();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -80,7 +80,7 @@ public final class MainLayout extends AppLayout {
|
|||||||
// Create navigation items for the collapsible list
|
// Create navigation items for the collapsible list
|
||||||
SideNavItem jobs = new SideNavItem("Aufträge", "jobs", new Icon(VaadinIcon.LIST));
|
SideNavItem jobs = new SideNavItem("Aufträge", "jobs", new Icon(VaadinIcon.LIST));
|
||||||
SideNavItem customers = new SideNavItem("Kunden", "customers", new Icon(VaadinIcon.USERS));
|
SideNavItem customers = new SideNavItem("Kunden", "customers", new Icon(VaadinIcon.USERS));
|
||||||
SideNavItem appUsers = new SideNavItem("App-Nutzer", "3", new Icon(VaadinIcon.COG));
|
SideNavItem appUsers = new SideNavItem("App-Nutzer", "app-user", new Icon(VaadinIcon.USERS));
|
||||||
SideNavItem devices = new SideNavItem("Endgeräte", "4", 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));
|
SideNavItem invoices = new SideNavItem("Rechnungen", "5", new Icon(VaadinIcon.COG));
|
||||||
SideNavItem statistics = new SideNavItem("Statistik", "6", new Icon(VaadinIcon.COG));
|
SideNavItem statistics = new SideNavItem("Statistik", "6", new Icon(VaadinIcon.COG));
|
||||||
|
|||||||
@@ -1,12 +1,9 @@
|
|||||||
package de.assecutor.votianlt.pages.domain;
|
package de.assecutor.votianlt.pages.domain;
|
||||||
|
|
||||||
import de.assecutor.votianlt.model.Company;
|
import de.assecutor.votianlt.model.Company;
|
||||||
import org.springframework.data.domain.Pageable;
|
|
||||||
import org.springframework.data.domain.Slice;
|
|
||||||
import org.springframework.data.mongodb.repository.MongoRepository;
|
import org.springframework.data.mongodb.repository.MongoRepository;
|
||||||
|
|
||||||
public interface AddCompanyRepository extends MongoRepository<Company, String> {
|
public interface AddCompanyRepository extends MongoRepository<Company, String> {
|
||||||
|
|
||||||
// If you don't need a total row count, Slice is better than Page.
|
|
||||||
Slice<Company> findAllBy(Pageable pageable);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,12 +2,9 @@ package de.assecutor.votianlt.pages.domain;
|
|||||||
|
|
||||||
import de.assecutor.votianlt.model.Customer;
|
import de.assecutor.votianlt.model.Customer;
|
||||||
import org.bson.types.ObjectId;
|
import org.bson.types.ObjectId;
|
||||||
import org.springframework.data.domain.Pageable;
|
|
||||||
import org.springframework.data.domain.Slice;
|
|
||||||
import org.springframework.data.mongodb.repository.MongoRepository;
|
import org.springframework.data.mongodb.repository.MongoRepository;
|
||||||
|
|
||||||
public interface AddCustomerRepository extends MongoRepository<Customer, ObjectId> {
|
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,16 +1,13 @@
|
|||||||
package de.assecutor.votianlt.pages.domain;
|
package de.assecutor.votianlt.pages.domain;
|
||||||
|
|
||||||
import de.assecutor.votianlt.model.User;
|
import de.assecutor.votianlt.model.User;
|
||||||
import org.springframework.data.domain.Pageable;
|
|
||||||
import org.springframework.data.domain.Slice;
|
|
||||||
import org.springframework.data.mongodb.repository.MongoRepository;
|
import org.springframework.data.mongodb.repository.MongoRepository;
|
||||||
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
public interface LoginRepository extends MongoRepository<User, String> {
|
public interface LoginRepository extends MongoRepository<User, String> {
|
||||||
|
|
||||||
// If you don't need a total row count, Slice is better than Page.
|
|
||||||
Slice<User> findAllBy(Pageable pageable);
|
|
||||||
|
|
||||||
Optional<User> findByEmail(String email);
|
Optional<User> findByEmail(String email);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,13 +2,10 @@ package de.assecutor.votianlt.pages.service;
|
|||||||
|
|
||||||
import de.assecutor.votianlt.model.Company;
|
import de.assecutor.votianlt.model.Company;
|
||||||
import de.assecutor.votianlt.pages.domain.AddCompanyRepository;
|
import de.assecutor.votianlt.pages.domain.AddCompanyRepository;
|
||||||
import org.springframework.data.domain.Pageable;
|
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Propagation;
|
import org.springframework.transaction.annotation.Propagation;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
@Transactional(propagation = Propagation.REQUIRES_NEW)
|
@Transactional(propagation = Propagation.REQUIRES_NEW)
|
||||||
public class AddCompanyService {
|
public class AddCompanyService {
|
||||||
@@ -18,9 +15,7 @@ public class AddCompanyService {
|
|||||||
this.addCompanyRepository = addCompanyRepository;
|
this.addCompanyRepository = addCompanyRepository;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Company> list(Pageable pageable) {
|
|
||||||
return addCompanyRepository.findAllBy(pageable).toList();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addCompany(Company company) {
|
public void addCompany(Company company) {
|
||||||
addCompanyRepository.save(company);
|
addCompanyRepository.save(company);
|
||||||
|
|||||||
@@ -3,14 +3,10 @@ package de.assecutor.votianlt.pages.service;
|
|||||||
import de.assecutor.votianlt.model.Customer;
|
import de.assecutor.votianlt.model.Customer;
|
||||||
import de.assecutor.votianlt.pages.domain.AddCustomerRepository;
|
import de.assecutor.votianlt.pages.domain.AddCustomerRepository;
|
||||||
import de.assecutor.votianlt.security.SecurityService;
|
import de.assecutor.votianlt.security.SecurityService;
|
||||||
import org.springframework.data.domain.Pageable;
|
|
||||||
|
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Propagation;
|
import org.springframework.transaction.annotation.Propagation;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
@Transactional(propagation = Propagation.REQUIRES_NEW)
|
@Transactional(propagation = Propagation.REQUIRES_NEW)
|
||||||
public class AddCustomerService {
|
public class AddCustomerService {
|
||||||
@@ -22,9 +18,7 @@ public class AddCustomerService {
|
|||||||
this.securityService = securityService;
|
this.securityService = securityService;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Customer> list(Pageable pageable) {
|
|
||||||
return addCustomerRepository.findAllBy(pageable).toList();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addCustomer(Customer customer) {
|
public void addCustomer(Customer customer) {
|
||||||
// Setze den aktuellen Benutzer als Ersteller - jetzt direkt aus der Session
|
// Setze den aktuellen Benutzer als Ersteller - jetzt direkt aus der Session
|
||||||
|
|||||||
@@ -112,51 +112,7 @@ public class AddJobService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Findet einen Auftrag anhand der ID
|
|
||||||
*/
|
|
||||||
public Optional<Job> findById(String id) {
|
|
||||||
try {
|
|
||||||
return jobRepository.findById(new org.bson.types.ObjectId(id));
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("Fehler beim Suchen des Auftrags mit ID {}: {}", id, e.getMessage());
|
|
||||||
return Optional.empty();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Findet einen Auftrag anhand der Auftragsnummer
|
|
||||||
*/
|
|
||||||
public Optional<Job> findByJobNumber(String jobNumber) {
|
|
||||||
return jobRepository.findByJobNumber(jobNumber);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Findet alle Aufträge eines Benutzers
|
|
||||||
*/
|
|
||||||
public List<Job> findJobsByUser(String username) {
|
|
||||||
return jobRepository.findByCreatedBy(username);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Findet alle Aufträge mit einem bestimmten Status
|
|
||||||
*/
|
|
||||||
public List<Job> findJobsByStatus(JobStatus status) {
|
|
||||||
return jobRepository.findByStatus(status);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Löscht einen Auftrag
|
|
||||||
*/
|
|
||||||
public void deleteJob(String id) {
|
|
||||||
try {
|
|
||||||
jobRepository.deleteById(new org.bson.types.ObjectId(id));
|
|
||||||
log.info("Auftrag mit ID {} erfolgreich gelöscht", id);
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("Fehler beim Löschen des Auftrags mit ID {}: {}", id, e.getMessage());
|
|
||||||
throw new RuntimeException("Auftrag konnte nicht gelöscht werden: " + e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generiert eine eindeutige Auftragsnummer
|
* Generiert eine eindeutige Auftragsnummer
|
||||||
@@ -181,19 +137,7 @@ public class AddJobService {
|
|||||||
return jobNumber;
|
return jobNumber;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Zählt alle Aufträge
|
|
||||||
*/
|
|
||||||
public long countAllJobs() {
|
|
||||||
return jobRepository.count();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Zählt Aufträge nach Status
|
|
||||||
*/
|
|
||||||
public long countJobsByStatus(JobStatus status) {
|
|
||||||
return jobRepository.countByStatus(status);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Speichert einen Auftrag als Entwurf (für automatisches Speichern)
|
* Speichert einen Auftrag als Entwurf (für automatisches Speichern)
|
||||||
|
|||||||
@@ -0,0 +1,40 @@
|
|||||||
|
package de.assecutor.votianlt.pages.service;
|
||||||
|
|
||||||
|
import de.assecutor.votianlt.model.AppUser;
|
||||||
|
import de.assecutor.votianlt.repository.AppUserRepository;
|
||||||
|
import de.assecutor.votianlt.security.SecurityService;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@Transactional
|
||||||
|
public class AppUserService {
|
||||||
|
|
||||||
|
private final AppUserRepository appUserRepository;
|
||||||
|
private final SecurityService securityService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
public AppUserService(AppUserRepository appUserRepository, SecurityService securityService) {
|
||||||
|
this.appUserRepository = appUserRepository;
|
||||||
|
this.securityService = securityService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AppUser createAppUser(AppUser appUser) {
|
||||||
|
// Set creation and update metadata
|
||||||
|
appUser.setErstelltAm(java.time.LocalDateTime.now());
|
||||||
|
appUser.setAktualisiertAm(java.time.LocalDateTime.now());
|
||||||
|
|
||||||
|
// Set creator and updater if user is logged in
|
||||||
|
try {
|
||||||
|
appUser.setErstelltVon(securityService.getCurrentUserId());
|
||||||
|
appUser.setAktualisiertVon(securityService.getCurrentUserId());
|
||||||
|
} catch (Exception e) {
|
||||||
|
// User might not be logged in, continue without user ID
|
||||||
|
}
|
||||||
|
|
||||||
|
return appUserRepository.save(appUser);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -2,14 +2,11 @@ package de.assecutor.votianlt.pages.service;
|
|||||||
|
|
||||||
import de.assecutor.votianlt.model.Customer;
|
import de.assecutor.votianlt.model.Customer;
|
||||||
import de.assecutor.votianlt.pages.domain.CustomerRepository;
|
import de.assecutor.votianlt.pages.domain.CustomerRepository;
|
||||||
import org.jspecify.annotations.Nullable;
|
|
||||||
import org.springframework.data.domain.Pageable;
|
import org.springframework.data.domain.Pageable;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Propagation;
|
import org.springframework.transaction.annotation.Propagation;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
import java.time.Clock;
|
|
||||||
import java.time.LocalDate;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import org.bson.types.ObjectId;
|
import org.bson.types.ObjectId;
|
||||||
|
|
||||||
@@ -19,25 +16,16 @@ public class CustomerService {
|
|||||||
|
|
||||||
private final CustomerRepository todoRepository;
|
private final CustomerRepository todoRepository;
|
||||||
|
|
||||||
private final Clock clock;
|
CustomerService(CustomerRepository todoRepository) {
|
||||||
|
|
||||||
CustomerService(CustomerRepository todoRepository, Clock clock) {
|
|
||||||
this.todoRepository = todoRepository;
|
this.todoRepository = todoRepository;
|
||||||
this.clock = clock;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void createTodo(String description, @Nullable LocalDate dueDate) {
|
public List<Customer> list(org.springframework.data.domain.Pageable pageable) {
|
||||||
if ("fail".equals(description)) {
|
|
||||||
throw new RuntimeException("This is for testing the error handler");
|
|
||||||
}
|
|
||||||
var todo = new Customer();
|
|
||||||
todoRepository.save(todo);
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<Customer> list(Pageable pageable) {
|
|
||||||
return todoRepository.findAllBy(pageable).toList();
|
return todoRepository.findAllBy(pageable).toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public List<Customer> findAll() {
|
public List<Customer> findAll() {
|
||||||
return todoRepository.findAll();
|
return todoRepository.findAll();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -57,9 +57,6 @@ public class AddJobView extends Main {
|
|||||||
private ComboBox<String> customerSelection;
|
private ComboBox<String> customerSelection;
|
||||||
private Button preloadAddressButton;
|
private Button preloadAddressButton;
|
||||||
|
|
||||||
// Required fields notice
|
|
||||||
private Span requiredFieldsNotice;
|
|
||||||
|
|
||||||
// Pickup address fields
|
// Pickup address fields
|
||||||
private TextField pickupCompany;
|
private TextField pickupCompany;
|
||||||
private ComboBox<String> pickupSalutation;
|
private ComboBox<String> pickupSalutation;
|
||||||
@@ -325,13 +322,10 @@ public class AddJobView extends Main {
|
|||||||
// Left column (50%) - Pickup address section
|
// Left column (50%) - Pickup address section
|
||||||
pickupSection = createPickupSection();
|
pickupSection = createPickupSection();
|
||||||
pickupSection.setWidth("50%");
|
pickupSection.setWidth("50%");
|
||||||
// Drag sources for dynamic control
|
|
||||||
DragSource<VerticalLayout> pickupDragSource = configureDragAndDrop(pickupSection, "pickup");
|
|
||||||
|
|
||||||
// Right column (50%) - Delivery address section
|
// Right column (50%) - Delivery address section
|
||||||
deliverySection = createDeliverySection();
|
deliverySection = createDeliverySection();
|
||||||
deliverySection.setWidth("50%");
|
deliverySection.setWidth("50%");
|
||||||
DragSource<VerticalLayout> deliveryDragSource = configureDragAndDrop(deliverySection, "delivery");
|
|
||||||
|
|
||||||
// Setup focus listeners for input fields
|
// Setup focus listeners for input fields
|
||||||
setupInputFieldFocusListeners();
|
setupInputFieldFocusListeners();
|
||||||
@@ -555,23 +549,6 @@ public class AddJobView extends Main {
|
|||||||
return section;
|
return section;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private void copyPickupToDelivery() {
|
|
||||||
deliveryCompany.setValue(pickupCompany.getValue());
|
|
||||||
deliverySalutation.setValue(pickupSalutation.getValue());
|
|
||||||
deliveryFirstName.setValue(pickupFirstName.getValue());
|
|
||||||
deliveryLastName.setValue(pickupLastName.getValue());
|
|
||||||
deliveryPhone.setValue(pickupPhone.getValue());
|
|
||||||
deliveryStreet.setValue(pickupStreet.getValue());
|
|
||||||
deliveryHouseNumber.setValue(pickupHouseNumber.getValue());
|
|
||||||
deliveryAddressAddition.setValue(pickupAddressAddition.getValue());
|
|
||||||
deliveryZip.setValue(pickupZip.getValue());
|
|
||||||
deliveryCity.setValue(pickupCity.getValue());
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setupValidation() {
|
private void setupValidation() {
|
||||||
// Bind pickup address fields with validation
|
// Bind pickup address fields with validation
|
||||||
binder.forField(pickupFirstName)
|
binder.forField(pickupFirstName)
|
||||||
@@ -723,7 +700,6 @@ public class AddJobView extends Main {
|
|||||||
|
|
||||||
private void triggerValidation() {
|
private void triggerValidation() {
|
||||||
// Create a temporary job object to trigger validation
|
// Create a temporary job object to trigger validation
|
||||||
Job tempJob = new Job();
|
|
||||||
binder.validate();
|
binder.validate();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -909,69 +885,6 @@ public class AddJobView extends Main {
|
|||||||
appUser.clear();
|
appUser.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Persistiert die aktuellen Formulardaten als Entwurf
|
|
||||||
*/
|
|
||||||
private void persistCurrentData() {
|
|
||||||
// Prüfen ob mindestens ein Feld ausgefüllt ist
|
|
||||||
if (isFormEmpty()) {
|
|
||||||
return; // Keine Daten zum Speichern
|
|
||||||
}
|
|
||||||
|
|
||||||
Job job = new Job();
|
|
||||||
|
|
||||||
// Alle aktuellen Werte aus dem Formular lesen
|
|
||||||
job.setCustomerSelection(customerSelection.getValue());
|
|
||||||
|
|
||||||
// Pickup address
|
|
||||||
job.setPickupCompany(pickupCompany.getValue());
|
|
||||||
job.setPickupSalutation(pickupSalutation.getValue());
|
|
||||||
job.setPickupFirstName(pickupFirstName.getValue());
|
|
||||||
job.setPickupLastName(pickupLastName.getValue());
|
|
||||||
job.setPickupPhone(pickupPhone.getValue());
|
|
||||||
job.setPickupStreet(pickupStreet.getValue());
|
|
||||||
job.setPickupHouseNumber(pickupHouseNumber.getValue());
|
|
||||||
job.setPickupAddressAddition(pickupAddressAddition.getValue());
|
|
||||||
job.setPickupZip(pickupZip.getValue());
|
|
||||||
job.setPickupCity(pickupCity.getValue());
|
|
||||||
|
|
||||||
// Delivery address
|
|
||||||
job.setDeliveryCompany(deliveryCompany.getValue());
|
|
||||||
job.setDeliverySalutation(deliverySalutation.getValue());
|
|
||||||
job.setDeliveryFirstName(deliveryFirstName.getValue());
|
|
||||||
job.setDeliveryLastName(deliveryLastName.getValue());
|
|
||||||
job.setDeliveryPhone(deliveryPhone.getValue());
|
|
||||||
job.setDeliveryStreet(deliveryStreet.getValue());
|
|
||||||
job.setDeliveryHouseNumber(deliveryHouseNumber.getValue());
|
|
||||||
job.setDeliveryAddressAddition(deliveryAddressAddition.getValue());
|
|
||||||
job.setDeliveryZip(deliveryZip.getValue());
|
|
||||||
job.setDeliveryCity(deliveryCity.getValue());
|
|
||||||
|
|
||||||
// Digital processing
|
|
||||||
job.setDigitalProcessing(digitalProcessing.getValue());
|
|
||||||
job.setAppUser(appUser.getValue());
|
|
||||||
|
|
||||||
// Als Entwurf speichern
|
|
||||||
addJobService.saveDraft(job);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Prüft ob das Formular komplett leer ist
|
|
||||||
*/
|
|
||||||
private boolean isFormEmpty() {
|
|
||||||
return (customerSelection.getValue() == null || customerSelection.getValue().trim().isEmpty()) &&
|
|
||||||
(pickupCompany.getValue() == null || pickupCompany.getValue().trim().isEmpty()) &&
|
|
||||||
(pickupFirstName.getValue() == null || pickupFirstName.getValue().trim().isEmpty()) &&
|
|
||||||
(pickupLastName.getValue() == null || pickupLastName.getValue().trim().isEmpty()) &&
|
|
||||||
(pickupStreet.getValue() == null || pickupStreet.getValue().trim().isEmpty()) &&
|
|
||||||
(pickupCity.getValue() == null || pickupCity.getValue().trim().isEmpty()) &&
|
|
||||||
(deliveryCompany.getValue() == null || deliveryCompany.getValue().trim().isEmpty()) &&
|
|
||||||
(deliveryFirstName.getValue() == null || deliveryFirstName.getValue().trim().isEmpty()) &&
|
|
||||||
(deliveryLastName.getValue() == null || deliveryLastName.getValue().trim().isEmpty()) &&
|
|
||||||
(deliveryStreet.getValue() == null || deliveryStreet.getValue().trim().isEmpty()) &&
|
|
||||||
(deliveryCity.getValue() == null || deliveryCity.getValue().trim().isEmpty());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Lädt einen bestehenden Entwurf, falls vorhanden
|
* Lädt einen bestehenden Entwurf, falls vorhanden
|
||||||
*/
|
*/
|
||||||
@@ -1401,59 +1314,6 @@ public class AddJobView extends Main {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Konfiguriert Drag-and-Drop für eine Etappen-Sektion
|
|
||||||
*/
|
|
||||||
private DragSource<VerticalLayout> configureDragAndDrop(VerticalLayout section, String sectionType) {
|
|
||||||
// Drag Source konfigurieren
|
|
||||||
DragSource<VerticalLayout> dragSource = DragSource.create(section);
|
|
||||||
dragSource.setEffectAllowed(EffectAllowed.MOVE);
|
|
||||||
dragSource.setDragData(sectionType);
|
|
||||||
|
|
||||||
// Visual feedback beim Drag-Start
|
|
||||||
dragSource.addDragStartListener(event -> {
|
|
||||||
section.getStyle().set("opacity", "0.5");
|
|
||||||
section.getStyle().set("border", "2px dashed var(--lumo-primary-color)");
|
|
||||||
});
|
|
||||||
|
|
||||||
// Visual feedback beim Drag-Ende
|
|
||||||
dragSource.addDragEndListener(event -> {
|
|
||||||
section.getStyle().remove("opacity");
|
|
||||||
section.getStyle().set("border", "1px solid var(--lumo-contrast-20pct)");
|
|
||||||
});
|
|
||||||
|
|
||||||
// Drop Target konfigurieren
|
|
||||||
DropTarget<VerticalLayout> dropTarget = DropTarget.create(section);
|
|
||||||
dropTarget.setActive(true);
|
|
||||||
|
|
||||||
// Drop Handler - Etappen tauschen
|
|
||||||
dropTarget.addDropListener(event -> {
|
|
||||||
Object draggedData = event.getDragData().orElse(null);
|
|
||||||
String draggedSectionType = draggedData != null ? draggedData.toString() : "";
|
|
||||||
|
|
||||||
if (!sectionType.equals(draggedSectionType)) {
|
|
||||||
swapStages();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Styles zurücksetzen
|
|
||||||
section.getStyle().set("background-color", "var(--lumo-base-color)");
|
|
||||||
section.getStyle().set("border", "1px solid var(--lumo-contrast-20pct)");
|
|
||||||
});
|
|
||||||
|
|
||||||
// Visual feedback bei Dragover mit JavaScript
|
|
||||||
section.getElement().addEventListener("dragover", e -> {
|
|
||||||
section.getStyle().set("background-color", "var(--lumo-primary-color-10pct)");
|
|
||||||
section.getStyle().set("border", "2px solid var(--lumo-primary-color)");
|
|
||||||
});
|
|
||||||
|
|
||||||
section.getElement().addEventListener("dragleave", e -> {
|
|
||||||
section.getStyle().set("background-color", "var(--lumo-base-color)");
|
|
||||||
section.getStyle().set("border", "1px solid var(--lumo-contrast-20pct)");
|
|
||||||
});
|
|
||||||
|
|
||||||
return dragSource;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tauscht die Inhalte der beiden Etappen (Pickup und Delivery)
|
* Tauscht die Inhalte der beiden Etappen (Pickup und Delivery)
|
||||||
*/
|
*/
|
||||||
|
|||||||
168
src/main/java/de/assecutor/votianlt/pages/view/AppUserView.java
Normal file
168
src/main/java/de/assecutor/votianlt/pages/view/AppUserView.java
Normal file
@@ -0,0 +1,168 @@
|
|||||||
|
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.H2;
|
||||||
|
import com.vaadin.flow.component.html.Span;
|
||||||
|
import com.vaadin.flow.component.icon.Icon;
|
||||||
|
import com.vaadin.flow.component.icon.VaadinIcon;
|
||||||
|
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.TextField;
|
||||||
|
import com.vaadin.flow.component.notification.Notification;
|
||||||
|
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 de.assecutor.votianlt.model.AppUser;
|
||||||
|
import de.assecutor.votianlt.pages.service.AppUserService;
|
||||||
|
import jakarta.annotation.security.RolesAllowed;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
|
||||||
|
@PageTitle("Neuen App-Nutzer anlegen")
|
||||||
|
@Route(value = "app-user", layout = de.assecutor.votianlt.pages.base.ui.view.MainLayout.class)
|
||||||
|
@RolesAllowed({"USER","ADMIN"})
|
||||||
|
public class AppUserView extends VerticalLayout {
|
||||||
|
|
||||||
|
private final Binder<AppUser> binder = new Binder<>(AppUser.class);
|
||||||
|
|
||||||
|
// Form fields
|
||||||
|
private final TextField designationField = new TextField("Bezeichnung (HH H 000)");
|
||||||
|
private final TextField firstnameField = new TextField("Vorname");
|
||||||
|
private final TextField lastnameField = new TextField("Nachname");
|
||||||
|
private final TextField phoneField = new TextField("Telefon (Mobil)");
|
||||||
|
private final TextField appCodeField = new TextField("App-Code");
|
||||||
|
private final TextField emailField = new TextField("E-Mail-Adresse");
|
||||||
|
private final ComboBox<String> deviceField = new ComboBox<>("kein Gerät");
|
||||||
|
|
||||||
|
private final AppUserService appUserService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
public AppUserView(AppUserService appUserService) {
|
||||||
|
this.appUserService = appUserService;
|
||||||
|
setSizeFull();
|
||||||
|
setPadding(true);
|
||||||
|
setSpacing(true);
|
||||||
|
|
||||||
|
// Center content vertically
|
||||||
|
setJustifyContentMode(FlexComponent.JustifyContentMode.CENTER);
|
||||||
|
setDefaultHorizontalComponentAlignment(FlexComponent.Alignment.CENTER);
|
||||||
|
|
||||||
|
// Create main content container
|
||||||
|
VerticalLayout contentContainer = new VerticalLayout();
|
||||||
|
contentContainer.setWidth("600px");
|
||||||
|
contentContainer.setMaxWidth("90%");
|
||||||
|
contentContainer.setSpacing(true);
|
||||||
|
contentContainer.setPadding(true);
|
||||||
|
contentContainer.getStyle().set("background", "var(--lumo-contrast-5pct)");
|
||||||
|
contentContainer.getStyle().set("border-radius", "var(--lumo-border-radius)");
|
||||||
|
contentContainer.getStyle().set("box-shadow", "var(--lumo-box-shadow-s)");
|
||||||
|
|
||||||
|
// Header with title and question mark icon
|
||||||
|
HorizontalLayout header = new HorizontalLayout();
|
||||||
|
header.setAlignItems(FlexComponent.Alignment.CENTER);
|
||||||
|
header.setSpacing(true);
|
||||||
|
|
||||||
|
H2 title = new H2("Neuen App-Nutzer anlegen");
|
||||||
|
title.getStyle().set("margin", "0");
|
||||||
|
|
||||||
|
Icon questionIcon = new Icon(VaadinIcon.QUESTION_CIRCLE);
|
||||||
|
questionIcon.getStyle().set("color", "var(--lumo-secondary-text-color)");
|
||||||
|
|
||||||
|
header.add(title, questionIcon);
|
||||||
|
header.setJustifyContentMode(FlexComponent.JustifyContentMode.CENTER);
|
||||||
|
contentContainer.add(header);
|
||||||
|
|
||||||
|
// Form layout
|
||||||
|
FormLayout formLayout = new FormLayout();
|
||||||
|
formLayout.setResponsiveSteps(
|
||||||
|
new FormLayout.ResponsiveStep("0", 1)
|
||||||
|
);
|
||||||
|
|
||||||
|
// Configure fields
|
||||||
|
designationField.setPlaceholder("(HH H 000)");
|
||||||
|
designationField.setWidthFull();
|
||||||
|
|
||||||
|
firstnameField.setWidthFull();
|
||||||
|
lastnameField.setWidthFull();
|
||||||
|
|
||||||
|
// Create horizontal layout for firstname and lastname
|
||||||
|
HorizontalLayout nameLayout = new HorizontalLayout();
|
||||||
|
nameLayout.setWidthFull();
|
||||||
|
nameLayout.setSpacing(true);
|
||||||
|
nameLayout.add(firstnameField, lastnameField);
|
||||||
|
|
||||||
|
phoneField.setWidthFull();
|
||||||
|
appCodeField.setWidthFull();
|
||||||
|
emailField.setWidthFull();
|
||||||
|
|
||||||
|
// Configure device dropdown
|
||||||
|
deviceField.setItems("kein Gerät", "iPhone", "Android", "Tablet", "Desktop");
|
||||||
|
deviceField.setValue("kein Gerät");
|
||||||
|
deviceField.setWidthFull();
|
||||||
|
|
||||||
|
// Add fields to form
|
||||||
|
formLayout.add(designationField);
|
||||||
|
formLayout.add(nameLayout);
|
||||||
|
formLayout.add(phoneField);
|
||||||
|
formLayout.add(appCodeField);
|
||||||
|
formLayout.add(emailField);
|
||||||
|
formLayout.add(deviceField);
|
||||||
|
|
||||||
|
contentContainer.add(formLayout);
|
||||||
|
|
||||||
|
// Submit button
|
||||||
|
Button submitButton = new Button("App-Nutzer anlegen", e -> createAppUser());
|
||||||
|
submitButton.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
|
||||||
|
submitButton.setWidthFull();
|
||||||
|
contentContainer.add(submitButton);
|
||||||
|
|
||||||
|
// Add content container to main layout
|
||||||
|
add(contentContainer);
|
||||||
|
|
||||||
|
// Setup binder
|
||||||
|
setupBinder();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setupBinder() {
|
||||||
|
// Bind fields to AppUser properties
|
||||||
|
binder.forField(designationField).bind(AppUser::getBezeichnung, AppUser::setBezeichnung);
|
||||||
|
binder.forField(firstnameField).bind(AppUser::getVorname, AppUser::setVorname);
|
||||||
|
binder.forField(lastnameField).bind(AppUser::getNachname, AppUser::setNachname);
|
||||||
|
binder.forField(phoneField).bind(AppUser::getTelefon, AppUser::setTelefon);
|
||||||
|
binder.forField(appCodeField).bind(AppUser::getAppCode, AppUser::setAppCode);
|
||||||
|
binder.forField(emailField).bind(AppUser::getEmail, AppUser::setEmail);
|
||||||
|
binder.forField(deviceField).bind(AppUser::getGeraet, AppUser::setGeraet);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createAppUser() {
|
||||||
|
try {
|
||||||
|
// Create new AppUser object
|
||||||
|
AppUser newAppUser = new AppUser();
|
||||||
|
binder.writeBean(newAppUser);
|
||||||
|
|
||||||
|
// Save to MongoDB collection
|
||||||
|
appUserService.createAppUser(newAppUser);
|
||||||
|
|
||||||
|
// Show success message
|
||||||
|
Notification.show(
|
||||||
|
"App-Nutzer erfolgreich angelegt",
|
||||||
|
3000,
|
||||||
|
Notification.Position.MIDDLE
|
||||||
|
);
|
||||||
|
|
||||||
|
// Clear form
|
||||||
|
binder.readBean(new AppUser());
|
||||||
|
|
||||||
|
} catch (ValidationException e) {
|
||||||
|
Notification.show(
|
||||||
|
"Bitte überprüfen Sie die Eingaben",
|
||||||
|
3000,
|
||||||
|
Notification.Position.MIDDLE
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
package de.assecutor.votianlt.repository;
|
||||||
|
|
||||||
|
import de.assecutor.votianlt.model.AppUser;
|
||||||
|
import org.bson.types.ObjectId;
|
||||||
|
import org.springframework.data.mongodb.repository.MongoRepository;
|
||||||
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
|
@Repository
|
||||||
|
public interface AppUserRepository extends MongoRepository<AppUser, ObjectId> {
|
||||||
|
|
||||||
|
// Custom query methods can be added here if needed
|
||||||
|
// For example:
|
||||||
|
// List<AppUser> findByEmail(String email);
|
||||||
|
// List<AppUser> findByBezeichnung(String bezeichnung);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user