Erweiterungen

This commit is contained in:
2025-09-25 20:54:34 +02:00
parent 28349a7d21
commit 6afd982f80
15 changed files with 37 additions and 797 deletions

View File

@@ -49,40 +49,6 @@ public class DataInitializer implements CommandLineRunner {
log.info("Created admin user: admin@votianlt.de / admin123"); log.info("Created admin user: admin@votianlt.de / admin123");
} }
// Test User
if (!userRepository.existsByEmail("test@votianlt.de")) {
User testUser = new User();
testUser.setEmail("test@votianlt.de");
testUser.setPassword(passwordEncoder.encode("test123"));
testUser.setName("Testmann");
testUser.setFirstname("Test");
testUser.setIsActivated((byte) 1);
testUser.setIsEmailConfirmed((byte) 1);
testUser.setCreatedAt(LocalDateTime.now());
testUser.setUpdatedAt(LocalDateTime.now());
testUser.setRoles(Set.of("USER"));
userRepository.save(testUser);
log.info("Created test user: test@votianlt.de / test123");
}
// Demo User
if (!userRepository.existsByEmail("demo@votianlt.de")) {
User demoUser = new User();
demoUser.setEmail("demo@votianlt.de");
demoUser.setPassword(passwordEncoder.encode("demo123"));
demoUser.setName("Demouser");
demoUser.setFirstname("Demo");
demoUser.setIsActivated((byte) 1);
demoUser.setIsEmailConfirmed((byte) 1);
demoUser.setCreatedAt(LocalDateTime.now());
demoUser.setUpdatedAt(LocalDateTime.now());
demoUser.setRoles(Set.of("USER"));
userRepository.save(demoUser);
log.info("Created demo user: demo@votianlt.de / demo123");
}
log.info("Test users initialization completed."); log.info("Test users initialization completed.");
} }
} }

View File

@@ -1,40 +0,0 @@
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_device")
public class AppDevice {
@Id
private ObjectId id;
@Field("name")
private String name;
@Field("app_user_id")
private ObjectId appUserId;
@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 AppDevice() {
this.erstelltAm = LocalDateTime.now();
this.aktualisiertAm = LocalDateTime.now();
}
}

View File

@@ -50,8 +50,6 @@ public class AppUser {
@Field("geraet") @Field("geraet")
private String geraet; private String geraet;
@Field("app_device_id")
private ObjectId appDeviceId;
@Field("owner") @Field("owner")
private ObjectId owner; private ObjectId owner;

View File

@@ -106,10 +106,9 @@ public final class MainLayout extends AppLayout {
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", "app-user", new Icon(VaadinIcon.USERS)); SideNavItem appUsers = new SideNavItem("App-Nutzer", "app-user", new Icon(VaadinIcon.USERS));
SideNavItem devices = new SideNavItem("Endgeräte", "app-devices", new Icon(VaadinIcon.MOBILE));
SideNavItem statistics = new SideNavItem("Statistiken", "statistics", new Icon(VaadinIcon.BAR_CHART)); SideNavItem statistics = new SideNavItem("Statistiken", "statistics", new Icon(VaadinIcon.BAR_CHART));
verwaltungContent.add(jobs, customers, appUsers, devices); verwaltungContent.add(jobs, customers, appUsers);
// Only show invoices menu if billing is enabled for the current user // Only show invoices menu if billing is enabled for the current user
if (isBillingEnabledForCurrentUser()) { if (isBillingEnabledForCurrentUser()) {

View File

@@ -1,61 +0,0 @@
package de.assecutor.votianlt.pages.service;
import de.assecutor.votianlt.model.AppDevice;
import de.assecutor.votianlt.repository.AppDeviceRepository;
import de.assecutor.votianlt.security.SecurityService;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
@Service
@Transactional
public class AppDeviceService {
private final AppDeviceRepository appDeviceRepository;
private final SecurityService securityService;
@Autowired
public AppDeviceService(AppDeviceRepository appDeviceRepository, SecurityService securityService) {
this.appDeviceRepository = appDeviceRepository;
this.securityService = securityService;
}
public AppDevice createAppDevice(AppDevice appDevice) {
// Set creation and update metadata
appDevice.setErstelltAm(java.time.LocalDateTime.now());
appDevice.setAktualisiertAm(java.time.LocalDateTime.now());
// Set creator and updater - current user ID is required
ObjectId currentUserId = securityService.getCurrentUserId();
appDevice.setErstelltVon(currentUserId);
appDevice.setAktualisiertVon(currentUserId);
return appDeviceRepository.save(appDevice);
}
public List<AppDevice> findByCurrentUser() {
ObjectId currentUserId = securityService.getCurrentUserId();
return appDeviceRepository.findByErstelltVon(currentUserId);
}
public List<AppDevice> findUnassignedDevices() {
return appDeviceRepository.findByAppUserIdIsNull();
}
public AppDevice findById(ObjectId id) {
return appDeviceRepository.findById(id).orElse(null);
}
public AppDevice updateAppDevice(AppDevice appDevice) {
appDevice.setAktualisiertAm(java.time.LocalDateTime.now());
appDevice.setAktualisiertVon(securityService.getCurrentUserId());
return appDeviceRepository.save(appDevice);
}
public void deleteById(ObjectId id) {
appDeviceRepository.deleteById(id);
}
}

View File

@@ -1,159 +0,0 @@
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.formlayout.FormLayout;
import com.vaadin.flow.component.html.H2;
import com.vaadin.flow.component.notification.Notification;
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.data.binder.Binder;
import com.vaadin.flow.router.PageTitle;
import com.vaadin.flow.router.Route;
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;
@PageTitle("Neues Endgerät anlegen")
@Route(value = "add-app-device", layout = de.assecutor.votianlt.pages.base.ui.view.MainLayout.class)
@RolesAllowed({ "USER", "ADMIN" })
public class AddAppDeviceView extends VerticalLayout {
private final AppDeviceService appDeviceService;
private final Binder<AppDevice> binder;
// Formularfelder
private final TextField nameField;
@Autowired
public AddAppDeviceView(AppDeviceService appDeviceService) {
this.appDeviceService = appDeviceService;
// Binder initialisieren
binder = new Binder<>(AppDevice.class);
// Formularfelder erstellen
nameField = new TextField("Gerätename");
nameField.setRequired(true);
nameField.setRequiredIndicatorVisible(true);
nameField.setPlaceholder("z.B. iPhone 15, Samsung Galaxy S24");
nameField.setWidth("100%");
nameField.addBlurListener(e -> validateNameField());
// Layout konfigurieren
setSizeFull();
setPadding(true);
setSpacing(true);
// Content zentrieren
setJustifyContentMode(FlexComponent.JustifyContentMode.CENTER);
setDefaultHorizontalComponentAlignment(FlexComponent.Alignment.CENTER);
// Hauptcontainer erstellen
VerticalLayout contentContainer = new VerticalLayout();
contentContainer.setWidth("600px");
contentContainer.setMaxWidth("90%");
contentContainer.getStyle().set("background", "var(--lumo-base-color)");
contentContainer.getStyle().set("border-radius", "8px");
contentContainer.getStyle().set("box-shadow", "0 2px 8px rgba(0,0,0,0.1)");
contentContainer.setPadding(true);
contentContainer.setSpacing(true);
// Titel
H2 title = new H2("Neues Endgerät anlegen");
title.getStyle().set("margin", "0");
title.getStyle().set("text-align", "center");
contentContainer.add(title);
// Formular
FormLayout formLayout = new FormLayout();
formLayout.setResponsiveSteps(new FormLayout.ResponsiveStep("0", 1));
formLayout.add(nameField);
contentContainer.add(formLayout);
// Buttons
HorizontalLayout buttonLayout = new HorizontalLayout();
buttonLayout.setWidthFull();
buttonLayout.setJustifyContentMode(FlexComponent.JustifyContentMode.CENTER);
buttonLayout.setSpacing(true);
Button backButton = new Button("Zurück");
backButton.addClickListener(e -> navigateBack());
Button saveButton = new Button("Speichern");
saveButton.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
saveButton.addClickListener(e -> createAppDevice());
buttonLayout.add(backButton, saveButton);
contentContainer.add(buttonLayout);
add(contentContainer);
// Testdaten einfügen
populateTestData();
// Binder konfigurieren
setupBinder();
}
private void setupBinder() {
binder.forField(nameField).asRequired("Gerätename ist erforderlich").bind(AppDevice::getName,
AppDevice::setName);
}
private void populateTestData() {
// No default values - field starts empty
}
private void createAppDevice() {
// Validate field first
validateNameField();
if (nameField.isInvalid()) {
Notification.show("Bitte füllen Sie das Pflichtfeld korrekt aus", 3000, Notification.Position.MIDDLE);
return;
}
if (binder.validate().isOk()) {
try {
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);
// Zurück zur Übersicht
navigateBack();
} catch (Exception e) {
Notification.show("Fehler beim Anlegen des Endgeräts: " + e.getMessage(), 5000,
Notification.Position.MIDDLE);
}
} else {
Notification.show("Bitte füllen Sie alle erforderlichen Felder aus", 3000, Notification.Position.MIDDLE);
}
}
private void navigateBack() {
getUI().ifPresent(ui -> ui.navigate("app-devices"));
}
private void validateNameField() {
String value = nameField.getValue();
if (value == null || value.trim().isEmpty()) {
nameField.setInvalid(true);
nameField.setErrorMessage("Gerätename ist ein Pflichtfeld");
} else {
nameField.setInvalid(false);
nameField.setErrorMessage("");
}
}
}

View File

@@ -2,7 +2,6 @@ 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.formlayout.FormLayout; import com.vaadin.flow.component.formlayout.FormLayout;
import com.vaadin.flow.component.html.H2; import com.vaadin.flow.component.html.H2;
import com.vaadin.flow.component.icon.Icon; import com.vaadin.flow.component.icon.Icon;
@@ -18,9 +17,7 @@ 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;
@@ -30,7 +27,6 @@ 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
@@ -38,16 +34,13 @@ public class AddAppUserView extends VerticalLayout {
private final TextField firstnameField = new TextField("Vorname"); private final TextField firstnameField = new TextField("Vorname");
private final TextField lastnameField = new TextField("Nachname"); private final TextField lastnameField = new TextField("Nachname");
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 emailField = new TextField("E-Mail-Adresse"); private final TextField emailField = new TextField("E-Mail-Adresse");
private final PasswordField passwordField = new PasswordField("Passwort"); private final PasswordField passwordField = new PasswordField("Passwort");
private final PasswordField confirmPasswordField = new PasswordField("Passwort wiederholen"); private final PasswordField confirmPasswordField = new PasswordField("Passwort wiederholen");
private final ComboBox<AppDevice> deviceComboBox = new ComboBox<>("Endgerät");
@Autowired @Autowired
public AddAppUserView(AppUserService appUserService, AppDeviceService appDeviceService) { public AddAppUserView(AppUserService appUserService) {
this.appUserService = appUserService; this.appUserService = appUserService;
this.appDeviceService = appDeviceService;
setSizeFull(); setSizeFull();
setPadding(true); setPadding(true);
setSpacing(true); setSpacing(true);
@@ -110,9 +103,6 @@ public class AddAppUserView extends VerticalLayout {
phoneField.setRequiredIndicatorVisible(true); phoneField.setRequiredIndicatorVisible(true);
phoneField.addBlurListener(e -> validateField(phoneField, "Telefonnummer ist ein Pflichtfeld")); phoneField.addBlurListener(e -> validateField(phoneField, "Telefonnummer ist ein Pflichtfeld"));
appCodeField.setWidthFull();
appCodeField.setRequiredIndicatorVisible(true);
appCodeField.addBlurListener(e -> validateField(appCodeField, "App-Code ist ein Pflichtfeld"));
emailField.setWidthFull(); emailField.setWidthFull();
emailField.setRequiredIndicatorVisible(true); emailField.setRequiredIndicatorVisible(true);
@@ -133,25 +123,14 @@ public class AddAppUserView extends VerticalLayout {
confirmPasswordField.setRequiredIndicatorVisible(true); confirmPasswordField.setRequiredIndicatorVisible(true);
confirmPasswordField.addBlurListener(e -> validateConfirmPasswordField()); confirmPasswordField.addBlurListener(e -> validateConfirmPasswordField());
// Configure device dropdown
// Geräteauswahl vorbereiten
deviceComboBox.setWidthFull();
deviceComboBox.setItemLabelGenerator(device -> device.getName());
deviceComboBox.setRequired(true);
deviceComboBox.setRequiredIndicatorVisible(true);
deviceComboBox.setPlaceholder("Bitte wählen...");
deviceComboBox.setItems(appDeviceService.findUnassignedDevices());
deviceComboBox.addBlurListener(e -> validateDeviceField());
// Add fields to form // Add fields to form
formLayout.add(designationField); formLayout.add(designationField);
formLayout.add(nameLayout); formLayout.add(nameLayout);
formLayout.add(phoneField); formLayout.add(phoneField);
formLayout.add(appCodeField);
formLayout.add(emailField); formLayout.add(emailField);
formLayout.add(passwordField); formLayout.add(passwordField);
formLayout.add(confirmPasswordField); formLayout.add(confirmPasswordField);
formLayout.add(deviceComboBox);
contentContainer.add(formLayout); contentContainer.add(formLayout);
@@ -177,7 +156,6 @@ public class AddAppUserView extends VerticalLayout {
binder.forField(firstnameField).bind(AppUser::getVorname, AppUser::setVorname); binder.forField(firstnameField).bind(AppUser::getVorname, AppUser::setVorname);
binder.forField(lastnameField).bind(AppUser::getNachname, AppUser::setNachname); binder.forField(lastnameField).bind(AppUser::getNachname, AppUser::setNachname);
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(emailField).bind(AppUser::getEmail, AppUser::setEmail); binder.forField(emailField).bind(AppUser::getEmail, AppUser::setEmail);
binder.forField(passwordField).asRequired("Passwort ist erforderlich").bind(AppUser::getPassword, binder.forField(passwordField).asRequired("Passwort ist erforderlich").bind(AppUser::getPassword,
AppUser::setPassword); AppUser::setPassword);
@@ -190,11 +168,6 @@ public class AddAppUserView extends VerticalLayout {
(appUser, value) -> { (appUser, value) -> {
} // Dummy setter - this field is not stored } // Dummy setter - this field is not stored
); );
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() {
@@ -212,12 +185,6 @@ public class AddAppUserView extends VerticalLayout {
// Save AppUser first to get the ObjectId // Save AppUser first to get the ObjectId
AppUser savedUser = 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("App-Nutzer erfolgreich angelegt", 3000, Notification.Position.MIDDLE); Notification.show("App-Nutzer erfolgreich angelegt", 3000, Notification.Position.MIDDLE);
@@ -304,29 +271,18 @@ public class AddAppUserView extends VerticalLayout {
} }
} }
private void validateDeviceField() {
if (deviceComboBox.getValue() == null) {
deviceComboBox.setInvalid(true);
deviceComboBox.setErrorMessage("Bitte wählen Sie ein Gerät aus");
} else {
deviceComboBox.setInvalid(false);
deviceComboBox.setErrorMessage("");
}
}
private boolean validateAllFields() { private boolean validateAllFields() {
validateField(designationField, "Kennung ist ein Pflichtfeld"); validateField(designationField, "Kennung ist ein Pflichtfeld");
validateField(firstnameField, "Vorname ist ein Pflichtfeld"); validateField(firstnameField, "Vorname ist ein Pflichtfeld");
validateField(lastnameField, "Nachname ist ein Pflichtfeld"); validateField(lastnameField, "Nachname ist ein Pflichtfeld");
validateField(phoneField, "Telefonnummer ist ein Pflichtfeld"); validateField(phoneField, "Telefonnummer ist ein Pflichtfeld");
validateField(appCodeField, "App-Code ist ein Pflichtfeld");
validateEmailField(); validateEmailField();
validatePasswordField(); validatePasswordField();
validateConfirmPasswordField(); validateConfirmPasswordField();
validateDeviceField();
return !designationField.isInvalid() && !firstnameField.isInvalid() && !lastnameField.isInvalid() return !designationField.isInvalid() && !firstnameField.isInvalid() && !lastnameField.isInvalid()
&& !phoneField.isInvalid() && !appCodeField.isInvalid() && !emailField.isInvalid() && !phoneField.isInvalid() && !emailField.isInvalid()
&& !passwordField.isInvalid() && !confirmPasswordField.isInvalid() && !deviceComboBox.isInvalid(); && !passwordField.isInvalid() && !confirmPasswordField.isInvalid();
} }
} }

View File

@@ -1235,9 +1235,20 @@ public class AddJobView extends Main {
IntegerField qty = new IntegerField("Anzahl"); IntegerField qty = new IntegerField("Anzahl");
qty.setMin(1); qty.setMin(1);
qty.setValue(1); qty.setMax(9999); // Set reasonable maximum
qty.setWidth("10%"); qty.setWidth("10%");
qty.setRequiredIndicatorVisible(true); qty.setRequiredIndicatorVisible(true);
qty.setPlaceholder("1");
// Add validation on blur
qty.addBlurListener(e -> {
if (qty.getValue() == null || qty.getValue() <= 0) {
qty.setInvalid(true);
qty.setErrorMessage("Anzahl muss größer als 0 sein");
} else {
qty.setInvalid(false);
qty.setErrorMessage("");
}
});
NumberField weight = new NumberField("Gewicht"); NumberField weight = new NumberField("Gewicht");
weight.setSuffixComponent(new Span("kg")); weight.setSuffixComponent(new Span("kg"));
@@ -1245,15 +1256,15 @@ public class AddJobView extends Main {
weight.setRequiredIndicatorVisible(true); weight.setRequiredIndicatorVisible(true);
NumberField len = new NumberField("Länge"); NumberField len = new NumberField("Länge");
len.setSuffixComponent(new Span("mm")); len.setSuffixComponent(new Span("cm"));
len.setWidth("12%"); len.setWidth("12%");
len.setRequiredIndicatorVisible(true); len.setRequiredIndicatorVisible(true);
NumberField wid = new NumberField("Breite"); NumberField wid = new NumberField("Breite");
wid.setSuffixComponent(new Span("mm")); wid.setSuffixComponent(new Span("cm"));
wid.setWidth("12%"); wid.setWidth("12%");
wid.setRequiredIndicatorVisible(true); wid.setRequiredIndicatorVisible(true);
NumberField hei = new NumberField("Höhe"); NumberField hei = new NumberField("Höhe");
hei.setSuffixComponent(new Span("mm")); hei.setSuffixComponent(new Span("cm"));
hei.setWidth("12%"); hei.setWidth("12%");
hei.setRequiredIndicatorVisible(true); hei.setRequiredIndicatorVisible(true);
@@ -1294,7 +1305,13 @@ public class AddJobView extends Main {
numField.setInvalid(numField.getValue() == null || numField.getValue() <= 0); numField.setInvalid(numField.getValue() == null || numField.getValue() <= 0);
} else if (field instanceof IntegerField) { } else if (field instanceof IntegerField) {
IntegerField intField = (IntegerField) field; IntegerField intField = (IntegerField) field;
intField.setInvalid(intField.getValue() == null || intField.getValue() <= 0); boolean isInvalid = intField.getValue() == null || intField.getValue() <= 0;
intField.setInvalid(isInvalid);
if (isInvalid) {
intField.setErrorMessage("Anzahl muss größer als 0 sein");
} else {
intField.setErrorMessage("");
}
} }
}; };

View File

@@ -1,107 +0,0 @@
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.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.FlexComponent;
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.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;
@PageTitle("Endgeräte")
@Route(value = "app-devices", layout = de.assecutor.votianlt.pages.base.ui.view.MainLayout.class)
@RolesAllowed({ "USER", "ADMIN" })
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, AppUserService appUserService) {
this.appDeviceService = appDeviceService;
this.appUserService = appUserService;
setSizeFull();
setPadding(true);
setSpacing(true);
// Header mit Titel und Button
HorizontalLayout header = new HorizontalLayout();
header.setWidthFull();
header.setAlignItems(FlexComponent.Alignment.CENTER);
H2 title = new H2("Endgeräte");
title.getStyle().set("margin", "0");
Button addButton = new Button("Neues Endgerät anlegen", new Icon(VaadinIcon.PLUS));
addButton.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
addButton.addClickListener(e -> navigateToAddAppDevice());
header.add(title, addButton);
header.setJustifyContentMode(FlexComponent.JustifyContentMode.BETWEEN);
add(header);
// Grid für Endgeräte
appDeviceGrid = new Grid<>(AppDevice.class, false);
appDeviceGrid.setSizeFull();
// 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
appDeviceGrid.setSelectionMode(Grid.SelectionMode.SINGLE);
appDeviceGrid.getStyle().set("cursor", "pointer");
// Add click listener to navigate to edit view
appDeviceGrid.addItemClickListener(event -> {
AppDevice appDevice = event.getItem();
if (appDevice != null && appDevice.getId() != null) {
getUI().ifPresent(ui -> ui.navigate("edit-app-device/" + appDevice.getId().toHexString()));
}
});
add(appDeviceGrid);
// Daten laden
loadAppDevices();
}
private void loadAppDevices() {
var appDevices = appDeviceService.findByCurrentUser();
appDeviceGrid.setItems(appDevices);
}
private void navigateToAddAppDevice() {
getUI().ifPresent(ui -> ui.navigate("add-app-device"));
}
}

View File

@@ -12,9 +12,7 @@ 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.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,7 +25,7 @@ public class AppUserView extends VerticalLayout {
private final Grid<AppUser> appUserGrid; private final Grid<AppUser> appUserGrid;
@Autowired @Autowired
public AppUserView(AppUserService appUserService, AppDeviceService appDeviceService) { public AppUserView(AppUserService appUserService) {
this.appUserService = appUserService; this.appUserService = appUserService;
setSizeFull(); setSizeFull();
@@ -61,13 +59,6 @@ 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 -> {
if (appUser.getAppDeviceId() != null) {
AppDevice device = appDeviceService.findById(appUser.getAppDeviceId());
return device != null ? device.getName() : "Nicht gefunden";
}
return "Kein Gerät zugewiesen";
}).setHeader("Endgerät").setAutoWidth(true);
// Make grid rows clickable // Make grid rows clickable
appUserGrid.setSelectionMode(Grid.SelectionMode.SINGLE); appUserGrid.setSelectionMode(Grid.SelectionMode.SINGLE);

View File

@@ -1,242 +0,0 @@
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.html.Span;
import com.vaadin.flow.component.confirmdialog.ConfirmDialog;
import com.vaadin.flow.component.formlayout.FormLayout;
import com.vaadin.flow.component.html.H2;
import com.vaadin.flow.component.notification.Notification;
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.data.binder.Binder;
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;
@PageTitle("Endgerät bearbeiten")
@Route(value = "edit-app-device", layout = de.assecutor.votianlt.pages.base.ui.view.MainLayout.class)
@RolesAllowed({ "USER", "ADMIN" })
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 Span appUserDisplay;
// Aktuelles Endgerät
private AppDevice currentAppDevice;
@Autowired
public EditAppDeviceView(AppDeviceService appDeviceService, AppUserService appUserService) {
this.appDeviceService = appDeviceService;
this.appUserService = appUserService;
// Binder initialisieren
binder = new Binder<>(AppDevice.class);
// Formularfelder erstellen
nameField = new TextField("Gerätename");
nameField.setRequired(true);
nameField.setPlaceholder("z.B. iPhone 15, Samsung Galaxy S24");
nameField.setWidth("100%");
// App-Nutzer Anzeige (nur lesend)
appUserDisplay = new Span();
appUserDisplay.getStyle().set("font-weight", "bold")
.set("padding", "var(--lumo-space-s)")
.set("border", "1px solid var(--lumo-contrast-20pct)")
.set("border-radius", "var(--lumo-border-radius-m)")
.set("background-color", "var(--lumo-contrast-5pct)")
.set("display", "block")
.set("width", "100%");
// Layout konfigurieren
setSizeFull();
setPadding(true);
setSpacing(true);
// Content zentrieren
setJustifyContentMode(FlexComponent.JustifyContentMode.CENTER);
setDefaultHorizontalComponentAlignment(FlexComponent.Alignment.CENTER);
// Hauptcontainer erstellen
VerticalLayout contentContainer = new VerticalLayout();
contentContainer.setWidth("600px");
contentContainer.setMaxWidth("90%");
contentContainer.getStyle().set("background", "var(--lumo-base-color)");
contentContainer.getStyle().set("border-radius", "8px");
contentContainer.getStyle().set("box-shadow", "0 2px 8px rgba(0,0,0,0.1)");
contentContainer.setPadding(true);
contentContainer.setSpacing(true);
// Titel
H2 title = new H2("Endgerät bearbeiten");
title.getStyle().set("margin", "0");
title.getStyle().set("text-align", "center");
contentContainer.add(title);
// Formular
FormLayout formLayout = new FormLayout();
formLayout.setResponsiveSteps(new FormLayout.ResponsiveStep("0", 1));
// Label für App-Nutzer
Span appUserLabel = new Span("Zugeordneter App-Nutzer:");
appUserLabel.getStyle().set("font-weight", "500")
.set("color", "var(--lumo-secondary-text-color)")
.set("font-size", "var(--lumo-font-size-s)");
formLayout.add(nameField);
formLayout.add(appUserLabel);
formLayout.add(appUserDisplay);
contentContainer.add(formLayout);
// Buttons
HorizontalLayout buttonLayout = new HorizontalLayout();
buttonLayout.setWidthFull();
buttonLayout.setJustifyContentMode(FlexComponent.JustifyContentMode.CENTER);
buttonLayout.setSpacing(true);
Button backButton = new Button("Zurück");
backButton.addClickListener(e -> navigateBack());
Button saveButton = new Button("Speichern");
saveButton.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
saveButton.addClickListener(e -> saveAppDevice());
Button deleteButton = new Button("Löschen");
deleteButton.addThemeVariants(ButtonVariant.LUMO_ERROR);
deleteButton.addClickListener(e -> deleteAppDevice());
buttonLayout.add(backButton, saveButton, deleteButton);
contentContainer.add(buttonLayout);
add(contentContainer);
// Binder konfigurieren
setupBinder();
}
@Override
public void setParameter(com.vaadin.flow.router.BeforeEvent event, String parameter) {
try {
ObjectId deviceId = new ObjectId(parameter);
loadAppDevice(deviceId);
} catch (IllegalArgumentException e) {
Notification.show("Ungültige Endgerät-ID", 3000, Notification.Position.MIDDLE);
navigateBack();
}
}
private void loadAppDevice(ObjectId deviceId) {
currentAppDevice = appDeviceService.findById(deviceId);
if (currentAppDevice != null) {
// Formular mit aktuellen Daten füllen
binder.readBean(currentAppDevice);
// App-Nutzer Anzeige aktualisieren
updateAppUserDisplay();
} else {
Notification.show("Endgerät nicht gefunden", 3000, Notification.Position.MIDDLE);
navigateBack();
}
}
private void setupBinder() {
binder.forField(nameField).asRequired("Gerätename ist erforderlich").bind(AppDevice::getName,
AppDevice::setName);
}
private void updateAppUserDisplay() {
if (currentAppDevice != null && currentAppDevice.getAppUserId() != null) {
try {
// Finde den zugeordneten App-Nutzer
AppUser assignedUser = appUserService.findByCurrentUser().stream()
.filter(user -> user.getId().equals(currentAppDevice.getAppUserId()))
.findFirst()
.orElse(null);
if (assignedUser != null) {
String displayText = assignedUser.getVorname() + " " + assignedUser.getNachname() +
" (" + assignedUser.getEmail() + ")";
appUserDisplay.setText(displayText);
appUserDisplay.getStyle().set("color", "var(--lumo-body-text-color)");
} else {
appUserDisplay.setText("App-Nutzer nicht gefunden (ID: " + currentAppDevice.getAppUserId() + ")");
appUserDisplay.getStyle().set("color", "var(--lumo-error-text-color)");
}
} catch (Exception e) {
appUserDisplay.setText("Fehler beim Laden des App-Nutzers");
appUserDisplay.getStyle().set("color", "var(--lumo-error-text-color)");
}
} else {
appUserDisplay.setText("Kein App-Nutzer zugeordnet");
appUserDisplay.getStyle().set("color", "var(--lumo-secondary-text-color)");
appUserDisplay.getStyle().set("font-style", "italic");
}
}
private void saveAppDevice() {
if (binder.validate().isOk()) {
try {
// Aktuelle Daten in das Modell schreiben
binder.writeBean(currentAppDevice);
// Endgerät aktualisieren
AppDevice updatedDevice = appDeviceService.updateAppDevice(currentAppDevice);
Notification.show("Endgerät erfolgreich aktualisiert: " + updatedDevice.getName(), 3000,
Notification.Position.MIDDLE);
// Zurück zur Übersicht
navigateBack();
} catch (Exception e) {
Notification.show("Fehler beim Aktualisieren des Endgeräts: " + e.getMessage(), 5000,
Notification.Position.MIDDLE);
}
} else {
Notification.show("Bitte füllen Sie alle erforderlichen Felder aus", 3000, Notification.Position.MIDDLE);
}
}
private void deleteAppDevice() {
if (currentAppDevice != null && currentAppDevice.getId() != null) {
ConfirmDialog confirmDialog = new ConfirmDialog();
confirmDialog.setHeader("Endgerät löschen");
confirmDialog.setText("Möchten Sie das Endgerät \"" + currentAppDevice.getName() + "\" wirklich löschen?");
confirmDialog.setCancelText("Abbrechen");
confirmDialog.setConfirmText("Löschen");
confirmDialog.setConfirmButtonTheme("error primary");
confirmDialog.addConfirmListener(event -> {
try {
appDeviceService.deleteById(currentAppDevice.getId());
Notification.show("Endgerät erfolgreich gelöscht", 3000, Notification.Position.MIDDLE);
navigateBack();
} catch (Exception e) {
Notification.show("Fehler beim Löschen des Endgeräts: " + e.getMessage(), 5000,
Notification.Position.MIDDLE);
}
});
confirmDialog.open();
}
}
private void navigateBack() {
getUI().ifPresent(ui -> ui.navigate("app-devices"));
}
}

View File

@@ -2,7 +2,6 @@ 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.formlayout.FormLayout; import com.vaadin.flow.component.formlayout.FormLayout;
import com.vaadin.flow.component.html.H2; import com.vaadin.flow.component.html.H2;
import com.vaadin.flow.component.icon.Icon; import com.vaadin.flow.component.icon.Icon;
@@ -20,15 +19,11 @@ 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.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.bson.types.ObjectId; import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import java.util.ArrayList;
import java.util.List;
@PageTitle("App-Nutzer bearbeiten") @PageTitle("App-Nutzer bearbeiten")
@Route(value = "edit-app-user", layout = de.assecutor.votianlt.pages.base.ui.view.MainLayout.class) @Route(value = "edit-app-user", layout = de.assecutor.votianlt.pages.base.ui.view.MainLayout.class)
@@ -36,7 +31,6 @@ import java.util.List;
public class EditAppUserView extends VerticalLayout implements HasUrlParameter<String> { public class EditAppUserView extends VerticalLayout implements HasUrlParameter<String> {
private final AppUserService appUserService; private final AppUserService appUserService;
private final AppDeviceService appDeviceService;
private AppUser appUser; private AppUser appUser;
private final Binder<AppUser> binder = new Binder<>(AppUser.class); private final Binder<AppUser> binder = new Binder<>(AppUser.class);
@@ -45,18 +39,13 @@ public class EditAppUserView extends VerticalLayout implements HasUrlParameter<S
private final TextField firstnameField = new TextField("Vorname"); private final TextField firstnameField = new TextField("Vorname");
private final TextField lastnameField = new TextField("Nachname"); private final TextField lastnameField = new TextField("Nachname");
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 emailField = new TextField("E-Mail-Adresse"); private final TextField emailField = new TextField("E-Mail-Adresse");
private final PasswordField changePasswordField = new PasswordField("Passwort ändern"); private final PasswordField changePasswordField = new PasswordField("Passwort ändern");
private final PasswordField confirmChangePasswordField = new PasswordField("Passwort ändern wiederholen"); private final PasswordField confirmChangePasswordField = new PasswordField("Passwort ändern wiederholen");
private final ComboBox<AppDevice> deviceComboBox = new ComboBox<>("Endgerät");
private ObjectId previousDeviceId;
@Autowired @Autowired
public EditAppUserView(AppUserService appUserService, AppDeviceService appDeviceService) { public EditAppUserView(AppUserService appUserService) {
this.appUserService = appUserService; this.appUserService = appUserService;
this.appDeviceService = appDeviceService;
setSizeFull(); setSizeFull();
setPadding(true); setPadding(true);
setSpacing(true); setSpacing(true);
@@ -109,7 +98,6 @@ public class EditAppUserView extends VerticalLayout implements HasUrlParameter<S
nameLayout.add(firstnameField, lastnameField); nameLayout.add(firstnameField, lastnameField);
phoneField.setWidthFull(); phoneField.setWidthFull();
appCodeField.setWidthFull();
emailField.setWidthFull(); emailField.setWidthFull();
// Configure password fields // Configure password fields
@@ -119,19 +107,14 @@ public class EditAppUserView extends VerticalLayout implements HasUrlParameter<S
confirmChangePasswordField.setPlaceholder("Leer lassen, wenn nicht ändern"); confirmChangePasswordField.setPlaceholder("Leer lassen, wenn nicht ändern");
// Configure device dropdown // Configure device dropdown
deviceComboBox.setWidthFull();
deviceComboBox.setItemLabelGenerator(device -> device.getName());
deviceComboBox.setPlaceholder("Bitte wählen...");
// Add fields to form // Add fields to form
formLayout.add(designationField); formLayout.add(designationField);
formLayout.add(nameLayout); formLayout.add(nameLayout);
formLayout.add(phoneField); formLayout.add(phoneField);
formLayout.add(appCodeField);
formLayout.add(emailField); formLayout.add(emailField);
formLayout.add(changePasswordField); formLayout.add(changePasswordField);
formLayout.add(confirmChangePasswordField); formLayout.add(confirmChangePasswordField);
formLayout.add(deviceComboBox);
contentContainer.add(formLayout); contentContainer.add(formLayout);
@@ -163,10 +146,7 @@ public class EditAppUserView extends VerticalLayout implements HasUrlParameter<S
binder.forField(firstnameField).bind(AppUser::getVorname, AppUser::setVorname); binder.forField(firstnameField).bind(AppUser::getVorname, AppUser::setVorname);
binder.forField(lastnameField).bind(AppUser::getNachname, AppUser::setNachname); binder.forField(lastnameField).bind(AppUser::getNachname, AppUser::setNachname);
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(emailField).bind(AppUser::getEmail, AppUser::setEmail); binder.forField(emailField).bind(AppUser::getEmail, AppUser::setEmail);
binder.forField(deviceComboBox).bind(appUser -> getCurrentDevice(appUser), // Get current device
(appUser, appDevice) -> appUser.setAppDeviceId(appDevice != null ? appDevice.getId() : null));
} }
@Override @Override
@@ -174,10 +154,6 @@ public class EditAppUserView extends VerticalLayout implements HasUrlParameter<S
try { try {
ObjectId appUserId = new ObjectId(parameter); ObjectId appUserId = new ObjectId(parameter);
appUser = appUserService.findById(appUserId); appUser = appUserService.findById(appUserId);
previousDeviceId = appUser.getAppDeviceId();
// Setup device ComboBox with available devices
setupDeviceComboBox();
// Load app user data into form // Load app user data into form
binder.readBean(appUser); binder.readBean(appUser);
@@ -218,22 +194,6 @@ public class EditAppUserView extends VerticalLayout implements HasUrlParameter<S
appUser.setPassword(originalPassword); appUser.setPassword(originalPassword);
} }
// Handle device assignment changes
AppDevice selectedDevice = deviceComboBox.getValue();
if (selectedDevice.getId() != previousDeviceId) {
AppDevice previousDevice = appDeviceService.findById(previousDeviceId);
if (previousDevice != null) {
previousDevice.setAppUserId(null);
appDeviceService.updateAppDevice(previousDevice);
}
AppDevice newDevice = appDeviceService.findById(selectedDevice.getId());
if (newDevice != null) {
newDevice.setAppUserId(appUser.getId());
appDeviceService.updateAppDevice(newDevice);
}
}
appUserService.updateAppUser(appUser); appUserService.updateAppUser(appUser);
Notification.show("App-Nutzer erfolgreich gespeichert", 3000, Notification.Position.MIDDLE); Notification.show("App-Nutzer erfolgreich gespeichert", 3000, Notification.Position.MIDDLE);
@@ -270,33 +230,6 @@ public class EditAppUserView extends VerticalLayout implements HasUrlParameter<S
return true; return true;
} }
private AppDevice getCurrentDevice(AppUser appUser) {
if (appUser != null && appUser.getAppDeviceId() != null) {
return appDeviceService.findById(appUser.getAppDeviceId());
}
return null;
}
private void setupDeviceComboBox() {
List<AppDevice> availableDevices = new ArrayList<>();
// First, add the currently assigned device if it exists
AppDevice currentDevice = getCurrentDevice(appUser);
if (currentDevice != null) {
availableDevices.add(currentDevice);
}
// Then add all unassigned devices
List<AppDevice> unassignedDevices = appDeviceService.findUnassignedDevices();
availableDevices.addAll(unassignedDevices);
deviceComboBox.setItems(availableDevices);
// Set the current device as selected
if (currentDevice != null) {
deviceComboBox.setValue(currentDevice);
}
}
private void deleteAppUser() { private void deleteAppUser() {
// Show confirmation dialog // Show confirmation dialog

View File

@@ -1,18 +0,0 @@
package de.assecutor.votianlt.repository;
import de.assecutor.votianlt.model.AppDevice;
import org.bson.types.ObjectId;
import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.stereotype.Repository;
import java.util.List;
@Repository
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();
}

View File

@@ -0,0 +1,7 @@
# Production-specific configuration
# MongoDB - Production database
spring.data.mongodb.uri=mongodb://192.168.180.25:27017/votianlt
# Disable browser launch in production
vaadin.launch-browser=false

View File

@@ -15,8 +15,8 @@ vaadin.allowed-packages=com.vaadin,org.vaadin,de.assecutor.votianlt
# Open-in-view is only needed if you use lazy-loaded entities in your Flow views. # Open-in-view is only needed if you use lazy-loaded entities in your Flow views.
spring.jpa.open-in-view=false spring.jpa.open-in-view=false
# MongoDB # MongoDB - Development database by default
spring.data.mongodb.uri=mongodb://192.168.180.25:27017/votianlt spring.data.mongodb.uri=mongodb://192.168.180.25:27017/votianlt_dev
spring.data.mongodb.auto-index-creation=true spring.data.mongodb.auto-index-creation=true
spring.data.mongodb.socket-timeout=30000 spring.data.mongodb.socket-timeout=30000
spring.data.mongodb.connect-timeout=10000 spring.data.mongodb.connect-timeout=10000