Render each app in the PR's spaces preview in a separate page (#6657)

* Use template response

* minor fix

* Return type hint

* add changeset

* Remove return types

* response_class=None

* Use relative path

* SPA

* remove pydantic pin

* Revert

* delete changeset

* Overflow hidden on body

* text gray

* Collapsible sidebar

* max-height

* Use search params

* document.location.search

---------

Co-authored-by: gradio-pr-bot <gradio-pr-bot@users.noreply.github.com>
This commit is contained in:
Freddy Boulton 2023-12-06 10:53:16 -05:00 committed by GitHub
parent 30c9fbb5c7
commit 1086542f17
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 143 additions and 10 deletions

View File

@ -4,12 +4,30 @@ import os
import sys
import copy
import pathlib
from fastapi import FastAPI, Request
from fastapi.templating import Jinja2Templates
import uvicorn
from gradio.utils import get_space
os.environ["GRADIO_ANALYTICS_ENABLED"] = "False"
demo_dir = pathlib.Path(__file__).parent / "demos"
app = FastAPI()
templates = Jinja2Templates(directory="templates")
names = sorted(os.listdir("./demos"))
@app.get("/")
def index(request: Request):
names = [[p[0], p[2]] for p in all_demos]
return templates.TemplateResponse("index.html", {"request": request, "names": names,
"initial_demo": names[0][0], "is_space": get_space()})
all_demos = []
demo_module = None
for p in sorted(os.listdir("./demos")):
@ -20,16 +38,15 @@ for p in sorted(os.listdir("./demos")):
demo_module = importlib.import_module(f"run")
else:
demo_module = importlib.reload(demo_module)
all_demos.append((p, demo_module.demo))
all_demos.append((p, demo_module.demo.queue(), False))
except Exception as e:
p = p + ""
with gr.Blocks() as demo:
gr.Markdown(f"Error loading demo: {e}")
all_demos.append((p, demo))
all_demos.append((p, demo, True))
with gr.Blocks() as mega_demo:
for demo_name, demo in all_demos:
with gr.Tab(demo_name):
demo.render()
for demo_name, demo, _ in all_demos:
app = gr.mount_gradio_app(app, demo, f"/demo/{demo_name}")
mega_demo.queue().launch()
if __name__ == "__main__":
uvicorn.run(app, port=7860, host="0.0.0.0")

View File

@ -0,0 +1,118 @@
<!DOCTYPE html>
<html>
<head>
{%if is_space %}
<meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests">
{% endif %}
<style>
/* Reset some default styles */
body, h1, h2, h3, p, ul {
margin: 0;
padding: 0;
}
body {
font-family: 'Arial', sans-serif;
overflow-y: hidden;
}
.sidebar {
position: absolute;
top: 0;
left: 0;
height: 100vh;
max-height: calc(100vh - 50px);
width: 300px;
overflow-y: scroll;
overflow-x: hidden;
font-size: 0.875rem; /* 14px */
line-height: 1.25rem; /* 20px */
transition: width 0.3s ease;
}
.sidebar.collapsed {
width: 0;
}
.sidebar a {
display: block;
padding: 8px 16px;
text-decoration: none;
color: rgb(107 114 128);
}
.sidebar a:hover {
color: black;
transform: translateX(1px);
}
/* Apply a different style to the selected item in the sidebar */
.sidebar a.active {
background-color: rgb(251 146 60);
color: white;
border-radius: 0.75rem;
font-weight: bold;
}
/* Styling for the close button */
.close-btn {
cursor: pointer;
border: none;
background-color: white;
font-size: xx-large;
position: relative;
}
/* Styling for the content */
.content {
margin-left: 300px;
padding: 20px;
display: block;
height: 100vh;
transition: margin-left 0.3s ease;
}
.content.collapsed {
margin-left: 0;
}
/* Make the iframe responsive */
.content iframe {
width: 100%;
border: 0;
height: 100%;
}
@media only screen and (max-width: 600px) {
/* Adjust styles for smaller screens */
.sidebar {
width: 100%;
position: relative;
height: auto;
}
.content {
margin-left: 0;
}
}
</style>
<script src="//unpkg.com/alpinejs" defer></script>
</head>
<body x-data="{ current_demo: '{{ initial_demo }}', is_collapsed: false }">
<div style="display: flex; flex-direction: column;">
<div>
<button @click="is_collapsed = !is_collapsed" class="close-btn">
<a x-text="is_collapsed ? '➡️' : '⬅️'"></a>
</button>
</div>
<div :class="{ 'sidebar': true, 'collapsed': is_collapsed }" style="margin-top: 50px;">
{% for name in names %}
<a @click="current_demo = '{{ name[0] }}'" :class="current_demo == '{{ name[0] }}' ? 'active' : ''">{{ name[0] }} {% if name[1] %}❌{% endif %}</a>
{% endfor %}
</div>
</div>
<div :class="{ 'content': true, 'collapsed': is_collapsed }">
<iframe :src="`/demo/${current_demo}${document.location.search}`"></iframe>
</div>
</body>
</html>

View File

@ -72,7 +72,5 @@ if __name__ == "__main__":
torch==1.12.1
altair
vega_datasets
pydantic==2.1.1
pydantic_core==2.4.0
"""
open(reqs_file_path, "w").write(textwrap.dedent(requirements))