Juggernaut1397 commited on
Commit
24d01fd
·
verified ·
1 Parent(s): f835c71

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +173 -62
app.py CHANGED
@@ -139,7 +139,35 @@ with gr.Blocks(
139
  text_size="md",
140
  radius_size="md",
141
  font=gr.themes.GoogleFont("Inter")
142
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
143
  ) as demo:
144
  gr.Markdown("# Data Connector Demo")
145
  gr.Markdown("Select an API spec, then click Refresh Endpoints to see available endpoints grouped in accordions.")
@@ -281,101 +309,182 @@ with gr.Blocks(
281
  gr.update(visible=visibilities[2])
282
  ]
283
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
284
  def confirm_selected_endpoints(spec_choice, *checkbox_values):
285
  """Collect and confirm all selected endpoints"""
 
 
286
  all_selected = []
287
-
288
  for checkbox_group in checkbox_values:
289
  if isinstance(checkbox_group, list) and checkbox_group:
290
  all_selected.extend(checkbox_group)
291
 
 
 
 
 
 
 
 
 
 
292
  # Get the API spec
293
  endpoints = get_endpoints(spec_choice)
294
 
295
  # Process selected endpoints to find ones with parameters
296
  endpoints_with_params = []
297
- display_values = [] # Track display values
 
 
298
  for selection in all_selected:
299
  endpoint = selection.split(" | ")[0]
300
  endpoint_spec = endpoints.get(endpoint, {}).get('get', {})
301
 
302
- # Get both path and query parameters
303
  path_params = extract_path_params(endpoint)
304
- query_params = extract_query_params(endpoint_spec)
 
 
305
 
306
  if path_params or query_params:
307
  endpoints_with_params.append((endpoint, path_params, query_params))
308
  display_values.append(f"Endpoint: {endpoint}")
 
309
 
310
  # Create updates for all components
311
- updates = []
 
 
 
312
  updates.append(endpoints_with_params) # confirmed_endpoints_state
313
  updates.append(display_values) # display_values_state
314
-
315
- # Determine parameter types present
316
- has_path_params = any(path_params for _, path_params, _ in endpoints_with_params)
317
- has_query_params = any(query_params for _, _, query_params in endpoints_with_params)
318
-
319
- # Set appropriate header based on parameter types
320
- if has_path_params and has_query_params:
321
- header_text = "### Path and Query Parameters Required"
322
- elif has_path_params:
323
- header_text = "### Path Parameters Required/Optional"
324
- elif has_query_params:
325
- header_text = "### Query Parameters Required/Optional"
326
  else:
327
- header_text = "### Parameters Required"
328
-
329
- # Update group visibility and header text separately
330
- updates.append(gr.update(visible=bool(endpoints_with_params))) # param_group visibility
331
- updates.append(gr.update(value=header_text, visible=True)) # param_header update
332
 
333
  # Then create updates for each parameter component
 
334
  param_index = 0
335
- for i in range(100): # Assuming max 5 endpoints
336
- if i < len(endpoints_with_params):
337
- endpoint, path_params, query_params = endpoints_with_params[i]
338
-
339
- # Handle path parameters
340
- for param_name in path_params: # Changed: iterate directly over parameter names
341
- if param_index < 5: # Stay within component limit
342
- updates.extend([
343
- gr.update(visible=True),
344
- gr.update(visible=True, value=f"Endpoint: {endpoint} - Path Parameter"),
345
- gr.update(
346
- visible=True,
347
- label=f"Enter path parameter: {param_name}",
348
- placeholder=f"Required path parameter for {endpoint}"
349
- )
350
- ])
351
- param_index += 1
352
-
353
- # Handle query parameters
354
- for param in query_params: # Changed: handle query parameter tuples
355
- _, name, required, description = param # Unpack all 4 values
356
- if param_index < 5: # Stay within component limit
357
- updates.extend([
358
- gr.update(visible=True),
359
- gr.update(visible=True, value=f"Endpoint: {endpoint} - Query Parameter"),
360
- gr.update(
361
- visible=True,
362
- label=f"Enter query parameter: {name}" + (" (Required)" if required else " (Optional)"),
363
- placeholder=description
364
- )
365
- ])
366
- param_index += 1
367
 
368
- # Fill remaining parameter components with hidden updates
369
  while param_index < 5:
370
  updates.extend([
371
- gr.update(visible=False),
372
- gr.update(visible=False, value=""),
373
- gr.update(visible=False, label="")
374
  ])
375
  param_index += 1
376
-
 
 
 
 
377
  return updates
378
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
379
  def handle_api_call(spec_choice, api_base_url, session_id, grant_type, client_id, client_secret,
380
  api_token, iiq_username, iiq_password, display_values, *args):
381
  # Create param_values dictionary
@@ -437,9 +546,11 @@ with gr.Blocks(
437
  confirmed_endpoints_state,
438
  display_values_state,
439
  param_group,
440
- param_header, # Add param_header to outputs
 
 
441
  *[item for group, display, input_box in param_components
442
- for item in (group, display, input_box)]
443
  ]
444
  )
445
 
 
139
  text_size="md",
140
  radius_size="md",
141
  font=gr.themes.GoogleFont("Inter")
142
+ ),
143
+ css="""
144
+ .disabled-button {
145
+ opacity: 0.5;
146
+ pointer-events: none;
147
+ }
148
+ .processing-popup {
149
+ position: fixed;
150
+ top: 50%;
151
+ left: 50%;
152
+ transform: translate(-50%, -50%);
153
+ background: rgba(255, 255, 255, 0.95);
154
+ padding: 20px 40px;
155
+ border-radius: 10px;
156
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
157
+ z-index: 1000;
158
+ text-align: center;
159
+ font-size: 1.2em;
160
+ }
161
+ .overlay-background {
162
+ position: fixed;
163
+ top: 0;
164
+ left: 0;
165
+ width: 100%;
166
+ height: 100%;
167
+ background: rgba(0, 0, 0, 0.5);
168
+ z-index: 999;
169
+ }
170
+ """
171
  ) as demo:
172
  gr.Markdown("# Data Connector Demo")
173
  gr.Markdown("Select an API spec, then click Refresh Endpoints to see available endpoints grouped in accordions.")
 
309
  gr.update(visible=visibilities[2])
310
  ]
311
 
312
+ loading_overlay = gr.HTML(
313
+ visible=False,
314
+ value='''
315
+ <div class="overlay-background"></div>
316
+ <div class="processing-popup">
317
+ ⏳ Processing Endpoints...
318
+ </div>
319
+ '''
320
+ )
321
+
322
+ # Add validation function for enabling/disabling Call API button
323
+ def validate_inputs(spec_choice, api_base_url, grant_type, client_id, client_secret,
324
+ api_token, iiq_username, iiq_password, *param_values):
325
+ """Validate all required inputs to enable/disable Call API button"""
326
+ if not api_base_url.strip():
327
+ return gr.update(interactive=False)
328
+
329
+ # Validate auth fields based on API choice
330
+ if spec_choice == "Okta (JSON)":
331
+ if not api_token:
332
+ return gr.update(interactive=False)
333
+ elif spec_choice == "SailPoint IdentityNow (YAML)":
334
+ if not all([grant_type, client_id, client_secret]):
335
+ return gr.update(interactive=False)
336
+ elif spec_choice == "Sailpoint IIQ (YAML)":
337
+ if not all([iiq_username, iiq_password]):
338
+ return gr.update(interactive=False)
339
+
340
+ # Validate parameter inputs if they're visible
341
+ param_inputs = param_values[:len(param_components)]
342
+ param_displays = [comp[1].value for comp in param_components]
343
+
344
+ for display, value in zip(param_displays, param_inputs):
345
+ if display and display.visible and not value.strip():
346
+ return gr.update(interactive=False)
347
+
348
+ return gr.update(interactive=True)
349
+
350
  def confirm_selected_endpoints(spec_choice, *checkbox_values):
351
  """Collect and confirm all selected endpoints"""
352
+ #gr.update(visible=True)(loading_overlay)
353
+ header_text = "### Parameters Required"
354
  all_selected = []
 
355
  for checkbox_group in checkbox_values:
356
  if isinstance(checkbox_group, list) and checkbox_group:
357
  all_selected.extend(checkbox_group)
358
 
359
+ if not all_selected:
360
+ return ([], # confirmed_endpoints_state
361
+ [], # display_values_state
362
+ gr.update(visible=False), # param_group
363
+ gr.update(value="❌ No endpoints selected", visible=True), # param_header
364
+ gr.update(visible=True), # loading_overlay - show processing message
365
+ gr.update(visible=False), # call_api_btn
366
+ *[gr.update(visible=False) for _ in range(15)]) # 5 sets of 3 components each
367
+
368
  # Get the API spec
369
  endpoints = get_endpoints(spec_choice)
370
 
371
  # Process selected endpoints to find ones with parameters
372
  endpoints_with_params = []
373
+ display_values = []
374
+ required_params_count = 0
375
+
376
  for selection in all_selected:
377
  endpoint = selection.split(" | ")[0]
378
  endpoint_spec = endpoints.get(endpoint, {}).get('get', {})
379
 
 
380
  path_params = extract_path_params(endpoint)
381
+ # Only include required query parameters
382
+ query_params = [param for param in extract_query_params(endpoint_spec)
383
+ if param[2]] # param[2] is the required flag
384
 
385
  if path_params or query_params:
386
  endpoints_with_params.append((endpoint, path_params, query_params))
387
  display_values.append(f"Endpoint: {endpoint}")
388
+ required_params_count += len(path_params) + len(query_params)
389
 
390
  # Create updates for all components
391
+ updates = [
392
+ endpoints_with_params, # confirmed_endpoints_state
393
+ display_values, # display_values_state
394
+ ]
395
  updates.append(endpoints_with_params) # confirmed_endpoints_state
396
  updates.append(display_values) # display_values_state
397
+ updates.append(gr.update(visible=bool(required_params_count))) # param_group
398
+ updates.append(gr.update(value=header_text, visible=True)) # param_header
399
+ updates.append(gr.update(visible=False)) # loading_overlay - hide when done
400
+ updates.append(gr.update(visible=True)) # call_api_btn
401
+
402
+ if not required_params_count:
403
+ updates.append(gr.update(value="✅ No parameters required. You can proceed to call the API.",
404
+ visible=True)) # param_header
 
 
 
 
405
  else:
406
+ updates.append(gr.update(value=f"⚠️ Required Parameters ({required_params_count})", visible=True))
407
+
408
+ updates.append(gr.update(visible=False)) # loading_overlay
409
+ updates.append(gr.update(visible=True)) # call_api_btn
 
410
 
411
  # Then create updates for each parameter component
412
+
413
  param_index = 0
414
+ for endpoint, path_params, query_params in endpoints_with_params:
415
+ # Handle path parameters
416
+ for param_name in path_params:
417
+ if param_index < 5:
418
+ updates.extend([
419
+ gr.update(visible=True,
420
+ value=f"Endpoint: {endpoint} - Path Parameter (Required)"), # markdown
421
+ gr.update(visible=True,
422
+ label=f"🔑 Enter path parameter: {param_name}",
423
+ placeholder=f"Required path parameter for {endpoint}") # textbox
424
+ ])
425
+ param_index += 1
426
+
427
+ # Handle query parameters
428
+ for _, name, required, description in query_params:
429
+ if required and param_index < 5:
430
+ updates.extend([
431
+ gr.update(visible=True,
432
+ value=f"Endpoint: {endpoint} - Query Parameter (Required)"), # markdown
433
+ gr.update(visible=True,
434
+ label=f"🔍 Enter query parameter: {name}",
435
+ placeholder=description) # textbox
436
+ ])
437
+ param_index += 1
 
 
 
 
 
 
 
 
438
 
439
+ # Fill remaining parameter slots
440
  while param_index < 5:
441
  updates.extend([
442
+ gr.update(visible=False), # markdown
443
+ gr.update(visible=False) # textbox
 
444
  ])
445
  param_index += 1
446
+
447
+ updates.append(gr.update(value=header_text, visible=True)) # param_header
448
+ updates.append(gr.update(visible=False)) # loading_overlay
449
+ updates.append(gr.update(visible=True)) # call_api_btn
450
+
451
  return updates
452
 
453
+ for input_component in [api_base_url, grant_type, client_id, client_secret,
454
+ api_token, iiq_username, iiq_password]:
455
+ input_component.change(
456
+ fn=validate_inputs,
457
+ inputs=[
458
+ spec_choice,
459
+ api_base_url,
460
+ grant_type,
461
+ client_id,
462
+ client_secret,
463
+ api_token,
464
+ iiq_username,
465
+ iiq_password,
466
+ *[input_box for _, _, input_box in param_components]
467
+ ],
468
+ outputs=call_api_btn
469
+ )
470
+
471
+ for _, _, input_box in param_components:
472
+ input_box.change(
473
+ fn=validate_inputs,
474
+ inputs=[
475
+ spec_choice,
476
+ api_base_url,
477
+ grant_type,
478
+ client_id,
479
+ client_secret,
480
+ api_token,
481
+ iiq_username,
482
+ iiq_password,
483
+ *[input_box for _, _, input_box in param_components]
484
+ ],
485
+ outputs=call_api_btn
486
+ )
487
+
488
  def handle_api_call(spec_choice, api_base_url, session_id, grant_type, client_id, client_secret,
489
  api_token, iiq_username, iiq_password, display_values, *args):
490
  # Create param_values dictionary
 
546
  confirmed_endpoints_state,
547
  display_values_state,
548
  param_group,
549
+ param_header,
550
+ loading_overlay,
551
+ call_api_btn,
552
  *[item for group, display, input_box in param_components
553
+ for item in (group, display, input_box)]
554
  ]
555
  )
556