File size: 3,066 Bytes
f7b9253
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
a96d4f1
f7b9253
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
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