bluenevus commited on
Commit
0902420
·
verified ·
1 Parent(s): c9922d7

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +100 -25
app.py CHANGED
@@ -24,6 +24,8 @@ model = genai.GenerativeModel('gemini-2.5-pro-preview-03-25')
24
  uploaded_files = {}
25
  current_document = None
26
  document_type = None
 
 
27
 
28
  # Document types and their descriptions
29
  document_types = {
@@ -73,7 +75,7 @@ app.layout = dbc.Container([
73
  ])
74
  ], width=3),
75
  dbc.Col([
76
- html.Div(style={"height": "20px"}), # Added small gap
77
  dcc.Loading(
78
  id="loading-indicator",
79
  type="dot",
@@ -83,7 +85,24 @@ app.layout = dbc.Container([
83
  dbc.Button("Download Document", id="btn-download", color="success", className="mt-3"),
84
  dcc.Download(id="download-document"),
85
  html.Hr(),
86
- html.Div(style={"height": "20px"}), # Added small gap
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
87
  dcc.Loading(
88
  id="chat-loading",
89
  type="dot",
@@ -118,12 +137,13 @@ def process_document(contents, filename):
118
 
119
  @app.callback(
120
  Output('file-list', 'children'),
 
121
  Input('upload-document', 'contents'),
122
  State('upload-document', 'filename'),
123
  State('file-list', 'children')
124
  )
125
  def update_output(list_of_contents, list_of_names, existing_files):
126
- global uploaded_files
127
  if list_of_contents is not None:
128
  new_files = []
129
  for i, (content, name) in enumerate(zip(list_of_contents, list_of_names)):
@@ -135,23 +155,26 @@ def update_output(list_of_contents, list_of_names, existing_files):
135
  ]))
136
  if existing_files is None:
137
  existing_files = []
138
- return existing_files + new_files
139
- return existing_files
 
140
 
141
  @app.callback(
142
  Output('file-list', 'children', allow_duplicate=True),
 
143
  Input({'type': 'remove-file', 'index': dash.ALL}, 'n_clicks'),
144
  State('file-list', 'children'),
145
  prevent_initial_call=True
146
  )
147
  def remove_file(n_clicks, existing_files):
148
- global uploaded_files
149
  ctx = dash.callback_context
150
  if not ctx.triggered:
151
  raise dash.exceptions.PreventUpdate
152
  removed_file = ctx.triggered[0]['prop_id'].split(',')[0].split(':')[-1].strip('}')
153
  uploaded_files.pop(removed_file, None)
154
- return [file for file in existing_files if file['props']['children'][1]['props']['children'] != removed_file]
 
155
 
156
  def generate_document(document_type, file_contents):
157
  prompt = f"""Generate a {document_type} based on the following project artifacts:
@@ -170,28 +193,69 @@ Now, generate the {document_type}:
170
  @app.callback(
171
  Output('document-preview', 'children'),
172
  Output('loading-output', 'children'),
 
 
173
  [Input(f'btn-{doc_type.lower().replace("_", "-")}', 'n_clicks') for doc_type in document_types.keys()],
 
174
  prevent_initial_call=True
175
  )
176
  def generate_document_preview(*args):
177
- global current_document, document_type
178
  ctx = dash.callback_context
179
  if not ctx.triggered:
180
  raise dash.exceptions.PreventUpdate
181
  button_id = ctx.triggered[0]['prop_id'].split('.')[0]
182
  document_type = button_id.replace('btn-', '').replace('-', '_').title()
183
-
184
- if not uploaded_files:
185
- return html.Div("Please upload project artifacts before generating a document."), ""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
186
 
187
- file_contents = list(uploaded_files.values())
188
-
189
  try:
190
- current_document = generate_document(document_type, file_contents)
191
- return dcc.Markdown(current_document), f"{document_type} generated"
 
 
 
 
 
 
 
 
 
192
  except Exception as e:
193
  print(f"Error generating document: {str(e)}")
194
- return html.Div(f"Error generating document: {str(e)}"), "Error"
 
 
 
 
 
 
 
 
 
 
195
 
196
  @app.callback(
197
  Output('chat-output', 'children'),
@@ -230,15 +294,26 @@ def download_document(n_clicks):
230
  if current_document is None:
231
  raise dash.exceptions.PreventUpdate
232
 
233
- # Create an in-memory Word document
234
- doc = Document()
235
- doc.add_paragraph(current_document)
236
-
237
- # Save the document to a BytesIO object
238
- output = BytesIO()
239
- doc.save(output)
240
-
241
- return dcc.send_bytes(output.getvalue(), f"{document_type}.docx")
 
 
 
 
 
 
 
 
 
 
 
242
 
243
  if __name__ == '__main__':
244
  print("Starting the Dash application...")
 
24
  uploaded_files = {}
25
  current_document = None
26
  document_type = None
27
+ shredded_document = None
28
+ pink_review_document = None
29
 
30
  # Document types and their descriptions
31
  document_types = {
 
75
  ])
76
  ], width=3),
77
  dbc.Col([
78
+ html.Div(id='status-bar', className="alert alert-info", style={'marginBottom': '20px'}),
79
  dcc.Loading(
80
  id="loading-indicator",
81
  type="dot",
 
85
  dbc.Button("Download Document", id="btn-download", color="success", className="mt-3"),
86
  dcc.Download(id="download-document"),
87
  html.Hr(),
88
+ html.Div(id='pink-review-upload', style={'display': 'none'}, children=[
89
+ dcc.Upload(
90
+ id='upload-pink-review',
91
+ children=html.Div(['Drag and Drop or ', html.A('Select Pink Review File')]),
92
+ style={
93
+ 'width': '100%',
94
+ 'height': '60px',
95
+ 'lineHeight': '60px',
96
+ 'borderWidth': '1px',
97
+ 'borderStyle': 'dashed',
98
+ 'borderRadius': '5px',
99
+ 'textAlign': 'center',
100
+ 'margin': '10px 0'
101
+ },
102
+ multiple=False
103
+ ),
104
+ html.Div(id='pink-review-file-name')
105
+ ]),
106
  dcc.Loading(
107
  id="chat-loading",
108
  type="dot",
 
137
 
138
  @app.callback(
139
  Output('file-list', 'children'),
140
+ Output('status-bar', 'children'),
141
  Input('upload-document', 'contents'),
142
  State('upload-document', 'filename'),
143
  State('file-list', 'children')
144
  )
145
  def update_output(list_of_contents, list_of_names, existing_files):
146
+ global uploaded_files, shredded_document
147
  if list_of_contents is not None:
148
  new_files = []
149
  for i, (content, name) in enumerate(zip(list_of_contents, list_of_names)):
 
155
  ]))
156
  if existing_files is None:
157
  existing_files = []
158
+ shredded_document = None # Reset shredded document when new files are uploaded
159
+ return existing_files + new_files, "Document uploaded. Please click 'Shred' to proceed."
160
+ return existing_files, "Please upload a document and click 'Shred' to begin."
161
 
162
  @app.callback(
163
  Output('file-list', 'children', allow_duplicate=True),
164
+ Output('status-bar', 'children', allow_duplicate=True),
165
  Input({'type': 'remove-file', 'index': dash.ALL}, 'n_clicks'),
166
  State('file-list', 'children'),
167
  prevent_initial_call=True
168
  )
169
  def remove_file(n_clicks, existing_files):
170
+ global uploaded_files, shredded_document
171
  ctx = dash.callback_context
172
  if not ctx.triggered:
173
  raise dash.exceptions.PreventUpdate
174
  removed_file = ctx.triggered[0]['prop_id'].split(',')[0].split(':')[-1].strip('}')
175
  uploaded_files.pop(removed_file, None)
176
+ shredded_document = None # Reset shredded document when a file is removed
177
+ return [file for file in existing_files if file['props']['children'][1]['props']['children'] != removed_file], "Document removed. Please upload a document and click 'Shred' to begin."
178
 
179
  def generate_document(document_type, file_contents):
180
  prompt = f"""Generate a {document_type} based on the following project artifacts:
 
193
  @app.callback(
194
  Output('document-preview', 'children'),
195
  Output('loading-output', 'children'),
196
+ Output('status-bar', 'children', allow_duplicate=True),
197
+ Output('pink-review-upload', 'style'),
198
  [Input(f'btn-{doc_type.lower().replace("_", "-")}', 'n_clicks') for doc_type in document_types.keys()],
199
+ State('pink-review-file-name', 'children'),
200
  prevent_initial_call=True
201
  )
202
  def generate_document_preview(*args):
203
+ global current_document, document_type, shredded_document, pink_review_document
204
  ctx = dash.callback_context
205
  if not ctx.triggered:
206
  raise dash.exceptions.PreventUpdate
207
  button_id = ctx.triggered[0]['prop_id'].split('.')[0]
208
  document_type = button_id.replace('btn-', '').replace('-', '_').title()
209
+ pink_review_file = args[-1]
210
+
211
+ if not uploaded_files and document_type != "Shred":
212
+ return html.Div("Please upload and shred a document first."), "", "Please upload and shred a document first.", {'display': 'none'}
213
+
214
+ if document_type == "Shred":
215
+ if not uploaded_files:
216
+ return html.Div("Please upload a document before shredding."), "", "Please upload a document before shredding.", {'display': 'none'}
217
+ file_contents = list(uploaded_files.values())
218
+ try:
219
+ shredded_document = generate_document(document_type, file_contents)
220
+ return dcc.Markdown(shredded_document), f"{document_type} generated", "Document shredded. You can now proceed with other operations.", {'display': 'none'}
221
+ except Exception as e:
222
+ print(f"Error generating document: {str(e)}")
223
+ return html.Div(f"Error generating document: {str(e)}"), "Error", "An error occurred while shredding the document.", {'display': 'none'}
224
+
225
+ if shredded_document is None:
226
+ return html.Div("Please shred a document first."), "", "Please shred a document first.", {'display': 'none'}
227
+
228
+ if document_type == "Pink Review":
229
+ return html.Div("Please upload a Pink Team document or use the generated one."), "", "Please upload a Pink Team document or use the generated one.", {'display': 'block'}
230
+
231
+ if document_type in ["Red", "Red Review"] and pink_review_document is None:
232
+ return html.Div("Please complete Pink Review first."), "", "Please complete Pink Review first.", {'display': 'none'}
233
 
 
 
234
  try:
235
+ if document_type == "Pink Review" and pink_review_file:
236
+ current_document = generate_document(document_type, [pink_review_file, shredded_document])
237
+ elif document_type in ["Red", "Red Review"]:
238
+ current_document = generate_document(document_type, [pink_review_document, shredded_document])
239
+ else:
240
+ current_document = generate_document(document_type, [shredded_document])
241
+
242
+ if document_type == "Pink Review":
243
+ pink_review_document = current_document
244
+
245
+ return dcc.Markdown(current_document), f"{document_type} generated", f"{document_type} document generated successfully.", {'display': 'none'}
246
  except Exception as e:
247
  print(f"Error generating document: {str(e)}")
248
+ return html.Div(f"Error generating document: {str(e)}"), "Error", "An error occurred while generating the document.", {'display': 'none'}
249
+
250
+ @app.callback(
251
+ Output('pink-review-file-name', 'children'),
252
+ Input('upload-pink-review', 'contents'),
253
+ State('upload-pink-review', 'filename')
254
+ )
255
+ def update_pink_review_filename(contents, filename):
256
+ if contents is not None:
257
+ return filename
258
+ return ""
259
 
260
  @app.callback(
261
  Output('chat-output', 'children'),
 
294
  if current_document is None:
295
  raise dash.exceptions.PreventUpdate
296
 
297
+ if document_type == "LOE":
298
+ # Create a pandas DataFrame for LOE
299
+ df = pd.read_csv(StringIO(current_document))
300
+
301
+ # Save the DataFrame to an Excel file
302
+ output = BytesIO()
303
+ with pd.ExcelWriter(output, engine='xlsxwriter') as writer:
304
+ df.to_excel(writer, sheet_name='LOE', index=False)
305
+
306
+ return dcc.send_bytes(output.getvalue(), f"{document_type}.xlsx")
307
+ else:
308
+ # Create an in-memory Word document
309
+ doc = Document()
310
+ doc.add_paragraph(current_document)
311
+
312
+ # Save the document to a BytesIO object
313
+ output = BytesIO()
314
+ doc.save(output)
315
+
316
+ return dcc.send_bytes(output.getvalue(), f"{document_type}.docx")
317
 
318
  if __name__ == '__main__':
319
  print("Starting the Dash application...")