Spaces:
Sleeping
Sleeping
File size: 23,709 Bytes
fe4792e |
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 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 |
import streamlit as st
import base64
import os
from datetime import datetime
import pytz
import logging
from utils.admin import supabase # Pour load_theme_preference et save_theme_preference
from utils.logging_utils import log_to_file
# Fonction pour charger la préférence de thème depuis la base de données
def load_theme_preference():
"""Charge la préférence de thème depuis la base de données"""
if 'user' in st.session_state and st.session_state['user']:
user_id = st.session_state['user'].get('id')
if user_id:
try:
response = supabase.table("notification_preferences").select("theme").eq("user_id", user_id).execute()
if response.data:
theme = response.data[0]['theme']
log_to_file(f"Thème '{theme}' chargé pour l'utilisateur {user_id}")
return theme
except Exception as e:
log_to_file(f"Erreur lors du chargement du thème : {str(e)}", logging.ERROR)
return 'Clair' # Thème par défaut
# Fonction pour sauvegarder la préférence de thème dans la base de données
def save_theme_preference(theme):
"""Sauvegarde la préférence de thème dans la base de données"""
if 'user' in st.session_state and st.session_state['user']:
user_id = st.session_state['user'].get('id')
if user_id:
try:
# Vérifier si une préférence existe déjà
existing_preference = supabase.table("notification_preferences").select("*").eq("user_id", user_id).execute()
if existing_preference.data:
# Mettre à jour la ligne existante
supabase.table("notification_preferences").update({"theme": theme}).eq("user_id", user_id).execute()
else:
# Insérer une nouvelle ligne
supabase.table("notification_preferences").insert({"user_id": user_id, "theme": theme}).execute()
st.session_state.user_theme = theme
log_to_file(f"Thème '{theme}' sauvegardé pour l'utilisateur {user_id}")
except Exception as e:
log_to_file(f"Erreur lors de la sauvegarde du thème : {str(e)}", logging.ERROR)
def apply_theme(theme):
# Définition des couleurs communes selon le thème choisi (sombre ou clair)
# Texte principal : Gris clair (#E0E0E0) pour le thème sombre, Gris foncé (#4a4a4a) pour le thème clair
text_color = "#E0E0E0" if theme == "Sombre" else "#4a4a4a"
# Couleur de fond de la page : Gris très foncé (#1E1E1E) pour le thème sombre, blanc cassé (#f7f9fc) pour le thème clair
bg_color = "#1E1E1E" if theme == "Sombre" else "#f7f9fc"
# Couleur de fond des zones de saisie (inputs) : Gris foncé (#333333) pour le thème sombre, gris très clair avec une légère teinte bleue (#eef3f7) pour le thème clair
input_bg_color= "#333333" if theme == "Sombre" else "#eef3f7"
# Couleur de fond des zones de saisie (inputs) : Gris foncé (#333333) pour le thème sombre, rouge saumon clair (#ffcccb pour le thème clair
input_text_area_inactive = "#333333" if theme == "Sombre" else "#ffcccb"
# Couleur de fond des zones de saisie active (inputs) : Gris foncé (#999999) pour le thème sombre, Blanc pur (#ffffff) pour le thème clair
input_text_area_active = "#666666" if theme == "Sombre" else "#ffffff"
# Définir la couleur du curseur (caret) selon le thème
caret_color = "white" if theme == "Sombre" else "black" # Blanc pour le thème sombre, noir pour le thème clair
# Couleur de fond de la barre latérale : Gris très foncé (#2D2D2D) pour le thème sombre, gris bleu très clair ( #e3e9f1) pour le thème clair
sidebar_bg_color = "#2D2D2D" if theme == "Sombre" else " #e3e9f1"
# Couleurs spécifiques pour les messages utilisateur et assistant :
# Messages de l'utilisateur : Bleu foncé (#0E4C92) pour le thème sombre, Bleu clair désaturé (#d1e7ff) pour le thème clair
user_msg_bg = "#0E4C92" if theme == "Sombre" else "#d1e7ff"
# Messages de l'assistant : Vert foncé (#1A472A) pour le thème sombre, Gris perle (#f0f0f0) pour le thème clair
assistant_msg_bg = "#1A472A" if theme == "Sombre" else "#f0f0f0"
# Couleurs pour les boutons et éléments interactifs :
# Fond des boutons : Bleu acier (#4682B4) pour le thème sombre, Or (#FFD700) pour le thème clair
button_bg = "#4682B4" if theme == "Sombre" else "#FFD700"
# Texte des boutons : Blanc (#FFFFFF) pour le thème sombre, Vert mer (#8FBC8F) pour le thème clair
button_text = "white" if theme == "Sombre" else "#8FBC8F"
# Fond du selectbox : Bleu foncé (#0E4C92) pour le thème sombre, gris très clair avec une légère teinte bleue (#eef3f7) pour le thème clair
select_bg = "#ff5e4d" if theme == "Sombre" else "#eef3f7"
# Fond du selectbox : Bleu foncé (#0E4C92) pour le thème sombre, Gris clair (#e6f7ff) pour le thème clair
select_option_bg = "#1c39bb" if theme == "Sombre" else "#e6f7ff"
select_text_color = "black" if theme == "Sombre" else "#333333" # Couleur du texte du selectbox
# Génération des styles CSS pour Streamlit
st.markdown(f"""
<style>
/* Styles généraux */
.stApp {{
background-color: {bg_color}; /* Couleur de fond générale */
color: {text_color} !important; /* Couleur de texte principale */
}}
/* Styles pour les messages de chat */
.stChatMessage {{
background-color: {input_bg_color} !important; /* Fond des messages */
color: {text_color} !important; /* Couleur de texte dans les messages */
}}
.stChatMessage.user {{ background-color: {user_msg_bg} !important; }} /* Fond des messages utilisateur */
.stChatMessage.assistant {{ background-color: {assistant_msg_bg} !important; }} /* Fond des messages assistant */
.stChatMessage * {{ color: {text_color} !important; }} /* Couleur de texte dans tous les éléments des messages */
/* Style pour le conteneur de la zone de saisie */
[data-testid="stBottomBlockContainer"] {{
background-color: {input_bg_color} !important; /* Fond de la zone de saisie */
}}
/* Styles pour la zone de saisie et son conteneur interne */
.stChatInput,
.stChatInput > div,
.stChatInput textarea {{
background-color: {input_text_area_inactive} !important; /* Fond de la zone de saisie */
border-color: {"#555555" if theme == "Sombre" else "#b0e0e6"} !important; /* Bordure des champs de saisie */
color: {text_color} !important; /* Texte dans la zone de saisie */
}}
.stChatInput textarea:focus {{
background-color: {input_text_area_active} !important; /* Fond quand la zone est active */
color: {text_color} !important; /* Texte actif */
caret-color: {caret_color} !important; /* Couleur du curseur actif */
box-shadow: none !important; /* Pas de halo lumineux lors de la saisie */
}}
/* Style pour le bouton d'envoi */
.stChatInput button {{
background-color: {button_bg} !important; /* Fond des boutons */
color: {button_text} !important; /* Couleur du texte des boutons */
}}
/* Styles pour la barre latérale */
[data-testid="stSidebar"] {{
background-color: {sidebar_bg_color}; /* Couleur de fond de la barre latérale */
color: {text_color}; /* Texte de la barre latérale */
}}
[data-testid="stSidebar"] .st-bw,
[data-testid="stSidebar"] h3 {{ color: {text_color} !important; }} /* Couleur des titres et textes dans la barre latérale */
/* Styles pour les boutons */
.stButton > button {{
background-color: {button_bg}; /* Fond des boutons généraux */
color: {button_text}; /* Couleur du texte des boutons */
}}
/* Styles pour les expandeurs */
.streamlit-expanderHeader {{
background-color: {input_bg_color}; /* Fond des en-têtes d'expandeur */
color: {text_color}; /* Couleur du texte des en-têtes d'expandeur */
transition: all 0.3s ease-out; /* Transition fluide pour l'expansion */
}}
.streamlit-expanderHeader[aria-expanded="true"] {{ transform: translateX(10px); }} /* Effet de déplacement quand l'expandeur est ouvert */
.streamlit-expanderContent {{
background-color: {"#1E90FF" if theme == "Sombre" else "#F0F0F0"} !important; /* Couleur de fond du contenu de l'expandeur */
padding: 10px;
border-radius: 5px; /* Coins arrondis du contenu de l'expandeur */
}}
/* Styles pour le selectbox */
.stSelectbox > div > div:first-child,
.stSelectbox > div > div:nth-child(2),
.stSelectbox ul {{
background-color: {select_bg} !important; /* Fond des éléments du selectbox */
color: {"white" if theme == "Sombre" else "#333333"} !important; /* Couleur du texte des éléments du selectbox */
}}
.stSelectbox ul li:hover, .stSelectbox ul li[aria-selected="true"] {{
background-color: {"#ffe4e1" if theme == "Sombre" else "#e6f7ff"} !important; /* Fond des éléments au survol et sélectionnés */
}}
/* Styles pour le selectbox */
[data-testid="stSelectboxVirtualDropdown"], .st-emotion-cache-1o2fhjg.e1811lun0 {{
background-color: {select_option_bg} !important; /* Fond des éléments du selectbox */
color: {select_text_color} !important; /* Couleur du texte des options */
}}
[data-testid="stSelectboxVirtualDropdown"] li[aria-selected="true"], .st-emotion-cache-1o2fhjg.e1811lun0[aria-selected="true"] {{
background-color: {"#1A6BBF" if theme == "Sombre" else "#ffcccb"} !important; /* Fond des options sélectionnées */
}}
[data-testid="stSelectboxVirtualDropdown"] li:hover {{
background-color: {"#1A6BBF" if theme == "Sombre" else "#ffa07a"} !important; /* Fond au survol des options */
}}
/* Styles pour les boutons de feedback */
.stChatMessage .stButton > button {{
background-color: transparent !important; /* Fond transparent pour les boutons dans les messages */
border: none !important;
box-shadow: none !important;
padding: 0 !important;
}}
.stChatMessage .stButton > button:hover {{
background-color: rgba(0, 0, 0, 0.05) !important; /* Léger changement de fond au survol */
}}
/* Styles pour les boutons de la barre latérale */
[data-testid="stSidebar"] .stButton > button {{
background-color: {"#1E90FF" if theme == "Sombre" else "#FFD700"} !important; /* Fond des boutons spécifiques dans la barre latérale */
color: {button_text} !important; /* Couleur du texte des boutons dans la barre latérale */
border: inherit !important;
box-shadow: inherit !important;
padding: inherit !important;
}}
/* Assurez-vous que tous les textes sont lisibles */
body, p, h1, h2, h3, h4, h5, h6, span, div {{
color: {"#E0E0E0" if theme == "Sombre" else "#4a4a4a"} !important; /* Couleur des textes dans tout le contenu de la page, */
}}
</style>
""", unsafe_allow_html=True)
# ajout de logo sur l'en -tête de l'application (cette focntion est appelé dans inject_custom_css(theme))
def get_base64_encoded_image(image_file):
with open(image_file, "rb") as img_file:
return base64.b64encode(img_file.read()).decode('utf-8')
# ajout de logo sur l'en -tête de l'application et animation du logo
def inject_custom_css(theme):
# Définition des paramètres visuels en fonction du thème
is_dark_theme = theme == "Sombre"
# Sélection du logo et des couleurs selon le thème
logo_file = "assets/logo2.svg" if is_dark_theme else "assets/logo.svg"
background_color = "#333333" if is_dark_theme else "#eef3f7"
text_color = "#E0E0E0" if is_dark_theme else "#333333"
# Encodage du logo en base64
logo_base64 = get_base64_encoded_image(logo_file)
st.markdown(
f"""
<style>
@keyframes rotate {{
from {{
transform: rotate(0deg);
}}
to {{
transform: rotate(360deg);
}}
}}
.stApp header {{
display: flex;
align-items: center;
background-color: {background_color} !important;
padding-left: 240px !important;
}}
.stApp header::before {{
content: "";
background-image: url("data:image/svg+xml;base64,{logo_base64}");
background-repeat: no-repeat;
background-position: center;
background-size: contain;
width: 190px;
height: 190px;
position: absolute;
left: 350px;
animation: rotate 10s linear infinite;
}}
.stApp header::after {{
content: "Colibri IA: la précision d'un colibri, la puissance d'un assistant";
font-size: 15px;
font-weight: normal;
color: {text_color};
margin-left: 250px;
background-color: rgba(0, 0, 0, 0.02) !important;
}}
</style>
""",
unsafe_allow_html=True,)
# ajout de logo sur la sidebar avec un texte simulant un en-tête
def add_sidebar_logo(theme):
# Définition des couleurs en fonction du thème
text_color = "#E0E0E0" if theme == "Sombre" else "#333333"
# #E0E0E0 : Gris très clair, presque blanc (pour le thème sombre)
# #333333 : Gris très foncé, presque noir (pour le thème clair)
# Utilisation d'un contexte 'with' pour la barre latérale
with st.sidebar:
# Ajout du logo (identique pour les deux thèmes)
st.image("assets/logo.png", width=150)
# Ajout du titre avec la couleur appropriée
st.markdown(
f"""
<h2 style="color:{text_color};">Colibri Assistant</h2>
""",
unsafe_allow_html=True
)
# Ajout d'une ligne de séparation
st.write("---")
def apply_chat_styles(theme):
light_user_bg = "#d1e7ff" # bleu clair désaturé (arrière-plan des messages utilisateur en thème clair)
light_assistant_bg = "#f0f0f0" # Gris perle (arrière-plan des messages assistant en thème clair)
dark_user_bg = "#0E4C92" # #0E4C92 = bleu foncé (arrière-plan des messages utilisateur en thème sombre)
dark_assistant_bg = "#1A472A" # #1A472A = vert foncé (arrière-plan des messages assistant en thème sombre)
user_bg = dark_user_bg if theme == "Sombre" else light_user_bg # Utilise la couleur bleu foncé en thème sombre ou bleu clair désaturé en thème clair pour l'utilisateur
assistant_bg = dark_assistant_bg if theme == "Sombre" else light_assistant_bg # Utilise la couleur vert foncé en thème sombre ou Gris perle en thème clair pour l'assistant
text_color = "#E0E0E0" if theme == "Sombre" else "#000000" # Utilise la couleur gris clair (#E0E0E0) en thème sombre ou noir (#000000) en thème clair pour le texte
st.markdown(f"""
<style>
[data-testid="stChatMessage"] {{
width: fit-content !important;
max-width: 80% !important;
padding: 10px !important;
border-radius: 15px !important;
margin-bottom: 10px !important;
clear: both !important;
}}
[data-testid="stChatMessage"]:has([data-testid="stChatMessageAvatarUser"]) {{
background-color: {user_bg} !important; # Arrière-plan des messages utilisateur (dépend du thème)
border-radius: 15px 15px 0 15px !important;
margin-left: auto !important;
margin-right: 10px !important;
text-align: right !important;
float: right !important;
}}
[data-testid="stChatMessage"]:not(:has([data-testid="stChatMessageAvatarUser"])) {{
background-color: {assistant_bg} !important; # Arrière-plan des messages assistant (dépend du thème)
border-radius: 15px 15px 15px 0 !important;
margin-right: auto !important;
margin-left: 10px !important;
text-align: left !important;
float: left !important;
}}
[data-testid="stChatMessage"] * {{
color: {text_color} !important; # Couleur du texte (dépend du thème)
}}
</style>
""", unsafe_allow_html=True)
def inject_custom_toggle_css(theme):
# Définition de la couleur du texte en fonction du thème
text_color = "#e0e0e0" if theme == "Sombre" else "#666666"
# #e0e0e0 : Gris très clair, presque blanc (pour le thème sombre)
# #666666 : Gris moyen foncé (pour le thème clair)
# CSS personnalisé pour le style des toggles
custom_css = f"""
<style>
/* Style pour le titre du toggle */
.stExpander .stToggleButton label,
.streamlit-expanderHeader .stToggleButton label {{
color: {text_color} !important;
font-weight: bold;
}}
</style>
"""
# Injection du CSS personnalisé dans la page Streamlit
st.markdown(custom_css, unsafe_allow_html=True)
def create_custom_footer():
footer = """
<style>
.footer {
position: fixed;
left: 0;
bottom: 0;
width: 100%;
background-color: #0E1117; # Couleur de fond sombre, ajustez selon votre thème
color: #FAFAFA; # Couleur du texte claire
text-align: center;
padding: 10px;
font-size: 14px;
}
</style>
<div class="footer">
<p>© 2024 Votre Entreprise. Tous droits réservés.</p>
</div>
"""
st.markdown(footer, unsafe_allow_html=True)
# Fonction pour permettre à l'utilisateur de changer de thème avec un toggle
def theme_switcher():
current_theme = st.session_state.get('user_theme', 'Clair')
# Utiliser des colonnes Streamlit pour l'alignement
col1, col2 = st.columns([0.9, 4]) # Ajustez les ratios selon vos besoins
with col1:
# Toggle sans label
is_dark = st.toggle("", value=current_theme == "Sombre", key=f"theme_toggle", label_visibility="collapsed")
with col2:
# Label personnalisé
title_color = "#FF6B6B" if current_theme == "Sombre" else "#1E90FF"
st.markdown(f'<p style="color: {title_color}; font-weight: normal; margin-top: 5px;">Thème sombre</i>', unsafe_allow_html=True)
new_theme = "Sombre" if is_dark else "Clair"
if new_theme != current_theme:
st.session_state.user_theme = new_theme
save_theme_preference(new_theme)
apply_theme(new_theme)
apply_chat_styles(new_theme)
st.rerun()
# Cette fonction supprimera certains styles par défaut de Streamlit qui pourraient interférer avec vos styles personnalisés.
def remove_streamlit_style():
st.markdown("""
<style>
#MainMenu {visibility: hidden;}
footer {visibility: hidden;}
</style>
""", unsafe_allow_html=True)
# Appelez cette fonction au début de votre improved_ui
def force_streamlit_style_update():
st.markdown("""
<script>
// Force Streamlit to re-evaluate the styles
window.parent.postMessage({
type: "streamlit:setComponentValue",
value: true
}, "*")
</script>
""", unsafe_allow_html=True
)
# Fonction pour cacher les pages de navigation spécifiques (voir dossier pages)
def hide_pages():
hide_pages_style = """
<style>
/* Cache les liens de navigation spécifiques */
.st-emotion-cache-79elbk .st-emotion-cache-1ekxtbt li:nth-child(2), /* admin page */
.st-emotion-cache-79elbk .st-emotion-cache-1ekxtbt li:nth-child(3) { /* reset password */
display: none !important;
}
/* Cache le séparateur si nécessaire */
.st-emotion-cache-uzxc3z {
display: none !important;
}
/* Pour s'assurer que tous les liens sont cachés même si les classes changent */
[data-testid="stSidebarNavItems"] li a[href*="/admin_page"],
[data-testid="stSidebarNavItems"] li a[href*="/reset_password"] {
display: none !important;
}
/* Cache les conteneurs parents si nécessaire */
[data-testid="stSidebarNavItems"] li:has(a[href*="/admin_page"]),
[data-testid="stSidebarNavItems"] li:has(a[href*="/reset_password"]) {
display: none !important;
}
</style>
"""
st.markdown(hide_pages_style, unsafe_allow_html=True)
# styles pour le dashboard administrateur (tooltip et bouttons)
def apply_tooltip_and_button_styles(theme):
# Définition des couleurs en fonction du thème
text_color = "#E0E0E0" if theme == "Sombre" else "#333333"
background_color = "#333333" if theme == "Sombre" else "#fff"
border_color = "#ccc" if theme == "Sombre" else "#333"
button_background_color = "#4682B4" if theme == "Sombre" else "#FFD700"
button_text_color = "white" if theme == "Sombre" else "#8FBC8F"
# Injection des styles CSS pour les tooltips et le bouton de soumission du formulaire
st.markdown(
f"""
<style>
/* Style pour le conteneur principal du tooltip */
.st-emotion-cache-oj1fi {{
background-color: {background_color} !important;
color: {text_color} !important;
border: 1px solid {border_color} !important;
}}
/* Style pour le contenu du tooltip */
.stTooltipIcon {{
background-color: {background_color} !important;
color: {text_color} !important;
}}
/* Style pour le texte du tooltip */
.st-emotion-cache-1whk732 {{
color: {text_color} !important;
}}
/* Style pour l'icône du tooltip */
.stTooltipIcon svg {{
stroke: {text_color} !important;
}}
/* Style pour la couche externe du popup */
div[data-baseweb="tooltip"] {{
background-color: {background_color} !important;
border: 1px solid {border_color} !important;
padding: 5px 10px !important;
border-radius: 4px !important;
font-size: 12px !important;
z-index: 999999 !important;
}}
/* Style pour la couche interne du popup et son contenu */
div[data-baseweb="tooltip"] > div,
div[data-baseweb="tooltip"] > div > div {{
background-color: {background_color} !important;
color: {text_color} !important;
}}
/* Force la couleur du texte sur toutes les couches possibles */
div[data-baseweb="tooltip"] *,
div[role="tooltip"] * {{
color: {text_color} !important;
background-color: {background_color} !important;
}}
/* Style pour le bouton de soumission du formulaire */
div[data-testid="stFormSubmitButton"] button {{
background-color: {button_background_color} !important;
color: {button_text_color} !important;
border: none !important;
padding: 0.5rem 1rem !important;
border-radius: 0.5rem !important;
font-weight: bold !important;
transition: all 0.3s ease !important;
}}
/* Style pour le bouton de soumission du formulaire lorsqu'il est survolé */
div[data-testid="stFormSubmitButton"] button:hover {{
border: 1px solid red !important; # Ajoutez cette ligne pour définir la bordure rouge au survol
opacity: 0.8 !important;
}}
</style>
""",
unsafe_allow_html=True
) |