Menü Projekt-Berechtigungen, Übersichtssichten und AppAdmin-Erkennung

- Menü: Dropdown "Projekt-Berechtigungen" unter Optionen mit
  Unterpunkten "Projekt-Zugriffe" und "Nutzer-Zugriffe" (nur SysAdmin/AppAdmin)
- AppAdmin-Erkennung: Server liefert isAppAdmin-Flag im Login- und
  getusers-Response (applikationsspezifisch via has_permission)
- Login: CurrentUserIsAppAdmin in sessionStorage speichern/entfernen
- Projekt-Zugriffe: geschachtelter Treetable (Projekt → Nutzer) als
  reine Anzeige, Detail-Sicht aus Projekt-Maske mit Bearbeitung
- Nutzer-Zugriffe: neue Komponente user_projektliste.ts, geschachtelter
  Treetable (Nutzer → Projekte), reine Anzeige
- Server: neuer Endpunkt GET /xhr/projektuser/listall (nur AppAdmin/SysAdmin)
- Server: get_all_projekt_users() mit Batch-Query für Projekte und User
- Treetable-Widget: Platzhalter-Pfeil bei kinderlosen Nodes nur wenn
  Geschwister mit Kindern existieren (hasSiblingsWithChildren)
- Datei projekt_user.ts umbenannt in projekt_userliste.ts (konsistent
  mit user_projektliste.ts)

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
This commit is contained in:
gg committed 2026-09-07 16:04:06 +02:00
1 parent 505177b5e2
commit 9ed5e88e01
10 files changed
+693 -82

No files matched your search

+56 -25
View File
@@ -5,7 +5,8 @@ import { appmanagementpage } from "./Components/auth/appmanagementpage"
import { changepasswordscreen, loginscreen } from "./Components/auth/login"
import {kunde, kundenliste} from "./Components/kunde"
import { Projekt, projektliste } from "./Components/projekt"
import { projektuserliste } from "./Components/projekt_user"
import { projektuserliste } from "./Components/projekt_userliste"
import { userprojektliste } from "./Components/user_projektliste"
import { Call_Log, call_log_liste } from "./Components/call_log"
import { Kontakt, kontaktliste } from "./Components/kontakt"
import { Kontaktadresse, kontaktadresseliste } from "./Components/kontaktadresse"
@@ -63,6 +64,7 @@ function logout() {
console.log(result)
sessionStorage.removeItem("CurrentUser");
sessionStorage.removeItem("CurrentUserIsSysAdmin");
sessionStorage.removeItem("CurrentUserIsAppAdmin");
headerdata.username = "Nicht angemeldet"
if (result['logout'] == true) {m.route.set("/blankpage")}
})
@@ -101,31 +103,59 @@ const knopf: m.Component = {
return m("button", {onclick: healthcheck}, "Aktualisieren")
}
}
const menu: m.Component = {
view: (vnode) => {
return m(menubar, [
m("a.w3-button.w3-bar-item", {href: "#!/kundenliste"}, "Kunden"),
m("a.w3-button.w3-bar-item", {href: "#!/projektliste"}, "Projekte"),
m("a.w3-button.w3-bar-item", {href: "#!/calllogliste"}, "Gesprächsnotizen"),
// m("a.w3-button.w3-bar-item", {onclick: healthcheck}, "Aktualisieren"),
m("div.w3-dropdown-hover",
m("button.w3-button", "Optionen"),
m("div.w3-dropdown-content.w3-bar-block.w3-card-4",
m("a.w3-button.w3-bar-item", {href: "#!/taglist"}, "Tags"),
m("a.w3-button.w3-bar-item", {href: "#!/default"}, "Datenexport"),
m("a.w3-button.w3-bar-item", {href: "#!/default"}, "Datenimport"),
const menu: m.ClosureComponent = () => {
let showProjektBerechtigungen = false
return {
oninit: (vnode) => {
showProjektBerechtigungen = false
},
view: (vnode) => {
return m(menubar, [
m("a.w3-button.w3-bar-item", {href: "#!/kundenliste"}, "Kunden"),
m("a.w3-button.w3-bar-item", {href: "#!/projektliste"}, "Projekte"),
m("a.w3-button.w3-bar-item", {href: "#!/calllogliste"}, "Gesprächsnotizen"),
m("div.w3-dropdown-hover",
m("button.w3-button", "Optionen"),
m("div.w3-dropdown-content.w3-bar-block.w3-card-4",
m("a.w3-button.w3-bar-item", {href: "#!/taglist"}, "Tags"),
m("a.w3-button.w3-bar-item", {href: "#!/default"}, "Datenexport"),
m("a.w3-button.w3-bar-item", {href: "#!/default"}, "Datenimport"),
// Projekt-Berechtigungen nur für SysAdmin/AppAdmin sichtbar.
// Als Toggle-Button realisiert, da verschachtelte w3-dropdown-hover
// innerhalb eines offenen Dropdowns nicht zuverlässig funktionieren.
(sessionStorage.getItem("CurrentUserIsSysAdmin") || sessionStorage.getItem("CurrentUserIsAppAdmin"))
? [
m("button.w3-button.w3-bar-item",
{
onclick: () => {showProjektBerechtigungen = !showProjektBerechtigungen}
},
m("span", showProjektBerechtigungen ? "Projekt-Berechtigungen \u25B2" : "Projekt-Berechtigungen \u25BC")
),
showProjektBerechtigungen
? m("div.w3-bar-block",
m("a.w3-button.w3-bar-item",
{href: "#!/projektuserliste", style: {'padding-left': '32px'}},
"Projekt-Zugriffe"),
m("a.w3-button.w3-bar-item",
{href: "#!/userprojektliste", style: {'padding-left': '32px'}},
"Nutzer-Zugriffe")
)
: null
]
: null,
)
),
m("div.w3-button.w3-right", {onclick: logout}, "Logout"),
m("div.w3-dropdown-hover.w3-right",
m("button.w3-button", "System"),
m("div.w3-dropdown-content.w3-bar-block.w3-card-4",
m("a.w3-button.w3-bar-item", {href: "#!/login"}, "Login"),
m("a.w3-button.w3-bar-item", {href: "#!/changepassword"}, "Kennwort ändern"),
m("a.w3-button.w3-bar-item", {href: "#!/usermanagement"}, "Verwalten"),
)
)
),
m("div.w3-button.w3-right", {onclick: logout}, "Logout"),
m("div.w3-dropdown-hover.w3-right",
m("button.w3-button", "System"),
m("div.w3-dropdown-content.w3-bar-block.w3-card-4",
m("a.w3-button.w3-bar-item", {href: "#!/login"}, "Login"),
m("a.w3-button.w3-bar-item", {href: "#!/changepassword"}, "Kennwort ändern"),
m("a.w3-button.w3-bar-item", {href: "#!/usermanagement"}, "Verwalten"),
)
)
])
])
}
}
}
@@ -154,6 +184,7 @@ m.route(gridMountpoints.main, "/blankpage", {
"/projektliste": projektliste,
"/projekt": Projekt,
"/projektuserliste": projektuserliste,
"/userprojektliste": userprojektliste,
"/calllogliste": call_log_liste,
"/call_log": Call_Log,
"/kontaktliste": kontaktliste,