Compare commits

...

1 Commits

Author SHA1 Message Date
knedlik
67170b8130 Änderung: parquet_store.py 2026-03-01 13:11:28 +01:00
7 changed files with 83 additions and 10 deletions

Binary file not shown.

View File

View File

@@ -1,11 +1,13 @@
import streamlit as st import streamlit as st
import pandas as pd import pandas as pd
from data.scriptloader import get_sql #from data.scriptloader import get_sql
from data.db import load_data from data.db import load_data
from auth_runtime import require_login from auth_runtime import require_login
from ui.sidebar import build_sidebar, hide_sidebar_if_logged_out #from ui.sidebar import build_sidebar, hide_sidebar_if_logged_out
from auth import get_fullname_for_user #from auth import get_fullname_for_user
import numpy as np import numpy as np
from tools.excel_export import df_to_excel_bytes
from tools.help_text import get_help
st.set_page_config(page_title="Co-App Home", page_icon="🏠", layout="wide") st.set_page_config(page_title="Co-App Home", page_icon="🏠", layout="wide")
@@ -13,7 +15,17 @@ st.set_page_config(page_title="Co-App Home", page_icon="🏠", layout="wide")
authenticator = require_login() authenticator = require_login()
st.session_state["authenticator"] = authenticator st.session_state["authenticator"] = authenticator
st.markdown("""
<style>
.block-container {
padding-top: 0.2rem;
}
</style>
""", unsafe_allow_html=True)
description = get_help("costobjects")
with st.expander(label=" Hilfe / Hinweise", expanded=False): # ❓
st.markdown(description)
@st.cache_data @st.cache_data
def cache_data() -> pd.DataFrame: def cache_data() -> pd.DataFrame:
@@ -38,18 +50,31 @@ def sidebar_filters(df) -> dict:
This function should contain UI concerns only (widgets, layout), This function should contain UI concerns only (widgets, layout),
and not data filtering logic, to keep the code maintainable. and not data filtering logic, to keep the code maintainable.
""" """
st.markdown("""
<style>
section[data-testid="stSidebar"] .block-container {
padding-top: 0.5rem;
padding-bottom: 0.5rem;
}
section[data-testid="stSidebar"] div[data-testid="stVerticalBlock"] > div {
gap: 0.2rem;
}
</style>
""", unsafe_allow_html=True)
st.sidebar.header("Filter") st.sidebar.header("Filter")
if st.sidebar.button("Refresh (Global)"): if st.sidebar.button("Refresh (Global)"):
cache_data.clear() cache_data.clear()
st.rerun() st.rerun()
year = st.sidebar.selectbox(label="Jahr", options=(2025, 2026), index=1)
filter_text = st.sidebar.text_input(label="Textsuche", placeholder="Suche Objekt, Text, Verantwortlicher") filter_text = st.sidebar.text_input(label="Textsuche", placeholder="Suche Objekt, Text, Verantwortlicher")
col_s1, col_s2 = st.sidebar.columns(2) col_s1, col_s2 = st.sidebar.columns(2)
with col_s1: with col_s1:
typ = st.sidebar.selectbox(label="Typ", options=sorted(df["typ"].dropna().unique()), index=1) year = st.selectbox(label="Jahr", options=(2025, 2026), index=1)
with col_s2: with col_s2:
typ = st.selectbox(label="Typ", options=sorted(df["typ"].dropna().unique()), index=1)
obj = st.sidebar.multiselect("obj", sorted(df["obj"].dropna().unique())) obj = st.sidebar.multiselect("obj", sorted(df["obj"].dropna().unique()))
zgrp1 = st.sidebar.multiselect("ZGrp1", sorted(df["zgrp1"].dropna().unique())) zgrp1 = st.sidebar.multiselect("ZGrp1", sorted(df["zgrp1"].dropna().unique()))
zgrp2 = st.sidebar.multiselect("ZGrp2", sorted(df["zgrp2"].dropna().unique())) zgrp2 = st.sidebar.multiselect("ZGrp2", sorted(df["zgrp2"].dropna().unique()))
@@ -100,9 +125,14 @@ def render_table(df):
Keep this function presentation-only: it should not modify data. Keep this function presentation-only: it should not modify data.
""" """
st.markdown("### Übersicht Kostenobjekte")
st.dataframe(df, hide_index=True, width="stretch", height="stretch") st.dataframe(df, hide_index=True, width="stretch", height="stretch")
def download_data(df):
df.to_excel(path)
def page(): def page():
""" """
Page entry point: orchestrates data loading, UI, filtering, and rendering. Page entry point: orchestrates data loading, UI, filtering, and rendering.
@@ -129,10 +159,9 @@ def page():
# ----------------------------- # -----------------------------
# Presentation # Presentation
# ----------------------------- # -----------------------------
df = df.sort_values(by="obj", key=lambda s: pd.to_numeric(s, errors="coerce"))
df_clean = df[df.columns[:-1]] # letzte Spalten entfernen (sysdate) df_clean = df[df.columns[:-1]] # letzte Spalten entfernen (sysdate)
df_display = df_clean.loc[mask] df_display = df_clean.loc[mask]
df_display = df_display.sort_values(by="obj", key=lambda s: pd.to_numeric(s, errors="coerce"))
render_table(df_display) render_table(df_display)
col1, col2 = st.columns(2) col1, col2 = st.columns(2)
@@ -141,11 +170,15 @@ def page():
with col1: with col1:
st.text(f"Datenstand: {data_as_of}") st.text(f"Datenstand: {data_as_of}")
st.text("Datenquelle: Oracle (PENTA)")
with col2: with col2:
st.markdown(f"<div style='text-align: right;'>Anzahl Zeilen: {row_count}</div>", unsafe_allow_html=True) st.markdown(f"<div style='text-align: right;'>Anzahl Zeilen: {row_count}</div>", unsafe_allow_html=True)
st.download_button(
"📊 Excel-Datei herunterladen",
data=df_to_excel_bytes(df_display),
file_name="kostenobjekte",
mime="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
)

16
app/tools/excel_export.py Normal file
View File

@@ -0,0 +1,16 @@
import pandas as pd
import io
def df_to_excel_bytes(df):
"""
Convert a DataFrame to an in-memory XLSX file.
Returns a BytesIO object suitable for st.download_button(data=...).
"""
buffer = io.BytesIO()
with pd.ExcelWriter(buffer, engine="openpyxl") as writer:
df.to_excel(writer, index=False, sheet_name="Daten")
buffer.seek(0)
return buffer

5
app/tools/help_text.py Normal file
View File

@@ -0,0 +1,5 @@
from app_db.app_db import get_value
def get_help(dashboard :str):
helptext = get_value(f"select dash_description from dashboards where dash_name = '{dashboard}.py'")
return helptext

11
config/settings.py Normal file
View File

@@ -0,0 +1,11 @@
from pathlib import Path
BASE_DIR = Path(__file__).resolve().parents[1]
STORAGE_DIR = BASE_DIR / "storage"
DB_DIR = STORAGE_DIR / "app_db"
DB_PATH = DB_DIR / "app.db"
DWH_DIR = STORAGE_DIR / "dwh"
print(BASE_DIR, DB_DIR)

View File

@@ -0,0 +1,8 @@
begin;
alter table dashboards
add column dash_name text not null default "";
INSERT INTO schema_version (version) VALUES ('20260226_095800_add_col_dashname_dashboards');
COMMIT;