Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -223,42 +223,15 @@ demo = gr.Interface(
|
|
223 |
"""
|
224 |
}
|
225 |
|
226 |
-
#
|
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="
|
257 |
gr.Markdown("# 🔄 Dynamic Gradio App Generator")
|
258 |
-
gr.Markdown("Select an app type to load it
|
259 |
|
260 |
-
#
|
261 |
-
|
|
|
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 |
-
#
|
|
|
|
|
|
|
|
|
300 |
def update_description_and_code(selection):
|
301 |
-
config = get_app_config(selection)
|
302 |
return (
|
303 |
-
f"**{
|
304 |
-
|
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
|
314 |
-
def
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
315 |
try:
|
316 |
-
#
|
317 |
-
|
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(
|
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"
|
388 |
f"Error: {error_msg}",
|
389 |
-
|
|
|
390 |
)
|
391 |
|
392 |
-
# Handle
|
393 |
load_btn.click(
|
394 |
-
|
395 |
-
inputs=app_selection,
|
396 |
-
outputs=[
|
397 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
398 |
|
399 |
return demo
|
400 |
|
401 |
-
#
|
402 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
403 |
|
404 |
-
#
|
405 |
-
|
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 |
-
|
|
|
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)
|