diff --git a/src/app/interface/chat.py b/src/app/interface/chat.py index e52a203..d71fd7c 100644 --- a/src/app/interface/chat.py +++ b/src/app/interface/chat.py @@ -1,5 +1,6 @@ import os import json +from pathlib import Path from typing import Any, Callable import gradio as gr from app.agents.action_registry import get_user_friendly_action @@ -89,48 +90,61 @@ class ChatManager: def gradio_build_interface(self) -> gr.Blocks: - with gr.Blocks(fill_height=True, fill_width=True) as interface: - gr.Markdown("# 🤖 Agente di Analisi e Consulenza Crypto (Chat)") + css_file_path = Path(__file__).parent / "styles" / "chat.css" - # --- Prepara le etichette di default per i dropdown - model_labels = self.inputs.list_models_names() - default_model_label = self.inputs.team_leader_model.label - if default_model_label not in model_labels: - default_model_label = model_labels[0] if model_labels else None + with gr.Blocks(fill_height=True, fill_width=True, css_paths=[str(css_file_path)]) as interface: + with gr.Column(elem_id="chat-wrapper-column"): + gr.Markdown("# 🤖 Agente di Analisi e Consulenza Crypto") - strategy_labels = self.inputs.list_strategies_names() - default_strategy_label = self.inputs.strategy.label - if default_strategy_label not in strategy_labels: - default_strategy_label = strategy_labels[0] if strategy_labels else None + # --- Prepara le etichette di default per i dropdown + model_labels = self.inputs.list_models_names() + default_model_label = self.inputs.team_leader_model.label + if default_model_label not in model_labels: + default_model_label = model_labels[0] if model_labels else None - # Dropdown provider e stile - with gr.Row(): - provider = gr.Dropdown( - choices=model_labels, - value=default_model_label, - type="index", - label="Modello da usare" + strategy_labels = self.inputs.list_strategies_names() + default_strategy_label = self.inputs.strategy.label + if default_strategy_label not in strategy_labels: + default_strategy_label = strategy_labels[0] if strategy_labels else None + + # Dropdown provider e stile + with gr.Row(elem_id="dropdown-row"): + provider = gr.Dropdown( + choices=model_labels, + value=default_model_label, + type="index", + label="Modello da usare" + ) + provider.change(fn=self.inputs.choose_team_leader, inputs=provider, outputs=None) + + style = gr.Dropdown( + choices=strategy_labels, + value=default_strategy_label, + type="index", + label="Stile di investimento" + ) + style.change(fn=self.inputs.choose_strategy, inputs=style, outputs=None) + + chat = gr.ChatInterface( + fn=self.gradio_respond, + chatbot=gr.Chatbot( + elem_classes=["borderless-chat"], # Applica la classe CSS + scale=1 # Mantiene l'altezza completa + ), + # Aggiungi un placeholder + textbox=gr.Textbox( + placeholder="Dimmi come posso aiutarti con le criptovalute...", + scale=1, # Assicura che la textbox si allinei correttamente + render=False # Importante: dice a Gradio di non renderizzarla due volte + ) ) - provider.change(fn=self.inputs.choose_team_leader, inputs=provider, outputs=None) - style = gr.Dropdown( - choices=strategy_labels, - value=default_strategy_label, - type="index", - label="Stile di investimento" - ) - style.change(fn=self.inputs.choose_strategy, inputs=style, outputs=None) + with gr.Row(): + clear_btn = gr.Button("🗑️ Reset Chat") + save_btn = gr.Button("💾 Salva Chat") + load_btn = gr.Button("📂 Carica Chat") - chat = gr.ChatInterface( - fn=self.gradio_respond - ) - - with gr.Row(): - clear_btn = gr.Button("🗑️ Reset Chat") - save_btn = gr.Button("💾 Salva Chat") - load_btn = gr.Button("📂 Carica Chat") - - clear_btn.click(self.gradio_clear, inputs=None, outputs=[chat.chatbot, chat.chatbot_state]) - save_btn.click(self.gradio_save, inputs=None, outputs=None) - load_btn.click(self.gradio_load, inputs=None, outputs=[chat.chatbot, chat.chatbot_state]) + clear_btn.click(self.gradio_clear, inputs=None, outputs=[chat.chatbot, chat.chatbot_state]) + save_btn.click(self.gradio_save, inputs=None, outputs=None) + load_btn.click(self.gradio_load, inputs=None, outputs=[chat.chatbot, chat.chatbot_state]) return interface diff --git a/src/app/interface/styles/chat.css b/src/app/interface/styles/chat.css new file mode 100644 index 0000000..756c213 --- /dev/null +++ b/src/app/interface/styles/chat.css @@ -0,0 +1,42 @@ +/* --- Contenitore Principale --- */ +#chat-wrapper-column {width: 40% !important; max-width: 1200px !important; margin: 0 auto !important;} + +/* --- Finestra Chat (Borderless) --- */ +.borderless-chat {border: none !important; box-shadow: none !important; background: none !important;} +.borderless-chat .message.bot {border: none !important; box-shadow: none !important;} + +/* --- Scrollbar --- */ +.borderless-chat ::-webkit-scrollbar-button { display: none; } +.borderless-chat ::-webkit-scrollbar-track { background: #1f2937; border-radius: 4px; } +.borderless-chat ::-webkit-scrollbar-thumb { background: #4b5563; border-radius: 4px; } +.borderless-chat ::-webkit-scrollbar-thumb:hover { background: #6b7280; } +.borderless-chat ::-webkit-scrollbar, #chat-wrapper-column textarea::-webkit-scrollbar { display: none; } +.borderless-chat, #chat-wrapper-column textarea { + scrollbar-width: none; /* Firefox */ + -ms-overflow-style: none; /* IE/Edge (vecchio) */ +} +#chat-wrapper-column textarea::-webkit-scrollbar-button { display: none; } +#chat-wrapper-column textarea::-webkit-scrollbar-track { background: #1f2937; border-radius: 4px; } +#chat-wrapper-column textarea::-webkit-scrollbar-thumb { background: #4b5563; border-radius: 4px; } +#chat-wrapper-column textarea::-webkit-scrollbar-thumb:hover { background: #6b7280; } + +/* Rimuove i bordi dal gr.Group usato da ChatInterface per la textbox */ +#chat-wrapper-column .gr-group { + border: none !important; + box-shadow: none !important; + background: none !important; +} + +/* La SOLUZIONE per il separatore dei dropdown */ +#dropdown-row > div { + border: none !important; + box-shadow: none !important; +} + +/* Stile "Pillola" per la Textbox interna (figlia del gr.Group di ChatInterface) */ +#chat-wrapper-column .gr-group textarea { + border: none !important; + box-shadow: none !important; + min-height: 56px !important; + padding: 18px 24px !important; +} \ No newline at end of file