bluenevus commited on
Commit
b640a17
·
verified ·
1 Parent(s): 655f0c5

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +51 -130
app.py CHANGED
@@ -26,8 +26,6 @@ current_document = None
26
  document_type = None
27
  shredded_document = None
28
  pink_review_document = None
29
- red_review_document = None
30
- generated_documents = {}
31
 
32
  # Document types and their descriptions
33
  document_types = {
@@ -36,7 +34,7 @@ document_types = {
36
  "Pink Review": "Evaluate compliance of the Pink Team document against the requirements and output a spreadsheet of non compliant findings by pws number, the goal of that pws section, what made it non compliant and your recommendations for recovery",
37
  "Red": "Produce a Red Team document based on the Pink Review by pws sections. Your goal is to be compliant and compelling by recovering all the findings in Pink Review",
38
  "Red Review": "Evaluate compliance of the Red Team document against the requirements and output a spreadsheet of non compliant findings by pws number, the goal of that pws section, what made it non compliant and your recommendations for recovery",
39
- "Gold": "Create a Gold Team document based on the PWS response by pws sections. Your goal is to be compliant and compelling by recovering all the findings in Red Review",
40
  "Gold Review": "Perform a final compliance review against the requirements and output a spreadsheet of non compliant findings by pws number, the goal of that pws section, what made it non compliant and your recommendations for recovery",
41
  "Virtual Board": "Based on the requirements and in particular the evaulation criteria, you will evaluate the proposal as if you were a contracting office and provide section by section evaluation as unsatisfactory, satisfactory, good, very good, excellent and why in a spreadsheet",
42
  "LOE": "Generate a Level of Effort (LOE) breakdown as a spreadsheet"
@@ -87,10 +85,10 @@ app.layout = dbc.Container([
87
  dbc.Button("Download Document", id="btn-download", color="success", className="mt-3"),
88
  dcc.Download(id="download-document"),
89
  html.Hr(),
90
- html.Div(id='document-upload', style={'display': 'none'}, children=[
91
  dcc.Upload(
92
- id='upload-specific-document',
93
- children=html.Div(['Drag and Drop or ', html.A('Select Document')]),
94
  style={
95
  'width': '100%',
96
  'height': '60px',
@@ -103,19 +101,8 @@ app.layout = dbc.Container([
103
  },
104
  multiple=False
105
  ),
106
- html.Div(id='specific-document-name')
107
  ]),
108
- html.Div(id='document-choice', style={'display': 'none'}, children=[
109
- dcc.RadioItems(
110
- id='document-source',
111
- options=[
112
- {'label': 'Use Generated Document', 'value': 'generated'},
113
- {'label': 'Use Uploaded Document', 'value': 'uploaded'}
114
- ],
115
- value='generated'
116
- )
117
- ]),
118
- dbc.Button("Generate Document", id="btn-generate-document", color="primary", className="mt-3", style={'display': 'none'}),
119
  dcc.Loading(
120
  id="chat-loading",
121
  type="dot",
@@ -168,13 +155,10 @@ def update_output(list_of_contents, list_of_names, existing_files):
168
  ]))
169
  if existing_files is None:
170
  existing_files = []
171
- elif not isinstance(existing_files, list):
172
- existing_files = [existing_files]
173
  shredded_document = None # Reset shredded document when new files are uploaded
174
- updated_files = existing_files + new_files
175
- return updated_files, f"{len(new_files)} document(s) uploaded. Please click 'Shred' to proceed."
176
- return dash.no_update, "Please upload a document and click 'Shred' to begin."
177
-
178
  @app.callback(
179
  Output('file-list', 'children', allow_duplicate=True),
180
  Output('status-bar', 'children', allow_duplicate=True),
@@ -188,11 +172,9 @@ def remove_file(n_clicks, existing_files):
188
  if not ctx.triggered:
189
  raise dash.exceptions.PreventUpdate
190
  removed_file = ctx.triggered[0]['prop_id'].split(',')[0].split(':')[-1].strip('}')
191
- if removed_file in uploaded_files:
192
- uploaded_files.pop(removed_file, None)
193
- shredded_document = None # Reset shredded document when a file is removed
194
- return [file for file in existing_files if file['props']['children'][1]['props']['children'] != removed_file], f"Document '{removed_file}' removed."
195
- return dash.no_update, dash.no_update
196
 
197
  def generate_document(document_type, file_contents):
198
  prompt = f"""Generate a {document_type} based on the following project artifacts:
@@ -204,7 +186,7 @@ Instructions:
204
  4. Start the output immediately with the document content.
205
  5. IMPORTANT: If the document type is Pink, Red, Gold and not review type, loe or board
206
  then your goal is to be compliant and compelling based on the
207
- requirements, write in paragraph in active voice as
208
  MicroHealth, limit bullets, answer the
209
  requirement with what MicroHealth will do
210
  to satisfy the requirement, the technical
@@ -232,126 +214,65 @@ Now, generate the {document_type}:
232
  Output('document-preview', 'children'),
233
  Output('loading-output', 'children'),
234
  Output('status-bar', 'children', allow_duplicate=True),
235
- Output('document-upload', 'style'),
236
- Output('document-choice', 'style'),
237
- Output('btn-generate-document', 'style'),
238
- [Input(f'btn-{doc_type.lower().replace(" ", "-")}', 'n_clicks') for doc_type in document_types.keys()],
239
  prevent_initial_call=True
240
  )
241
- def update_document_type(*args):
242
- global document_type
243
  ctx = dash.callback_context
244
  if not ctx.triggered:
245
  raise dash.exceptions.PreventUpdate
246
-
247
- triggered_id = ctx.triggered[0]['prop_id'].split('.')[0]
248
-
249
- if triggered_id.startswith('btn-'):
250
- document_type = triggered_id.replace('btn-', '').replace('-', ' ').title()
251
- if document_type == "Shred":
252
- return html.Div("Ready to shred. Click 'Generate Document' to proceed."), "", dash.no_update, {'display': 'none'}, {'display': 'none'}, {'display': 'block'}
253
- elif document_type in ["Pink", "Red", "Gold"]:
254
- return html.Div(f"Ready to generate {document_type} document."), "", dash.no_update, {'display': 'block'}, {'display': 'flex'}, {'display': 'block'}
255
- elif document_type in ["Pink Review", "Red Review", "Gold Review", "Virtual Board", "Loe"]:
256
- return html.Div(f"Ready to generate {document_type}."), "", dash.no_update, {'display': 'block'}, {'display': 'flex'}, {'display': 'block'}
257
-
258
- return dash.no_update, dash.no_update, dash.no_update, dash.no_update, dash.no_update, dash.no_update
259
 
260
- @app.callback(
261
- Output('document-preview', 'children', allow_duplicate=True),
262
- Output('loading-output', 'children', allow_duplicate=True),
263
- Output('status-bar', 'children', allow_duplicate=True),
264
- Input('btn-generate-document', 'n_clicks'),
265
- State('document-source', 'value'),
266
- State('specific-document-name', 'children'),
267
- prevent_initial_call=True
268
- )
269
- @app.callback(
270
- Output('document-preview', 'children', allow_duplicate=True),
271
- Output('loading-output', 'children', allow_duplicate=True),
272
- Output('status-bar', 'children', allow_duplicate=True),
273
- Input('btn-generate-document', 'n_clicks'),
274
- State('document-source', 'value'),
275
- State('specific-document-name', 'children'),
276
- prevent_initial_call=True
277
- )
278
- @app.callback(
279
- Output('document-preview', 'children', allow_duplicate=True),
280
- Output('loading-output', 'children', allow_duplicate=True),
281
- Output('status-bar', 'children', allow_duplicate=True),
282
- Input('btn-generate-document', 'n_clicks'),
283
- State('document-source', 'value'),
284
- State('specific-document-name', 'children'),
285
- prevent_initial_call=True
286
- )
287
- def generate_document_preview(n_clicks, document_source, specific_document):
288
- global current_document, document_type, shredded_document, generated_documents
289
-
290
  if document_type == "Shred":
291
  if not uploaded_files:
292
- return html.Div("Please upload a document before shredding."), "", "Please upload a document before shredding."
293
  file_contents = list(uploaded_files.values())
294
  try:
295
  shredded_document = generate_document(document_type, file_contents)
296
- generated_documents['Shred'] = shredded_document
297
- return dcc.Markdown(shredded_document), f"{document_type} generated", "Document shredded successfully."
298
  except Exception as e:
299
  print(f"Error generating document: {str(e)}")
300
- return html.Div(f"Error generating document: {str(e)}"), "Error", "An error occurred while shredding the document."
301
-
302
  if shredded_document is None:
303
- return html.Div("Please shred a document first."), "", "Please shred a document first."
304
-
 
 
 
 
 
 
305
  try:
306
- if document_type == "Pink":
307
- if document_source == 'uploaded' and specific_document:
308
- current_document = generate_document(document_type, [specific_document, shredded_document])
309
- else:
310
- current_document = generate_document(document_type, [shredded_document])
311
- elif document_type == "Red":
312
- if 'Pink Review' not in generated_documents:
313
- return html.Div("Please complete Pink Review first."), "", "Please complete Pink Review first."
314
- if document_source == 'uploaded' and specific_document:
315
- current_document = generate_document(document_type, [specific_document, generated_documents['Pink Review'], shredded_document])
316
- else:
317
- current_document = generate_document(document_type, [generated_documents['Pink Review'], shredded_document])
318
- elif document_type == "Gold":
319
- if 'Red Review' not in generated_documents:
320
- return html.Div("Please complete Red Review first."), "", "Please complete Red Review first."
321
- if document_source == 'uploaded' and specific_document:
322
- current_document = generate_document(document_type, [specific_document, generated_documents['Red Review'], shredded_document])
323
- else:
324
- current_document = generate_document(document_type, [generated_documents['Red Review'], shredded_document])
325
- elif document_type in ["Pink Review", "Red Review", "Gold Review"]:
326
- previous_document = generated_documents.get(document_type.split(' ')[0], None)
327
- if not previous_document:
328
- return html.Div(f"Please generate {document_type.split(' ')[0]} document first."), "", f"Please generate {document_type.split(' ')[0]} document first."
329
- if document_source == 'uploaded' and specific_document:
330
- current_document = generate_document(document_type, [specific_document, previous_document, shredded_document])
331
- else:
332
- current_document = generate_document(document_type, [previous_document, shredded_document])
333
- elif document_type in ["Virtual Board", "Loe"]:
334
- if 'Gold' not in generated_documents:
335
- return html.Div("Please complete Gold document first."), "", "Please complete Gold document first."
336
- if document_source == 'uploaded' and specific_document:
337
- current_document = generate_document(document_type, [specific_document, generated_documents['Gold'], shredded_document])
338
- else:
339
- current_document = generate_document(document_type, [generated_documents['Gold'], shredded_document])
340
  else:
341
  current_document = generate_document(document_type, [shredded_document])
342
 
343
- generated_documents[document_type] = current_document
344
- return dcc.Markdown(current_document), f"{document_type} generated", f"{document_type} document generated successfully."
 
 
345
  except Exception as e:
346
  print(f"Error generating document: {str(e)}")
347
- return html.Div(f"Error generating document: {str(e)}"), "Error", "An error occurred while generating the document."
348
 
349
  @app.callback(
350
- Output('specific-document-name', 'children'),
351
- Input('upload-specific-document', 'contents'),
352
- State('upload-specific-document', 'filename')
353
  )
354
- def update_specific_document_filename(contents, filename):
355
  if contents is not None:
356
  return filename
357
  return ""
@@ -393,14 +314,14 @@ def download_document(n_clicks):
393
  if current_document is None:
394
  raise dash.exceptions.PreventUpdate
395
 
396
- if document_type in ["LOE", "Pink Review", "Red Review", "Gold Review", "Virtual Board"]:
397
- # Create a pandas DataFrame for spreadsheet-type documents
398
  df = pd.read_csv(StringIO(current_document))
399
 
400
  # Save the DataFrame to an Excel file
401
  output = BytesIO()
402
  with pd.ExcelWriter(output, engine='xlsxwriter') as writer:
403
- df.to_excel(writer, sheet_name=document_type, index=False)
404
 
405
  return dcc.send_bytes(output.getvalue(), f"{document_type}.xlsx")
406
  else:
 
26
  document_type = None
27
  shredded_document = None
28
  pink_review_document = None
 
 
29
 
30
  # Document types and their descriptions
31
  document_types = {
 
34
  "Pink Review": "Evaluate compliance of the Pink Team document against the requirements and output a spreadsheet of non compliant findings by pws number, the goal of that pws section, what made it non compliant and your recommendations for recovery",
35
  "Red": "Produce a Red Team document based on the Pink Review by pws sections. Your goal is to be compliant and compelling by recovering all the findings in Pink Review",
36
  "Red Review": "Evaluate compliance of the Red Team document against the requirements and output a spreadsheet of non compliant findings by pws number, the goal of that pws section, what made it non compliant and your recommendations for recovery",
37
+ "Gold": "Create a Pink Team document based on the PWS response by pws sections. Your goal is to be compliant and compelling by recovering all the findings in Red Review",
38
  "Gold Review": "Perform a final compliance review against the requirements and output a spreadsheet of non compliant findings by pws number, the goal of that pws section, what made it non compliant and your recommendations for recovery",
39
  "Virtual Board": "Based on the requirements and in particular the evaulation criteria, you will evaluate the proposal as if you were a contracting office and provide section by section evaluation as unsatisfactory, satisfactory, good, very good, excellent and why in a spreadsheet",
40
  "LOE": "Generate a Level of Effort (LOE) breakdown as a spreadsheet"
 
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',
 
101
  },
102
  multiple=False
103
  ),
104
+ html.Div(id='pink-review-file-name')
105
  ]),
 
 
 
 
 
 
 
 
 
 
 
106
  dcc.Loading(
107
  id="chat-loading",
108
  type="dot",
 
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),
 
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:
 
186
  4. Start the output immediately with the document content.
187
  5. IMPORTANT: If the document type is Pink, Red, Gold and not review type, loe or board
188
  then your goal is to be compliant and compelling based on the
189
+ requrements, write in paragraph in active voice as
190
  MicroHealth, limit bullets, answer the
191
  requirement with what MicroHealth will do
192
  to satisfy the requirement, the technical
 
214
  Output('document-preview', 'children'),
215
  Output('loading-output', 'children'),
216
  Output('status-bar', 'children', allow_duplicate=True),
217
+ Output('pink-review-upload', 'style'),
218
+ [Input(f'btn-{doc_type.lower().replace("_", "-")}', 'n_clicks') for doc_type in document_types.keys()],
219
+ State('pink-review-file-name', 'children'),
 
220
  prevent_initial_call=True
221
  )
222
+ def generate_document_preview(*args):
223
+ global current_document, document_type, shredded_document, pink_review_document
224
  ctx = dash.callback_context
225
  if not ctx.triggered:
226
  raise dash.exceptions.PreventUpdate
227
+ button_id = ctx.triggered[0]['prop_id'].split('.')[0]
228
+ document_type = button_id.replace('btn-', '').replace('-', '_').title()
229
+ pink_review_file = args[-1]
230
+
231
+ if not uploaded_files and document_type != "Shred":
232
+ return html.Div("Please upload and shred a document first."), "", "Please upload and shred a document first.", {'display': 'none'}
 
 
 
 
 
 
 
233
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
234
  if document_type == "Shred":
235
  if not uploaded_files:
236
+ return html.Div("Please upload a document before shredding."), "", "Please upload a document before shredding.", {'display': 'none'}
237
  file_contents = list(uploaded_files.values())
238
  try:
239
  shredded_document = generate_document(document_type, file_contents)
240
+ return dcc.Markdown(shredded_document), f"{document_type} generated", "Document shredded. You can now proceed with other operations.", {'display': 'none'}
 
241
  except Exception as e:
242
  print(f"Error generating document: {str(e)}")
243
+ return html.Div(f"Error generating document: {str(e)}"), "Error", "An error occurred while shredding the document.", {'display': 'none'}
244
+
245
  if shredded_document is None:
246
+ return html.Div("Please shred a document first."), "", "Please shred a document first.", {'display': 'none'}
247
+
248
+ if document_type == "Pink Review":
249
+ 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'}
250
+
251
+ if document_type in ["Red", "Red Review"] and pink_review_document is None:
252
+ return html.Div("Please complete Pink Review first."), "", "Please complete Pink Review first.", {'display': 'none'}
253
+
254
  try:
255
+ if document_type == "Pink Review" and pink_review_file:
256
+ current_document = generate_document(document_type, [pink_review_file, shredded_document])
257
+ elif document_type in ["Red", "Red Review"]:
258
+ current_document = generate_document(document_type, [pink_review_document, shredded_document])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
259
  else:
260
  current_document = generate_document(document_type, [shredded_document])
261
 
262
+ if document_type == "Pink Review":
263
+ pink_review_document = current_document
264
+
265
+ return dcc.Markdown(current_document), f"{document_type} generated", f"{document_type} document generated successfully.", {'display': 'none'}
266
  except Exception as e:
267
  print(f"Error generating document: {str(e)}")
268
+ return html.Div(f"Error generating document: {str(e)}"), "Error", "An error occurred while generating the document.", {'display': 'none'}
269
 
270
  @app.callback(
271
+ Output('pink-review-file-name', 'children'),
272
+ Input('upload-pink-review', 'contents'),
273
+ State('upload-pink-review', 'filename')
274
  )
275
+ def update_pink_review_filename(contents, filename):
276
  if contents is not None:
277
  return filename
278
  return ""
 
314
  if current_document is None:
315
  raise dash.exceptions.PreventUpdate
316
 
317
+ if document_type == "LOE":
318
+ # Create a pandas DataFrame for LOE
319
  df = pd.read_csv(StringIO(current_document))
320
 
321
  # Save the DataFrame to an Excel file
322
  output = BytesIO()
323
  with pd.ExcelWriter(output, engine='xlsxwriter') as writer:
324
+ df.to_excel(writer, sheet_name='LOE', index=False)
325
 
326
  return dcc.send_bytes(output.getvalue(), f"{document_type}.xlsx")
327
  else: