Erweiterungen

This commit is contained in:
2025-09-18 18:02:06 +02:00
parent 4a84ac8fa4
commit 2f46ac3177
3 changed files with 63 additions and 30 deletions

View File

@@ -37,6 +37,7 @@ public class Application implements AppShellConfigurator {
); );
public static final Map<String, String> activeNiederlassungen = new ConcurrentHashMap<>(); public static final Map<String, String> activeNiederlassungen = new ConcurrentHashMap<>();
public static final Map<String, String> activeUsers = new ConcurrentHashMap<>();
public static void main(String[] args) { public static void main(String[] args) {
SpringApplication.run(Application.class, args); SpringApplication.run(Application.class, args);

View File

@@ -50,12 +50,18 @@ public class LoginView extends VerticalLayout {
return; return;
} }
if (Application.activeUsers.containsKey(username)) {
Notification.show("Benutzer ist bereits angemeldet", 3000, Notification.Position.MIDDLE);
return;
}
if (Application.activeNiederlassungen.containsKey(niederlassung)) { if (Application.activeNiederlassungen.containsKey(niederlassung)) {
Notification.show("Niederlassung ist bereits von einem anderen Benutzer belegt", 3000, Notification.Position.MIDDLE); Notification.show("Niederlassung ist bereits von einem anderen Benutzer belegt", 3000, Notification.Position.MIDDLE);
return; return;
} }
Application.activeNiederlassungen.put(niederlassung, username); Application.activeNiederlassungen.put(niederlassung, username);
Application.activeUsers.put(username, niederlassung);
// Spring Security Authentifizierung setzen // Spring Security Authentifizierung setzen
var authorities = List.of(new SimpleGrantedAuthority("ROLE_USER")); var authorities = List.of(new SimpleGrantedAuthority("ROLE_USER"));

View File

@@ -46,6 +46,7 @@ public final class MainView extends Main implements BeforeEnterObserver
private final IFrame webView = new IFrame(); private final IFrame webView = new IFrame();
private final Div emulatorContainer = new Div(); private final Div emulatorContainer = new Div();
private final Div welcomeMessage = new Div(); private final Div welcomeMessage = new Div();
private Button startBtn;
private final ExecutorService executor = Executors.newSingleThreadExecutor(); private final ExecutorService executor = Executors.newSingleThreadExecutor();
@@ -113,7 +114,8 @@ public final class MainView extends Main implements BeforeEnterObserver
.set("background-color", "#f8f9fa") .set("background-color", "#f8f9fa")
.set("border", "2px dashed #dee2e6") .set("border", "2px dashed #dee2e6")
.set("border-radius", "8px") .set("border-radius", "8px")
.set("color", "#6c757d"); .set("color", "#6c757d")
.set("margin-bottom", "16px");
Icon icon = new Icon(VaadinIcon.DESKTOP); Icon icon = new Icon(VaadinIcon.DESKTOP);
icon.setSize("48px"); icon.setSize("48px");
@@ -135,9 +137,10 @@ public final class MainView extends Main implements BeforeEnterObserver
buttonLayout.getStyle() buttonLayout.getStyle()
.set("margin", "0") .set("margin", "0")
.set("padding", "8px 0") .set("padding", "8px 0")
.set("flex-shrink", "0"); .set("flex-shrink", "0")
.set("order", "999");
Button startBtn = new Button("Emulator starten", new Icon(VaadinIcon.PLAY), event -> startup()); startBtn = new Button("Emulator starten", new Icon(VaadinIcon.PLAY), event -> startup());
startBtn.addThemeVariants(ButtonVariant.LUMO_PRIMARY); startBtn.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
Button logoutBtn = new Button("Abmelden", new Icon(VaadinIcon.SIGN_OUT), event -> logout()); Button logoutBtn = new Button("Abmelden", new Icon(VaadinIcon.SIGN_OUT), event -> logout());
@@ -155,10 +158,25 @@ public final class MainView extends Main implements BeforeEnterObserver
.set("box-shadow", "0 2px 4px rgba(0,0,0,0.1)") .set("box-shadow", "0 2px 4px rgba(0,0,0,0.1)")
.set("overflow", "hidden") .set("overflow", "hidden")
.set("display", "none") .set("display", "none")
.set("flex-grow", "1"); .set("flex-grow", "1")
.set("margin-bottom", "16px");
webView.setSizeFull(); webView.setSizeFull();
webView.getElement().setAttribute("frameborder", "0"); webView.getElement().setAttribute("frameborder", "0");
webView.getElement().setAttribute("scrolling", "no");
webView.getElement().getStyle()
.set("overflow", "hidden")
.set("-webkit-overflow-scrolling", "touch")
.set("-ms-overflow-style", "none")
.set("scrollbar-width", "none");
// CSS für Webkit-Browser (Chrome, Safari)
webView.getElement().executeJs(
"this.style.setProperty('overflow', 'hidden', 'important');" +
"var style = document.createElement('style');" +
"style.textContent = 'iframe::-webkit-scrollbar { display: none !important; }';" +
"document.head.appendChild(style);"
);
emulatorContainer.add(webView); emulatorContainer.add(webView);
container.add(emulatorContainer); container.add(emulatorContainer);
@@ -198,6 +216,10 @@ public final class MainView extends Main implements BeforeEnterObserver
private void startup() { private void startup() {
UI ui = UI.getCurrent(); UI ui = UI.getCurrent();
// Button sofort sperren
startBtn.setEnabled(false);
startBtn.setText("Emulator starten");
var dialog = showWaitDialog("Der Emulator wird gestartet, bitte warten..."); var dialog = showWaitDialog("Der Emulator wird gestartet, bitte warten...");
executor.submit(() -> { executor.submit(() -> {
@@ -225,6 +247,9 @@ public final class MainView extends Main implements BeforeEnterObserver
welcomeMessage.getStyle().set("display", "none"); welcomeMessage.getStyle().set("display", "none");
emulatorContainer.getStyle().set("display", "block"); emulatorContainer.getStyle().set("display", "block");
// Button bleibt dauerhaft deaktiviert
startBtn.setText("Emulator gestartet");
refreshWebView(); refreshWebView();
}); });
} }
@@ -536,33 +561,34 @@ public final class MainView extends Main implements BeforeEnterObserver
@ClientCallable @ClientCallable
public void logout() { public void logout() {
UI ui = UI.getCurrent(); try {
var vaadinSession = VaadinService.getCurrentRequest().getWrappedSession(); // Cleanup in separatem Thread ohne UI-Navigation
executor.submit(() -> {
try {
shutdown();
} catch (Exception ex) {
logger.error("Fehler beim Shutdown während Logout", ex);
}
});
var dialog = showWaitDialog("Sie werden abgemeldet. Bitte warten..."); // Session cleanup sofort
dialog.open(); if (niederlassung != null) {
Application.activeNiederlassungen.remove(niederlassung);
executor.submit(() -> {
try {
shutdown();
} catch (Exception ex) {
// Logging, Fehlerbehandlung …
} finally {
// 4) UI-update sicher aus Nicht-UI-Thread heraus
ui.access(() -> {
dialog.close();
// Session cleanup vor Navigation
if (niederlassung != null) {
Application.activeNiederlassungen.remove(niederlassung);
}
vaadinSession.invalidate();
// Navigiere direkt zur Login-Seite
ui.navigate("login");
});
} }
}); if (username != null) {
Application.activeUsers.remove(username);
}
// Session invalidieren
UI.getCurrent().getSession().getSession().invalidate();
// Direkte Browser-Weiterleitung ohne Vaadin Navigation
UI.getCurrent().getPage().setLocation("login");
} catch (Exception ex) {
logger.error("Fehler beim Logout", ex);
// Fallback: Browser reload
UI.getCurrent().getPage().reload();
}
} }
} }