diff --git a/app/frontend/ui_components.py b/app/frontend/ui_components.py index 733c778..df585d7 100644 --- a/app/frontend/ui_components.py +++ b/app/frontend/ui_components.py @@ -10,30 +10,33 @@ from ui_api import save_draft_to_vault, analyze_draft_text, send_chat_message, s from ui_config import HISTORY_FILE, COLLECTION_PREFIX, GRAPH_COLORS # --- CALLBACKS --- -# Diese müssen oben definiert sein, damit sie VOR dem Re-Run bekannt sind. def switch_to_editor_callback(note_payload): """ - Callback-Funktion: Wird ausgeführt, wenn der 'Bearbeiten'-Button geklickt wird. - Da dies ein Callback ist, können wir session_state Werte ändern, bevor die UI neu gezeichnet wird. + Lädt eine Note in den Editor. + Versucht, den Original-Dateinamen zu erraten oder zu finden, um Duplikate zu vermeiden. """ - # 1. Inhalt vorbereiten + # 1. Inhalt holen content = note_payload.get('fulltext', '') if not content: - # Fallback: Markdown aus Metadaten rekonstruieren, falls kein Fulltext da ist content = build_markdown_doc(note_payload, "Inhalt konnte nicht geladen werden (nur Metadaten verfügbar).") - # 2. Nachricht simulieren (als ob der Chatbot sie generiert hätte) - # Dies füllt den Editor mit dem Inhalt der Notiz + # 2. Dateinamen-Heuristik (Single Source of Truth) + # Idealfall: Qdrant hat das Feld 'file_path' oder 'filename' gespeichert. + # Fallback: Wir nutzen die note_id oder den Titel, müssen aber beim Speichern aufpassen. + origin_fname = note_payload.get('file_path') or note_payload.get('filename') + + # Nachricht simulieren, die Daten in den Editor trägt st.session_state.messages.append({ "role": "assistant", "intent": "INTERVIEW", "content": content, - "query_id": f"edit_{note_payload['note_id']}" + "query_id": f"edit_{note_payload['note_id']}", + "origin_filename": origin_fname, # WICHTIG: Pfad mitschleifen + "origin_note_id": note_payload['note_id'] # ID für Fallback mitschleifen }) # 3. Modus umschalten - # Das ist der entscheidende Fix: Wir ändern den Wert des Radio-Buttons im State direkt. st.session_state["sidebar_mode_selection"] = "📝 Manueller Editor" # --- UI RENDERER --- @@ -44,7 +47,6 @@ def render_sidebar(): st.caption("v2.6 | WP-19 Graph View") # State-gebundenes Radio Widget - # Wir nutzen 'sidebar_mode_selection' als Key, damit wir ihn programmgesteuert (Callback) ändern können. if "sidebar_mode_selection" not in st.session_state: st.session_state["sidebar_mode_selection"] = "💬 Chat" @@ -69,7 +71,7 @@ def render_sidebar(): def render_draft_editor(msg): """ - Der Editor-Kern. Wird sowohl im Chat (Interview-Modus) als auch im manuellen Modus verwendet. + Smart Editor: Unterscheidet zwischen 'Neu' und 'Update'. """ if "query_id" not in msg or not msg["query_id"]: msg["query_id"] = str(uuid.uuid4()) @@ -77,7 +79,7 @@ def render_draft_editor(msg): qid = msg["query_id"] key_base = f"draft_{qid}" - # State Keys für Persistenz + # State Keys data_meta_key = f"{key_base}_data_meta" data_sugg_key = f"{key_base}_data_suggestions" widget_body_key = f"{key_base}_widget_body" @@ -85,27 +87,40 @@ def render_draft_editor(msg): # --- INIT STATE --- if f"{key_base}_init" not in st.session_state: + # Metadaten parsen meta, body = parse_markdown_draft(msg["content"]) if "type" not in meta: meta["type"] = "default" if "title" not in meta: meta["title"] = "" tags = meta.get("tags", []) meta["tags_str"] = ", ".join(tags) if isinstance(tags, list) else str(tags) + # Daten in Session State laden st.session_state[data_meta_key] = meta st.session_state[data_sugg_key] = [] st.session_state[data_body_key] = body.strip() - # Widget States initialisieren + # Widget States st.session_state[f"{key_base}_wdg_title"] = meta["title"] st.session_state[f"{key_base}_wdg_type"] = meta["type"] st.session_state[f"{key_base}_wdg_tags"] = meta["tags_str"] + + # --- EDITOR LOGIK: Origin Filename --- + # Wir speichern den Original-Namen im State, um beim Speichern zu wissen, ob wir überschreiben müssen. + origin_file = msg.get("origin_filename") + if not origin_file and "origin_note_id" in msg: + # Fallback: Wenn wir keinen Pfad haben, aber eine ID, merken wir uns diese, + # um später ggf. intelligent zu speichern (z.B. {id}.md suchen) + # Hier vereinfacht: Wir setzen es erstmal auf None, User muss aufpassen. + pass + + st.session_state[f"{key_base}_origin_filename"] = origin_file st.session_state[f"{key_base}_init"] = True - # --- STATE RESURRECTION --- + # --- RESURRECTION --- if widget_body_key not in st.session_state and data_body_key in st.session_state: st.session_state[widget_body_key] = st.session_state[data_body_key] - # --- CALLBACKS --- + # --- SYNC FUNCTIONS --- def _sync_meta(): meta = st.session_state[data_meta_key] meta["title"] = st.session_state.get(f"{key_base}_wdg_title", "") @@ -129,11 +144,19 @@ def render_draft_editor(msg): st.session_state[data_body_key] = new_text # --- UI LAYOUT --- - st.markdown(f'