Spaces:
Running
Running
| import os, html, json | |
| import gradio as gr | |
| from jinja2 import Environment, FileSystemLoader | |
| from utils import read_file, get_models_data, get_contacts, img_b64, opis_to_html | |
| BASE_DIR = os.path.dirname(os.path.abspath(__file__)) | |
| ASSETS_DIR = os.path.join(BASE_DIR, "assets") | |
| env = Environment(loader=FileSystemLoader(ASSETS_DIR), autoescape=True) | |
| SHOWCASE_EXTRA_CSS = """ | |
| footer, footer *, .footer, | |
| div[class*="footer"], .built-with, [class*="built-with"], | |
| [class*="ApiLink"], [class*="api-link"], .show-api, | |
| a[href*="gradio.app"], a[href*="huggingface"], | |
| button[title*="API"], button[title*="Setting"], | |
| button[aria-label*="Setting"], | |
| .top-panel, div.top-panel, [class*="top-panel"] | |
| { display: none !important; visibility: hidden !important; | |
| height: 0 !important; overflow: hidden !important; } | |
| .gradio-container { min-height: unset !important; } | |
| """ | |
| HIDE_FOOTER_JS = """ | |
| () => { | |
| const kill = () => { | |
| document.querySelectorAll('footer, .footer, [class*="footer"]').forEach(el => el.remove()); | |
| document.querySelectorAll('.show-api, [class*="ApiLink"], [class*="api-link"]').forEach(el => el.remove()); | |
| document.querySelectorAll('button[title*="Setting"], button[aria-label*="Setting"]').forEach(el => el.remove()); | |
| document.querySelectorAll('a[href*="gradio.app"]').forEach(el => { let p = el.closest('div'); if(p) p.remove(); }); | |
| }; | |
| kill(); | |
| setTimeout(kill, 300); | |
| setTimeout(kill, 1000); | |
| new MutationObserver(kill).observe(document.body, {childList:true, subtree:true}); | |
| } | |
| """ | |
| def build_gallery(images): | |
| if not images: | |
| return '<div style="padding:40px;text-align:center;color:#888">Фото відсутні</div>' | |
| imgs_json = json.dumps([img_b64(p) for p in images]) | |
| gallery_tpl = env.get_template("gallery.html") | |
| gallery_html = gallery_tpl.render(imgs_json=imgs_json, n=len(images)) | |
| return f'<iframe srcdoc="{html.escape(gallery_html)}" allow="fullscreen" class="ur-gallery-frame" scrolling="no"></iframe>' | |
| def render_showcase(): | |
| models_data = get_models_data(BASE_DIR) | |
| contacts = get_contacts(BASE_DIR) | |
| for m in models_data: | |
| m['desc_html'] = opis_to_html(m['opis_raw']) | |
| m['gallery_html'] = build_gallery(m['images']) | |
| landing_tpl = env.get_template("landing.html") | |
| rendered = landing_tpl.render(models=models_data, contacts=contacts) | |
| return rendered, models_data | |
| shell_css = read_file(os.path.join(ASSETS_DIR, "shell.css")) + SHOWCASE_EXTRA_CSS | |
| def build_showcase_app(): | |
| # Gradio 4: css= и js= работают в конструкторе | |
| with gr.Blocks( | |
| title="Unstop Retail", | |
| css=shell_css, | |
| js=HIDE_FOOTER_JS, | |
| analytics_enabled=False, | |
| ) as app_showcase: # show_api не используем — несовместим с gr 4.x | |
| showcase_html = gr.HTML() | |
| def get_current_html(): | |
| html_content, _ = render_showcase() | |
| return html_content | |
| app_showcase.load(fn=get_current_html, inputs=[], outputs=[showcase_html]) | |
| return app_showcase | |