Spaces:
Paused
Paused
Update app.py via AI Editor
Browse files
app.py
CHANGED
|
@@ -668,6 +668,9 @@ def master_callback(
|
|
| 668 |
)
|
| 669 |
|
| 670 |
# File uploads
|
|
|
|
|
|
|
|
|
|
| 671 |
if triggered_id == 'upload-document' and rfp_content is not None and rfp_filename:
|
| 672 |
content_type, content_string = rfp_content.split(',')
|
| 673 |
decoded = base64.b64decode(content_string)
|
|
@@ -682,6 +685,7 @@ def master_callback(
|
|
| 682 |
if fileid:
|
| 683 |
session_dict['uploaded_documents_fileid'][rfp_filename] = fileid
|
| 684 |
logging.info(f"Document uploaded: {rfp_filename}")
|
|
|
|
| 685 |
else:
|
| 686 |
logging.error(f"Failed to decode uploaded document: {rfp_filename}")
|
| 687 |
|
|
@@ -697,10 +701,12 @@ def master_callback(
|
|
| 697 |
if fileid:
|
| 698 |
session_dict['proposals_fileid'][proposal_filename] = fileid
|
| 699 |
logging.info(f"Proposal uploaded: {proposal_filename}")
|
|
|
|
| 700 |
else:
|
| 701 |
logging.error(f"Failed to decode uploaded proposal: {proposal_filename}")
|
| 702 |
|
| 703 |
# Deletion handling
|
|
|
|
| 704 |
if triggered_id and isinstance(doc_delete_clicks, list):
|
| 705 |
for i, n_click in enumerate(doc_delete_clicks):
|
| 706 |
if n_click:
|
|
@@ -720,10 +726,12 @@ def master_callback(
|
|
| 720 |
if del_filename in session_dict['shredded_documents']:
|
| 721 |
del session_dict['shredded_documents'][del_filename]
|
| 722 |
logging.info(f"Shredded doc deleted: {del_filename}")
|
| 723 |
-
if
|
| 724 |
-
|
|
|
|
| 725 |
break
|
| 726 |
|
|
|
|
| 727 |
if triggered_id and isinstance(proposal_delete_clicks, list):
|
| 728 |
for i, n_click in enumerate(proposal_delete_clicks):
|
| 729 |
if n_click:
|
|
@@ -738,16 +746,20 @@ def master_callback(
|
|
| 738 |
logging.warning(f"Failed to delete Gemini proposal file {del_filename}: {e}")
|
| 739 |
del session_dict['proposals_fileid'][del_filename]
|
| 740 |
logging.info(f"Proposal deleted: {del_filename}")
|
| 741 |
-
if
|
| 742 |
-
|
|
|
|
| 743 |
break
|
| 744 |
|
| 745 |
doc_options = [{'label': fn, 'value': fn} for fn in session_dict['uploaded_documents'].keys()]
|
| 746 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 747 |
documents_list = get_documents_list(session_dict['uploaded_documents'], session_dict['shredded_documents'])
|
| 748 |
proposals_list = get_proposals_list(session_dict['proposals'])
|
| 749 |
-
proposal_options = [{'label': fn, 'value': fn} for fn in session_dict['proposals'].keys()]
|
| 750 |
-
proposal_value = selected_proposal if selected_proposal in session_dict['proposals'] else (next(iter(session_dict['proposals']), None) if session_dict['proposals'] else None)
|
| 751 |
|
| 752 |
output_data_upload = html.Div("No action taken yet.", style={"wordWrap": "break-word"})
|
| 753 |
|
|
@@ -801,10 +813,13 @@ def master_callback(
|
|
| 801 |
output_data_upload = dcc.Markdown(result, style={"whiteSpace": "pre-wrap", "wordWrap": "break-word"})
|
| 802 |
finally:
|
| 803 |
lock.release()
|
|
|
|
| 804 |
doc_options = [{'label': fn, 'value': fn} for fn in session_dict['uploaded_documents'].keys()]
|
| 805 |
-
|
|
|
|
| 806 |
proposal_options = [{'label': fn, 'value': fn} for fn in session_dict['proposals'].keys()]
|
| 807 |
-
|
|
|
|
| 808 |
documents_list = get_documents_list(session_dict['uploaded_documents'], session_dict['shredded_documents'])
|
| 809 |
proposals_list = get_proposals_list(session_dict['proposals'])
|
| 810 |
return (
|
|
@@ -814,8 +829,7 @@ def master_callback(
|
|
| 814 |
"expanded"
|
| 815 |
)
|
| 816 |
|
| 817 |
-
|
| 818 |
-
proposal_value = proposal_value if proposal_value in session_dict['proposals'] else (next(iter(session_dict['proposals']), None) if session_dict['proposals'] else None)
|
| 819 |
return (
|
| 820 |
output_data_upload,
|
| 821 |
documents_list, doc_options, doc_value,
|
|
|
|
| 668 |
)
|
| 669 |
|
| 670 |
# File uploads
|
| 671 |
+
doc_value = selected_doc
|
| 672 |
+
proposal_value = selected_proposal
|
| 673 |
+
|
| 674 |
if triggered_id == 'upload-document' and rfp_content is not None and rfp_filename:
|
| 675 |
content_type, content_string = rfp_content.split(',')
|
| 676 |
decoded = base64.b64decode(content_string)
|
|
|
|
| 685 |
if fileid:
|
| 686 |
session_dict['uploaded_documents_fileid'][rfp_filename] = fileid
|
| 687 |
logging.info(f"Document uploaded: {rfp_filename}")
|
| 688 |
+
doc_value = rfp_filename # Set selection to the newly uploaded doc
|
| 689 |
else:
|
| 690 |
logging.error(f"Failed to decode uploaded document: {rfp_filename}")
|
| 691 |
|
|
|
|
| 701 |
if fileid:
|
| 702 |
session_dict['proposals_fileid'][proposal_filename] = fileid
|
| 703 |
logging.info(f"Proposal uploaded: {proposal_filename}")
|
| 704 |
+
proposal_value = proposal_filename # Set selection to the newly uploaded proposal
|
| 705 |
else:
|
| 706 |
logging.error(f"Failed to decode uploaded proposal: {proposal_filename}")
|
| 707 |
|
| 708 |
# Deletion handling
|
| 709 |
+
deleted_doc = False
|
| 710 |
if triggered_id and isinstance(doc_delete_clicks, list):
|
| 711 |
for i, n_click in enumerate(doc_delete_clicks):
|
| 712 |
if n_click:
|
|
|
|
| 726 |
if del_filename in session_dict['shredded_documents']:
|
| 727 |
del session_dict['shredded_documents'][del_filename]
|
| 728 |
logging.info(f"Shredded doc deleted: {del_filename}")
|
| 729 |
+
if doc_value == del_filename:
|
| 730 |
+
doc_value = None
|
| 731 |
+
deleted_doc = True
|
| 732 |
break
|
| 733 |
|
| 734 |
+
deleted_proposal = False
|
| 735 |
if triggered_id and isinstance(proposal_delete_clicks, list):
|
| 736 |
for i, n_click in enumerate(proposal_delete_clicks):
|
| 737 |
if n_click:
|
|
|
|
| 746 |
logging.warning(f"Failed to delete Gemini proposal file {del_filename}: {e}")
|
| 747 |
del session_dict['proposals_fileid'][del_filename]
|
| 748 |
logging.info(f"Proposal deleted: {del_filename}")
|
| 749 |
+
if proposal_value == del_filename:
|
| 750 |
+
proposal_value = None
|
| 751 |
+
deleted_proposal = True
|
| 752 |
break
|
| 753 |
|
| 754 |
doc_options = [{'label': fn, 'value': fn} for fn in session_dict['uploaded_documents'].keys()]
|
| 755 |
+
# Always keep the selected doc if it's still present, otherwise select the first available or None
|
| 756 |
+
if not doc_value or doc_value not in session_dict['uploaded_documents']:
|
| 757 |
+
doc_value = next(iter(session_dict['uploaded_documents']), None)
|
| 758 |
+
proposal_options = [{'label': fn, 'value': fn} for fn in session_dict['proposals'].keys()]
|
| 759 |
+
if not proposal_value or proposal_value not in session_dict['proposals']:
|
| 760 |
+
proposal_value = next(iter(session_dict['proposals']), None)
|
| 761 |
documents_list = get_documents_list(session_dict['uploaded_documents'], session_dict['shredded_documents'])
|
| 762 |
proposals_list = get_proposals_list(session_dict['proposals'])
|
|
|
|
|
|
|
| 763 |
|
| 764 |
output_data_upload = html.Div("No action taken yet.", style={"wordWrap": "break-word"})
|
| 765 |
|
|
|
|
| 813 |
output_data_upload = dcc.Markdown(result, style={"whiteSpace": "pre-wrap", "wordWrap": "break-word"})
|
| 814 |
finally:
|
| 815 |
lock.release()
|
| 816 |
+
# After processing, update lists/options/values, but do NOT clear any document/proposal unless deleted
|
| 817 |
doc_options = [{'label': fn, 'value': fn} for fn in session_dict['uploaded_documents'].keys()]
|
| 818 |
+
if not doc_value or doc_value not in session_dict['uploaded_documents']:
|
| 819 |
+
doc_value = next(iter(session_dict['uploaded_documents']), None)
|
| 820 |
proposal_options = [{'label': fn, 'value': fn} for fn in session_dict['proposals'].keys()]
|
| 821 |
+
if not proposal_value or proposal_value not in session_dict['proposals']:
|
| 822 |
+
proposal_value = next(iter(session_dict['proposals']), None)
|
| 823 |
documents_list = get_documents_list(session_dict['uploaded_documents'], session_dict['shredded_documents'])
|
| 824 |
proposals_list = get_proposals_list(session_dict['proposals'])
|
| 825 |
return (
|
|
|
|
| 829 |
"expanded"
|
| 830 |
)
|
| 831 |
|
| 832 |
+
# Always keep selections sticky, unless user has deleted the item
|
|
|
|
| 833 |
return (
|
| 834 |
output_data_upload,
|
| 835 |
documents_list, doc_options, doc_value,
|