bluenevus commited on
Commit
8c75998
·
1 Parent(s): 1215454

Update app.py via AI Editor

Browse files
Files changed (1) hide show
  1. app.py +86 -18
app.py CHANGED
@@ -49,12 +49,16 @@ def get_or_create_session_data(session_id):
49
  'generated_pptx': None,
50
  'uploaded_file': None,
51
  'uploaded_filename': None,
52
- 'lock': threading.Lock()
 
 
 
53
  }
54
  return SESSION_DATA[session_id]
55
 
56
  app.layout = html.Div([
57
  dcc.Store(id='session-id', storage_type='local'),
 
58
  html.Script('''
59
  (function() {
60
  function uuidv4() {
@@ -75,7 +79,6 @@ app.layout = html.Div([
75
  window.dash_clientside.sessionid = sessionid;
76
  })();
77
  '''),
78
- # Invisible persistent download links for Dash callback tracking
79
  html.A(id='uploaded-file-download-link', href="", style={'display': 'none'}),
80
  html.A(id='pptx-download-link', href="", style={'display': 'none'}),
81
  dbc.Container([
@@ -87,7 +90,7 @@ app.layout = html.Div([
87
  dbc.Textarea(
88
  id='document-text',
89
  placeholder='Enter or paste your document here',
90
- style={'height': '200px'},
91
  className="mb-3"
92
  ),
93
  dcc.Upload(
@@ -105,12 +108,17 @@ app.layout = html.Div([
105
  },
106
  className="mb-3"
107
  ),
108
- html.Div(id="upload-file-link", className="text-muted"),
109
- html.Div(id="pptx-file-link", className="text-muted"),
110
- dbc.Button("Generate Slides", id='generate-button', color="primary", className="w-100 mt-3", size="lg")
 
 
 
 
 
111
  ])
112
  ], className="mb-4 shadow-sm")
113
- ], md=6),
114
  dbc.Col([
115
  dbc.Card([
116
  dbc.CardHeader("Edit Slide Content", className="bg-light"),
@@ -118,7 +126,7 @@ app.layout = html.Div([
118
  dbc.Textarea(
119
  id='slides-content',
120
  placeholder='Generated or pasted markdown will appear here. You can edit the content.',
121
- style={'height': '400px'},
122
  className="mb-3"
123
  ),
124
  dcc.Loading(
@@ -129,10 +137,9 @@ app.layout = html.Div([
129
  ],
130
  style={'width': '100%'}
131
  ),
132
- html.Div(id='log-output', style={'whiteSpace': 'pre-line', 'height': '200px', 'overflowY': 'scroll', 'border': '1px solid #ddd', 'padding': '10px', 'marginTop': '10px'})
133
  ])
134
  ], className="mb-4 shadow-sm")
135
- ], md=6)
136
  ])
137
  ], fluid=True, className="mt-4"),
138
  dcc.Download(id="download-dynamic")
@@ -273,16 +280,20 @@ def store_session_id(n_intervals):
273
  Output('pptx-file-link', 'children'),
274
  Output('slides-content', 'value'),
275
  Output('log-output', 'children'),
 
 
276
  Input('upload-file', 'contents'),
277
  Input('generate-button', 'n_clicks'),
278
  Input('generate-ppt-button', 'n_clicks'),
 
279
  State('upload-file', 'filename'),
280
  State('document-text', 'value'),
281
  State('slides-content', 'value'),
282
  State('session-id', 'data'),
 
283
  prevent_initial_call=True
284
  )
285
- def unified_callback(upload_contents, gen_btn, gen_ppt_btn, upload_filename, document_text, slides_content, session_id):
286
  ctx = callback_context
287
  if not ctx.triggered or not session_id:
288
  raise PreventUpdate
@@ -292,6 +303,10 @@ def unified_callback(upload_contents, gen_btn, gen_ppt_btn, upload_filename, doc
292
  pptx_file_link = ""
293
  slides_md = slides_content
294
  log_str = ""
 
 
 
 
295
  with session['lock']:
296
  if session['uploaded_file'] and session['uploaded_filename']:
297
  upload_file_link = html.A(
@@ -310,6 +325,25 @@ def unified_callback(upload_contents, gen_btn, gen_ppt_btn, upload_filename, doc
310
  style={'display': 'block'}
311
  )
312
  log_str = '\n'.join(session['log_messages'][:100])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
313
  if button_id == 'upload-file':
314
  if upload_contents and upload_filename:
315
  try:
@@ -332,7 +366,7 @@ def unified_callback(upload_contents, gen_btn, gen_ppt_btn, upload_filename, doc
332
  with session['lock']:
333
  session['log_messages'].insert(0, f"{time.strftime('%H:%M:%S')} - Error uploading file: {str(e)}")
334
  log_str = '\n'.join(session['log_messages'][:100])
335
- return upload_file_link, pptx_file_link, slides_content, log_str
336
  elif button_id == 'generate-button':
337
  decoded_file_text = None
338
  if session.get('uploaded_file'):
@@ -345,7 +379,7 @@ def unified_callback(upload_contents, gen_btn, gen_ppt_btn, upload_filename, doc
345
  with session['lock']:
346
  session['log_messages'].insert(0, f"{time.strftime('%H:%M:%S')} - Could not decode uploaded file as text. Please upload a UTF-8 or Latin-1 encoded text file.")
347
  log_str = '\n'.join(session['log_messages'][:100])
348
- return upload_file_link, pptx_file_link, "Could not decode uploaded file as text. Please upload a UTF-8 or Latin-1 encoded text file.", log_str
349
  combined_text = ""
350
  if decoded_file_text and document_text:
351
  combined_text = decoded_file_text.strip() + "\n\n" + document_text.strip()
@@ -357,20 +391,41 @@ def unified_callback(upload_contents, gen_btn, gen_ppt_btn, upload_filename, doc
357
  with session['lock']:
358
  session['log_messages'].insert(0, f"{time.strftime('%H:%M:%S')} - Please upload a file or enter text.")
359
  log_str = '\n'.join(session['log_messages'][:100])
360
- return upload_file_link, pptx_file_link, "Please upload a file or enter text.", log_str
361
  try:
362
  add_log("Starting slide generation...", session_id)
363
  slides_markdown = process_document(combined_text, session_id)
364
  add_log("Slide generation completed.", session_id)
365
  with session['lock']:
 
 
 
 
366
  slides_md = slides_markdown
 
 
367
  log_str = '\n'.join(session['log_messages'][:100])
368
- return upload_file_link, pptx_file_link, slides_md, log_str
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
369
  except Exception as e:
370
  add_log(f"An error occurred during slide generation: {str(e)}", session_id)
371
  with session['lock']:
372
  log_str = '\n'.join(session['log_messages'][:100])
373
- return upload_file_link, pptx_file_link, f"An error occurred: {str(e)}", log_str
374
  elif button_id == 'generate-ppt-button':
375
  if not slides_content or not session_id:
376
  raise PreventUpdate
@@ -388,12 +443,25 @@ def unified_callback(upload_contents, gen_btn, gen_ppt_btn, upload_filename, doc
388
  )
389
  add_log("PowerPoint generation completed.", session_id)
390
  log_str = '\n'.join(session['log_messages'][:100])
391
- return upload_file_link, pptx_file_link, slides_content, log_str
392
  except Exception as e:
393
  add_log(f"An error occurred during PowerPoint generation: {str(e)}", session_id)
394
  with session['lock']:
395
  log_str = '\n'.join(session['log_messages'][:100])
396
- return upload_file_link, pptx_file_link, slides_content, log_str
 
 
 
 
 
 
 
 
 
 
 
 
 
397
  else:
398
  raise PreventUpdate
399
 
 
49
  'generated_pptx': None,
50
  'uploaded_file': None,
51
  'uploaded_filename': None,
52
+ 'lock': threading.Lock(),
53
+ 'slide_markdowns': [], # store generated slide markdowns as list of dicts
54
+ 'slide_markdown_names': [], # Friendly names for dropdown
55
+ 'current_slide_md': "",
56
  }
57
  return SESSION_DATA[session_id]
58
 
59
  app.layout = html.Div([
60
  dcc.Store(id='session-id', storage_type='local'),
61
+ dcc.Store(id='current-slide-index', storage_type='session'),
62
  html.Script('''
63
  (function() {
64
  function uuidv4() {
 
79
  window.dash_clientside.sessionid = sessionid;
80
  })();
81
  '''),
 
82
  html.A(id='uploaded-file-download-link', href="", style={'display': 'none'}),
83
  html.A(id='pptx-download-link', href="", style={'display': 'none'}),
84
  dbc.Container([
 
90
  dbc.Textarea(
91
  id='document-text',
92
  placeholder='Enter or paste your document here',
93
+ style={'height': '80px', 'resize': 'vertical'},
94
  className="mb-3"
95
  ),
96
  dcc.Upload(
 
108
  },
109
  className="mb-3"
110
  ),
111
+ html.Div(id="upload-file-link", className="text-muted mb-2"),
112
+ dbc.Button("Generate Slides", id='generate-button', color="primary", className="w-100 mt-2", size="lg"),
113
+ html.Div(id="slide-generation-list-container", className="mt-3"),
114
+ html.Div(id="pptx-file-link", className="text-muted mb-2"),
115
+ html.Div([
116
+ html.Div("Status / Log:", className="fw-bold mb-1"),
117
+ html.Div(id='log-output', style={'whiteSpace': 'pre-line', 'height': '150px', 'overflowY': 'scroll', 'border': '1px solid #ddd', 'padding': '10px'})
118
+ ], className="mt-3"),
119
  ])
120
  ], className="mb-4 shadow-sm")
121
+ ], width=4, xs=12, sm=12, md=4, lg=4, xl=4, xxl=4),
122
  dbc.Col([
123
  dbc.Card([
124
  dbc.CardHeader("Edit Slide Content", className="bg-light"),
 
126
  dbc.Textarea(
127
  id='slides-content',
128
  placeholder='Generated or pasted markdown will appear here. You can edit the content.',
129
+ style={'height': '400px', 'resize': 'vertical'},
130
  className="mb-3"
131
  ),
132
  dcc.Loading(
 
137
  ],
138
  style={'width': '100%'}
139
  ),
 
140
  ])
141
  ], className="mb-4 shadow-sm")
142
+ ], width=8, xs=12, sm=12, md=8, lg=8, xl=8, xxl=8)
143
  ])
144
  ], fluid=True, className="mt-4"),
145
  dcc.Download(id="download-dynamic")
 
280
  Output('pptx-file-link', 'children'),
281
  Output('slides-content', 'value'),
282
  Output('log-output', 'children'),
283
+ Output('slide-generation-list-container', 'children'),
284
+ Output('current-slide-index', 'data'),
285
  Input('upload-file', 'contents'),
286
  Input('generate-button', 'n_clicks'),
287
  Input('generate-ppt-button', 'n_clicks'),
288
+ Input('slide-generation-list', 'value'),
289
  State('upload-file', 'filename'),
290
  State('document-text', 'value'),
291
  State('slides-content', 'value'),
292
  State('session-id', 'data'),
293
+ State('current-slide-index', 'data'),
294
  prevent_initial_call=True
295
  )
296
+ def unified_callback(upload_contents, gen_btn, gen_ppt_btn, selected_slide_idx, upload_filename, document_text, slides_content, session_id, current_slide_idx):
297
  ctx = callback_context
298
  if not ctx.triggered or not session_id:
299
  raise PreventUpdate
 
303
  pptx_file_link = ""
304
  slides_md = slides_content
305
  log_str = ""
306
+ slide_list = session.get('slide_markdown_names', [])
307
+ slide_md_list = session.get('slide_markdowns', [])
308
+ slide_dropdown = None
309
+ slide_idx = current_slide_idx if current_slide_idx is not None else None
310
  with session['lock']:
311
  if session['uploaded_file'] and session['uploaded_filename']:
312
  upload_file_link = html.A(
 
325
  style={'display': 'block'}
326
  )
327
  log_str = '\n'.join(session['log_messages'][:100])
328
+
329
+ # Build slide markdown dropdown
330
+ dropdown_options = [
331
+ {'label': slide_name, 'value': idx}
332
+ for idx, slide_name in enumerate(slide_list)
333
+ ]
334
+ slide_dropdown = dbc.FormGroup([
335
+ dbc.Label("Generated Slide Sets", className="fw-bold"),
336
+ dcc.Dropdown(
337
+ id='slide-generation-list',
338
+ options=dropdown_options,
339
+ value=slide_idx if (slide_idx is not None and slide_idx < len(slide_list)) else (len(slide_list) - 1 if slide_list else None),
340
+ placeholder="No slides generated yet",
341
+ clearable=False,
342
+ style={'marginBottom': '10px'}
343
+ )
344
+ ]) if slide_list else html.Div("No slides generated yet.", className="text-muted")
345
+
346
+ # Handle triggers
347
  if button_id == 'upload-file':
348
  if upload_contents and upload_filename:
349
  try:
 
366
  with session['lock']:
367
  session['log_messages'].insert(0, f"{time.strftime('%H:%M:%S')} - Error uploading file: {str(e)}")
368
  log_str = '\n'.join(session['log_messages'][:100])
369
+ return upload_file_link, pptx_file_link, slides_content, log_str, slide_dropdown, slide_idx
370
  elif button_id == 'generate-button':
371
  decoded_file_text = None
372
  if session.get('uploaded_file'):
 
379
  with session['lock']:
380
  session['log_messages'].insert(0, f"{time.strftime('%H:%M:%S')} - Could not decode uploaded file as text. Please upload a UTF-8 or Latin-1 encoded text file.")
381
  log_str = '\n'.join(session['log_messages'][:100])
382
+ return upload_file_link, pptx_file_link, "Could not decode uploaded file as text. Please upload a UTF-8 or Latin-1 encoded text file.", log_str, slide_dropdown, slide_idx
383
  combined_text = ""
384
  if decoded_file_text and document_text:
385
  combined_text = decoded_file_text.strip() + "\n\n" + document_text.strip()
 
391
  with session['lock']:
392
  session['log_messages'].insert(0, f"{time.strftime('%H:%M:%S')} - Please upload a file or enter text.")
393
  log_str = '\n'.join(session['log_messages'][:100])
394
+ return upload_file_link, pptx_file_link, "Please upload a file or enter text.", log_str, slide_dropdown, slide_idx
395
  try:
396
  add_log("Starting slide generation...", session_id)
397
  slides_markdown = process_document(combined_text, session_id)
398
  add_log("Slide generation completed.", session_id)
399
  with session['lock']:
400
+ # Add as new slide set to session
401
+ slide_name = f"Slides {time.strftime('%Y-%m-%d %H:%M:%S')}"
402
+ session['slide_markdowns'].append(slides_markdown)
403
+ session['slide_markdown_names'].append(slide_name)
404
  slides_md = slides_markdown
405
+ session['current_slide_md'] = slides_markdown
406
+ slide_idx = len(session['slide_markdowns']) - 1
407
  log_str = '\n'.join(session['log_messages'][:100])
408
+ dropdown_options = [
409
+ {'label': n, 'value': idx}
410
+ for idx, n in enumerate(session['slide_markdown_names'])
411
+ ]
412
+ slide_dropdown = dbc.FormGroup([
413
+ dbc.Label("Generated Slide Sets", className="fw-bold"),
414
+ dcc.Dropdown(
415
+ id='slide-generation-list',
416
+ options=dropdown_options,
417
+ value=slide_idx,
418
+ placeholder="No slides generated yet",
419
+ clearable=False,
420
+ style={'marginBottom': '10px'}
421
+ )
422
+ ])
423
+ return upload_file_link, pptx_file_link, slides_md, log_str, slide_dropdown, slide_idx
424
  except Exception as e:
425
  add_log(f"An error occurred during slide generation: {str(e)}", session_id)
426
  with session['lock']:
427
  log_str = '\n'.join(session['log_messages'][:100])
428
+ return upload_file_link, pptx_file_link, f"An error occurred: {str(e)}", log_str, slide_dropdown, slide_idx
429
  elif button_id == 'generate-ppt-button':
430
  if not slides_content or not session_id:
431
  raise PreventUpdate
 
443
  )
444
  add_log("PowerPoint generation completed.", session_id)
445
  log_str = '\n'.join(session['log_messages'][:100])
446
+ return upload_file_link, pptx_file_link, slides_content, log_str, slide_dropdown, slide_idx
447
  except Exception as e:
448
  add_log(f"An error occurred during PowerPoint generation: {str(e)}", session_id)
449
  with session['lock']:
450
  log_str = '\n'.join(session['log_messages'][:100])
451
+ return upload_file_link, pptx_file_link, slides_content, log_str, slide_dropdown, slide_idx
452
+ elif button_id == 'slide-generation-list':
453
+ try:
454
+ if selected_slide_idx is not None and 0 <= selected_slide_idx < len(slide_md_list):
455
+ slides_md = slide_md_list[selected_slide_idx]
456
+ slide_idx = selected_slide_idx
457
+ else:
458
+ slides_md = ""
459
+ return upload_file_link, pptx_file_link, slides_md, log_str, slide_dropdown, slide_idx
460
+ except Exception as e:
461
+ add_log(f"An error occurred while loading slide set: {str(e)}", session_id)
462
+ with session['lock']:
463
+ log_str = '\n'.join(session['log_messages'][:100])
464
+ return upload_file_link, pptx_file_link, slides_content, log_str, slide_dropdown, slide_idx
465
  else:
466
  raise PreventUpdate
467