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")
private String name;
@Field("app_user_id")
private ObjectId appUserId;
@Field("erstellt_am")
private LocalDateTime erstelltAm;

View File

@@ -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;

View File

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

View File

@@ -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);

View File

@@ -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<AppUser> 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<String> deviceField = new ComboBox<>("kein Gerät");
private final ComboBox<AppDevice> 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<AppDevice>
}
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.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<AppDevice> 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

View File

@@ -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<AppUser> 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);

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.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<String> {
private final AppDeviceService appDeviceService;
private final AppUserService appUserService;
private final Binder<AppDevice> binder;
// Formularfelder
private final TextField nameField;
private final ComboBox<AppUser> 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() {

View File

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