datasaur-dev commited on
Commit
1bb5b82
·
verified ·
1 Parent(s): dd58b09

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +169 -16
app.py CHANGED
@@ -3,9 +3,14 @@ import json
3
  import gradio as gr
4
  import pandas as pd
5
  from python_request import process_wod_document
6
-
7
  from dummy import output_test
8
 
 
 
 
 
 
9
  # --- Authentication Function ---
10
  def authenticate_user(username, password):
11
  """
@@ -14,6 +19,20 @@ def authenticate_user(username, password):
14
  """
15
  return username == "demo" and password == os.environ["PASSWORD"]
16
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
17
  # --- Core Application Logic ---
18
  def analyze_wod(file_obj, wod_type):
19
  """
@@ -24,18 +43,17 @@ def analyze_wod(file_obj, wod_type):
24
  wod_type: The selected type of Work Order Document.
25
 
26
  Returns:
27
- A pandas DataFrame with the analysis results.
28
  """
29
- # Check if user has selected a valid WOD type
 
30
  if wod_type == "-- WOD type --" or wod_type is None:
31
- # Show warning dialog and return empty DataFrame
32
  gr.Warning("Please select a WOD type first!")
33
- return "", pd.DataFrame()
34
 
35
- # Check if file is uploaded
36
  if file_obj is None:
37
  gr.Warning("Please upload a PDF file first!")
38
- return "", pd.DataFrame()
39
 
40
  print(f"Analyzing '{file_obj.name}' (Type: {wod_type})...")
41
 
@@ -53,7 +71,7 @@ def analyze_wod(file_obj, wod_type):
53
 
54
  # Process the document using the API
55
  api_response = process_wod_document(temp_file_path, wod_type)
56
-
57
  # api_response = json.loads(output_test)
58
 
59
  # Clean up temporary file if we created one
@@ -62,9 +80,13 @@ def analyze_wod(file_obj, wod_type):
62
 
63
  # Check if API call was successful
64
  if api_response.get("status") != "success":
 
 
 
 
65
  error_msg = api_response.get("message", "Unknown error occurred")
66
  gr.Error(f"API Error: {error_msg}")
67
- return "", pd.DataFrame()
68
 
69
  # Parse the API response
70
  results = api_response.get("results", {})
@@ -95,19 +117,119 @@ def analyze_wod(file_obj, wod_type):
95
 
96
  # Get prediction for display
97
  prediction = results.get("prediction", "Unknown")
98
- gr.Info(f"Analysis completed! Overall prediction: {prediction}")
99
 
100
  # Format prediction as centered H1 for display
101
  prediction_display = f"<h1 style='text-align: center; color: #1f77b4;'>{prediction}</h1>" if prediction != "Unknown" else ""
102
 
103
- return prediction_display, df
 
 
 
 
 
104
 
105
  except Exception as e:
 
 
 
 
106
  error_msg = f"Error processing document: {str(e)}"
107
  print(error_msg)
108
  gr.Error(error_msg)
109
- return "", pd.DataFrame()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
110
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
111
  js_func = """
112
  function refresh() {
113
  const url = new URL(window.location);
@@ -123,8 +245,8 @@ function refresh() {
123
  # Using gr.Blocks() for a custom layout that matches the elegant design.
124
  with gr.Blocks(
125
  #theme=gr.themes.Soft(primary_hue="blue", secondary_hue="sky"),
126
- theme=gr.themes.Default(primary_hue="blue", secondary_hue="sky"),
127
  js=js_func,
 
128
  css=".gradio-container {max-width: 960px !important; margin: auto !important;}"
129
  ) as demo:
130
 
@@ -169,13 +291,44 @@ with gr.Blocks(
169
  wrap=True
170
  )
171
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
172
  # Define the interaction: clicking the button calls the function
173
  analyze_btn.click(
174
- fn=analyze_wod,
175
- inputs=[file_input, type_input],
176
- outputs=[prediction_output, results_output],
 
 
 
 
 
 
177
  show_progress=False
178
  )
 
 
 
 
 
 
 
179
 
180
  # --- Launch the Application with Authentication ---
181
  if __name__ == "__main__":
 
3
  import gradio as gr
4
  import pandas as pd
5
  from python_request import process_wod_document
6
+ import time
7
  from dummy import output_test
8
 
9
+ # --- Global Variables for Timer ---
10
+ processing_start_time = None
11
+ is_processing = False
12
+ analysis_completed = False
13
+
14
  # --- Authentication Function ---
15
  def authenticate_user(username, password):
16
  """
 
19
  """
20
  return username == "demo" and password == os.environ["PASSWORD"]
21
 
22
+ def update_processing_timer():
23
+ """
24
+ Update the processing button with elapsed time ONLY during active processing
25
+ """
26
+ global processing_start_time, is_processing, analysis_completed
27
+
28
+ # Only update button during active processing
29
+ if is_processing and processing_start_time is not None:
30
+ elapsed = int(time.time() - processing_start_time)
31
+ return gr.Button(f"Processing... ({elapsed}s)", variant="primary", interactive=False)
32
+
33
+ # Don't interfere with button state when not processing
34
+ return gr.update()
35
+
36
  # --- Core Application Logic ---
37
  def analyze_wod(file_obj, wod_type):
38
  """
 
43
  wod_type: The selected type of Work Order Document.
44
 
45
  Returns:
46
+ A tuple containing: prediction_display, DataFrame, updated button, file_input, type_input
47
  """
48
+ global is_processing, analysis_completed
49
+ # These checks are now done earlier, but keeping as safety net
50
  if wod_type == "-- WOD type --" or wod_type is None:
 
51
  gr.Warning("Please select a WOD type first!")
52
+ return "", pd.DataFrame(), gr.Button("Analyze Document", variant="primary", interactive=True), file_obj, wod_type
53
 
 
54
  if file_obj is None:
55
  gr.Warning("Please upload a PDF file first!")
56
+ return "", pd.DataFrame(), gr.Button("Analyze Document", variant="primary", interactive=True), file_obj, wod_type
57
 
58
  print(f"Analyzing '{file_obj.name}' (Type: {wod_type})...")
59
 
 
71
 
72
  # Process the document using the API
73
  api_response = process_wod_document(temp_file_path, wod_type)
74
+ # time.sleep(3)
75
  # api_response = json.loads(output_test)
76
 
77
  # Clean up temporary file if we created one
 
80
 
81
  # Check if API call was successful
82
  if api_response.get("status") != "success":
83
+ # Stop processing timer on API error
84
+ is_processing = False
85
+ analysis_completed = False
86
+
87
  error_msg = api_response.get("message", "Unknown error occurred")
88
  gr.Error(f"API Error: {error_msg}")
89
+ return "", pd.DataFrame(), gr.Button("Analyze Document", variant="primary", interactive=True), file_obj, wod_type
90
 
91
  # Parse the API response
92
  results = api_response.get("results", {})
 
117
 
118
  # Get prediction for display
119
  prediction = results.get("prediction", "Unknown")
120
+ # gr.Info(f"Analysis completed! Overall prediction: {prediction}")
121
 
122
  # Format prediction as centered H1 for display
123
  prediction_display = f"<h1 style='text-align: center; color: #1f77b4;'>{prediction}</h1>" if prediction != "Unknown" else ""
124
 
125
+ # Stop processing timer and mark analysis as completed
126
+ is_processing = False
127
+ analysis_completed = True
128
+
129
+ # Return results with reset button, keeping current inputs
130
+ return prediction_display, df, gr.Button("Reset", variant="secondary", interactive=True), file_obj, wod_type
131
 
132
  except Exception as e:
133
+ # Stop processing timer on error
134
+ is_processing = False
135
+ analysis_completed = False
136
+
137
  error_msg = f"Error processing document: {str(e)}"
138
  print(error_msg)
139
  gr.Error(error_msg)
140
+ return "", pd.DataFrame(), gr.Button("Analyze Document", variant="primary", interactive=True), file_obj, wod_type
141
+
142
+ def reset_interface():
143
+ """
144
+ Reset the interface to initial state
145
+ """
146
+ global analysis_completed, is_processing
147
+
148
+ # Reset global state
149
+ analysis_completed = False
150
+ is_processing = False
151
+
152
+ # Create completely clean DataFrame to avoid any pandas confusion
153
+ clean_df = pd.DataFrame(columns=["Requirement", "Reason", "Status"])
154
+
155
+ return (
156
+ None, # Clear file input
157
+ "-- WOD type --", # Reset dropdown
158
+ "", # Clear prediction output
159
+ clean_df, # Clear results with proper columns
160
+ gr.Button("Analyze Document", variant="primary", interactive=True) # Reset button
161
+ )
162
+
163
+ def check_button_state_and_act(file_obj, wod_type, button_state):
164
+ """
165
+ Check button state and decide what to do
166
+ """
167
+ # Get button text safely
168
+ try:
169
+ button_text = button_state.value if hasattr(button_state, 'value') else str(button_state)
170
+ except:
171
+ button_text = "Analyze Document" # Default fallback
172
+
173
+ # If button shows "Reset", we'll let JavaScript handle the page refresh
174
+ if "Reset" in button_text:
175
+ # Return current state - JavaScript will refresh the page
176
+ clean_df = pd.DataFrame(columns=["Requirement", "Reason", "Status"])
177
+ return "", clean_df, button_state, file_obj, wod_type
178
+
179
+ # If button shows "Analyze Document", check requirements first
180
+ elif "Analyze Document" in button_text:
181
+ # Check if WOD type is selected
182
+ if wod_type == "-- WOD type --" or wod_type is None:
183
+ gr.Warning("Please select a WOD type first!")
184
+ clean_df = pd.DataFrame(columns=["Requirement", "Reason", "Status"])
185
+ return "", clean_df, gr.Button("Analyze Document", variant="primary", interactive=True), file_obj, wod_type
186
+
187
+ # Check if file is uploaded
188
+ if file_obj is None:
189
+ gr.Warning("Please upload a PDF file first!")
190
+ clean_df = pd.DataFrame(columns=["Requirement", "Reason", "Status"])
191
+ return "", clean_df, gr.Button("Analyze Document", variant="primary", interactive=True), file_obj, wod_type
192
+
193
+ # All requirements met, start processing timer
194
+ global processing_start_time, is_processing, analysis_completed
195
+ processing_start_time = time.time()
196
+ is_processing = True
197
+ analysis_completed = False
198
 
199
+ clean_df = pd.DataFrame(columns=["Requirement", "Reason", "Status"])
200
+ # Return loading state and flag for next step
201
+ return "", clean_df, gr.Button("Processing... (0s)", variant="primary", interactive=False), file_obj, wod_type
202
+
203
+ # Fallback case
204
+ return "", pd.DataFrame(columns=["Requirement", "Reason", "Status"]), gr.Button("Analyze Document", variant="primary", interactive=True), file_obj, wod_type
205
+
206
+ def perform_analysis_if_needed(pred, df, button_state, file_obj, wod_type):
207
+ """
208
+ Perform analysis if button was in processing state
209
+ """
210
+ # Get button text safely
211
+ try:
212
+ button_text = button_state.value if hasattr(button_state, 'value') else str(button_state)
213
+ except:
214
+ button_text = "Analyze Document" # Default fallback
215
+
216
+ # If button shows "Processing...", perform analysis
217
+ if "Processing" in button_text:
218
+ # Inputs are already validated, proceed with analysis
219
+ return analyze_wod(file_obj, wod_type)
220
+
221
+ # If button shows "Analyze Document" (after reset or clean state), ensure clean state
222
+ elif "Analyze Document" in button_text:
223
+ # Ensure we have clean DataFrame with proper columns
224
+ if df.empty or len(df.columns) == 0:
225
+ clean_df = pd.DataFrame(columns=["Requirement", "Reason", "Status"])
226
+ else:
227
+ clean_df = df
228
+ return pred, clean_df, button_state, file_obj, wod_type
229
+
230
+ # Otherwise, keep current state
231
+ return pred, df, button_state, file_obj, wod_type
232
+
233
  js_func = """
234
  function refresh() {
235
  const url = new URL(window.location);
 
245
  # Using gr.Blocks() for a custom layout that matches the elegant design.
246
  with gr.Blocks(
247
  #theme=gr.themes.Soft(primary_hue="blue", secondary_hue="sky"),
 
248
  js=js_func,
249
+ theme=gr.themes.Default(primary_hue="blue", secondary_hue="sky"),
250
  css=".gradio-container {max-width: 960px !important; margin: auto !important;}"
251
  ) as demo:
252
 
 
291
  wrap=True
292
  )
293
 
294
+ # JavaScript to handle reset button
295
+ reset_js = """
296
+ function(file_obj, wod_type, button_state) {
297
+ // Get button text
298
+ let button_text = typeof button_state === 'object' && button_state.value ? button_state.value : button_state.toString();
299
+
300
+ // If it's reset button, refresh the page
301
+ if (button_text.includes('Reset')) {
302
+ setTimeout(() => {
303
+ window.location.reload();
304
+ }, 100);
305
+ }
306
+
307
+ // Return the inputs as-is for the Python function
308
+ return [file_obj, wod_type, button_state];
309
+ }
310
+ """
311
+
312
  # Define the interaction: clicking the button calls the function
313
  analyze_btn.click(
314
+ fn=check_button_state_and_act,
315
+ inputs=[file_input, type_input, analyze_btn],
316
+ outputs=[prediction_output, results_output, analyze_btn, file_input, type_input],
317
+ show_progress=False,
318
+ js=reset_js
319
+ ).then(
320
+ fn=perform_analysis_if_needed,
321
+ inputs=[prediction_output, results_output, analyze_btn, file_input, type_input],
322
+ outputs=[prediction_output, results_output, analyze_btn, file_input, type_input],
323
  show_progress=False
324
  )
325
+
326
+ # Add timer to update processing button every second
327
+ timer = gr.Timer(1.0) # Update every 1 second
328
+ timer.tick(
329
+ fn=update_processing_timer,
330
+ outputs=[analyze_btn]
331
+ )
332
 
333
  # --- Launch the Application with Authentication ---
334
  if __name__ == "__main__":