Spaces:
Paused
Paused
Update app.py via AI Editor
Browse files
app.py
CHANGED
@@ -6,7 +6,7 @@ from docx import Document
|
|
6 |
from io import BytesIO
|
7 |
import dash
|
8 |
import dash_bootstrap_components as dbc
|
9 |
-
from dash import html, dcc, Input, Output, State, callback_context, ALL
|
10 |
from dash.dash_table import DataTable
|
11 |
from PyPDF2 import PdfReader
|
12 |
import logging
|
@@ -229,7 +229,7 @@ def get_left_col_content():
|
|
229 |
chat_card
|
230 |
]
|
231 |
|
232 |
-
def get_right_col_content(selected_type,
|
233 |
controls = []
|
234 |
controls.append(html.Div([
|
235 |
html.Div(className="blinking-dot", style={'margin':'0 auto','width':'16px','height':'16px'}),
|
@@ -239,11 +239,13 @@ def get_right_col_content(selected_type, shred_doc, pink_doc, pink_review_doc, r
|
|
239 |
type="dot",
|
240 |
children=[html.Div(id="loading-output")]
|
241 |
))
|
|
|
|
|
242 |
if selected_type == "Shred":
|
243 |
controls.append(
|
244 |
html.Div([
|
245 |
dcc.Upload(
|
246 |
-
id='upload-
|
247 |
children=html.Div([
|
248 |
'Drag and Drop or ',
|
249 |
html.A('Select Files')
|
@@ -263,40 +265,35 @@ def get_right_col_content(selected_type, shred_doc, pink_doc, pink_review_doc, r
|
|
263 |
file_list_component()
|
264 |
])
|
265 |
)
|
|
|
266 |
elif selected_type in doc_dependencies:
|
267 |
sources = doc_dependencies[selected_type]["source"]
|
268 |
for src in sources:
|
269 |
label = ""
|
270 |
loaded_preview = None
|
271 |
-
store_var =
|
272 |
if src == "shred":
|
273 |
label = "Shred (Requirements)"
|
274 |
-
|
275 |
-
loaded_preview = markdown_table_preview(shred_doc)
|
276 |
elif src == "pink":
|
277 |
label = "Pink Document"
|
278 |
-
|
279 |
-
loaded_preview = markdown_narrative_preview(pink_doc)
|
280 |
elif src == "pink_review":
|
281 |
label = "Pink Review"
|
282 |
-
|
283 |
-
loaded_preview = markdown_table_preview(pink_review_doc)
|
284 |
elif src == "red":
|
285 |
label = "Red Document"
|
286 |
-
|
287 |
-
loaded_preview = markdown_narrative_preview(red_doc)
|
288 |
elif src == "red_review":
|
289 |
label = "Red Review"
|
290 |
-
|
291 |
-
loaded_preview = markdown_table_preview(red_review_doc)
|
292 |
elif src == "gold":
|
293 |
label = "Gold Document"
|
294 |
-
|
295 |
-
loaded_preview = markdown_narrative_preview(gold_doc)
|
296 |
controls.append(html.Div([
|
297 |
html.Label(f"Upload {label}"),
|
298 |
dcc.Upload(
|
299 |
-
id={'type':
|
300 |
children=html.Div(['Drag and Drop or ', html.A('Select File')]),
|
301 |
style={
|
302 |
'width': '100%',
|
@@ -310,14 +307,13 @@ def get_right_col_content(selected_type, shred_doc, pink_doc, pink_review_doc, r
|
|
310 |
},
|
311 |
multiple=False
|
312 |
),
|
313 |
-
html.Div(id={'type':
|
314 |
dbc.RadioItems(
|
315 |
-
id={'type':
|
316 |
options=[
|
317 |
-
{'label': 'Loaded Document', 'value': 'loaded'}
|
318 |
-
|
319 |
-
|
320 |
-
value='loaded' if store_var else 'uploaded',
|
321 |
inline=True,
|
322 |
className="mb-2"
|
323 |
),
|
@@ -438,75 +434,143 @@ def update_selected_doc_type(n_clicks_list, btn_ids):
|
|
438 |
State('store-red', 'data'),
|
439 |
State('store-red-review', 'data'),
|
440 |
State('store-gold', 'data'),
|
441 |
-
)
|
442 |
-
def update_right_col(selected_type, shred_doc, pink_doc, pink_review_doc, red_doc, red_review_doc, gold_doc):
|
443 |
-
return get_right_col_content(selected_type, shred_doc, pink_doc, pink_review_doc, red_doc, red_review_doc, gold_doc)
|
444 |
-
|
445 |
-
@app.callback(
|
446 |
-
Output('file-list', 'children'),
|
447 |
-
Output('store-shred', 'data'),
|
448 |
-
Output('document-preview', 'children'),
|
449 |
-
Output('loading-output', 'children'),
|
450 |
-
Output('store-generated-doc', 'data'),
|
451 |
-
Input('upload-document', 'contents'),
|
452 |
-
State('upload-document', 'filename'),
|
453 |
-
State('file-list', 'children'),
|
454 |
-
State('store-shred', 'data'),
|
455 |
-
Input({'type': 'btn-generate-doc', 'index': ALL}, 'n_clicks'),
|
456 |
-
State('selected-doc-type', 'data'),
|
457 |
-
State('store-shred', 'data'),
|
458 |
-
State('store-pink', 'data'),
|
459 |
-
State('store-pink-review', 'data'),
|
460 |
-
State('store-red', 'data'),
|
461 |
-
State('store-red-review', 'data'),
|
462 |
-
State('store-gold', 'data'),
|
463 |
State('store-gold-review', 'data'),
|
464 |
State('store-loe', 'data'),
|
465 |
State('store-virtual-board', 'data'),
|
466 |
-
prevent_initial_call=True
|
467 |
)
|
468 |
-
def
|
469 |
-
|
470 |
-
|
471 |
-
|
472 |
-
|
473 |
-
|
474 |
-
|
475 |
-
|
476 |
-
|
477 |
-
|
478 |
-
|
|
|
|
|
479 |
|
480 |
-
|
481 |
-
|
482 |
-
|
483 |
-
|
484 |
-
|
485 |
-
|
486 |
-
|
487 |
-
|
488 |
-
|
489 |
-
|
490 |
-
|
491 |
-
|
492 |
-
|
493 |
-
|
494 |
-
|
495 |
-
|
496 |
-
|
497 |
-
|
498 |
-
|
499 |
-
|
500 |
-
|
501 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
502 |
|
503 |
-
|
504 |
-
|
505 |
-
|
506 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
507 |
|
508 |
-
|
509 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
510 |
logging.info(f"Generating document for type: {selected_type}")
|
511 |
inputs = {
|
512 |
"shred": shred,
|
@@ -541,46 +605,115 @@ def combined_callback(
|
|
541 |
t.start()
|
542 |
t.join(timeout=60)
|
543 |
generated_doc = result_holder.get('result', 'Error: No document generated.')
|
544 |
-
|
545 |
if selected_type in spreadsheet_types:
|
546 |
preview = markdown_table_preview(generated_doc)
|
547 |
else:
|
548 |
preview = markdown_narrative_preview(generated_doc)
|
549 |
logging.info("Document preview updated.")
|
550 |
-
return
|
551 |
-
|
552 |
-
|
553 |
-
|
554 |
-
if
|
555 |
-
|
556 |
-
|
557 |
-
|
558 |
-
|
559 |
-
|
560 |
-
|
561 |
-
|
562 |
-
|
563 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
564 |
|
565 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
566 |
|
567 |
@app.callback(
|
568 |
Output("download-document", "data"),
|
569 |
Input("btn-download", "n_clicks"),
|
570 |
State('selected-doc-type', 'data'),
|
571 |
State('store-generated-doc', 'data'),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
572 |
prevent_initial_call=True
|
573 |
)
|
574 |
-
def download_document(n_clicks, selected_type, generated_doc):
|
575 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
576 |
logging.warning("No generated document to download.")
|
577 |
return dash.no_update
|
578 |
if selected_type in spreadsheet_types:
|
579 |
-
xlsx_io = markdown_tables_to_xlsx(
|
580 |
logging.info("Spreadsheet document prepared for download.")
|
581 |
return dcc.send_bytes(xlsx_io.getvalue(), filename=f"{selected_type}_output.xlsx")
|
582 |
else:
|
583 |
-
content =
|
584 |
logging.info("Narrative document prepared for download.")
|
585 |
return dcc.send_bytes(content, filename=f"{selected_type}_output.md")
|
586 |
|
|
|
6 |
from io import BytesIO
|
7 |
import dash
|
8 |
import dash_bootstrap_components as dbc
|
9 |
+
from dash import html, dcc, Input, Output, State, callback_context, ALL, MATCH
|
10 |
from dash.dash_table import DataTable
|
11 |
from PyPDF2 import PdfReader
|
12 |
import logging
|
|
|
229 |
chat_card
|
230 |
]
|
231 |
|
232 |
+
def get_right_col_content(selected_type, store_data):
|
233 |
controls = []
|
234 |
controls.append(html.Div([
|
235 |
html.Div(className="blinking-dot", style={'margin':'0 auto','width':'16px','height':'16px'}),
|
|
|
239 |
type="dot",
|
240 |
children=[html.Div(id="loading-output")]
|
241 |
))
|
242 |
+
|
243 |
+
# For Shred, show upload
|
244 |
if selected_type == "Shred":
|
245 |
controls.append(
|
246 |
html.Div([
|
247 |
dcc.Upload(
|
248 |
+
id={'type': 'upload-doc-type', 'subtype': 'shred', 'index': selected_type},
|
249 |
children=html.Div([
|
250 |
'Drag and Drop or ',
|
251 |
html.A('Select Files')
|
|
|
265 |
file_list_component()
|
266 |
])
|
267 |
)
|
268 |
+
# For others, show dependency uploads and previews
|
269 |
elif selected_type in doc_dependencies:
|
270 |
sources = doc_dependencies[selected_type]["source"]
|
271 |
for src in sources:
|
272 |
label = ""
|
273 |
loaded_preview = None
|
274 |
+
store_var = store_data.get(src)
|
275 |
if src == "shred":
|
276 |
label = "Shred (Requirements)"
|
277 |
+
loaded_preview = markdown_table_preview(store_var)
|
|
|
278 |
elif src == "pink":
|
279 |
label = "Pink Document"
|
280 |
+
loaded_preview = markdown_narrative_preview(store_var)
|
|
|
281 |
elif src == "pink_review":
|
282 |
label = "Pink Review"
|
283 |
+
loaded_preview = markdown_table_preview(store_var)
|
|
|
284 |
elif src == "red":
|
285 |
label = "Red Document"
|
286 |
+
loaded_preview = markdown_narrative_preview(store_var)
|
|
|
287 |
elif src == "red_review":
|
288 |
label = "Red Review"
|
289 |
+
loaded_preview = markdown_table_preview(store_var)
|
|
|
290 |
elif src == "gold":
|
291 |
label = "Gold Document"
|
292 |
+
loaded_preview = markdown_narrative_preview(store_var)
|
|
|
293 |
controls.append(html.Div([
|
294 |
html.Label(f"Upload {label}"),
|
295 |
dcc.Upload(
|
296 |
+
id={'type': 'upload-doc-type', 'subtype': src, 'index': selected_type},
|
297 |
children=html.Div(['Drag and Drop or ', html.A('Select File')]),
|
298 |
style={
|
299 |
'width': '100%',
|
|
|
307 |
},
|
308 |
multiple=False
|
309 |
),
|
310 |
+
html.Div(id={'type': 'uploaded-doc-name', 'subtype': src, 'index': selected_type}),
|
311 |
dbc.RadioItems(
|
312 |
+
id={'type': 'radio-doc-source', 'subtype': src, 'index': selected_type},
|
313 |
options=[
|
314 |
+
{'label': 'Loaded Document', 'value': 'loaded'}
|
315 |
+
] if store_var else [],
|
316 |
+
value='loaded' if store_var else None,
|
|
|
317 |
inline=True,
|
318 |
className="mb-2"
|
319 |
),
|
|
|
434 |
State('store-red', 'data'),
|
435 |
State('store-red-review', 'data'),
|
436 |
State('store-gold', 'data'),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
437 |
State('store-gold-review', 'data'),
|
438 |
State('store-loe', 'data'),
|
439 |
State('store-virtual-board', 'data'),
|
|
|
440 |
)
|
441 |
+
def update_right_col(selected_type, shred, pink, pink_review, red, red_review, gold, gold_review, loe, virtual_board):
|
442 |
+
store_data = {
|
443 |
+
"shred": shred,
|
444 |
+
"pink": pink,
|
445 |
+
"pink_review": pink_review,
|
446 |
+
"red": red,
|
447 |
+
"red_review": red_review,
|
448 |
+
"gold": gold,
|
449 |
+
"gold_review": gold_review,
|
450 |
+
"loe": loe,
|
451 |
+
"virtual_board": virtual_board
|
452 |
+
}
|
453 |
+
return get_right_col_content(selected_type, store_data)
|
454 |
|
455 |
+
@app.callback(
|
456 |
+
[
|
457 |
+
Output('store-shred', 'data'),
|
458 |
+
Output('file-list', 'children'),
|
459 |
+
Output({'type': 'uploaded-doc-name', 'subtype': 'shred', 'index': 'Shred'}, 'children')
|
460 |
+
],
|
461 |
+
[
|
462 |
+
Input({'type': 'upload-doc-type', 'subtype': 'shred', 'index': 'Shred'}, 'contents')
|
463 |
+
],
|
464 |
+
[
|
465 |
+
State({'type': 'upload-doc-type', 'subtype': 'shred', 'index': 'Shred'}, 'filename'),
|
466 |
+
State('store-shred', 'data'),
|
467 |
+
State('file-list', 'children')
|
468 |
+
],
|
469 |
+
prevent_initial_call=True
|
470 |
+
)
|
471 |
+
def handle_shred_upload(contents, filenames, current_shred, file_list):
|
472 |
+
if not contents or not filenames:
|
473 |
+
raise dash.exceptions.PreventUpdate
|
474 |
+
if isinstance(contents, str):
|
475 |
+
contents = [contents]
|
476 |
+
filenames = [filenames]
|
477 |
+
file_previews = []
|
478 |
+
latest_text = current_shred
|
479 |
+
for content, name in zip(contents, filenames):
|
480 |
+
file_text = process_document(content, name)
|
481 |
+
uploaded_files[name] = file_text
|
482 |
+
latest_text = file_text
|
483 |
+
file_previews.append(
|
484 |
+
dbc.Row([
|
485 |
+
dbc.Col(
|
486 |
+
html.Button('×', id={'type': 'remove-file', 'index': name}, style={'marginRight': '5px', 'fontSize': '10px'}),
|
487 |
+
width=1
|
488 |
+
),
|
489 |
+
dbc.Col(
|
490 |
+
html.Span(name, style={'wordBreak': 'break-all'}),
|
491 |
+
width=11
|
492 |
+
)
|
493 |
+
], id={'type': 'file-row', 'index': name}, align="center", className="mb-1")
|
494 |
+
)
|
495 |
+
logging.info("Shred document uploaded and stored.")
|
496 |
+
return latest_text, file_previews, filenames[-1]
|
497 |
|
498 |
+
# Pattern-matching callback for all dependency uploads
|
499 |
+
@app.callback(
|
500 |
+
[
|
501 |
+
Output('store-pink', 'data'),
|
502 |
+
Output('store-pink-review', 'data'),
|
503 |
+
Output('store-red', 'data'),
|
504 |
+
Output('store-red-review', 'data'),
|
505 |
+
Output('store-gold', 'data'),
|
506 |
+
Output('store-gold-review', 'data'),
|
507 |
+
Output('store-loe', 'data'),
|
508 |
+
Output('store-virtual-board', 'data'),
|
509 |
+
Output({'type': 'uploaded-doc-name', 'subtype': MATCH, 'index': MATCH}, 'children')
|
510 |
+
],
|
511 |
+
[
|
512 |
+
Input({'type': 'upload-doc-type', 'subtype': ALL, 'index': ALL}, 'contents')
|
513 |
+
],
|
514 |
+
[
|
515 |
+
State({'type': 'upload-doc-type', 'subtype': ALL, 'index': ALL}, 'filename')
|
516 |
+
],
|
517 |
+
prevent_initial_call=True
|
518 |
+
)
|
519 |
+
def handle_dep_upload(contents_list, filenames_list):
|
520 |
+
stores = [dash.no_update]*8
|
521 |
+
upload_name = ""
|
522 |
+
if not contents_list or not filenames_list:
|
523 |
+
return [dash.no_update]*8 + [upload_name]
|
524 |
+
for i, (contents, filenames) in enumerate(zip(contents_list, filenames_list)):
|
525 |
+
if contents and filenames:
|
526 |
+
if isinstance(contents, str):
|
527 |
+
contents = [contents]
|
528 |
+
filenames = [filenames]
|
529 |
+
for content, name in zip(contents, filenames):
|
530 |
+
file_text = process_document(content, name)
|
531 |
+
if 'pink' in name.lower():
|
532 |
+
stores[0] = file_text
|
533 |
+
elif 'pink_review' in name.lower():
|
534 |
+
stores[1] = file_text
|
535 |
+
elif 'red' in name.lower() and 'review' not in name.lower():
|
536 |
+
stores[2] = file_text
|
537 |
+
elif 'red_review' in name.lower():
|
538 |
+
stores[3] = file_text
|
539 |
+
elif 'gold' in name.lower() and 'review' not in name.lower():
|
540 |
+
stores[4] = file_text
|
541 |
+
elif 'gold_review' in name.lower():
|
542 |
+
stores[5] = file_text
|
543 |
+
elif 'loe' in name.lower():
|
544 |
+
stores[6] = file_text
|
545 |
+
elif 'virtual' in name.lower():
|
546 |
+
stores[7] = file_text
|
547 |
+
upload_name = name
|
548 |
+
return stores + [upload_name]
|
549 |
|
550 |
+
@app.callback(
|
551 |
+
Output('document-preview', 'children'),
|
552 |
+
[
|
553 |
+
Input({'type': 'btn-generate-doc', 'index': ALL}, 'n_clicks'),
|
554 |
+
Input('selected-doc-type', 'data'),
|
555 |
+
Input('store-shred', 'data'),
|
556 |
+
Input('store-pink', 'data'),
|
557 |
+
Input('store-pink-review', 'data'),
|
558 |
+
Input('store-red', 'data'),
|
559 |
+
Input('store-red-review', 'data'),
|
560 |
+
Input('store-gold', 'data'),
|
561 |
+
Input('store-gold-review', 'data'),
|
562 |
+
Input('store-loe', 'data'),
|
563 |
+
Input('store-virtual-board', 'data'),
|
564 |
+
State('store-generated-doc', 'data')
|
565 |
+
],
|
566 |
+
prevent_initial_call=True
|
567 |
+
)
|
568 |
+
def preview_or_generate_doc(n_clicks_list, selected_type, shred, pink, pink_review, red, red_review, gold, gold_review, loe, virtual_board, prev_generated):
|
569 |
+
ctx = callback_context
|
570 |
+
trigger = ctx.triggered[0]['prop_id'] if ctx.triggered else ""
|
571 |
+
logging.info(f"Document preview trigger: {trigger}")
|
572 |
+
# If generate button pressed
|
573 |
+
if any(n_clicks_list):
|
574 |
logging.info(f"Generating document for type: {selected_type}")
|
575 |
inputs = {
|
576 |
"shred": shred,
|
|
|
605 |
t.start()
|
606 |
t.join(timeout=60)
|
607 |
generated_doc = result_holder.get('result', 'Error: No document generated.')
|
608 |
+
app.server.config['last_generated_doc'] = generated_doc
|
609 |
if selected_type in spreadsheet_types:
|
610 |
preview = markdown_table_preview(generated_doc)
|
611 |
else:
|
612 |
preview = markdown_narrative_preview(generated_doc)
|
613 |
logging.info("Document preview updated.")
|
614 |
+
return preview
|
615 |
+
# If just switching doc type, show preview of loaded doc (from store)
|
616 |
+
else:
|
617 |
+
# For Shred, show table preview
|
618 |
+
if selected_type == "Shred" and shred:
|
619 |
+
return markdown_table_preview(shred)
|
620 |
+
# For spreadsheet types, preview from store
|
621 |
+
elif selected_type in spreadsheet_types:
|
622 |
+
doc_store = {
|
623 |
+
"Pink Review": pink_review,
|
624 |
+
"Red Review": red_review,
|
625 |
+
"Gold Review": gold_review,
|
626 |
+
"Virtual Board": virtual_board,
|
627 |
+
"LOE": loe
|
628 |
+
}
|
629 |
+
doc = doc_store.get(selected_type, "")
|
630 |
+
return markdown_table_preview(doc)
|
631 |
+
# For narrative types, preview from store
|
632 |
+
elif selected_type in narrative_types:
|
633 |
+
doc_store = {
|
634 |
+
"Pink": pink,
|
635 |
+
"Red": red,
|
636 |
+
"Gold": gold
|
637 |
+
}
|
638 |
+
doc = doc_store.get(selected_type, "")
|
639 |
+
return markdown_narrative_preview(doc)
|
640 |
+
return html.Div("No document loaded.")
|
641 |
|
642 |
+
@app.callback(
|
643 |
+
Output('store-generated-doc', 'data'),
|
644 |
+
[
|
645 |
+
Input({'type': 'btn-generate-doc', 'index': ALL}, 'n_clicks'),
|
646 |
+
Input('selected-doc-type', 'data'),
|
647 |
+
Input('document-preview', 'children')
|
648 |
+
],
|
649 |
+
[
|
650 |
+
State('store-shred', 'data'),
|
651 |
+
State('store-pink', 'data'),
|
652 |
+
State('store-pink-review', 'data'),
|
653 |
+
State('store-red', 'data'),
|
654 |
+
State('store-red-review', 'data'),
|
655 |
+
State('store-gold', 'data'),
|
656 |
+
State('store-gold-review', 'data'),
|
657 |
+
State('store-loe', 'data'),
|
658 |
+
State('store-virtual-board', 'data'),
|
659 |
+
State('store-generated-doc', 'data')
|
660 |
+
],
|
661 |
+
prevent_initial_call=True
|
662 |
+
)
|
663 |
+
def update_generated_doc(n_clicks_list, selected_type, preview_content, shred, pink, pink_review, red, red_review, gold, gold_review, loe, virtual_board, prev_generated):
|
664 |
+
ctx = callback_context
|
665 |
+
trigger = ctx.triggered[0]['prop_id'] if ctx.triggered else ""
|
666 |
+
if any(n_clicks_list):
|
667 |
+
return app.server.config.get('last_generated_doc', prev_generated)
|
668 |
+
return prev_generated
|
669 |
|
670 |
@app.callback(
|
671 |
Output("download-document", "data"),
|
672 |
Input("btn-download", "n_clicks"),
|
673 |
State('selected-doc-type', 'data'),
|
674 |
State('store-generated-doc', 'data'),
|
675 |
+
State('store-shred', 'data'),
|
676 |
+
State('store-pink', 'data'),
|
677 |
+
State('store-pink-review', 'data'),
|
678 |
+
State('store-red', 'data'),
|
679 |
+
State('store-red-review', 'data'),
|
680 |
+
State('store-gold', 'data'),
|
681 |
+
State('store-gold-review', 'data'),
|
682 |
+
State('store-loe', 'data'),
|
683 |
+
State('store-virtual-board', 'data'),
|
684 |
prevent_initial_call=True
|
685 |
)
|
686 |
+
def download_document(n_clicks, selected_type, generated_doc, shred, pink, pink_review, red, red_review, gold, gold_review, loe, virtual_board):
|
687 |
+
doc = generated_doc
|
688 |
+
# If not generated, try to get from store for preview/download
|
689 |
+
if not doc:
|
690 |
+
if selected_type == "Shred":
|
691 |
+
doc = shred
|
692 |
+
elif selected_type == "Pink":
|
693 |
+
doc = pink
|
694 |
+
elif selected_type == "Pink Review":
|
695 |
+
doc = pink_review
|
696 |
+
elif selected_type == "Red":
|
697 |
+
doc = red
|
698 |
+
elif selected_type == "Red Review":
|
699 |
+
doc = red_review
|
700 |
+
elif selected_type == "Gold":
|
701 |
+
doc = gold
|
702 |
+
elif selected_type == "Gold Review":
|
703 |
+
doc = gold_review
|
704 |
+
elif selected_type == "LOE":
|
705 |
+
doc = loe
|
706 |
+
elif selected_type == "Virtual Board":
|
707 |
+
doc = virtual_board
|
708 |
+
if not doc:
|
709 |
logging.warning("No generated document to download.")
|
710 |
return dash.no_update
|
711 |
if selected_type in spreadsheet_types:
|
712 |
+
xlsx_io = markdown_tables_to_xlsx(doc)
|
713 |
logging.info("Spreadsheet document prepared for download.")
|
714 |
return dcc.send_bytes(xlsx_io.getvalue(), filename=f"{selected_type}_output.xlsx")
|
715 |
else:
|
716 |
+
content = doc.encode('utf-8')
|
717 |
logging.info("Narrative document prepared for download.")
|
718 |
return dcc.send_bytes(content, filename=f"{selected_type}_output.md")
|
719 |
|