Add sidebar builder
This commit is contained in:
@@ -67,7 +67,7 @@ def verify_user(username: str, password: str):
|
|||||||
def get_role_for_user(username: str) -> str:
|
def get_role_for_user(username: str) -> str:
|
||||||
with closing(get_conn()) as conn:
|
with closing(get_conn()) as conn:
|
||||||
row = conn.execute(
|
row = conn.execute(
|
||||||
"SELECT role_id FROM users WHERE username = ?",
|
"SELECT r.role_text from users u left join roles r on u.role_id = r.role_id WHERE username = ?",
|
||||||
(username,),
|
(username,),
|
||||||
).fetchone()
|
).fetchone()
|
||||||
return row[0] if row else "user"
|
return row[0] if row else "user"
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import sqlite3
|
import sqlite3
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
import bcrypt
|
import bcrypt
|
||||||
|
import pandas as pd
|
||||||
|
|
||||||
BASE_DIR = Path(__file__).resolve().parent.parent
|
BASE_DIR = Path(__file__).resolve().parent.parent
|
||||||
DB_PATH = BASE_DIR / "data" / "app.db"
|
DB_PATH = BASE_DIR / "data" / "app.db"
|
||||||
@@ -10,3 +11,7 @@ def get_conn():
|
|||||||
# check_same_thread=False, damit Streamlit mehrere Threads nutzen kann
|
# check_same_thread=False, damit Streamlit mehrere Threads nutzen kann
|
||||||
return sqlite3.connect(DB_PATH, check_same_thread=False)
|
return sqlite3.connect(DB_PATH, check_same_thread=False)
|
||||||
|
|
||||||
|
def get_list(sql, params=None):
|
||||||
|
conn = get_conn()
|
||||||
|
df = pd.read_sql_query(sql, conn, params=params)
|
||||||
|
return df
|
||||||
@@ -11,7 +11,7 @@ authenticator = require_login()
|
|||||||
st.session_state["authenticator"] = authenticator
|
st.session_state["authenticator"] = authenticator
|
||||||
username = st.session_state.get("username")
|
username = st.session_state.get("username")
|
||||||
|
|
||||||
build_sidebar()
|
# build_sidebar()
|
||||||
|
|
||||||
st.title("Benutzerverwaltung")
|
st.title("Benutzerverwaltung")
|
||||||
|
|
||||||
@@ -1,5 +1,9 @@
|
|||||||
|
from contextlib import closing
|
||||||
import streamlit as st
|
import streamlit as st
|
||||||
from auth import get_fullname_for_user, get_role_for_user
|
from auth import get_fullname_for_user, get_role_for_user
|
||||||
|
from db import get_conn, get_list
|
||||||
|
import sqlite3
|
||||||
|
|
||||||
|
|
||||||
def build_sidebar():
|
def build_sidebar():
|
||||||
|
|
||||||
@@ -15,6 +19,53 @@ def build_sidebar():
|
|||||||
role = get_role_for_user(username)
|
role = get_role_for_user(username)
|
||||||
fullname = get_fullname_for_user(username)
|
fullname = get_fullname_for_user(username)
|
||||||
|
|
||||||
|
if role == "admin":
|
||||||
|
sql = """
|
||||||
|
select
|
||||||
|
g.group_id,
|
||||||
|
g.group_text,
|
||||||
|
d.dash_id,
|
||||||
|
d.dash_text,
|
||||||
|
d.page_file,
|
||||||
|
d.dash_type
|
||||||
|
from
|
||||||
|
groups g
|
||||||
|
left join dashboards d
|
||||||
|
on g.group_id = d.group_id
|
||||||
|
where
|
||||||
|
g.active = 1
|
||||||
|
and d.active = 1
|
||||||
|
"""
|
||||||
|
else:
|
||||||
|
sql = """
|
||||||
|
SELECT
|
||||||
|
d.group_id,
|
||||||
|
g.group_text,
|
||||||
|
p.dash_id,
|
||||||
|
d.dash_text,
|
||||||
|
d.page_file,
|
||||||
|
d.dash_type
|
||||||
|
FROM
|
||||||
|
users u
|
||||||
|
left join permissions p
|
||||||
|
on u.role_id = p.role_id
|
||||||
|
left join dashboards d
|
||||||
|
on p.dash_id = d.dash_id
|
||||||
|
left join groups g
|
||||||
|
on d.group_id = g.group_id
|
||||||
|
where
|
||||||
|
u.active = 1
|
||||||
|
and g.active = 1
|
||||||
|
and d.active = 1
|
||||||
|
and p.active = 1
|
||||||
|
and u.username = ?
|
||||||
|
order by
|
||||||
|
g.order_no,
|
||||||
|
d.order_no
|
||||||
|
"""
|
||||||
|
params = (username,) if "?" in sql else None
|
||||||
|
df = get_list(sql, params)
|
||||||
|
|
||||||
with st.sidebar:
|
with st.sidebar:
|
||||||
st.logo("app/images/GMN_Logo_neu_rgb.png", size="small")
|
st.logo("app/images/GMN_Logo_neu_rgb.png", size="small")
|
||||||
st.write(f"**{fullname}** ({role})")
|
st.write(f"**{fullname}** ({role})")
|
||||||
@@ -30,11 +81,79 @@ def build_sidebar():
|
|||||||
st.divider()
|
st.divider()
|
||||||
st.markdown("## Menü")
|
st.markdown("## Menü")
|
||||||
|
|
||||||
st.page_link("pages/Benutzer.py", label="Benutzer anlegen")
|
# for group_text, df_group in df.groupby("group_text"):
|
||||||
|
# with st.expander(group_text, expanded=False):
|
||||||
|
# for _, row in df_group.iterrows():
|
||||||
|
# dash_type = row.get("dash_type")
|
||||||
|
# page_file = row.get("page_file")
|
||||||
|
# label = row.get("dash_text", "")
|
||||||
|
# print(dash_type, page_file, label)
|
||||||
|
# # 1) echte Streamlit-Page
|
||||||
|
# if dash_type == "page" and isinstance(page_file, str) and page_file.strip():
|
||||||
|
# st.page_link(
|
||||||
|
# page_file, # z.B. "pages/umsatz.py"
|
||||||
|
# label=label,
|
||||||
|
# )
|
||||||
|
|
||||||
|
# # 2) externer Link (oder interner HTTP-Link)
|
||||||
|
# elif dash_type == "url" and isinstance(page_file, str) and page_file.strip():
|
||||||
|
# st.markdown(
|
||||||
|
# f"[{label}]({page_file})",
|
||||||
|
# unsafe_allow_html=False,
|
||||||
|
# )
|
||||||
|
|
||||||
|
# # 3) Platzhalter / noch nicht implementiert
|
||||||
|
# else:
|
||||||
|
# st.write(f"▫️ {label} (in Vorbereitung)")
|
||||||
|
|
||||||
|
|
||||||
|
# --- Suchfeld ---
|
||||||
|
query = st.text_input("Menü-Suche", "", placeholder="z.B. Umsatz, Kosten, User ...")
|
||||||
|
query = query.strip()
|
||||||
|
|
||||||
|
# Aktive Seite ermitteln (für Expander-Status / Highlight)
|
||||||
|
current_page = st.session_state.get("_page_path")
|
||||||
|
|
||||||
|
# --- DF filtern, falls Suchbegriff gesetzt ---
|
||||||
|
if query:
|
||||||
|
mask = (
|
||||||
|
df["dash_text"].str.contains(query, case=False, na=False)
|
||||||
|
| df["group_text"].str.contains(query, case=False, na=False)
|
||||||
|
)
|
||||||
|
df_view = df[mask].copy()
|
||||||
|
else:
|
||||||
|
df_view = df
|
||||||
|
|
||||||
|
if df_view.empty:
|
||||||
|
st.info("Keine Einträge zum Suchbegriff gefunden.")
|
||||||
|
return
|
||||||
|
|
||||||
|
# --- Gruppiert durchlaufen ---
|
||||||
|
for group_text, df_group in df_view.groupby("group_text"):
|
||||||
|
# Expander offen, wenn:
|
||||||
|
# - aktuelle Seite in dieser Gruppe liegt
|
||||||
|
group_open = any(
|
||||||
|
(row["page_file"] == current_page)
|
||||||
|
for _, row in df_group.iterrows()
|
||||||
|
)
|
||||||
|
|
||||||
|
with st.expander(group_text, expanded=(group_open or bool(query))):
|
||||||
|
for _, row in df_group.iterrows():
|
||||||
|
dash_type = row.get("dash_type")
|
||||||
|
page_file = row.get("page_file")
|
||||||
|
label = row.get("dash_text", "")
|
||||||
|
|
||||||
|
# Streamlit-Page
|
||||||
|
if dash_type == "page" and isinstance(page_file, str) and page_file.strip():
|
||||||
|
st.page_link(page_file, label=label)
|
||||||
|
|
||||||
|
# Externer Link
|
||||||
|
elif dash_type == "url" and isinstance(page_file, str) and page_file.strip():
|
||||||
|
st.markdown(f"[{label}]({page_file})")
|
||||||
|
|
||||||
|
# Platzhalter / Sonstiges
|
||||||
|
else:
|
||||||
|
st.write(f"▫️ {label}")
|
||||||
|
|
||||||
# Damit die leere Sidebar komplett verschwindet nach dem Logout
|
# Damit die leere Sidebar komplett verschwindet nach dem Logout
|
||||||
def hide_sidebar_if_logged_out():
|
def hide_sidebar_if_logged_out():
|
||||||
|
|||||||
BIN
data/app.db
BIN
data/app.db
Binary file not shown.
11
migrations/20251204_210700_add_col_page_dashboards.sql
Normal file
11
migrations/20251204_210700_add_col_page_dashboards.sql
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
begin;
|
||||||
|
|
||||||
|
alter table dashboards
|
||||||
|
add column page_file text;
|
||||||
|
|
||||||
|
alter table dashboards
|
||||||
|
add column dash_type text;
|
||||||
|
|
||||||
|
INSERT INTO schema_version (version) VALUES ('20251204_210700_add_col_page_dashboards');
|
||||||
|
|
||||||
|
COMMIT;
|
||||||
Reference in New Issue
Block a user