Erweiterungen

This commit is contained in:
2025-08-15 10:51:35 +02:00
parent 5826bf33db
commit f864022ebd
9 changed files with 123 additions and 19 deletions

View File

@@ -18,6 +18,9 @@ public class AppDevice {
@Field("name") @Field("name")
private String name; private String name;
@Field("app_user_id")
private ObjectId appUserId;
@Field("erstellt_am") @Field("erstellt_am")
private LocalDateTime erstelltAm; private LocalDateTime erstelltAm;

View File

@@ -37,6 +37,9 @@ public class AppUser {
@Field("geraet") @Field("geraet")
private String geraet; private String geraet;
@Field("app_device_id")
private ObjectId appDeviceId;
@Field("erstellt_am") @Field("erstellt_am")
private LocalDateTime erstelltAm; private LocalDateTime erstelltAm;

View File

@@ -41,6 +41,10 @@ public class AppDeviceService {
return appDeviceRepository.findByErstelltVon(currentUserId); return appDeviceRepository.findByErstelltVon(currentUserId);
} }
public List<AppDevice> findUnassignedDevices() {
return appDeviceRepository.findByAppUserIdIsNull();
}
public AppDevice findById(ObjectId id) { public AppDevice findById(ObjectId id) {
return appDeviceRepository.findById(id).orElse(null); return appDeviceRepository.findById(id).orElse(null);
} }

View File

@@ -113,6 +113,9 @@ public class AddAppDeviceView extends VerticalLayout {
AppDevice appDevice = new AppDevice(); AppDevice appDevice = new AppDevice();
binder.writeBean(appDevice); binder.writeBean(appDevice);
// Explizit als nicht zugeordnet speichern
appDevice.setAppUserId(null);
AppDevice savedDevice = appDeviceService.createAppDevice(appDevice); AppDevice savedDevice = appDeviceService.createAppDevice(appDevice);
Notification.show("Endgerät erfolgreich angelegt: " + savedDevice.getName(), 3000, Notification.Position.MIDDLE); Notification.show("Endgerät erfolgreich angelegt: " + savedDevice.getName(), 3000, Notification.Position.MIDDLE);

View File

@@ -17,7 +17,9 @@ import com.vaadin.flow.data.binder.ValidationException;
import com.vaadin.flow.router.PageTitle; import com.vaadin.flow.router.PageTitle;
import com.vaadin.flow.router.Route; import com.vaadin.flow.router.Route;
import de.assecutor.votianlt.model.AppUser; import de.assecutor.votianlt.model.AppUser;
import de.assecutor.votianlt.model.AppDevice;
import de.assecutor.votianlt.pages.service.AppUserService; import de.assecutor.votianlt.pages.service.AppUserService;
import de.assecutor.votianlt.pages.service.AppDeviceService;
import jakarta.annotation.security.RolesAllowed; import jakarta.annotation.security.RolesAllowed;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@@ -27,6 +29,7 @@ import org.springframework.beans.factory.annotation.Autowired;
public class AddAppUserView extends VerticalLayout { public class AddAppUserView extends VerticalLayout {
private final AppUserService appUserService; private final AppUserService appUserService;
private final AppDeviceService appDeviceService;
private final Binder<AppUser> binder = new Binder<>(AppUser.class); private final Binder<AppUser> binder = new Binder<>(AppUser.class);
// Form fields // Form fields
@@ -36,11 +39,12 @@ public class AddAppUserView extends VerticalLayout {
private final TextField phoneField = new TextField("Telefon (Mobil)"); private final TextField phoneField = new TextField("Telefon (Mobil)");
private final TextField appCodeField = new TextField("App-Code"); private final TextField appCodeField = new TextField("App-Code");
private final TextField emailField = new TextField("E-Mail-Adresse"); private final TextField emailField = new TextField("E-Mail-Adresse");
private final ComboBox<String> deviceField = new ComboBox<>("kein Gerät"); private final ComboBox<AppDevice> deviceComboBox = new ComboBox<>("Endgerät");
@Autowired @Autowired
public AddAppUserView(AppUserService appUserService) { public AddAppUserView(AppUserService appUserService, AppDeviceService appDeviceService) {
this.appUserService = appUserService; this.appUserService = appUserService;
this.appDeviceService = appDeviceService;
setSizeFull(); setSizeFull();
setPadding(true); setPadding(true);
setSpacing(true); setSpacing(true);
@@ -99,9 +103,12 @@ public class AddAppUserView extends VerticalLayout {
emailField.setWidthFull(); emailField.setWidthFull();
// Configure device dropdown // Configure device dropdown
deviceField.setItems("kein Gerät", "iPhone", "Android", "Tablet", "Desktop"); // Geräteauswahl vorbereiten
deviceField.setValue("kein Gerät"); deviceComboBox.setWidthFull();
deviceField.setWidthFull(); deviceComboBox.setItemLabelGenerator(device -> device.getName());
deviceComboBox.setRequired(true);
deviceComboBox.setPlaceholder("Bitte wählen...");
deviceComboBox.setItems(appDeviceService.findUnassignedDevices());
// Add fields to form // Add fields to form
formLayout.add(designationField); formLayout.add(designationField);
@@ -109,7 +116,7 @@ public class AddAppUserView extends VerticalLayout {
formLayout.add(phoneField); formLayout.add(phoneField);
formLayout.add(appCodeField); formLayout.add(appCodeField);
formLayout.add(emailField); formLayout.add(emailField);
formLayout.add(deviceField); formLayout.add(deviceComboBox);
contentContainer.add(formLayout); contentContainer.add(formLayout);
@@ -137,7 +144,12 @@ public class AddAppUserView extends VerticalLayout {
binder.forField(phoneField).bind(AppUser::getTelefon, AppUser::setTelefon); binder.forField(phoneField).bind(AppUser::getTelefon, AppUser::setTelefon);
binder.forField(appCodeField).bind(AppUser::getAppCode, AppUser::setAppCode); binder.forField(appCodeField).bind(AppUser::getAppCode, AppUser::setAppCode);
binder.forField(emailField).bind(AppUser::getEmail, AppUser::setEmail); binder.forField(emailField).bind(AppUser::getEmail, AppUser::setEmail);
binder.forField(deviceField).bind(AppUser::getGeraet, AppUser::setGeraet); binder.forField(deviceComboBox)
.asRequired("Bitte ein Gerät auswählen")
.bind(
appUser -> null, // Initialwert, wird beim Erstellen gesetzt
(appUser, appDevice) -> appUser.setAppDeviceId(appDevice != null ? appDevice.getId() : null)
);
} }
private void createAppUser() { private void createAppUser() {
@@ -146,8 +158,15 @@ public class AddAppUserView extends VerticalLayout {
AppUser newAppUser = new AppUser(); AppUser newAppUser = new AppUser();
binder.writeBean(newAppUser); binder.writeBean(newAppUser);
// Save to MongoDB collection // Save AppUser first to get the ObjectId
appUserService.createAppUser(newAppUser); AppUser savedUser = appUserService.createAppUser(newAppUser);
// Referenz im AppDevice setzen
AppDevice selectedDevice = deviceComboBox.getValue();
if (selectedDevice != null && savedUser != null && savedUser.getId() != null) {
selectedDevice.setAppUserId(savedUser.getId());
appDeviceService.updateAppDevice(selectedDevice);
}
// Show success message // Show success message
Notification.show( Notification.show(
@@ -186,7 +205,7 @@ public class AddAppUserView extends VerticalLayout {
emailField.setValue("max.mustermann@example.com"); emailField.setValue("max.mustermann@example.com");
// Set device to iPhone // Set device to iPhone
deviceField.setValue("iPhone"); // deviceComboBox.setValue("iPhone"); // This line is removed as deviceComboBox is now a ComboBox<AppDevice>
} }
private void navigateBack() { private void navigateBack() {

View File

@@ -12,7 +12,9 @@ import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.router.PageTitle; import com.vaadin.flow.router.PageTitle;
import com.vaadin.flow.router.Route; import com.vaadin.flow.router.Route;
import de.assecutor.votianlt.model.AppDevice; import de.assecutor.votianlt.model.AppDevice;
import de.assecutor.votianlt.model.AppUser;
import de.assecutor.votianlt.pages.service.AppDeviceService; import de.assecutor.votianlt.pages.service.AppDeviceService;
import de.assecutor.votianlt.pages.service.AppUserService;
import jakarta.annotation.security.RolesAllowed; import jakarta.annotation.security.RolesAllowed;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@@ -22,11 +24,14 @@ import org.springframework.beans.factory.annotation.Autowired;
public class AppDevicesView extends VerticalLayout { public class AppDevicesView extends VerticalLayout {
private final AppDeviceService appDeviceService; private final AppDeviceService appDeviceService;
@SuppressWarnings("unused") // Wird in Grid-Spalte verwendet
private final AppUserService appUserService;
private final Grid<AppDevice> appDeviceGrid; private final Grid<AppDevice> appDeviceGrid;
@Autowired @Autowired
public AppDevicesView(AppDeviceService appDeviceService) { public AppDevicesView(AppDeviceService appDeviceService, AppUserService appUserService) {
this.appDeviceService = appDeviceService; this.appDeviceService = appDeviceService;
this.appUserService = appUserService;
setSizeFull(); setSizeFull();
setPadding(true); setPadding(true);
@@ -54,6 +59,24 @@ public class AppDevicesView extends VerticalLayout {
// Grid-Spalten konfigurieren // Grid-Spalten konfigurieren
appDeviceGrid.addColumn(AppDevice::getName).setHeader("Gerätename").setAutoWidth(true); appDeviceGrid.addColumn(AppDevice::getName).setHeader("Gerätename").setAutoWidth(true);
// App-Nutzer Spalte mit Name anzeigen
appDeviceGrid.addColumn(appDevice -> {
if (appDevice.getAppUserId() != null) {
try {
AppUser appUser = appUserService.findByCurrentUser().stream()
.filter(user -> user.getId().equals(appDevice.getAppUserId()))
.findFirst().orElse(null);
if (appUser != null) {
return appUser.getVorname() + " " + appUser.getNachname();
}
} catch (Exception e) {
// Fehler beim Laden des App-Nutzers ignorieren
}
}
return "Nicht zugeordnet";
}).setHeader("Zugeordneter App-Nutzer").setAutoWidth(true);
appDeviceGrid.addColumn(AppDevice::getErstelltAm).setHeader("Erstellt am").setAutoWidth(true); appDeviceGrid.addColumn(AppDevice::getErstelltAm).setHeader("Erstellt am").setAutoWidth(true);
// Make grid rows clickable // Make grid rows clickable

View File

@@ -13,6 +13,8 @@ import com.vaadin.flow.router.PageTitle;
import com.vaadin.flow.router.Route; import com.vaadin.flow.router.Route;
import de.assecutor.votianlt.model.AppUser; import de.assecutor.votianlt.model.AppUser;
import de.assecutor.votianlt.pages.service.AppUserService; 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 jakarta.annotation.security.RolesAllowed;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@@ -23,10 +25,12 @@ public class AppUserView extends VerticalLayout {
private final AppUserService appUserService; private final AppUserService appUserService;
private final Grid<AppUser> appUserGrid; private final Grid<AppUser> appUserGrid;
private final AppDeviceService appDeviceService;
@Autowired @Autowired
public AppUserView(AppUserService appUserService) { public AppUserView(AppUserService appUserService, AppDeviceService appDeviceService) {
this.appUserService = appUserService; this.appUserService = appUserService;
this.appDeviceService = appDeviceService;
setSizeFull(); setSizeFull();
setPadding(true); setPadding(true);
@@ -59,7 +63,13 @@ public class AppUserView extends VerticalLayout {
appUserGrid.addColumn(AppUser::getTelefon).setHeader("Telefon").setAutoWidth(true); appUserGrid.addColumn(AppUser::getTelefon).setHeader("Telefon").setAutoWidth(true);
appUserGrid.addColumn(AppUser::getAppCode).setHeader("App-Code").setAutoWidth(true); appUserGrid.addColumn(AppUser::getAppCode).setHeader("App-Code").setAutoWidth(true);
appUserGrid.addColumn(AppUser::getEmail).setHeader("E-Mail").setAutoWidth(true); appUserGrid.addColumn(AppUser::getEmail).setHeader("E-Mail").setAutoWidth(true);
appUserGrid.addColumn(AppUser::getGeraet).setHeader("Gerät").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);
// Make grid rows clickable // Make grid rows clickable
appUserGrid.setSelectionMode(Grid.SelectionMode.SINGLE); appUserGrid.setSelectionMode(Grid.SelectionMode.SINGLE);

View File

@@ -2,6 +2,7 @@ package de.assecutor.votianlt.pages.view;
import com.vaadin.flow.component.button.Button; import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.button.ButtonVariant; import com.vaadin.flow.component.button.ButtonVariant;
import com.vaadin.flow.component.combobox.ComboBox;
import com.vaadin.flow.component.confirmdialog.ConfirmDialog; import com.vaadin.flow.component.confirmdialog.ConfirmDialog;
import com.vaadin.flow.component.formlayout.FormLayout; import com.vaadin.flow.component.formlayout.FormLayout;
import com.vaadin.flow.component.html.H2; import com.vaadin.flow.component.html.H2;
@@ -15,7 +16,9 @@ import com.vaadin.flow.router.HasUrlParameter;
import com.vaadin.flow.router.PageTitle; import com.vaadin.flow.router.PageTitle;
import com.vaadin.flow.router.Route; import com.vaadin.flow.router.Route;
import de.assecutor.votianlt.model.AppDevice; import de.assecutor.votianlt.model.AppDevice;
import de.assecutor.votianlt.model.AppUser;
import de.assecutor.votianlt.pages.service.AppDeviceService; import de.assecutor.votianlt.pages.service.AppDeviceService;
import de.assecutor.votianlt.pages.service.AppUserService;
import jakarta.annotation.security.RolesAllowed; import jakarta.annotation.security.RolesAllowed;
import org.bson.types.ObjectId; import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@@ -26,17 +29,20 @@ import org.springframework.beans.factory.annotation.Autowired;
public class EditAppDeviceView extends VerticalLayout implements HasUrlParameter<String> { public class EditAppDeviceView extends VerticalLayout implements HasUrlParameter<String> {
private final AppDeviceService appDeviceService; private final AppDeviceService appDeviceService;
private final AppUserService appUserService;
private final Binder<AppDevice> binder; private final Binder<AppDevice> binder;
// Formularfelder // Formularfelder
private final TextField nameField; private final TextField nameField;
private final ComboBox<AppUser> appUserComboBox;
// Aktuelles Endgerät // Aktuelles Endgerät
private AppDevice currentAppDevice; private AppDevice currentAppDevice;
@Autowired @Autowired
public EditAppDeviceView(AppDeviceService appDeviceService) { public EditAppDeviceView(AppDeviceService appDeviceService, AppUserService appUserService) {
this.appDeviceService = appDeviceService; this.appDeviceService = appDeviceService;
this.appUserService = appUserService;
// Binder initialisieren // Binder initialisieren
binder = new Binder<>(AppDevice.class); binder = new Binder<>(AppDevice.class);
@@ -47,6 +53,20 @@ public class EditAppDeviceView extends VerticalLayout implements HasUrlParameter
nameField.setPlaceholder("z.B. iPhone 15, Samsung Galaxy S24"); nameField.setPlaceholder("z.B. iPhone 15, Samsung Galaxy S24");
nameField.setWidth("100%"); nameField.setWidth("100%");
// AppUser ComboBox
appUserComboBox = new ComboBox<>("App-Nutzer zuordnen");
appUserComboBox.setPlaceholder("App-Nutzer auswählen (optional)");
appUserComboBox.setWidth("100%");
appUserComboBox.setItemLabelGenerator(appUser ->
appUser.getVorname() + " " + appUser.getNachname() + " (" + appUser.getEmail() + ")");
// Lade verfügbare App-Nutzer
try {
appUserComboBox.setItems(appUserService.findByCurrentUser());
} catch (Exception e) {
Notification.show("Fehler beim Laden der App-Nutzer: " + e.getMessage(), 3000, Notification.Position.MIDDLE);
}
// Layout konfigurieren // Layout konfigurieren
setSizeFull(); setSizeFull();
setPadding(true); setPadding(true);
@@ -75,7 +95,7 @@ public class EditAppDeviceView extends VerticalLayout implements HasUrlParameter
// Formular // Formular
FormLayout formLayout = new FormLayout(); FormLayout formLayout = new FormLayout();
formLayout.setResponsiveSteps(new FormLayout.ResponsiveStep("0", 1)); formLayout.setResponsiveSteps(new FormLayout.ResponsiveStep("0", 1));
formLayout.add(nameField); formLayout.add(nameField, appUserComboBox);
contentContainer.add(formLayout); contentContainer.add(formLayout);
// Buttons // Buttons
@@ -131,6 +151,22 @@ public class EditAppDeviceView extends VerticalLayout implements HasUrlParameter
binder.forField(nameField) binder.forField(nameField)
.asRequired("Gerätename ist erforderlich") .asRequired("Gerätename ist erforderlich")
.bind(AppDevice::getName, AppDevice::setName); .bind(AppDevice::getName, AppDevice::setName);
binder.forField(appUserComboBox)
.bind(appDevice -> {
if (appDevice.getAppUserId() != null) {
return appUserService.findByCurrentUser().stream()
.filter(user -> user.getId().equals(appDevice.getAppUserId()))
.findFirst().orElse(null);
}
return null;
}, (appDevice, appUser) -> {
if (appUser != null) {
appDevice.setAppUserId(appUser.getId());
} else {
appDevice.setAppUserId(null);
}
});
} }
private void saveAppDevice() { private void saveAppDevice() {

View File

@@ -12,4 +12,7 @@ public interface AppDeviceRepository extends MongoRepository<AppDevice, ObjectId
// Find all devices created by a specific user // Find all devices created by a specific user
List<AppDevice> findByErstelltVon(ObjectId erstelltVon); List<AppDevice> findByErstelltVon(ObjectId erstelltVon);
// Find all devices not assigned to any user
List<AppDevice> findByAppUserIdIsNull();
} }