Compare commits

..

6 Commits

Author SHA1 Message Date
knedlik
07854cc0ad Modify dashboard management 2025-12-29 11:04:16 +01:00
knedlik
3725e7fe5d Add dashboard management delete and edit 2025-12-29 09:46:37 +01:00
hansi
3f3ec5097d Add dashboard management - edit function 2025-12-22 22:02:36 +01:00
hansi
13385db5ef Add dashboard management 2025-12-22 08:21:04 +01:00
hansi
c711a75eed reorder database ids 2025-12-20 00:42:33 +01:00
hansi
00692e1641 Add role management 2025-12-19 22:59:50 +01:00
7 changed files with 550 additions and 2 deletions

View File

@@ -1,7 +1,8 @@
[client] [client]
showSidebarNavigation = false showSidebarNavigation = false
toolbarMode = "minimal" # toolbarMode = "minimal"
# toolbarMode = "auto" # toolbarMode = "auto"
toolbarMode = "viewer"
[theme] [theme]
# primaryColor = "blue" # primaryColor = "blue"

Binary file not shown.

318
app/pages/dashboards.py Normal file
View File

@@ -0,0 +1,318 @@
import streamlit as st
from auth_runtime import require_login
from pathlib import Path
from tools.load_css import load_css
from app_db.app_db import get_list, send_cmd
from ui.selectboxes import get_groups, get_id
from tools.numgen import get_num, update_num
DASH_NAME = Path(__file__).stem # Hier muss die dash_id aus der DB stehen -> wird gegen die session_state geprüft (User-Berechtigung)
DASH_PATH = Path(__file__).resolve().parent
load_css()
st.set_page_config(page_title="Co-App Benutzer", page_icon=":material/person:", layout="wide", initial_sidebar_state="collapsed")
authenticator = require_login()
st.session_state["authenticator"] = authenticator
def get_dashboards_from_pages():
dashboards = sorted(
d.stem
for d in DASH_PATH.glob("*.py")
if d.name != "__init__.py"
)
#dash_list = [""] + dashboards
return dashboards
def sidebar():
fullname = st.session_state.get("fullname")
role_text = st.session_state.get("role_text")
with st.sidebar:
st.logo("app/images/GMN_Logo_neu_rgb.png", size="small")
st.markdown(f"**{fullname}** ({role_text})")
col1, col2 = st.columns([2,2])
with col1:
authenticator.logout("Logout")
with col2:
if st.button("Home", use_container_width=True, icon=":material/home:"):
st.switch_page("pages/home.py")
dashborad()
#-------------------------------------------------------------------------------------
# Dialog Dashboard anlegen
#-------------------------------------------------------------------------------------
@st.dialog("Dashboard anlegen")
def dialog_create_dashboard(dash_id):
dash_types = ["page", "url"]
df_groups = get_groups()
groups = df_groups["group"].tolist()
dash_list = get_dashboards_from_pages()
dash_default_index = dash_list.index("default")
txt_dash_id = st.text_input("Dash-Id", value=dash_id, disabled=True)
col1, col2 = st.columns([2,1],vertical_alignment="center")
with col1:
txt_dash_text = st.text_input(label="Dashboard")
with col2:
is_active = st.checkbox(label="Aktiv", value=1)
txt_dash_description = st.text_area(label="Beschreibung")
cmb_dash_type = st.selectbox(label="Typ", options=dash_types)
if cmb_dash_type == "url":
txt_page_file = st.text_input(label="URL", placeholder="URL, z.B. https://www.gmn.de")
else:
txt_page_file = st.selectbox(label="Dashboard", options=dash_list, index=dash_default_index)
cmb_group = st.selectbox(label="Gruppe", options=groups, placeholder="Gruppe auswählen")
txt_order_no = st.text_input(label="Order-Nr")
if st.button("Save"):
sql = """
insert into dashboards (
dash_id,
dash_text,
dash_description,
group_id,
page_file,
dash_type,
active,
order_no
)
values (?, ?, ?, ?, ?, ?, ?, ?)
"""
params = (
txt_dash_id,
txt_dash_text,
txt_dash_description,
get_id(cmb_group),
txt_page_file,
cmb_dash_type,
is_active,
txt_order_no,
)
if send_cmd(sql, params):
st.session_state.save_msg = f"✅ Dashboard '{txt_dash_text}' erfolgreich gespeichert"
update_num(dash_id,1,"numgen_dashboard")
else:
st.session_state.save_msg = "❌ Fehler beim Speichern"
st.rerun()
#-------------------------------------------------------------------------------------
# Dialog Dashboard löschen
#-------------------------------------------------------------------------------------
@st.dialog("Dashboard löschen")
def dialog_delete_dashboard(dash_id):
if dash_id == None:
st.write("kein Dashboard ausgewählt")
else:
df = get_list("select dash_text from dashboards where dash_id = ?",(dash_id,))
dash_text = df.iloc[0]["dash_text"]
st.write(f"Das Dashboard {dash_text} wird gelöscht! Sind Sie sicher?")
if st.button("Löschen"):
if send_cmd("delete from dashboards where dash_id = ?",(dash_id,)):
st.session_state.delete_msg = f"✅ Dashboard '{dash_text}' erfolgreich gelöscht!"
else:
st.session_state.delete_msg = f"❌ Daschboard '{dash_id}' konnte nicht gelöscht werden!"
st.rerun()
#-------------------------------------------------------------------------------------
# Dialog Dashboard bearbeiten
#-------------------------------------------------------------------------------------
@st.dialog("Dashboard bearbeiten")
def dialog_edit_dashboard(dash_id):
if dash_id == None:
st.write("kein Dashboard ausgewählt")
else:
sql = """
select
d.dash_id,
d.dash_text,
d.dash_description,
d.group_id || ' | ' || g.group_text as "group",
d.page_file,
d.dash_type,
d.active,
d.order_no
from
dashboards d
left join groups g
on d.group_id = g.group_id
where
d.dash_id = ?
"""
df = get_list(sql,(dash_id,))
# Index für Gruppe aus DB für selectbox ermitteln
df_groups = get_groups()
groups = df_groups["group"].tolist()
group = df.iloc[0]["group"]
try:
idx = groups.index(group)
except:
idx = None
# Index für Dash-Typ aus DB für selectbox ermitteln
dash_types = ["page", "url"]
dash_type_index = dash_types.index(df.iloc[0]["dash_type"])
dash_list = get_dashboards_from_pages()
dash_default_index = dash_list.index(df.iloc[0]["page_file"]) if df.iloc[0]["page_file"] in dash_list else dash_list.index("default")
col1, col2 = st.columns([2,1],vertical_alignment="center")
with col1:
txt_dash_text = st.text_input(label="Dashboard", value=df.iloc[0]["dash_text"])
with col2:
is_active = st.checkbox(label="Aktiv", value=df.iloc[0]["active"])
txt_dash_description = st.text_area(label="Beschreibung", value=df.iloc[0]["dash_description"])
cmb_dash_type = st.selectbox(label="Typ", options=dash_types, index=dash_type_index)
if cmb_dash_type == "url":
if df.iloc[0]["dash_type"] == "page":
txt_page_file = st.text_input(label="URL", value="", placeholder="URL, z.B. https://www.gmn.de")
else:
txt_page_file = st.text_input(label="URL", value=df.iloc[0]["page_file"])
dash_default_index = dash_list.index("default")
else:
txt_page_file = st.selectbox(label="Dashboard", options=dash_list, index=dash_default_index)
cmb_group = st.selectbox(label="Gruppe", options=groups, placeholder="Gruppe auswählen", index=idx)
txt_order_no = st.text_input(label="Order-Nr",value=df.iloc[0]["order_no"])
if st.button("Save"):
sql = """
update dashboards set
dash_text = ?,
dash_description = ?,
group_id = ?,
page_file = ?,
dash_type = ?,
active = ?,
order_no = ?
where dash_id = ?
"""
params = (txt_dash_text, txt_dash_description, get_id(cmb_group), txt_page_file, cmb_dash_type, is_active, txt_order_no, dash_id)
if send_cmd(sql, params):
st.session_state.save_msg = f"✅ Dashboard '{txt_dash_text}' erfolgreich geändert"
else:
st.session_state.save_msg = "❌ Fehler beim Speichern"
st.rerun()
def dashborad():
if "selected_dash_id" not in st.session_state:
st.session_state.selected_dash_id = None
#--------------------------------------------------------------------------------------------------
# Dashboard-Verwaltung
#--------------------------------------------------------------------------------------------------
df = get_list("""
select
d.dash_id,
d.dash_text,
d.dash_description,
d.group_id || ' | ' || g.group_text as "group",
d.page_file,
d.dash_type,
d.active,
d.order_no
from
dashboards d
left join groups g
on d.group_id = g.group_id
""")
col_find_dashboard, col_create_dashboard, col_edit_dashboard, col_delete_dashboard = st.columns([3,2,2,2], vertical_alignment="bottom")
with col_find_dashboard:
txt_search = st.text_input(label="Suche", label_visibility="hidden", placeholder="Dashboard, Beschreibung ...", icon=":material/search:")
with col_create_dashboard:
if st.button(label="Dashboard anlegen", use_container_width=True, icon=":material/add:"):
dialog_create_dashboard(get_num("numgen_dashboard"))
if "save_msg" in st.session_state:
st.toast(st.session_state.save_msg)
del st.session_state.save_msg
with col_edit_dashboard:
if st.button(label="Dashboard bearbeiten", use_container_width=True, icon=":material/edit:"):
if not st.session_state.selected_dash_id is None:
dialog_edit_dashboard(st.session_state.selected_dash_id)
else:
st.toast("❌ Bitte erst eine Zeile auswählen")
if "save_msg" in st.session_state:
st.toast(st.session_state.save_msg)
del st.session_state.save_msg
with col_delete_dashboard:
if st.button(label="Dashboard löschen", use_container_width=True, icon=":material/delete:"):
if not st.session_state.selected_dash_id is None:
dialog_delete_dashboard(st.session_state.selected_dash_id)
else:
st.toast("❌ Bitte erst eine Zeile auswählen")
if "delete_msg" in st.session_state:
st.toast(st.session_state.delete_msg)
del st.session_state.delete_msg
if txt_search.strip():
txt_search_norm = txt_search.strip().lower()
mask = (
df["dash_text"].fillna("").str.lower().str.contains(txt_search_norm)
| df["dash_description"].fillna("").str.lower().str.contains(txt_search_norm)
| df["group"].fillna("").str.lower().str.contains(txt_search_norm)
)
df_view = df.loc[mask].copy()
else:
df_view = df.copy()
event = st.dataframe(df_view,key="dash_data", on_select="rerun", selection_mode="single-row")
rows = event.selection.rows
if rows:
row_idx = rows[0]
st.session_state.selected_dash_id = int(df_view.iloc[row_idx]["dash_id"])
else:
st.session_state.selected_dash_id = None
if __name__ == "__main__":
sidebar()

3
app/pages/default.py Normal file
View File

@@ -0,0 +1,3 @@
import streamlit as st
st.header("Baustelle!")

View File

@@ -59,7 +59,7 @@ def dialog_create_group(group_id):
# Dialog Gruppe bearbeiten # Dialog Gruppe bearbeiten
#------------------------------------------------------------------------------------- #-------------------------------------------------------------------------------------
@st.dialog("Benutzer bearbeiten") @st.dialog("Gruppe bearbeiten")
def dialog_edit_group(group_id): def dialog_edit_group(group_id):
if group_id == None: if group_id == None:
st.write("keine Gruppe ausgewählt") st.write("keine Gruppe ausgewählt")

View File

@@ -0,0 +1,213 @@
import streamlit as st
from auth_runtime import require_login
# from ui.sidebar import build_sidebar
from pathlib import Path
from tools.load_css import load_css
from app_db.app_db import get_list, send_cmd
from tools.numgen import get_num, update_num
DASH_NAME = Path(__file__).stem
load_css()
st.set_page_config(page_title="Co-App Benutzer", page_icon=":material/person:", layout="wide", initial_sidebar_state="collapsed")
authenticator = require_login()
st.session_state["authenticator"] = authenticator
def sidebar():
fullname = st.session_state.get("fullname")
role_text = st.session_state.get("role_text")
with st.sidebar:
st.logo("app/images/GMN_Logo_neu_rgb.png", size="small")
st.markdown(f"**{fullname}** ({role_text})")
col1, col2 = st.columns([2,2])
with col1:
authenticator.logout("Logout")
with col2:
if st.button("Home", use_container_width=True, icon=":material/home:"):
st.switch_page("pages/home.py")
roles()
#-------------------------------------------------------------------------------------
# Dialog Rollen anlegen
#-------------------------------------------------------------------------------------
@st.dialog("Rolle anlegen")
def dialog_create_role(role_id):
txt_role_id = st.text_input("RoleId", value=role_id, disabled=True)
txt_role_text = st.text_input("Gruppenbezeichnung")
txt_description = st.text_area("Beschreibung")
txt_order_no = st.text_input("Reihenfolge")
if st.button("Save"):
if send_cmd(f"insert into roles (role_id, role_text, role_description, order_no) " \
"values (?, ?, ?, ?)",(txt_role_id, txt_role_text, txt_description, txt_order_no)):
st.session_state.save_msg = f"✅ Rolle '{txt_role_text}' erfolgreich gespeichert"
update_num(role_id,1,"numgen_role")
else:
st.session_state.save_msg = "❌ Fehler beim Speichern"
st.rerun()
#-------------------------------------------------------------------------------------
# Dialog Rollen bearbeiten
#-------------------------------------------------------------------------------------
@st.dialog("Rolle bearbeiten")
def dialog_edit_role(role_id):
if role_id == None:
st.write("keine Rolle ausgewählt")
else:
sql = """
select
role_id,
role_text,
role_description,
active,
order_no
from
roles
where
role_id = ?
order by
order_no
"""
df = get_list(sql,(role_id,))
col1, col2 = st.columns([2,1],vertical_alignment="center")
with col1:
txt_role_text = st.text_input(label="Rollenbezeichnung", value=df.iloc[0]["role_text"])
with col2:
is_active = st.checkbox(label="Aktiv", value=df.iloc[0]["active"])
txt_role_description = st.text_area(label="Beschreibung", value=df.iloc[0]["role_description"])
txt_oder_no = st.text_input(label="Reihenfolge", value=df.iloc[0]["order_no"])
if st.button("Save"):
sql = """
update roles set
role_text = ?,
active = ?,
role_description = ?,
order_no = ?
where role_id = ?
"""
params = (txt_role_text, is_active, txt_role_description, txt_oder_no, role_id)
if send_cmd(sql, params):
st.session_state.save_msg = f"✅ Rolle '{txt_role_text}' erfolgreich geändert"
else:
st.session_state.save_msg = "❌ Fehler beim Speichern"
st.rerun()
#-------------------------------------------------------------------------------------
# Dialog Rollen löschen
#-------------------------------------------------------------------------------------
@st.dialog("Rolle löschen")
def dialog_delete_role(role_id):
if role_id == None:
st.write("keine Rolle ausgewählt")
else:
df = get_list("select role_text from roles where role_id = ?",(role_id,))
role_text = df.iloc[0]["role_text"]
if role_text != "admin":
st.write(f"Die Rolle {role_text} wird gelöscht! Sind Sie sicher?")
if st.button("Löschen"):
if send_cmd("delete from roles where role_id = ?",(role_id,)):
st.session_state.delete_msg = f"✅ Rolle '{role_text}' erfolgreich gelöscht!"
else:
st.session_state.delete_msg = f"❌ Rolle '{role_text}' konnte nicht gelöscht werden!"
else:
st.session_state.delete_msg = f"❌ Rolle '{role_text}' darf nicht gelöscht werden!"
st.rerun()
def roles():
if "selected_role_id" not in st.session_state:
st.session_state.selected_role_id = None
#--------------------------------------------------------------------------------------------------
# Rollenverwaltung
#--------------------------------------------------------------------------------------------------
df = get_list("""
select
role_id,
role_text,
role_description,
active,
order_no
from
roles
order by
order_no
""")
col_find_role, col_create_role, col_edit_role, col_delete_role = st.columns([3,2,2,2], vertical_alignment="bottom")
with col_find_role:
txt_search = st.text_input(label="Suche", label_visibility="hidden", placeholder="Rolle", icon=":material/search:")
with col_create_role:
if st.button(label="Rolle anlegen", use_container_width=True, icon=":material/add:"):
dialog_create_role(get_num("numgen_role"))
if "save_msg" in st.session_state:
st.toast(st.session_state.save_msg,)
del st.session_state.save_msg
with col_edit_role:
if st.button(label="Rolle bearbeiten", use_container_width=True, icon=":material/edit:"):
if not st.session_state.selected_role_id is None:
dialog_edit_role(st.session_state.selected_role_id)
else:
st.toast("❌ Bitte erst eine Zeile auswählen")
if "save_msg" in st.session_state:
st.toast(st.session_state.save_msg)
del st.session_state.save_msg
with col_delete_role:
if st.button(label="Rolle löschen", use_container_width=True, icon=":material/delete:"):
if not st.session_state.selected_role_id is None:
dialog_delete_role(st.session_state.selected_role_id)
else:
st.toast("❌ Bitte erst eine Zeile auswählen")
if "delete_msg" in st.session_state:
st.toast(st.session_state.delete_msg)
del st.session_state.delete_msg
if txt_search.strip():
txt_search_norm = txt_search.strip().lower()
mask = (
df["role_text"].fillna("").str.lower().str.contains(txt_search_norm)
)
df_view = df.loc[mask].copy()
else:
df_view = df.copy()
event = st.dataframe(df_view, key="role_data", on_select="rerun", selection_mode="single-row", height="auto")
rows = event.selection.rows
if rows:
row_idx = rows[0]
st.session_state.selected_role_id = int(df_view.iloc[row_idx]["role_id"])
else:
st.session_state.selected_role_id = None
if __name__ == "__main__":
sidebar()

View File

@@ -12,6 +12,19 @@ def get_roles():
return df return df
def get_groups():
sql = """
select
group_id || ' | ' || group_text as "group"
from
groups
"""
df = get_list(sql)
return df
def get_id(id_text: str): def get_id(id_text: str):
id = int(id_text.split("|")[0]) id = int(id_text.split("|")[0])
if not id: if not id: