Add custom CSS styles and improve chat interface layout (#77)
This commit was merged in pull request #77.
This commit is contained in:
@@ -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
|
||||||
|
|||||||
42
src/app/interface/styles/chat.css
Normal file
42
src/app/interface/styles/chat.css
Normal 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;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user