diff --git a/src/main/java/de/assecutor/votianlt/model/AppDevice.java b/src/main/java/de/assecutor/votianlt/model/AppDevice.java index 21c9241..1d830f4 100644 --- a/src/main/java/de/assecutor/votianlt/model/AppDevice.java +++ b/src/main/java/de/assecutor/votianlt/model/AppDevice.java @@ -18,6 +18,9 @@ public class AppDevice { @Field("name") private String name; + @Field("app_user_id") + private ObjectId appUserId; + @Field("erstellt_am") private LocalDateTime erstelltAm; diff --git a/src/main/java/de/assecutor/votianlt/model/AppUser.java b/src/main/java/de/assecutor/votianlt/model/AppUser.java index 7fe731a..432ea19 100644 --- a/src/main/java/de/assecutor/votianlt/model/AppUser.java +++ b/src/main/java/de/assecutor/votianlt/model/AppUser.java @@ -37,6 +37,9 @@ public class AppUser { @Field("geraet") private String geraet; + @Field("app_device_id") + private ObjectId appDeviceId; + @Field("erstellt_am") private LocalDateTime erstelltAm; diff --git a/src/main/java/de/assecutor/votianlt/pages/service/AppDeviceService.java b/src/main/java/de/assecutor/votianlt/pages/service/AppDeviceService.java index d4529b3..2865ab9 100644 --- a/src/main/java/de/assecutor/votianlt/pages/service/AppDeviceService.java +++ b/src/main/java/de/assecutor/votianlt/pages/service/AppDeviceService.java @@ -41,6 +41,10 @@ public class AppDeviceService { return appDeviceRepository.findByErstelltVon(currentUserId); } + public List findUnassignedDevices() { + return appDeviceRepository.findByAppUserIdIsNull(); + } + public AppDevice findById(ObjectId id) { return appDeviceRepository.findById(id).orElse(null); } diff --git a/src/main/java/de/assecutor/votianlt/pages/view/AddAppDeviceView.java b/src/main/java/de/assecutor/votianlt/pages/view/AddAppDeviceView.java index ae59e43..45b79e6 100644 --- a/src/main/java/de/assecutor/votianlt/pages/view/AddAppDeviceView.java +++ b/src/main/java/de/assecutor/votianlt/pages/view/AddAppDeviceView.java @@ -113,6 +113,9 @@ public class AddAppDeviceView extends VerticalLayout { AppDevice appDevice = new AppDevice(); binder.writeBean(appDevice); + // Explizit als nicht zugeordnet speichern + appDevice.setAppUserId(null); + AppDevice savedDevice = appDeviceService.createAppDevice(appDevice); Notification.show("Endgerät erfolgreich angelegt: " + savedDevice.getName(), 3000, Notification.Position.MIDDLE); diff --git a/src/main/java/de/assecutor/votianlt/pages/view/AddAppUserView.java b/src/main/java/de/assecutor/votianlt/pages/view/AddAppUserView.java index 9f42aa1..cbcb43e 100644 --- a/src/main/java/de/assecutor/votianlt/pages/view/AddAppUserView.java +++ b/src/main/java/de/assecutor/votianlt/pages/view/AddAppUserView.java @@ -17,7 +17,9 @@ 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.model.AppDevice; import de.assecutor.votianlt.pages.service.AppUserService; +import de.assecutor.votianlt.pages.service.AppDeviceService; import jakarta.annotation.security.RolesAllowed; import org.springframework.beans.factory.annotation.Autowired; @@ -27,6 +29,7 @@ import org.springframework.beans.factory.annotation.Autowired; public class AddAppUserView extends VerticalLayout { private final AppUserService appUserService; + private final AppDeviceService appDeviceService; private final Binder binder = new Binder<>(AppUser.class); // Form fields @@ -36,11 +39,12 @@ public class AddAppUserView extends VerticalLayout { 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 deviceField = new ComboBox<>("kein Gerät"); + private final ComboBox deviceComboBox = new ComboBox<>("Endgerät"); @Autowired - public AddAppUserView(AppUserService appUserService) { + public AddAppUserView(AppUserService appUserService, AppDeviceService appDeviceService) { this.appUserService = appUserService; + this.appDeviceService = appDeviceService; setSizeFull(); setPadding(true); setSpacing(true); @@ -99,9 +103,12 @@ public class AddAppUserView extends VerticalLayout { emailField.setWidthFull(); // Configure device dropdown - deviceField.setItems("kein Gerät", "iPhone", "Android", "Tablet", "Desktop"); - deviceField.setValue("kein Gerät"); - deviceField.setWidthFull(); + // Geräteauswahl vorbereiten + deviceComboBox.setWidthFull(); + deviceComboBox.setItemLabelGenerator(device -> device.getName()); + deviceComboBox.setRequired(true); + deviceComboBox.setPlaceholder("Bitte wählen..."); + deviceComboBox.setItems(appDeviceService.findUnassignedDevices()); // Add fields to form formLayout.add(designationField); @@ -109,7 +116,7 @@ public class AddAppUserView extends VerticalLayout { formLayout.add(phoneField); formLayout.add(appCodeField); formLayout.add(emailField); - formLayout.add(deviceField); + formLayout.add(deviceComboBox); contentContainer.add(formLayout); @@ -137,7 +144,12 @@ public class AddAppUserView extends VerticalLayout { 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); + 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() { @@ -145,20 +157,27 @@ public class AddAppUserView extends VerticalLayout { // Create new AppUser object AppUser newAppUser = new AppUser(); binder.writeBean(newAppUser); - - // Save to MongoDB collection - appUserService.createAppUser(newAppUser); - + + // Save AppUser first to get the ObjectId + 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 Notification.show( "App-Nutzer erfolgreich angelegt", 3000, Notification.Position.MIDDLE ); - + // Navigate back to app user list navigateBack(); - + } catch (ValidationException e) { Notification.show( "Bitte überprüfen Sie die Eingaben", @@ -186,7 +205,7 @@ public class AddAppUserView extends VerticalLayout { emailField.setValue("max.mustermann@example.com"); // Set device to iPhone - deviceField.setValue("iPhone"); + // deviceComboBox.setValue("iPhone"); // This line is removed as deviceComboBox is now a ComboBox } private void navigateBack() { diff --git a/src/main/java/de/assecutor/votianlt/pages/view/AppDevicesView.java b/src/main/java/de/assecutor/votianlt/pages/view/AppDevicesView.java index 4b02d2d..071499b 100644 --- a/src/main/java/de/assecutor/votianlt/pages/view/AppDevicesView.java +++ b/src/main/java/de/assecutor/votianlt/pages/view/AppDevicesView.java @@ -12,7 +12,9 @@ import com.vaadin.flow.component.orderedlayout.VerticalLayout; import com.vaadin.flow.router.PageTitle; import com.vaadin.flow.router.Route; 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.AppUserService; import jakarta.annotation.security.RolesAllowed; import org.springframework.beans.factory.annotation.Autowired; @@ -22,11 +24,14 @@ import org.springframework.beans.factory.annotation.Autowired; public class AppDevicesView extends VerticalLayout { private final AppDeviceService appDeviceService; + @SuppressWarnings("unused") // Wird in Grid-Spalte verwendet + private final AppUserService appUserService; private final Grid appDeviceGrid; @Autowired - public AppDevicesView(AppDeviceService appDeviceService) { + public AppDevicesView(AppDeviceService appDeviceService, AppUserService appUserService) { this.appDeviceService = appDeviceService; + this.appUserService = appUserService; setSizeFull(); setPadding(true); @@ -54,6 +59,24 @@ public class AppDevicesView extends VerticalLayout { // Grid-Spalten konfigurieren 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); // Make grid rows clickable diff --git a/src/main/java/de/assecutor/votianlt/pages/view/AppUserView.java b/src/main/java/de/assecutor/votianlt/pages/view/AppUserView.java index b5cb60c..264c7eb 100644 --- a/src/main/java/de/assecutor/votianlt/pages/view/AppUserView.java +++ b/src/main/java/de/assecutor/votianlt/pages/view/AppUserView.java @@ -13,6 +13,8 @@ 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; @@ -23,10 +25,12 @@ public class AppUserView extends VerticalLayout { private final AppUserService appUserService; private final Grid appUserGrid; + private final AppDeviceService appDeviceService; @Autowired - public AppUserView(AppUserService appUserService) { + public AppUserView(AppUserService appUserService, AppDeviceService appDeviceService) { this.appUserService = appUserService; + this.appDeviceService = appDeviceService; setSizeFull(); setPadding(true); @@ -59,7 +63,13 @@ 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::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 appUserGrid.setSelectionMode(Grid.SelectionMode.SINGLE); diff --git a/src/main/java/de/assecutor/votianlt/pages/view/EditAppDeviceView.java b/src/main/java/de/assecutor/votianlt/pages/view/EditAppDeviceView.java index e418059..be850ed 100644 --- a/src/main/java/de/assecutor/votianlt/pages/view/EditAppDeviceView.java +++ b/src/main/java/de/assecutor/votianlt/pages/view/EditAppDeviceView.java @@ -2,6 +2,7 @@ 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.confirmdialog.ConfirmDialog; import com.vaadin.flow.component.formlayout.FormLayout; 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.Route; 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.AppUserService; import jakarta.annotation.security.RolesAllowed; import org.bson.types.ObjectId; 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 { private final AppDeviceService appDeviceService; + private final AppUserService appUserService; private final Binder binder; // Formularfelder private final TextField nameField; + private final ComboBox appUserComboBox; // Aktuelles Endgerät private AppDevice currentAppDevice; @Autowired - public EditAppDeviceView(AppDeviceService appDeviceService) { + public EditAppDeviceView(AppDeviceService appDeviceService, AppUserService appUserService) { this.appDeviceService = appDeviceService; + this.appUserService = appUserService; // Binder initialisieren 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.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 setSizeFull(); setPadding(true); @@ -75,7 +95,7 @@ public class EditAppDeviceView extends VerticalLayout implements HasUrlParameter // Formular FormLayout formLayout = new FormLayout(); formLayout.setResponsiveSteps(new FormLayout.ResponsiveStep("0", 1)); - formLayout.add(nameField); + formLayout.add(nameField, appUserComboBox); contentContainer.add(formLayout); // Buttons @@ -131,6 +151,22 @@ public class EditAppDeviceView extends VerticalLayout implements HasUrlParameter binder.forField(nameField) .asRequired("Gerätename ist erforderlich") .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() { diff --git a/src/main/java/de/assecutor/votianlt/repository/AppDeviceRepository.java b/src/main/java/de/assecutor/votianlt/repository/AppDeviceRepository.java index a3a7229..557c061 100644 --- a/src/main/java/de/assecutor/votianlt/repository/AppDeviceRepository.java +++ b/src/main/java/de/assecutor/votianlt/repository/AppDeviceRepository.java @@ -12,4 +12,7 @@ public interface AppDeviceRepository extends MongoRepository findByErstelltVon(ObjectId erstelltVon); + + // Find all devices not assigned to any user + List findByAppUserIdIsNull(); }