render draft_editor in ui.py

This commit is contained in:
Lars 2025-12-11 12:11:55 +01:00
parent f4299db347
commit aba6f0c38b

View File

@ -242,6 +242,20 @@ def render_sidebar():
def render_draft_editor(msg):
qid = msg.get('query_id', str(uuid.uuid4()))
key_base = f"draft_{qid}"
body_key = f"{key_base}_txt_body"
# --- CALLBACKS (Lösung für den State-Error) ---
def _append_text(k, text):
current = st.session_state.get(k, "")
st.session_state[k] = f"{current}\n\n{text}"
# Sync auch den generischen Key
st.session_state[f"{key_base}_body"] = st.session_state[k]
def _remove_text(k, text):
current = st.session_state.get(k, "")
# Einfaches Replace (könnte man robuster machen)
st.session_state[k] = current.replace(text, "").strip()
st.session_state[f"{key_base}_body"] = st.session_state[k]
# 1. Init (Nur beim allerersten Laden)
if f"{key_base}_init" not in st.session_state:
@ -251,7 +265,11 @@ def render_draft_editor(msg):
st.session_state[f"{key_base}_title"] = meta.get("title", "")
tags_raw = meta.get("tags", [])
st.session_state[f"{key_base}_tags"] = ", ".join(tags_raw) if isinstance(tags_raw, list) else str(tags_raw)
# Initialisiere beide Keys
st.session_state[body_key] = body.strip()
st.session_state[f"{key_base}_body"] = body.strip()
st.session_state[f"{key_base}_meta"] = meta
st.session_state[f"{key_base}_suggestions"] = []
st.session_state[f"{key_base}_init"] = True
@ -263,7 +281,6 @@ def render_draft_editor(msg):
# Metadata
c1, c2 = st.columns([2, 1])
with c1:
# Titel immer aus State lesen/schreiben
new_title = st.text_input("Titel", key=f"{key_base}_inp_title", value=st.session_state.get(f"{key_base}_title", ""))
with c2:
known_types = ["concept", "project", "decision", "experience", "journal", "person", "value", "goal", "principle", "default"]
@ -278,15 +295,14 @@ def render_draft_editor(msg):
# --- TAB 1: EDITOR ---
with tab_edit:
# WICHTIG: Das Text-Area ist an session_state gebunden via 'key'.
# Das Widget rendert HIER. Änderungen am State müssen VORHER (via Callback) passieren.
current_body = st.text_area(
"Body",
key=f"{key_base}_txt_body", # Master-Key
value=st.session_state.get(f"{key_base}_body", ""),
key=body_key,
height=500,
label_visibility="collapsed"
)
# Sync zurück zum generischen Key für andere Tabs
# Sync manueller Änderungen in den generischen Key
st.session_state[f"{key_base}_body"] = current_body
# --- TAB 2: INTELLIGENCE ---
@ -295,8 +311,7 @@ def render_draft_editor(msg):
if st.button("🔍 Analyse starten", key=f"{key_base}_analyze"):
with st.spinner("Analysiere..."):
# Wir nehmen explizit den Text aus dem Widget-State
text_to_analyze = st.session_state[f"{key_base}_txt_body"]
text_to_analyze = st.session_state[body_key]
analysis = analyze_draft_text(text_to_analyze, new_type)
if "error" in analysis:
@ -313,8 +328,8 @@ def render_draft_editor(msg):
for idx, sugg in enumerate(suggestions):
link_text = sugg.get('suggested_markdown', '')
# Check: Ist der Link schon im Text?
is_inserted = link_text in st.session_state[f"{key_base}_txt_body"]
# Prüfe ob Text vorhanden (Case Insensitive Check wäre besser, hier simpel)
is_inserted = link_text in st.session_state[body_key]
# Card Styling
card_style = "border-left: 3px solid #28a745;" if is_inserted else "border-left: 3px solid #1a73e8;"
@ -328,24 +343,23 @@ def render_draft_editor(msg):
</div>
""", unsafe_allow_html=True)
# Button Logik (Toggle)
# Button Logik mit CALLBACKS (on_click)
if is_inserted:
if st.button(f"❌ Entfernen", key=f"del_{idx}_{key_base}"):
new_text = st.session_state[f"{key_base}_txt_body"].replace(link_text, "").strip()
st.session_state[f"{key_base}_txt_body"] = new_text
st.session_state[f"{key_base}_body"] = new_text
st.rerun()
st.button(
f"❌ Entfernen",
key=f"del_{idx}_{key_base}",
on_click=_remove_text, # Callback
args=(body_key, link_text) # Argumente für Callback
)
else:
if st.button(f" Einfügen", key=f"add_{idx}_{key_base}"):
old_text = st.session_state[f"{key_base}_txt_body"]
new_text = f"{old_text}\n\n{link_text}"
st.session_state[f"{key_base}_txt_body"] = new_text
st.session_state[f"{key_base}_body"] = new_text
st.rerun()
st.button(
f" Einfügen",
key=f"add_{idx}_{key_base}",
on_click=_append_text, # Callback
args=(body_key, link_text) # Argumente für Callback
)
# --- TAB 3: PREVIEW & SAVE ---
# Reassemble Metadata & Body (Always use latest state)
final_tags_list = [t.strip() for t in new_tags.split(",") if t.strip()]
final_meta = {
"id": "generated_on_save",
@ -355,8 +369,8 @@ def render_draft_editor(msg):
"tags": final_tags_list
}
# Wir nehmen den aktuellsten Body aus dem State
final_body_content = st.session_state.get(f"{key_base}_txt_body", "")
# Nimm immer den aktuellsten Text aus dem Widget-State
final_body_content = st.session_state[body_key]
final_doc = build_markdown_doc(final_meta, final_body_content)
with tab_view:
@ -372,9 +386,10 @@ def render_draft_editor(msg):
if st.button("💾 Speichern & Indizieren", type="primary", key=f"{key_base}_save"):
with st.spinner("Speichere im Vault..."):
safe_title = re.sub(r'[^a-zA-Z0-9]', '-', new_title).lower()[:30]
if not safe_title: safe_title = "draft"
fname = f"{datetime.now().strftime('%Y%m%d')}-{safe_title}.md"
# Hier der entscheidende Call mit dem aktuellen Dokument
# Speichern mit aktuellstem Inhalt
result = save_draft_to_vault(final_doc, filename=fname)
if "error" in result: