Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -223,15 +223,17 @@ demo = gr.Interface(
|
|
223 |
"""
|
224 |
}
|
225 |
|
226 |
-
#
|
227 |
def create_main_app():
|
228 |
-
with gr.Blocks(title="Dynamic Gradio App Generator"
|
229 |
gr.Markdown("# 🔄 Dynamic Gradio App Generator")
|
230 |
-
gr.Markdown("Select an app type to load it dynamically")
|
231 |
|
232 |
-
#
|
233 |
-
|
234 |
-
|
|
|
|
|
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 |
-
#
|
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 |
-
#
|
283 |
-
|
284 |
-
|
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
|
303 |
-
|
|
|
304 |
|
305 |
-
#
|
306 |
-
return
|
307 |
-
|
308 |
-
|
309 |
-
|
310 |
-
new_app_instance
|
311 |
-
)
|
312 |
except Exception as e:
|
313 |
error_msg = str(e)
|
314 |
-
return
|
315 |
-
|
316 |
-
|
317 |
-
|
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 |
-
#
|
329 |
-
demo.load(None,
|
330 |
function() {
|
331 |
-
|
332 |
-
|
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 |
-
|
360 |
-
|
361 |
-
|
362 |
-
|
363 |
-
|
364 |
-
|
365 |
-
|
366 |
-
|
367 |
-
|
368 |
-
}
|
369 |
-
});
|
370 |
|
371 |
-
|
372 |
-
|
373 |
-
|
374 |
-
|
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 |
-
#
|
389 |
-
def
|
390 |
-
|
391 |
-
|
392 |
-
|
393 |
-
|
394 |
-
|
395 |
-
|
396 |
-
|
397 |
-
|
398 |
-
|
|
|
|
|
|
|
399 |
|
400 |
# Launch the app
|
401 |
if __name__ == "__main__":
|
402 |
-
|
|
|
|
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)
|