nakas commited on
Commit
2070667
·
verified ·
1 Parent(s): 9ecb17f

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +106 -113
app.py CHANGED
@@ -223,15 +223,17 @@ demo = gr.Interface(
223
  """
224
  }
225
 
226
- # Main app with inline app loading for Gradio 3.50.2
227
  def create_main_app():
228
- with gr.Blocks(title="Dynamic Gradio App Generator", css="footer {visibility: hidden}") as demo:
229
  gr.Markdown("# 🔄 Dynamic Gradio App Generator")
230
- gr.Markdown("Select an app type to load it dynamically")
231
 
232
- # Keep track of the current loaded app
233
- current_app_name = gr.State(value=None)
234
- current_app_instance = gr.State(value=None)
 
 
235
 
236
  with gr.Row():
237
  with gr.Column(scale=1):
@@ -261,12 +263,15 @@ def create_main_app():
261
 
262
  # Status message
263
  status_msg = gr.Markdown("Select an app and click 'Load Selected App'")
 
 
 
 
 
 
 
264
 
265
- # App container (this will be dynamically updated with different apps)
266
- with gr.Row(id="app-container"):
267
- app_placeholder = gr.Markdown("No app loaded yet. Select an app and click 'Load Selected App'.")
268
-
269
- # Update description when selection changes
270
  def update_description_and_code(selection):
271
  return (
272
  f"**{APP_REGISTRY[selection]['title']}**: {APP_REGISTRY[selection]['description']}",
@@ -279,124 +284,112 @@ def create_main_app():
279
  outputs=[app_description, code_display]
280
  )
281
 
282
- # Function to load the selected app within the main app
283
- def load_app(app_name, previous_app_name, previous_app_instance):
284
- if app_name not in APP_REGISTRY:
285
- return (
286
- gr.update(value="App not found!"),
287
- f"Error: App '{app_name}' not found",
288
- previous_app_name,
289
- previous_app_instance
290
- )
291
-
292
- # If we already have this app loaded, just return it
293
- if app_name == previous_app_name and previous_app_instance is not None:
294
- return (
295
- gr.update(visible=False),
296
- f"{APP_REGISTRY[app_name]['title']} is already loaded",
297
- app_name,
298
- previous_app_instance
299
- )
300
-
301
  try:
302
- # Create a new instance of the selected app
303
- new_app_instance = APP_REGISTRY[app_name]["function"]()
 
304
 
305
- # Return values to update the UI
306
- return (
307
- gr.update(visible=False),
308
- f"Successfully loaded {APP_REGISTRY[app_name]['title']}",
309
- app_name,
310
- new_app_instance
311
- )
312
  except Exception as e:
313
  error_msg = str(e)
314
- return (
315
- gr.update(value=f"Error loading app: {error_msg}"),
316
- f"Error: {error_msg}",
317
- previous_app_name,
318
- previous_app_instance
319
- )
320
-
321
- # Handle app loading when button is clicked
322
- load_btn.click(
323
- load_app,
324
- inputs=[app_selection, current_app_name, current_app_instance],
325
- outputs=[app_placeholder, status_msg, current_app_name, current_app_instance]
326
- )
327
 
328
- # Custom JavaScript to handle dynamic app loading
329
- demo.load(None, None, None, _js="""
330
  function() {
331
- // Function to handle app loading and swapping
332
- window.loadGradioApp = function(appName, appInstance) {
333
- const appContainer = document.getElementById('app-container');
334
- if (!appContainer) return;
335
-
336
- // Clear existing app container
337
- while (appContainer.firstChild) {
338
- appContainer.removeChild(appContainer.firstChild);
339
- }
340
-
341
- // Add new app to container
342
- if (appInstance && appInstance.wrapper) {
343
- appContainer.appendChild(appInstance.wrapper);
344
- }
345
- };
346
-
347
- // Function to check for app updates
348
- window.checkAppUpdates = function() {
349
- const gradioEl = document.querySelector("gradio-app");
350
- if (!gradioEl) return;
351
-
352
- const shadowRoot = gradioEl.shadowRoot || gradioEl;
353
- const appContainer = shadowRoot.querySelector("#app-container");
354
- if (!appContainer) return;
355
-
356
- // Find any newly loaded app by looking for interface/blocks elements
357
- const newAppElements = shadowRoot.querySelectorAll(".gradio-container:not([id='main-container'])");
358
 
359
- if (newAppElements.length > 0) {
360
- let foundNew = false;
361
- newAppElements.forEach(el => {
362
- // Only move elements that aren't already in our container
363
- if (!appContainer.contains(el)) {
364
- // Move the app to our container
365
- appContainer.innerHTML = '';
366
- appContainer.appendChild(el);
367
- foundNew = true;
368
- }
369
- });
370
 
371
- if (foundNew) {
372
- // Hide the placeholder message
373
- const placeholder = shadowRoot.querySelector("#app-container gradio-markdown");
374
- if (placeholder) {
375
- placeholder.style.display = "none";
376
  }
377
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
378
  }
379
- };
380
-
381
- // Set up an interval to check for app updates
382
- setInterval(window.checkAppUpdates, 500);
383
  }
384
  """)
385
 
386
  return demo
387
 
388
- # Helper function to save the app name for persistence
389
- def save_app_name(app_name):
390
- try:
391
- with open("current_app.txt", "w") as f:
392
- f.write(app_name)
393
- return True
394
- except:
395
- return False
396
-
397
- # Create the main app
398
- main_app = create_main_app()
 
 
 
399
 
400
  # Launch the app
401
  if __name__ == "__main__":
402
- main_app.launch(server_name="0.0.0.0", server_port=7860, share=False)
 
 
223
  """
224
  }
225
 
226
+ # Create an app selector that loads apps dynamically
227
  def create_main_app():
228
+ with gr.Blocks(title="Dynamic Gradio App Generator") as demo:
229
  gr.Markdown("# 🔄 Dynamic Gradio App Generator")
230
+ gr.Markdown("Select an app type to load it dynamically without refreshing the page")
231
 
232
+ # Create placeholders for dynamic app loading
233
+ app_blocks_container = gr.Blocks(visible=False)
234
+ with app_blocks_container:
235
+ # This container will be dynamically replaced
236
+ app_placeholder = gr.Markdown("Loading app...")
237
 
238
  with gr.Row():
239
  with gr.Column(scale=1):
 
263
 
264
  # Status message
265
  status_msg = gr.Markdown("Select an app and click 'Load Selected App'")
266
+
267
+ with gr.Column(scale=2):
268
+ # This is where our dynamically loaded app will appear
269
+ app_container = gr.Group(visible=True)
270
+ with app_container:
271
+ gr.Markdown("### App Preview")
272
+ gr.Markdown("No app loaded yet. Select an app and click 'Load Selected App'.")
273
 
274
+ # Update description and code when selection changes
 
 
 
 
275
  def update_description_and_code(selection):
276
  return (
277
  f"**{APP_REGISTRY[selection]['title']}**: {APP_REGISTRY[selection]['description']}",
 
284
  outputs=[app_description, code_display]
285
  )
286
 
287
+ # Load the selected app
288
+ @gr.on(load_btn, "click")
289
+ def load_selected_app(selection):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
290
  try:
291
+ # Create the app
292
+ app_func = APP_REGISTRY[selection]["function"]
293
+ app = app_func()
294
 
295
+ # Update the container content (this is done via JavaScript)
296
+ return {
297
+ status_msg: f"Successfully loaded {APP_REGISTRY[selection]['title']}",
298
+ app_container: gr.update(visible=False), # Hide temporarily for replacement
299
+ }
 
 
300
  except Exception as e:
301
  error_msg = str(e)
302
+ return {
303
+ status_msg: f"Error loading app: {error_msg}",
304
+ app_container: gr.update(visible=True),
305
+ }
 
 
 
 
 
 
 
 
 
306
 
307
+ # This uses Gradio's JavaScript event handling to dynamically mount the app
308
+ demo.load(None, js="""
309
  function() {
310
+ let loadedAppIframe = null;
311
+ let intervalId = null;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
312
 
313
+ // Function to handle the "Load Selected App" button click
314
+ document.addEventListener('click', function(event) {
315
+ // Find button by text or class
316
+ if (event.target.textContent === 'Load Selected App' ||
317
+ (event.target.parentElement && event.target.parentElement.textContent === 'Load Selected App')) {
318
+
319
+ // Get the selected app
320
+ const radioButtons = document.querySelectorAll('input[type="radio"]');
321
+ let selectedApp = null;
 
 
322
 
323
+ for (const radio of radioButtons) {
324
+ if (radio.checked) {
325
+ selectedApp = radio.value;
326
+ break;
 
327
  }
328
  }
329
+
330
+ if (!selectedApp) return;
331
+
332
+ // Stop any previous timer
333
+ if (intervalId) {
334
+ clearInterval(intervalId);
335
+ }
336
+
337
+ // Show loading indicator
338
+ const appContainer = document.querySelector('.app-preview');
339
+ if (appContainer) {
340
+ appContainer.innerHTML = '<p>Loading app...</p>';
341
+ }
342
+
343
+ // Create route for app
344
+ const appUrl = '/' + selectedApp;
345
+
346
+ // Clean up previous iframe if exists
347
+ if (loadedAppIframe) {
348
+ loadedAppIframe.remove();
349
+ }
350
+
351
+ // Create an iframe and load the app
352
+ loadedAppIframe = document.createElement('iframe');
353
+ loadedAppIframe.style.width = '100%';
354
+ loadedAppIframe.style.height = '600px';
355
+ loadedAppIframe.style.border = 'none';
356
+ loadedAppIframe.src = appUrl;
357
+
358
+ // Find the app container column (second column)
359
+ const columns = document.querySelectorAll('.gradio-column');
360
+ if (columns.length > 1) {
361
+ columns[1].innerHTML = ''; // Clear existing content
362
+ columns[1].appendChild(loadedAppIframe);
363
+ }
364
+
365
+ // Update the status
366
+ const statusEl = document.querySelector('#status-message');
367
+ if (statusEl) {
368
+ statusEl.textContent = 'App loaded successfully';
369
+ }
370
  }
371
+ });
 
 
 
372
  }
373
  """)
374
 
375
  return demo
376
 
377
+ # Function to create and mount all apps
378
+ def create_app():
379
+ # Create the main selector app
380
+ main_app = create_main_app()
381
+
382
+ # Create all the individual apps
383
+ for app_name, app_info in APP_REGISTRY.items():
384
+ app_func = app_info["function"]
385
+ if app_func:
386
+ app_instance = app_func()
387
+ # This is for Gradio 4.x - it mounts each app at its own route
388
+ main_app = gr.mount_gradio_app(main_app, app_instance, f"/{app_name}")
389
+
390
+ return main_app
391
 
392
  # Launch the app
393
  if __name__ == "__main__":
394
+ demo = create_app()
395
+ demo.launch(server_name="0.0.0.0", server_port=7860)