Spaces:
Paused
Paused
Update app.py via AI Editor
Browse files
app.py
CHANGED
|
@@ -680,6 +680,68 @@ def unified_master_callback(
|
|
| 680 |
output_data_upload = html.Div("No action taken yet.", style={"wordWrap": "break-word"})
|
| 681 |
uploaded_rfp_decoded_bytes = None
|
| 682 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 683 |
def safe_get_n_clicks(ctx, idx):
|
| 684 |
try:
|
| 685 |
return ctx.inputs_list[idx]
|
|
@@ -757,53 +819,6 @@ def unified_master_callback(
|
|
| 757 |
else:
|
| 758 |
logging.error(f"[{sid}] Failed to decode uploaded proposal: {proposal_filename}")
|
| 759 |
|
| 760 |
-
# --- Fix for delete buttons below ---
|
| 761 |
-
if triggered_id and isinstance(doc_delete_clicks, list):
|
| 762 |
-
for i, n_click in enumerate(doc_delete_clicks):
|
| 763 |
-
if n_click:
|
| 764 |
-
btn_id = ctx.inputs_list[8][i]['id']
|
| 765 |
-
del_filename = btn_id['index']
|
| 766 |
-
# Remove from uploaded_documents
|
| 767 |
-
if del_filename in sess_data["uploaded_documents"]:
|
| 768 |
-
del sess_data["uploaded_documents"][del_filename]
|
| 769 |
-
# Remove from uploaded_documents_fileid and delete Gemini file if exists
|
| 770 |
-
if del_filename in sess_data["uploaded_documents_fileid"]:
|
| 771 |
-
try:
|
| 772 |
-
genai.delete_file(sess_data["uploaded_documents_fileid"][del_filename])
|
| 773 |
-
except Exception as e:
|
| 774 |
-
logging.warning(f"[{sid}] Failed to delete Gemini file {del_filename}: {e}")
|
| 775 |
-
del sess_data["uploaded_documents_fileid"][del_filename]
|
| 776 |
-
# Remove from uploaded_documents_bytes
|
| 777 |
-
if del_filename in sess_data["uploaded_documents_bytes"]:
|
| 778 |
-
del sess_data["uploaded_documents_bytes"][del_filename]
|
| 779 |
-
# Remove from shredded_documents
|
| 780 |
-
if del_filename in sess_data["shredded_documents"]:
|
| 781 |
-
del sess_data["shredded_documents"][del_filename]
|
| 782 |
-
logging.info(f"[{sid}] Document deleted: {del_filename}")
|
| 783 |
-
if selected_doc == del_filename:
|
| 784 |
-
selected_doc = None
|
| 785 |
-
break
|
| 786 |
-
|
| 787 |
-
if triggered_id and isinstance(proposal_delete_clicks, list):
|
| 788 |
-
for i, n_click in enumerate(proposal_delete_clicks):
|
| 789 |
-
if n_click:
|
| 790 |
-
btn_id = ctx.inputs_list[12][i]['id']
|
| 791 |
-
del_filename = btn_id['index']
|
| 792 |
-
# Remove from proposals
|
| 793 |
-
if del_filename in sess_data["proposals"]:
|
| 794 |
-
del sess_data["proposals"][del_filename]
|
| 795 |
-
# Remove from proposals_fileid and delete Gemini file if exists
|
| 796 |
-
if del_filename in sess_data["proposals_fileid"]:
|
| 797 |
-
try:
|
| 798 |
-
genai.delete_file(sess_data["proposals_fileid"][del_filename])
|
| 799 |
-
except Exception as e:
|
| 800 |
-
logging.warning(f"[{sid}] Failed to delete Gemini proposal file {del_filename}: {e}")
|
| 801 |
-
del sess_data["proposals_fileid"][del_filename]
|
| 802 |
-
logging.info(f"[{sid}] Proposal deleted: {del_filename}")
|
| 803 |
-
if selected_proposal == del_filename:
|
| 804 |
-
selected_proposal = None
|
| 805 |
-
break
|
| 806 |
-
|
| 807 |
doc_options = [{'label': truncate_filename(fn), 'value': fn} for fn in sess_data["uploaded_documents"].keys()]
|
| 808 |
doc_value = selected_doc if selected_doc in sess_data["uploaded_documents"] else (next(iter(sess_data["uploaded_documents"]), None) if sess_data["uploaded_documents"] else None)
|
| 809 |
documents_list = get_documents_list(sess_data["uploaded_documents"], sess_data["shredded_documents"])
|
|
|
|
| 680 |
output_data_upload = html.Div("No action taken yet.", style={"wordWrap": "break-word"})
|
| 681 |
uploaded_rfp_decoded_bytes = None
|
| 682 |
|
| 683 |
+
# --- Fix for delete buttons using callback_context.triggered ---
|
| 684 |
+
# Check if a delete button was pressed (documents or proposals)
|
| 685 |
+
if ctx.triggered and ctx.triggered[0]['prop_id']:
|
| 686 |
+
prop_id_str = ctx.triggered[0]['prop_id'].split('.')[0]
|
| 687 |
+
if prop_id_str == "{'type': 'delete-doc-btn', 'index': '*', 'group': 'doc'}" or prop_id_str == "{'type': 'delete-proposal-btn', 'index': '*', 'group': 'proposal'}":
|
| 688 |
+
# fallback for some Dash versions
|
| 689 |
+
prop_id = eval(ctx.triggered[0]['prop_id'].split('.')[0])
|
| 690 |
+
else:
|
| 691 |
+
try:
|
| 692 |
+
import json
|
| 693 |
+
prop_id = json.loads(prop_id_str.replace("'", '"'))
|
| 694 |
+
except Exception:
|
| 695 |
+
prop_id = ctx.triggered[0]['prop_id']
|
| 696 |
+
if isinstance(prop_id, dict) and prop_id.get('type') == 'delete-doc-btn' and prop_id.get('group') == 'doc':
|
| 697 |
+
del_filename = prop_id.get('index')
|
| 698 |
+
if del_filename in sess_data["uploaded_documents"]:
|
| 699 |
+
del sess_data["uploaded_documents"][del_filename]
|
| 700 |
+
if del_filename in sess_data["uploaded_documents_fileid"]:
|
| 701 |
+
try:
|
| 702 |
+
genai.delete_file(sess_data["uploaded_documents_fileid"][del_filename])
|
| 703 |
+
except Exception as e:
|
| 704 |
+
logging.warning(f"[{sid}] Failed to delete Gemini file {del_filename}: {e}")
|
| 705 |
+
del sess_data["uploaded_documents_fileid"][del_filename]
|
| 706 |
+
if del_filename in sess_data["uploaded_documents_bytes"]:
|
| 707 |
+
del sess_data["uploaded_documents_bytes"][del_filename]
|
| 708 |
+
if del_filename in sess_data["shredded_documents"]:
|
| 709 |
+
del sess_data["shredded_documents"][del_filename]
|
| 710 |
+
# If there are temp files on disk, attempt to remove them
|
| 711 |
+
tempdir = sess_data.get("session_tempdir")
|
| 712 |
+
if tempdir and os.path.isdir(tempdir):
|
| 713 |
+
try:
|
| 714 |
+
file_path = os.path.join(tempdir, del_filename)
|
| 715 |
+
if os.path.exists(file_path):
|
| 716 |
+
os.remove(file_path)
|
| 717 |
+
except Exception:
|
| 718 |
+
pass
|
| 719 |
+
if selected_doc == del_filename:
|
| 720 |
+
selected_doc = None
|
| 721 |
+
logging.info(f"[{sid}] Document deleted: {del_filename}")
|
| 722 |
+
elif isinstance(prop_id, dict) and prop_id.get('type') == 'delete-proposal-btn' and prop_id.get('group') == 'proposal':
|
| 723 |
+
del_filename = prop_id.get('index')
|
| 724 |
+
if del_filename in sess_data["proposals"]:
|
| 725 |
+
del sess_data["proposals"][del_filename]
|
| 726 |
+
if del_filename in sess_data["proposals_fileid"]:
|
| 727 |
+
try:
|
| 728 |
+
genai.delete_file(sess_data["proposals_fileid"][del_filename])
|
| 729 |
+
except Exception as e:
|
| 730 |
+
logging.warning(f"[{sid}] Failed to delete Gemini proposal file {del_filename}: {e}")
|
| 731 |
+
del sess_data["proposals_fileid"][del_filename]
|
| 732 |
+
# If there are temp files on disk, attempt to remove them
|
| 733 |
+
tempdir = sess_data.get("session_tempdir")
|
| 734 |
+
if tempdir and os.path.isdir(tempdir):
|
| 735 |
+
try:
|
| 736 |
+
file_path = os.path.join(tempdir, del_filename)
|
| 737 |
+
if os.path.exists(file_path):
|
| 738 |
+
os.remove(file_path)
|
| 739 |
+
except Exception:
|
| 740 |
+
pass
|
| 741 |
+
if selected_proposal == del_filename:
|
| 742 |
+
selected_proposal = None
|
| 743 |
+
logging.info(f"[{sid}] Proposal deleted: {del_filename}")
|
| 744 |
+
|
| 745 |
def safe_get_n_clicks(ctx, idx):
|
| 746 |
try:
|
| 747 |
return ctx.inputs_list[idx]
|
|
|
|
| 819 |
else:
|
| 820 |
logging.error(f"[{sid}] Failed to decode uploaded proposal: {proposal_filename}")
|
| 821 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 822 |
doc_options = [{'label': truncate_filename(fn), 'value': fn} for fn in sess_data["uploaded_documents"].keys()]
|
| 823 |
doc_value = selected_doc if selected_doc in sess_data["uploaded_documents"] else (next(iter(sess_data["uploaded_documents"]), None) if sess_data["uploaded_documents"] else None)
|
| 824 |
documents_list = get_documents_list(sess_data["uploaded_documents"], sess_data["shredded_documents"])
|