Spaces:
Sleeping
Sleeping
Download app.py from QnoM/Chatbot_confirmation: direct link, hf CLI and curl.
- Browser
- Download file 4.42 kB
-
https://huggingface.co/spaces/QnoM/Chatbot_confirmation/resolve/main/app.py
- Command line
-
hf download hf://spaces/QnoM/Chatbot_confirmation/app.py
-
curl -L -o app.py https://huggingface.co/spaces/QnoM/Chatbot_confirmation/resolve/main/app.py
4.42 kB
| import gradio as gr | |
| from gradio_htmlinjector import HTMLInjector | |
| # 1) Choix dans la popup -> ajoute (Oui/Non, confirmation) | |
| def handle_choice(choice: str, chat_history: list[tuple[str, str]]): | |
| c = (choice or "").strip().lower() | |
| if c in {"oui", "o", "yes", "y"}: | |
| user_choice, reply = "Oui", "✅ Vous avez choisi **OUI**. Action validée." | |
| elif c in {"non", "n", "no"}: | |
| user_choice, reply = "Non", "❌ Vous avez choisi **NON**. Action annulée." | |
| else: | |
| return chat_history, "" # ignore valeurs inattendues | |
| return chat_history + [(user_choice, reply)], "" # reset du pont | |
| # 2) Soumission utilisateur : réponse fixe | |
| def on_submit(user_msg: str, chat_history: list[tuple[str, str]]): | |
| if not user_msg: | |
| return chat_history, "" # rien | |
| assistant_reply = "Ceci est une réponse de démonstration.\n\nConfirmez-vous l’action ?" | |
| return chat_history + [(user_msg, assistant_reply)], "" # clear textbox | |
| # 3) Injection HTML/CSS + helper | |
| def inject_assets(): | |
| js = r""" | |
| function setGradioValue(elemId, value){ | |
| const root = (window.gradioApp && window.gradioApp()) || document; | |
| const host = root.querySelector(`#${elemId}`); | |
| if (!host) return; | |
| const input = host.querySelector('input, textarea'); | |
| if (!input) return; | |
| input.value = value; | |
| input.dispatchEvent(new Event('input', {bubbles:true})); | |
| input.dispatchEvent(new Event('change', {bubbles:true})); | |
| } | |
| """ | |
| css = r""" | |
| #confirm-modal{ | |
| display:none; position:fixed; inset:0; z-index:9999; | |
| background: rgba(0,0,0,.45); align-items:center; justify-content:center; | |
| } | |
| #confirm-card{ | |
| background: var(--panel-background-fill, #fff); color: var(--body-text-color, #111); | |
| border: 1px solid var(--border-color-primary, #ccc); border-radius: 10px; | |
| padding: 20px; min-width: 320px; max-width: 90vw; box-shadow: 0 10px 30px rgba(0,0,0,.2); | |
| } | |
| #confirm-actions{ display:flex; gap:8px; justify-content:flex-end; margin-top:14px; } | |
| #confirm-actions button{ cursor:pointer; padding:8px 14px; border-radius:8px; border:1px solid #bbb; background:#f4f4f5; } | |
| #confirm-actions button.primary{ background:#2563eb; color:#fff; border-color:transparent; } | |
| #bridge-choice{ display:none; } /* pont caché mais monté */ | |
| """ | |
| html = r""" | |
| <div id="confirm-modal" role="dialog" aria-modal="true" aria-labelledby="confirm-title"> | |
| <div id="confirm-card"> | |
| <h3 id="confirm-title">Confirmer ?</h3> | |
| <p>Souhaitez-vous continuer ?</p> | |
| <div id="confirm-actions"> | |
| <button type="button" | |
| onclick="setGradioValue('bridge-choice','non'); document.getElementById('confirm-modal').style.display='none'; document.body.style.overflow=''">Non</button> | |
| <button type="button" class="primary" | |
| onclick="setGradioValue('bridge-choice','oui'); document.getElementById('confirm-modal').style.display='none'; document.body.style.overflow=''">Oui</button> | |
| </div> | |
| </div> | |
| </div> | |
| """ | |
| return {"css": css, "js": js, "body_html": html} | |
| # 4) UI | |
| with gr.Blocks(title="Démo Chat + Popup", fill_height=True) as demo: | |
| html_injector = HTMLInjector() | |
| chat = gr.Chatbot(label="Chatbot", height=420) | |
| user_in = gr.Textbox(placeholder="Tapez un message…", lines=2) | |
| bridge_choice = gr.Textbox(visible=True, elem_id="bridge-choice") # pont oui/non | |
| # (A) submit -> (user, question) | |
| evt = user_in.submit( | |
| fn=on_submit, | |
| inputs=[user_in, chat], | |
| outputs=[chat, user_in], | |
| ) | |
| # (B) puis -> ouvrir la popup côté client (sans inputs/outputs) | |
| evt.then( | |
| fn=None, | |
| inputs=None, | |
| outputs=None, | |
| js=""" | |
| () => { | |
| const start = Date.now(); | |
| (function tick(){ | |
| const modal = document.getElementById('confirm-modal'); | |
| if (modal) { | |
| modal.style.display = 'flex'; | |
| document.body.style.overflow = 'hidden'; | |
| return; | |
| } | |
| if (Date.now() - start < 3000) setTimeout(tick, 60); | |
| })(); | |
| } | |
| """, | |
| ) | |
| # (C) clic Oui/Non -> ajoute (Oui/Non, confirmation) | |
| bridge_choice.change( | |
| fn=handle_choice, | |
| inputs=[bridge_choice, chat], | |
| outputs=[chat, bridge_choice], | |
| ) | |
| # Injection initiale (structure + styles + helper) | |
| demo.load(fn=inject_assets, inputs=None, outputs=[html_injector]) | |
| demo.launch() |