Add custom CSS styles and improve chat interface layout (#77)

This commit was merged in pull request #77.
This commit is contained in:
trojanhorse47
2025-10-31 18:05:20 +01:00
committed by GitHub
parent 52a25e3804
commit 2996bd4616
2 changed files with 94 additions and 38 deletions

View File

@@ -1,5 +1,6 @@
import os import os
import json import json
from pathlib import Path
from typing import Any, Callable from typing import Any, Callable
import gradio as gr import gradio as gr
from app.agents.action_registry import get_user_friendly_action from app.agents.action_registry import get_user_friendly_action
@@ -89,48 +90,61 @@ class ChatManager:
def gradio_build_interface(self) -> gr.Blocks: def gradio_build_interface(self) -> gr.Blocks:
with gr.Blocks(fill_height=True, fill_width=True) as interface: css_file_path = Path(__file__).parent / "styles" / "chat.css"
gr.Markdown("# 🤖 Agente di Analisi e Consulenza Crypto (Chat)")
# --- Prepara le etichette di default per i dropdown with gr.Blocks(fill_height=True, fill_width=True, css_paths=[str(css_file_path)]) as interface:
model_labels = self.inputs.list_models_names() with gr.Column(elem_id="chat-wrapper-column"):
default_model_label = self.inputs.team_leader_model.label gr.Markdown("# 🤖 Agente di Analisi e Consulenza Crypto")
if default_model_label not in model_labels:
default_model_label = model_labels[0] if model_labels else None
strategy_labels = self.inputs.list_strategies_names() # --- Prepara le etichette di default per i dropdown
default_strategy_label = self.inputs.strategy.label model_labels = self.inputs.list_models_names()
if default_strategy_label not in strategy_labels: default_model_label = self.inputs.team_leader_model.label
default_strategy_label = strategy_labels[0] if strategy_labels else None if default_model_label not in model_labels:
default_model_label = model_labels[0] if model_labels else None
# Dropdown provider e stile strategy_labels = self.inputs.list_strategies_names()
with gr.Row(): default_strategy_label = self.inputs.strategy.label
provider = gr.Dropdown( if default_strategy_label not in strategy_labels:
choices=model_labels, default_strategy_label = strategy_labels[0] if strategy_labels else None
value=default_model_label,
type="index", # Dropdown provider e stile
label="Modello da usare" 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( with gr.Row():
choices=strategy_labels, clear_btn = gr.Button("🗑️ Reset Chat")
value=default_strategy_label, save_btn = gr.Button("💾 Salva Chat")
type="index", load_btn = gr.Button("📂 Carica Chat")
label="Stile di investimento"
)
style.change(fn=self.inputs.choose_strategy, inputs=style, outputs=None)
chat = gr.ChatInterface( clear_btn.click(self.gradio_clear, inputs=None, outputs=[chat.chatbot, chat.chatbot_state])
fn=self.gradio_respond save_btn.click(self.gradio_save, inputs=None, outputs=None)
) load_btn.click(self.gradio_load, inputs=None, outputs=[chat.chatbot, chat.chatbot_state])
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])
return interface return interface

View File

@@ -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;
}