nakas commited on
Commit
0f94be4
·
verified ·
1 Parent(s): ef388e2

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +114 -125
app.py CHANGED
@@ -223,42 +223,15 @@ demo = gr.Interface(
223
  """
224
  }
225
 
226
- # Create an endpoint to get the app configuration
227
- def get_app_config(app_name):
228
- if app_name not in APP_REGISTRY:
229
- return {"error": f"App '{app_name}' not found"}
230
-
231
- return {
232
- "title": APP_REGISTRY[app_name]["title"],
233
- "description": APP_REGISTRY[app_name]["description"],
234
- "code": APP_CODES[app_name]
235
- }
236
-
237
- # Create an endpoint to load an app
238
- def load_app_interface(app_name):
239
- if app_name not in APP_REGISTRY:
240
- return None
241
-
242
- try:
243
- # Capture stdout/stderr to prevent it from polluting the response
244
- stdout_buffer = io.StringIO()
245
- stderr_buffer = io.StringIO()
246
-
247
- with redirect_stdout(stdout_buffer), redirect_stderr(stderr_buffer):
248
- app = APP_REGISTRY[app_name]["function"]()
249
-
250
- return app
251
- except Exception as e:
252
- return None
253
-
254
- # Main app with dynamic loading capabilities
255
  def create_main_app():
256
- with gr.Blocks(title="Dynamic Gradio App Generator", css="#app-container { min-height: 400px; }") as demo:
257
  gr.Markdown("# 🔄 Dynamic Gradio App Generator")
258
- gr.Markdown("Select an app type to load it without refreshing the page")
259
 
260
- # Create a state variable to track the current app
261
- current_app = gr.State("none")
 
262
 
263
  with gr.Row():
264
  with gr.Column(scale=1):
@@ -288,20 +261,16 @@ def create_main_app():
288
 
289
  # Status message
290
  status_msg = gr.Markdown("Select an app and click 'Load Selected App'")
291
-
292
- with gr.Column(scale=2):
293
- # App container (where the dynamic app will be loaded)
294
- app_container = gr.HTML(
295
- value="<div id='app-container'><p>No app loaded yet. Select an app template and click 'Load Selected App'.</p></div>",
296
- label="App Preview"
297
- )
298
 
299
- # Update description and code when selection changes
 
 
 
 
300
  def update_description_and_code(selection):
301
- config = get_app_config(selection)
302
  return (
303
- f"**{config['title']}**: {config['description']}",
304
- config['code']
305
  )
306
 
307
  app_selection.change(
@@ -310,104 +279,124 @@ def create_main_app():
310
  outputs=[app_description, code_display]
311
  )
312
 
313
- # Function to dynamically load the selected app
314
- def load_selected_app(app_name):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
315
  try:
316
- # Clear the previous app
317
- gr.update(value="<div id='app-container'><p>Loading app...</p></div>")
318
-
319
- # Create a new app instance
320
- selected_app = load_app_interface(app_name)
321
- if selected_app is None:
322
- return (
323
- gr.update(value="<div id='app-container'><p>Error loading app. Please try again.</p></div>"),
324
- f"Error: Could not load {APP_REGISTRY[app_name]['title']}",
325
- app_name
326
- )
327
-
328
- # Generate a unique ID for this app instance
329
- app_id = f"app-{app_name}-{id(selected_app)}"
330
-
331
- # Create a custom JavaScript function that will inject the app
332
- js_code = f"""
333
- <div id="{app_id}-container">
334
- <p>Loading {APP_REGISTRY[app_name]['title']}...</p>
335
- </div>
336
- <script>
337
- (function() {{
338
- const appContainer = document.getElementById('{app_id}-container');
339
-
340
- // Create a timer to check when Gradio is fully loaded
341
- const checkInterval = setInterval(() => {{
342
- if (window.gradio_config && window.gradioApp) {{
343
- clearInterval(checkInterval);
344
-
345
- // Create a temporary element to mount the app
346
- const tempElement = document.createElement('div');
347
- document.body.appendChild(tempElement);
348
-
349
- // Move the app to our container
350
- setTimeout(() => {{
351
- try {{
352
- // Find the app elements with the right ID
353
- const appElements = Array.from(
354
- document.querySelectorAll(
355
- `.gradio-container[id^='{app_id}']`
356
- )
357
- );
358
-
359
- if (appElements.length > 0) {{
360
- // Move the app to our container
361
- appContainer.innerHTML = '';
362
- appElements.forEach(el => {{
363
- appContainer.appendChild(el);
364
- }});
365
- }} else {{
366
- appContainer.innerHTML = '<p>App loaded but could not be displayed. Please refresh the page.</p>';
367
- }}
368
- }} catch (e) {{
369
- console.error('Error moving app:', e);
370
- appContainer.innerHTML = '<p>Error loading app: ' + e.message + '</p>';
371
- }}
372
- }}, 1000);
373
- }}
374
- }}, 100);
375
- }})();
376
- </script>
377
- """
378
 
 
379
  return (
380
- gr.update(value=js_code),
381
  f"Successfully loaded {APP_REGISTRY[app_name]['title']}",
382
- app_name
 
383
  )
384
  except Exception as e:
385
  error_msg = str(e)
386
  return (
387
- gr.update(value=f"<div id='app-container'><p>Error: {error_msg}</p></div>"),
388
  f"Error: {error_msg}",
389
- app_name
 
390
  )
391
 
392
- # Handle the load button click
393
  load_btn.click(
394
- load_selected_app,
395
- inputs=app_selection,
396
- outputs=[app_container, status_msg, current_app]
397
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
398
 
399
  return demo
400
 
401
- # Create and launch the main app
402
- demo = create_main_app()
 
 
 
 
 
 
403
 
404
- # Add endpoints for direct API access to apps
405
- for app_name, app_info in APP_REGISTRY.items():
406
- app_func = app_info["function"]
407
- if app_func:
408
- app = app_func()
409
- demo = gr.mount_gradio_app(demo, app, f"/{app_name}")
410
 
411
  # Launch the app
412
  if __name__ == "__main__":
413
- demo.launch(server_name="0.0.0.0", server_port=7860)
 
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
 
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']}",
273
+ APP_CODES[selection]
274
  )
275
 
276
  app_selection.change(
 
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)