Coloring's picture
feat: add layout template `coder_artifacts`
f18a2c3
from typing import Callable
import gradio as gr
import modelscope_studio.components.antd as antd
import modelscope_studio.components.base as ms
from gradio.components.base import Component
class Site:
def __init__(self,
tabs: list,
docs: dict,
default_active_tab: str | None = None,
logo: Component | Callable | None = None):
self.tabs = tabs
self.docs = docs
self.default_active_tab = default_active_tab
self.default_active_tab_item = next(
(item for item in self.tabs if item["key"] == default_active_tab),
{})
self.logo = logo
def _render_docs(self, items: list, tab: dict):
docs_tabs = []
for item in items:
if "children" in item:
docs_tabs.extend(self._render_docs(item["children"], tab))
elif "key" in item:
key = item["key"].replace("-", "_")
tab_docs = self.docs.get(tab["key"], {})
if key in tab_docs:
with antd.Tabs.Item(
key=key,
visible=True if tab.get("default_active_key")
== key else False) as docs_tab:
docs_tabs.append(docs_tab)
tab_docs[key].render()
return docs_tabs
def render(self):
def on_tab_menu_select(e: gr.EventData):
selected_tab = e._data["payload"][0]["key"]
item = next(
(item for item in tab_components if item.key == selected_tab),
tab_components[0])
return {
tab_menu: gr.update(selected_keys=[selected_tab]),
tabs: gr.update(active_key=selected_tab),
item: gr.update(visible=True)
}
# Css is not working in demo if there are multiple Blocks, so we need to add css from demos
css = ""
for category in self.docs:
for component in self.docs[category]:
css += self.docs[category][component].get_css()
with gr.Blocks(css=css + """
.gradio-container {
max-width: 100% !important;
padding: 0 !important;
}
.gradio-container > main.fillable {
max-width: 100% !important;
padding: 0 !important;
}
.docs-layout-sider {
width: 100% !important;
max-width: 100% !important;
}
""") as demo:
with ms.Application() as app:
with antd.ConfigProvider():
with antd.Layout(elem_style=dict(
height=
"calc(100vh - var(--size-4) - var(--body-text-size) * 1.5)"
)):
with antd.Layout.Header(elem_style=dict(
padding='0 16px',
backgroundColor=
"var(--ms-gr-ant-color-bg-container)")):
with antd.Flex(align='center', gap=8):
if self.logo:
with antd.Flex(
justify="center",
align='center',
elem_style=dict(height='100%')):
if callable(self.logo):
self.logo()
else:
self.logo.render()
tab_menu = antd.Menu(
mode="horizontal",
selected_keys=[self.default_active_tab],
items=self.tabs,
elem_style=dict(flex=1, minWidth=0))
with ms.AutoLoading(show_mask=True):
with antd.Tabs(
active_key=self.default_active_tab,
render_tab_bar="() => null",
) as tabs:
tab_components = []
for tab in self.tabs:
with antd.Tabs.Item(
key=tab["key"],
elem_style=dict(
height=
"calc(100vh - var(--size-4) - var(--body-text-size) * 1.5 - 64px)"
),
visible=True
if self.default_active_tab
== tab["key"] else
False) as tab_item:
tab_components.append(tab_item)
if "content" in tab:
# custom render
with ms.Div(elem_style=dict(
maxHeight="100%",
overflow="auto")):
tab["content"].render()
elif "menus" in tab:
# menus render
with antd.Layout(elem_style=dict(
height='100%')):
with antd.Splitter():
with antd.Splitter.Panel(
default_size=213,
max="50%",
min=82,
elem_style=dict(
backgroundColor=
"var(--ms-gr-ant-color-bg-container)"
)) as sider_panel:
with antd.Layout.Sider(
breakpoint="sm",
trigger=None,
elem_classes=
"docs-layout-sider",
elem_style=dict(
# height=
# "calc(100vh - 64px)",
# overflow=
# "auto",
position=
"relative",
backgroundColor
="var(--ms-gr-ant-color-bg-container)"
)):
sider_menu = antd.Menu(
selected_keys=[
tab.get(
"default_active_key",
None)
],
mode="inline",
items=tab.get(
"menus",
[]))
if "extra_menu_footer" in tab:
if callable(tab[
"extra_menu_footer"]
):
tab["extra_menu_footer"](
)
else:
tab["extra_menu_footer"].render(
)
with antd.Splitter.Panel():
with antd.Layout(
elem_style=dict(
width=
"100%",
backgroundColor
="var(--ms-gr-ant-color-bg-container)"
)):
with antd.Layout.Content(
elem_style=
dict(
padding=
'12px 28px',
overflow
="auto"
)):
with antd.Tabs(
active_key
=tab.
get(
"default_active_key",
None
),
render_tab_bar
="() => null"
) as layout_content_tabs:
docs_tabs = self._render_docs(
tab.
get(
"menus",
[]
), tab)
def on_layout_menu_select_wrapper(
tabs, sider_menu,
layout_content_tabs):
def on_layout_menu_select(
e: gr.EventData):
selected_menu = e._data[
"payload"][0]["key"]
item = next(
(item for item in tabs
if item.key ==
selected_menu), tabs[0])
return {
sider_menu:
gr.update(selected_keys=[
selected_menu
]),
layout_content_tabs:
gr.update(
active_key=selected_menu
),
item:
gr.update(visible=True)
}
return on_layout_menu_select
sider_menu.select(
fn=on_layout_menu_select_wrapper(
docs_tabs, sider_menu,
layout_content_tabs),
outputs=[
sider_menu, layout_content_tabs,
*docs_tabs
])
def on_app_mount(e: gr.EventData):
screen_width = e._data["screen"][
"width"]
return gr.update(
default_size=82 if screen_width <
576 else 213)
app.mount(on_app_mount,
outputs=[sider_panel])
tab_menu.select(
fn=on_tab_menu_select,
outputs=[tab_menu, tabs, *tab_components])
return demo