bluenevus commited on
Commit
4dc0cab
·
1 Parent(s): 9dfe505

Update app.py via AI Editor

Browse files
Files changed (1) hide show
  1. app.py +102 -85
app.py CHANGED
@@ -336,28 +336,49 @@ app.layout = dbc.Container([
336
  Output('generated-doc-list', 'children'),
337
  Output('select-generated-dropdown', 'options'),
338
  Output('select-generated-dropdown', 'value'),
339
- Input('upload-document', 'contents'),
340
- State('upload-document', 'filename'),
341
- Input({'type': 'delete-doc-btn', 'index': dash.ALL, 'group': 'rfp'}, 'n_clicks'),
342
- State('select-document-dropdown', 'value'),
343
- Input('upload-proposal', 'contents'),
344
- State('upload-proposal', 'filename'),
345
- Input({'type': 'delete-proposal-btn', 'index': dash.ALL, 'group': 'proposal'}, 'n_clicks'),
346
- State('select-proposal-dropdown', 'value'),
347
- Input({'type': 'delete-generated-btn', 'index': dash.ALL, 'group': 'generated'}, 'n_clicks'),
348
- State('select-generated-dropdown', 'value'),
349
- State('select-generated-dropdown', 'options'),
 
 
 
 
 
 
 
 
 
 
 
 
 
 
350
  prevent_initial_call=True
351
  )
352
- def update_uploaded_docs(
353
  rfp_content, rfp_filename, rfp_delete_clicks, selected_doc,
354
  proposal_content, proposal_filename, proposal_delete_clicks, selected_proposal,
355
- generated_delete_clicks, selected_generated, generated_options
 
 
 
356
  ):
357
  ctx = callback_context
358
- triggered = ctx.triggered
359
 
360
- if rfp_content is not None and rfp_filename:
 
 
 
 
361
  content_type, content_string = rfp_content.split(',')
362
  decoded = base64.b64decode(content_string)
363
  text = decode_document(decoded)
@@ -366,8 +387,10 @@ def update_uploaded_docs(
366
  logging.info(f"Document uploaded: {rfp_filename}")
367
  else:
368
  logging.error(f"Failed to decode uploaded document: {rfp_filename}")
 
369
 
370
- if proposal_content is not None and proposal_filename:
 
371
  content_type, content_string = proposal_content.split(',')
372
  decoded = base64.b64decode(content_string)
373
  text = decode_document(decoded)
@@ -376,8 +399,10 @@ def update_uploaded_docs(
376
  logging.info(f"Proposal uploaded: {proposal_filename}")
377
  else:
378
  logging.error(f"Failed to decode uploaded proposal: {proposal_filename}")
 
379
 
380
- if rfp_delete_clicks:
 
381
  for i, n_click in enumerate(rfp_delete_clicks):
382
  if n_click:
383
  btn_id = ctx.inputs_list[2][i]['id']
@@ -387,8 +412,11 @@ def update_uploaded_docs(
387
  logging.info(f"Document deleted: {del_filename}")
388
  if selected_doc == del_filename:
389
  selected_doc = next(iter(uploaded_documents), None)
 
390
  break
391
- if proposal_delete_clicks:
 
 
392
  for i, n_click in enumerate(proposal_delete_clicks):
393
  if n_click:
394
  btn_id = ctx.inputs_list[6][i]['id']
@@ -398,8 +426,11 @@ def update_uploaded_docs(
398
  logging.info(f"Proposal deleted: {del_filename}")
399
  if selected_proposal == del_filename:
400
  selected_proposal = next(iter(uploaded_proposals), None)
 
401
  break
402
- if generated_delete_clicks:
 
 
403
  for i, n_click in enumerate(generated_delete_clicks):
404
  if n_click:
405
  btn_id = ctx.inputs_list[10][i]['id']
@@ -409,6 +440,7 @@ def update_uploaded_docs(
409
  logging.info(f"Generated doc deleted: {del_filename}")
410
  if selected_generated == del_filename:
411
  selected_generated = next(iter(generated_documents), None)
 
412
  break
413
 
414
  doc_options = [{'label': fn, 'value': fn} for fn in uploaded_documents.keys()]
@@ -417,60 +449,25 @@ def update_uploaded_docs(
417
  proposal_value = selected_proposal if selected_proposal in uploaded_proposals else (next(iter(uploaded_proposals), None) if uploaded_proposals else None)
418
  generated_doc_options = [{'label': fn, 'value': fn} for fn in generated_documents.keys()]
419
  generated_doc_value = selected_generated if selected_generated in generated_documents else (next(iter(generated_documents), None) if generated_documents else None)
420
- return (
421
- get_uploaded_doc_list(uploaded_documents),
422
- doc_options,
423
- doc_value,
424
- proposal_options,
425
- proposal_value,
426
- get_uploaded_proposal_list(uploaded_proposals),
427
- get_generated_doc_list(generated_documents),
428
- generated_doc_options,
429
- generated_doc_value
430
- )
431
 
432
- @app.callback(
433
- Output('output-data-upload', 'children'),
434
- Output('generated-doc-list', 'children'),
435
- Output('select-generated-dropdown', 'options'),
436
- Output('select-generated-dropdown', 'value'),
437
- [
438
- Input('shred-action-btn', 'n_clicks'),
439
- Input('generate-action-btn', 'n_clicks'),
440
- Input('compliance-action-btn', 'n_clicks'),
441
- Input('recover-action-btn', 'n_clicks'),
442
- Input('board-action-btn', 'n_clicks'),
443
- Input('loe-action-btn', 'n_clicks'),
444
- Input('select-generated-dropdown', 'value'),
445
- ],
446
- State('chat-input', 'value'),
447
- State('select-document-dropdown', 'value'),
448
- State('select-proposal-dropdown', 'value'),
449
- State('select-generated-dropdown', 'value'),
450
- prevent_initial_call=True
451
- )
452
- def handle_all_actions(
453
- shred_clicks, generate_clicks, compliance_clicks, recover_clicks, board_clicks, loe_clicks, selected_generated_dropdown,
454
- chat_input, selected_filename, selected_proposal, selected_generated
455
- ):
456
- ctx = callback_context
457
- if not ctx.triggered:
458
- logging.info("No action triggered yet.")
459
- return html.Div("No action taken yet.", style={"wordWrap": "break-word"}), get_generated_doc_list(generated_documents), [{'label': fn, 'value': fn} for fn in generated_documents.keys()], selected_generated
460
 
461
- button_ids = [
 
 
 
462
  'shred-action-btn', 'generate-action-btn', 'compliance-action-btn',
463
  'recover-action-btn', 'board-action-btn', 'loe-action-btn'
464
  ]
465
- triggered_id = ctx.triggered[0]['prop_id'].split('.')[0]
466
- logging.info(f"Trigger: {triggered_id}")
467
 
468
- # if a button is pressed
469
- if triggered_id in button_ids:
470
  result = ""
471
  generated_docx_bytes = None
472
  generated_docx_name = None
473
- new_selected_generated = selected_generated
474
 
475
  if triggered_id == 'shred-action-btn':
476
  result, generated_docx_bytes, generated_docx_name = process_document('shred', selected_filename, chat_input)
@@ -492,31 +489,51 @@ def handle_all_actions(
492
  result = "Action not implemented yet."
493
 
494
  if isinstance(result, str) and result.strip().startswith("Error"):
495
- return html.Div(result, style={"wordWrap": "break-word"}), get_generated_doc_list(generated_documents), [{'label': fn, 'value': fn} for fn in generated_documents.keys()], new_selected_generated
496
- if isinstance(result, str) and ("not implemented" in result or "No document uploaded" in result or "Shredding in progress" in result or "Generating response" in result or "Shredded document not available" in result):
497
- return html.Div(result, style={"wordWrap": "break-word"}), get_generated_doc_list(generated_documents), [{'label': fn, 'value': fn} for fn in generated_documents.keys()], new_selected_generated
498
- return dcc.Markdown(result, style={"whiteSpace": "pre-wrap", "wordWrap": "break-word"}), get_generated_doc_list(generated_documents), [{'label': fn, 'value': fn} for fn in generated_documents.keys()], new_selected_generated
 
 
 
 
 
499
 
500
- # if the generated doc dropdown is changed
501
- if triggered_id == 'select-generated-dropdown':
502
  sel_gen = selected_generated_dropdown
503
  if not sel_gen or sel_gen not in generated_documents:
504
- return html.Div("No generated document selected.", style={"wordWrap": "break-word"}), get_generated_doc_list(generated_documents), [{'label': fn, 'value': fn} for fn in generated_documents.keys()], sel_gen
505
- docx_bytes = generated_documents[sel_gen]
506
- b64 = base64.b64encode(docx_bytes).decode('utf-8')
507
- download_link = html.A(
508
- f"Download {sel_gen}",
509
- href=f"data:application/vnd.openxmlformats-officedocument.wordprocessingml.document;base64,{b64}",
510
- download=sel_gen,
511
- target="_blank",
512
- style={"wordWrap": "break-word"}
513
- )
514
- return html.Div([
515
- html.Div(download_link, style={"marginBottom": "15px"}),
516
- html.Div("Preview not available for docx. Download to view.", style={"wordWrap": "break-word"})
517
- ]), get_generated_doc_list(generated_documents), [{'label': fn, 'value': fn} for fn in generated_documents.keys()], sel_gen
 
 
 
 
518
 
519
- return html.Div("No action taken.", style={"wordWrap": "break-word"}), get_generated_doc_list(generated_documents), [{'label': fn, 'value': fn} for fn in generated_documents.keys()], selected_generated
 
 
 
 
 
 
 
 
 
 
 
520
 
521
  if __name__ == '__main__':
522
  print("Starting the Dash application...")
 
336
  Output('generated-doc-list', 'children'),
337
  Output('select-generated-dropdown', 'options'),
338
  Output('select-generated-dropdown', 'value'),
339
+ Output('output-data-upload', 'children'),
340
+ [
341
+ Input('upload-document', 'contents'),
342
+ State('upload-document', 'filename'),
343
+ Input({'type': 'delete-doc-btn', 'index': dash.ALL, 'group': 'rfp'}, 'n_clicks'),
344
+ State('select-document-dropdown', 'value'),
345
+ Input('upload-proposal', 'contents'),
346
+ State('upload-proposal', 'filename'),
347
+ Input({'type': 'delete-proposal-btn', 'index': dash.ALL, 'group': 'proposal'}, 'n_clicks'),
348
+ State('select-proposal-dropdown', 'value'),
349
+ Input({'type': 'delete-generated-btn', 'index': dash.ALL, 'group': 'generated'}, 'n_clicks'),
350
+ State('select-generated-dropdown', 'value'),
351
+ State('select-generated-dropdown', 'options'),
352
+ Input('shred-action-btn', 'n_clicks'),
353
+ Input('generate-action-btn', 'n_clicks'),
354
+ Input('compliance-action-btn', 'n_clicks'),
355
+ Input('recover-action-btn', 'n_clicks'),
356
+ Input('board-action-btn', 'n_clicks'),
357
+ Input('loe-action-btn', 'n_clicks'),
358
+ Input('select-generated-dropdown', 'value'),
359
+ State('chat-input', 'value'),
360
+ State('select-document-dropdown', 'value'),
361
+ State('select-proposal-dropdown', 'value'),
362
+ State('select-generated-dropdown', 'value'),
363
+ ],
364
  prevent_initial_call=True
365
  )
366
+ def master_callback(
367
  rfp_content, rfp_filename, rfp_delete_clicks, selected_doc,
368
  proposal_content, proposal_filename, proposal_delete_clicks, selected_proposal,
369
+ generated_delete_clicks, selected_generated, generated_options,
370
+ shred_clicks, generate_clicks, compliance_clicks, recover_clicks, board_clicks, loe_clicks,
371
+ selected_generated_dropdown,
372
+ chat_input, selected_filename, selected_proposal_dropdown, selected_generated_dropdown_state
373
  ):
374
  ctx = callback_context
375
+ triggered_id = ctx.triggered[0]['prop_id'].split('.')[0] if ctx.triggered else None
376
 
377
+ # Upload or delete document or proposal or generated document
378
+ upload_triggered = False
379
+
380
+ # Handle upload document
381
+ if triggered_id == 'upload-document' and rfp_content is not None and rfp_filename:
382
  content_type, content_string = rfp_content.split(',')
383
  decoded = base64.b64decode(content_string)
384
  text = decode_document(decoded)
 
387
  logging.info(f"Document uploaded: {rfp_filename}")
388
  else:
389
  logging.error(f"Failed to decode uploaded document: {rfp_filename}")
390
+ upload_triggered = True
391
 
392
+ # Handle upload proposal
393
+ if triggered_id == 'upload-proposal' and proposal_content is not None and proposal_filename:
394
  content_type, content_string = proposal_content.split(',')
395
  decoded = base64.b64decode(content_string)
396
  text = decode_document(decoded)
 
399
  logging.info(f"Proposal uploaded: {proposal_filename}")
400
  else:
401
  logging.error(f"Failed to decode uploaded proposal: {proposal_filename}")
402
+ upload_triggered = True
403
 
404
+ # Handle delete document
405
+ if triggered_id and isinstance(ctx.inputs_list[2], list):
406
  for i, n_click in enumerate(rfp_delete_clicks):
407
  if n_click:
408
  btn_id = ctx.inputs_list[2][i]['id']
 
412
  logging.info(f"Document deleted: {del_filename}")
413
  if selected_doc == del_filename:
414
  selected_doc = next(iter(uploaded_documents), None)
415
+ upload_triggered = True
416
  break
417
+
418
+ # Handle delete proposal
419
+ if triggered_id and isinstance(ctx.inputs_list[6], list):
420
  for i, n_click in enumerate(proposal_delete_clicks):
421
  if n_click:
422
  btn_id = ctx.inputs_list[6][i]['id']
 
426
  logging.info(f"Proposal deleted: {del_filename}")
427
  if selected_proposal == del_filename:
428
  selected_proposal = next(iter(uploaded_proposals), None)
429
+ upload_triggered = True
430
  break
431
+
432
+ # Handle delete generated document
433
+ if triggered_id and isinstance(ctx.inputs_list[10], list):
434
  for i, n_click in enumerate(generated_delete_clicks):
435
  if n_click:
436
  btn_id = ctx.inputs_list[10][i]['id']
 
440
  logging.info(f"Generated doc deleted: {del_filename}")
441
  if selected_generated == del_filename:
442
  selected_generated = next(iter(generated_documents), None)
443
+ upload_triggered = True
444
  break
445
 
446
  doc_options = [{'label': fn, 'value': fn} for fn in uploaded_documents.keys()]
 
449
  proposal_value = selected_proposal if selected_proposal in uploaded_proposals else (next(iter(uploaded_proposals), None) if uploaded_proposals else None)
450
  generated_doc_options = [{'label': fn, 'value': fn} for fn in generated_documents.keys()]
451
  generated_doc_value = selected_generated if selected_generated in generated_documents else (next(iter(generated_documents), None) if generated_documents else None)
 
 
 
 
 
 
 
 
 
 
 
452
 
453
+ uploaded_doc_list = get_uploaded_doc_list(uploaded_documents)
454
+ uploaded_proposal_list = get_uploaded_proposal_list(uploaded_proposals)
455
+ generated_doc_list = get_generated_doc_list(generated_documents)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
456
 
457
+ # Default output
458
+ output_data_upload = html.Div("No action taken yet.", style={"wordWrap": "break-word"})
459
+
460
+ action_buttons = [
461
  'shred-action-btn', 'generate-action-btn', 'compliance-action-btn',
462
  'recover-action-btn', 'board-action-btn', 'loe-action-btn'
463
  ]
 
 
464
 
465
+ # Handle action buttons
466
+ if triggered_id in action_buttons:
467
  result = ""
468
  generated_docx_bytes = None
469
  generated_docx_name = None
470
+ new_selected_generated = generated_doc_value
471
 
472
  if triggered_id == 'shred-action-btn':
473
  result, generated_docx_bytes, generated_docx_name = process_document('shred', selected_filename, chat_input)
 
489
  result = "Action not implemented yet."
490
 
491
  if isinstance(result, str) and result.strip().startswith("Error"):
492
+ output_data_upload = html.Div(result, style={"wordWrap": "break-word"})
493
+ elif isinstance(result, str) and ("not implemented" in result or "No document uploaded" in result or "Shredding in progress" in result or "Generating response" in result or "Shredded document not available" in result):
494
+ output_data_upload = html.Div(result, style={"wordWrap": "break-word"})
495
+ else:
496
+ output_data_upload = dcc.Markdown(result, style={"whiteSpace": "pre-wrap", "wordWrap": "break-word"})
497
+
498
+ generated_doc_options = [{'label': fn, 'value': fn} for fn in generated_documents.keys()]
499
+ generated_doc_value = new_selected_generated if new_selected_generated in generated_documents else (next(iter(generated_documents), None) if generated_documents else None)
500
+ generated_doc_list = get_generated_doc_list(generated_documents)
501
 
502
+ # Handle select-generated-dropdown for download
503
+ elif triggered_id == 'select-generated-dropdown':
504
  sel_gen = selected_generated_dropdown
505
  if not sel_gen or sel_gen not in generated_documents:
506
+ output_data_upload = html.Div("No generated document selected.", style={"wordWrap": "break-word"})
507
+ else:
508
+ docx_bytes = generated_documents[sel_gen]
509
+ b64 = base64.b64encode(docx_bytes).decode('utf-8')
510
+ download_link = html.A(
511
+ f"Download {sel_gen}",
512
+ href=f"data:application/vnd.openxmlformats-officedocument.wordprocessingml.document;base64,{b64}",
513
+ download=sel_gen,
514
+ target="_blank",
515
+ style={"wordWrap": "break-word"}
516
+ )
517
+ output_data_upload = html.Div([
518
+ html.Div(download_link, style={"marginBottom": "15px"}),
519
+ html.Div("Preview not available for docx. Download to view.", style={"wordWrap": "break-word"})
520
+ ])
521
+
522
+ elif upload_triggered:
523
+ output_data_upload = html.Div("Upload/Delete completed.", style={"wordWrap": "break-word"})
524
 
525
+ return (
526
+ uploaded_doc_list,
527
+ doc_options,
528
+ doc_value,
529
+ proposal_options,
530
+ proposal_value,
531
+ uploaded_proposal_list,
532
+ generated_doc_list,
533
+ generated_doc_options,
534
+ generated_doc_value,
535
+ output_data_upload
536
+ )
537
 
538
  if __name__ == '__main__':
539
  print("Starting the Dash application...")