diff --git a/app/.streamlit/config.toml b/app/.streamlit/config.toml index 74812cd..658c3f9 100644 --- a/app/.streamlit/config.toml +++ b/app/.streamlit/config.toml @@ -1,2 +1,3 @@ [client] -showSidebarNavigation = false \ No newline at end of file +showSidebarNavigation = false +toolbarMode = "minimal" diff --git a/app/.streamlit/style.css b/app/.streamlit/style.css new file mode 100644 index 0000000..3e15944 --- /dev/null +++ b/app/.streamlit/style.css @@ -0,0 +1,21 @@ + + +/* Footer entfernen */ +footer {visibility: hidden !important;} +div[data-testid="stStatusWidget"] {display: none !important;} + +/* Sidebar-Spacing kompakter */ +section[data-testid="stSidebar"] > div { + padding-top: 0.5rem !important; +} + +/* Haupt-Container kompakter */ +.block-container { + padding-top: 0.6rem !important; + padding-bottom: 0.6rem !important; +} + +/* Widgets enger */ +.stButton, .stTextInput, .stSelectbox { + margin-bottom: 0.3rem !important; +} diff --git a/app/auth_runtime.py b/app/auth_runtime.py index 98679d2..ed466c7 100644 --- a/app/auth_runtime.py +++ b/app/auth_runtime.py @@ -3,8 +3,30 @@ import yaml from yaml.loader import SafeLoader import streamlit_authenticator as stauth from streamlit_authenticator.utilities.exceptions import LoginError +from auth import ( + load_credentials_from_db, + needs_password_change, + update_password, + get_role_for_user, + get_fullname_for_user, + get_sidebar +) + + +st.markdown(""" + + """, unsafe_allow_html=True) -from auth import load_credentials_from_db, needs_password_change, update_password def get_authenticator(): with open("config/auth.yaml", "r", encoding="utf-8") as f: @@ -41,8 +63,23 @@ def require_login(): st.warning("Bitte Benutzername und Passwort eingeben.") st.stop() - # Passwortwechsel erzwingen + #-------------------------------------------------------------------------------------- + # Ab hier bin ich eingeloggt + #-------------------------------------------------------------------------------------- + username = st.session_state.get("username") + + if "df_sidebar" not in st.session_state: + role_text = get_role_for_user(username) + fullname = get_fullname_for_user(username) + sidebar = get_sidebar(role_text, username) + + st.session_state["role_text"] = role_text + st.session_state["fullname"] = fullname + st.session_state["df_sidebar"] = sidebar + + # Passwortwechsel erzwingen + if needs_password_change(username): st.warning("Du musst dein Passwort ändern, bevor du die Anwendung nutzen kannst.") diff --git a/app/main.py b/app/main.py index 232b9aa..dbd8da6 100644 --- a/app/main.py +++ b/app/main.py @@ -7,24 +7,31 @@ from auth_runtime import require_login from ui.sidebar import build_sidebar import os from app_db.app_db import get_list +from pathlib import Path +from tools.load_css import load_css + APP_ENV = os.environ.get("APP_ENV", "dev") logger = setup_logging(APP_ENV) logger = logging.getLogger(__name__) +load_css() + def main(): + st.set_page_config( page_title=f"Co-App Home - V{__version__}", page_icon="🔒", layout="centered", + menu_items=None, ) authenticator = require_login() -#-------------------------------------------------------------------------------- -# Ab hier ist Benutzer angemeldet!! -#-------------------------------------------------------------------------------- + #-------------------------------------------------------------------------------- + # Ab hier ist Benutzer angemeldet!! + #-------------------------------------------------------------------------------- # Alles was man so braucht in der App wird in session_state abgelegt @@ -32,7 +39,6 @@ def main(): st.session_state["authenticator"] = authenticator # ... dann ist der name des users in der sesstion_state verfügbar! - # Ich suche mir erst mal alles zusammen, was ich dann in session_state speichern will ... username = st.session_state.get("name") # wird duch authenticator gesetzt role_text = get_role_for_user(username) diff --git a/app/pages/costobjects.py b/app/pages/costobjects.py index 065a5bf..35c5d77 100644 --- a/app/pages/costobjects.py +++ b/app/pages/costobjects.py @@ -6,7 +6,7 @@ from auth_runtime import require_login from ui.sidebar import build_sidebar, hide_sidebar_if_logged_out from auth import get_fullname_for_user -hide_sidebar_if_logged_out() +# hide_sidebar_if_logged_out() st.set_page_config(page_title="Co-App Home", page_icon="🏠") diff --git a/app/pages/home.py b/app/pages/home.py index 7c9dcab..1edf249 100644 --- a/app/pages/home.py +++ b/app/pages/home.py @@ -1,18 +1,31 @@ import streamlit as st from auth_runtime import require_login -from ui.sidebar import build_sidebar, hide_sidebar_if_logged_out +from ui.sidebar import build_sidebar from auth import get_fullname_for_user +import pandas as pd +from numpy.random import default_rng as rng +from tools.load_css import load_css -hide_sidebar_if_logged_out() +load_css() st.set_page_config(page_title="Co-App Home", page_icon="🏠") authenticator = require_login() st.session_state["authenticator"] = authenticator +build_sidebar() -#build_sidebar() -username = st.session_state.get("username") -st.header("Controlling-Portal") -st.info(f"Willkommen, {get_fullname_for_user(username)}!") -st.markdown("**Hier könnte eine Hinweistext für den Benutzer stehen**") \ No newline at end of file +def home(): + username = st.session_state.get("name") + st.header("Controlling-Portal") + st.info(f"Willkommen, {get_fullname_for_user(username)}!") + st.markdown("**Hier könnte eine Hinweistext für den Benutzer stehen**") + + df = pd.DataFrame(rng(0).standard_normal((20, 3)), columns=["a", "b", "c"]) + st.area_chart(df) + + + + +if __name__ == "__main__": + home() \ No newline at end of file diff --git a/app/pages/user.py b/app/pages/user.py index 29963e8..08688ab 100644 --- a/app/pages/user.py +++ b/app/pages/user.py @@ -1,52 +1,115 @@ import streamlit as st from auth_runtime import require_login -from ui.sidebar import hide_sidebar_if_logged_out +from ui.sidebar import build_sidebar from auth import create_user from pathlib import Path -from tools.check_permission import check +from tools.load_css import load_css DASH_NAME = Path(__file__).stem # Hier muss die dash_id aus der DB stehen -> wird gegen die session_state geprüft (User-Berechtigung) - - -hide_sidebar_if_logged_out() +load_css() st.set_page_config(page_title="Co-App Benutzer", page_icon="🏠") authenticator = require_login() -username = st.session_state.get("username") -df = st.session_state.get("df_sidebar") +st.session_state["authenticator"] = authenticator -if check(df,DASH_NAME) == False: - st.markdown("**FEHLER**") - st.error("Die Seite kann nicht angezeigt werden - keine Berechtigung!") - st.stop() +def sidebar(): -st.title("Benutzerverwaltung") + 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, col3 = st.columns([2,2,1]) + # with col1: + + # if st.button("Logout", use_container_width=True): + # st.rerun() + with col1: + + authenticator.logout("Logout") + # st.rerun() + # if st.button("Home", use_container_width=True): + # st.switch_page("pages/home.py") -with st.expander("Neuen Nutzer anlegen"): - new_u = st.text_input("Neuer Username", key="new_u") - new_fname = st.text_input("Vorname", key="new_fname") - new_lname = st.text_input("Nachname", key="new_lname") - new_email = st.text_input("E-Mail", key="new_email") - new_p = st.text_input("Neues Passwort", type="password", key="new_p") - new_role = st.selectbox("Rolle", ["user", "admin"], key="new_role") + with col2: + if st.button("🏠 Home", use_container_width=True): + st.switch_page("pages/home.py") + + user() - if st.button("Anlegen"): - if new_u and new_p: - ok = create_user( - new_u.strip(), - new_p, - new_role, - new_email.strip() or None, - new_fname.strip() or None, - new_lname.strip() or None, - ) - st.success("Nutzer angelegt.") if ok else st.error( - "Username bereits vorhanden oder Fehler." - ) - else: - st.warning("Bitte Username und Passwort eingeben.") +def user(): + + st.header("Benutzerverwaltung") - st.subheader("Dein Bereich") - st.write(f"Personalisierter Content für **{username}**.") + + + + + + + + +if __name__ == "__main__": + sidebar() + + + + + + + + + + + + + + +# username = st.session_state.get("username") +# df = st.session_state.get("df_sidebar") + + +# if check(df,DASH_NAME) == False: +# st.markdown("**FEHLER**") +# st.error("Die Seite kann nicht angezeigt werden - keine Berechtigung!") +# st.stop() + +# df = st.session_state.get("df_sidebar") +# st.text(DASH_NAME) +# st.text(st.session_state.get(username)) + +# print(df) + + + +# st.title("Benutzerverwaltung") + +# with st.expander("Neuen Nutzer anlegen"): +# new_u = st.text_input("Neuer Username", key="new_u") +# new_fname = st.text_input("Vorname", key="new_fname") +# new_lname = st.text_input("Nachname", key="new_lname") +# new_email = st.text_input("E-Mail", key="new_email") +# new_p = st.text_input("Neues Passwort", type="password", key="new_p") +# new_role = st.selectbox("Rolle", ["user", "admin"], key="new_role") + +# if st.button("Anlegen"): +# if new_u and new_p: +# ok = create_user( +# new_u.strip(), +# new_p, +# new_role, +# new_email.strip() or None, +# new_fname.strip() or None, +# new_lname.strip() or None, +# ) +# st.success("Nutzer angelegt.") if ok else st.error( +# "Username bereits vorhanden oder Fehler." +# ) +# else: +# st.warning("Bitte Username und Passwort eingeben.") + +# st.subheader("Dein Bereich") +# st.write(f"Personalisierter Content für **{username}**.") diff --git a/app/tools/__init__.py b/app/tools/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/app/tools/check_permission.py b/app/tools/check_permission.py deleted file mode 100644 index bc59e4a..0000000 --- a/app/tools/check_permission.py +++ /dev/null @@ -1,27 +0,0 @@ -import streamlit as st -from auth_runtime import require_login -from auth import get_sidebar, get_fullname_for_user, get_role_for_user - - - -def check(df, page_name): - if "df_sidebar" not in st.session_state: - # authenticator = require_login() - username = st.session_state.get("username") - role_text = get_role_for_user(username) - fullname = get_fullname_for_user(username) - df = get_sidebar(role_text, username) - - st.session_state["role_text"] = role_text - st.session_state["fullname"] = fullname - st.session_state["df_sidebar"] = df - - if df is None or df.empty: - return False # oder True – je nach gewünschtem Verhalten - - allowed = not df[ - (df["dash_type"] == "page") & - (df["page_file"] == page_name) - ].empty - - return True \ No newline at end of file diff --git a/app/tools/load_css.py b/app/tools/load_css.py new file mode 100644 index 0000000..b23b082 --- /dev/null +++ b/app/tools/load_css.py @@ -0,0 +1,8 @@ +import streamlit as st +from pathlib import Path + + +def load_css(): + css_path = Path(__file__).parent.parent / ".streamlit" / "style.css" + if css_path.exists(): + st.markdown(f"", unsafe_allow_html=True) diff --git a/app/ui/sidebar.py b/app/ui/sidebar.py index eb3fe26..7f13e6c 100644 --- a/app/ui/sidebar.py +++ b/app/ui/sidebar.py @@ -7,8 +7,8 @@ from app_db.app_db import get_conn, get_list def build_sidebar(): - if st.session_state.get("authentication_status") != True: - return + # if st.session_state.get("authentication_status") != True: + # return authenticator = st.session_state.get("authenticator") username = st.session_state.get("name") @@ -21,19 +21,18 @@ def build_sidebar(): df = st.session_state.get("df_sidebar") with st.sidebar: + st.logo("app/images/GMN_Logo_neu_rgb.png", size="small") st.markdown(f"**{fullname}** ({role_text})") + col1, col2, col3 = st.columns([2,2,1]) - col1, col2 = st.columns(2) with col1: - if st.button("Logout", use_container_width=True): - authenticator.logout("Logout", "unrendered") - st.rerun() + + authenticator.logout("Logout") + with col2: if st.button("Home", use_container_width=True): st.switch_page("pages/home.py") - st.divider() - st.markdown("## Menü") # --- Suchfeld --- query = st.text_input("Menü-Suche", "", placeholder="z.B. Umsatz, Kosten, User ...") @@ -42,6 +41,9 @@ def build_sidebar(): # Aktive Seite ermitteln (für Expander-Status / Highlight) current_page = st.session_state.get("_page_path") + + + # --- DF filtern, falls Suchbegriff gesetzt --- if query: mask = ( @@ -55,6 +57,7 @@ def build_sidebar(): 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"):