# teacher_panel.py from typing import List, Tuple import gradio as gr # needed for gr.SelectData type import qa_store from qa_store import normalize_question from loader import ( generate_new_manual_id, save_manual_qa_file, rebuild_combined_qa, manual_qa_table_data, sync_upload_manual_qa, ) # ๐Ÿ‘‡๐Ÿ‘‡๐Ÿ‘‡ THIS IMPORT WAS MISSING ๐Ÿ‘‡๐Ÿ‘‡๐Ÿ‘‡ from model_utils import admin_force_rebuild_cache def _table() -> List[List[str]]: return manual_qa_table_data() def teacher_save_add_overwrite( question: str, answer: str, current_id: str ) -> Tuple[str, str, str, List[List[str]], str]: question = (question or "").strip() answer = (answer or "").strip() current_id = current_id or "" if not question or not answer: msg = "โŒ เบเบฐเบฅเบธเบ™เบฒเปƒเบชเปˆเบ—เบฑเบ‡เบ„เปเบฒเบ–เบฒเบกเปเบฅเบฐเบ„เปเบฒเบ•เบญเบš." return question, answer, current_id, _table(), msg norm_q = normalize_question(question) entry = qa_store.MANUAL_QA_INDEX.get(norm_q) if entry: entry["q"] = question entry["a"] = answer entry["norm_q"] = norm_q current_id = entry["id"] local_msg = "โœ… เบญเบฑเบšเป€เบ”เบ” Q&A เปเบฅเป‰เบง." else: new_id = generate_new_manual_id() entry = { "id": new_id, "q": question, "a": answer, "norm_q": norm_q, } qa_store.MANUAL_QA_LIST.append(entry) qa_store.MANUAL_QA_INDEX[norm_q] = entry current_id = new_id local_msg = "โœ… เบšเบฑเบ™เบ—เบถเบ Q&A เปƒเปเปˆเปเบฅเป‰เบง." save_manual_qa_file() rebuild_combined_qa() # Capture the upload status and add it to the message cloud_status = sync_upload_manual_qa() final_msg = f"{local_msg} ({cloud_status})" return question, answer, current_id, _table(), final_msg def teacher_rebuild_cache_click(): """Handler for the Rebuild Cache button""" # This checks model_utils.py for the function msg = admin_force_rebuild_cache() return msg def teacher_update_current( question: str, answer: str, current_id: str ) -> Tuple[str, str, str, List[List[str]], str]: question = (question or "").strip() answer = (answer or "").strip() current_id = current_id or "" if not current_id: msg = "โŒ เบเบฐเบฅเบธเบ™เบฒเป€เบฅเบทเบญเบ Q&A เบˆเบฒเบเบ•เบฒเบ•เบฐเบฅเบฒเบ‡เบเปˆเบญเบ™." return question, answer, current_id, _table(), msg if not question or not answer: msg = "โŒ เบเบฐเบฅเบธเบ™เบฒเปƒเบชเปˆเบ—เบฑเบ‡เบ„เปเบฒเบ–เบฒเบกเปเบฅเบฐเบ„เปเบฒเบ•เบญเบš." return question, answer, current_id, _table(), msg entry = next((e for e in qa_store.MANUAL_QA_LIST if e["id"] == current_id), None) if not entry: msg = "โš ๏ธ เบšเปเปˆเบžเบปเบš Q&A เบ—เบตเปˆเป€เบฅเบทเบญเบ." current_id = "" return question, answer, current_id, _table(), msg qa_store.MANUAL_QA_INDEX.pop(entry["norm_q"], None) new_norm = normalize_question(question) entry["q"] = question entry["a"] = answer entry["norm_q"] = new_norm qa_store.MANUAL_QA_INDEX[new_norm] = entry save_manual_qa_file() rebuild_combined_qa() # Capture the upload status cloud_status = sync_upload_manual_qa() final_msg = f"โœ… เปเบเป‰เป„เบ‚ Q&A เบชเปเบฒเป€เบฅเบฑเบ”. ({cloud_status})" return question, answer, current_id, _table(), final_msg def teacher_delete_current( current_id: str, ) -> Tuple[str, str, str, List[List[str]], str]: current_id = current_id or "" if not current_id: msg = "โŒ เบเบฐเบฅเบธเบ™เบฒเป€เบฅเบทเบญเบ Q&A เบเปˆเบญเบ™เบˆเบฐเบฅเบถเบš." return "", "", current_id, _table(), msg entry = next((e for e in qa_store.MANUAL_QA_LIST if e["id"] == current_id), None) if not entry: msg = "โš ๏ธ เบšเปเปˆเบžเบปเบš Q&A เบ—เบตเปˆเบˆเบฐเบฅเบถเบš." return "", "", "", _table(), msg qa_store.MANUAL_QA_LIST = [e for e in qa_store.MANUAL_QA_LIST if e["id"] != current_id] qa_store.MANUAL_QA_INDEX.pop(entry["norm_q"], None) save_manual_qa_file() rebuild_combined_qa() # Capture the upload status cloud_status = sync_upload_manual_qa() final_msg = f"๐Ÿ—‘๏ธ เบฅเบถเบš Q&A เบชเปเบฒเป€เบฅเบฑเบ”. ({cloud_status})" return "", "", "", _table(), final_msg def teacher_on_table_select( evt: gr.SelectData, ) -> Tuple[str, str, str, str]: """ When teacher clicks a row in the Q&A table, load Q/A into textboxes. """ try: if evt is None or evt.index is None or evt.row_value is None: raise ValueError("Empty select event") row = list(evt.row_value) current_id = str(row[0]) if len(row) > 0 else "" question = str(row[1]) if len(row) > 1 else "" answer = str(row[2]) if len(row) > 2 else "" if not current_id: raise ValueError("Empty ID from selected row") msg = f"โœ๏ธ เป€เบฅเบทเบญเบ Q&A ID {current_id} เบชเปเบฒเบฅเบฑเบšเปเบเป‰เป„เบ‚." except Exception as e: # noqa: BLE001 print(f"[WARN] teacher_on_table_select error: {e}") current_id = "" question = "" answer = "" msg = "โš ๏ธ เบšเปเปˆเบชเบฒเบกเบฒเบ”เป€เบฅเบทเบญเบเปเบ–เบงเป„เบ”เป‰." return question, answer, current_id, msg