import streamlit as st
import re
# Configuration Gitea
from config import INSTRUCTIONS
from utils.gitea import (
charger_instructions_depuis_gitea
)
def afficher_instructions_avec_expanders(markdown_content):
"""
Affiche le contenu markdown avec les sections de niveau 2 (## Titre) dans des expanders
"""
# Extraction du titre principal (niveau 1)
titre_pattern = r'^# (.+)$'
titre_match = re.search(titre_pattern, markdown_content, re.MULTILINE)
# Affichage du titre principal
if titre_match:
titre_principal = titre_match.group(1)
st.markdown(f"# {titre_principal}")
# Division en sections de niveau 2
sections = re.split(r'^## ', markdown_content, flags=re.MULTILINE)
# Affichage du contenu avant la première section de niveau 2 (sans le titre principal)
introduction = sections[0]
if titre_match:
# Supprimer le titre principal de l'introduction car on l'a déjà affiché
introduction = re.sub(titre_pattern, '', introduction, flags=re.MULTILINE).strip()
if introduction:
st.markdown(introduction, unsafe_allow_html=True)
# Affichage des sections dans des expanders
for i, section in enumerate(sections[1:], 1):
# Extraction du titre de la section
lignes = section.split('\n', 1)
titre_section = lignes[0].strip()
# Garder le titre dans le contenu
contenu_section = f"## {titre_section}"
if len(lignes) > 1:
contenu_section += "\n\n" + lignes[1].strip()
# Affichage dans un expander
status = True if i == 1 else False
with st.expander(f"## {titre_section}", expanded=status):
st.markdown(contenu_section, unsafe_allow_html=True)
from utils.graph_utils import (
charger_graphe
)
from components.sidebar import (
afficher_menu,
afficher_impact
)
from components.header import afficher_entete
from components.footer import afficher_pied_de_page
from app.fiches import interface_fiches
from app.visualisations import interface_visualisations
from app.personnalisation import interface_personnalisation
from app.analyse import interface_analyse
st.set_page_config(
page_title="Fabnum – Analyse de chaîne",
page_icon="assets/weakness.png", # ajout
layout="centered",
initial_sidebar_state="expanded"
)
session_id = st.context.headers.get("x-session-id")
def get_total_bytes_for_session(session_id):
total_bytes = 0
try:
with open("/var/log/nginx/fabnum-dev.access.log", "r") as f:
for line in f:
if session_id in line:
match = re.search(r'"GET.*?" \d+ (\d+)', line)
if match:
bytes_sent = int(match.group(1))
total_bytes += bytes_sent
except Exception as e:
st.error(f"Erreur lecture log: {e}")
return total_bytes
def charger_theme():
# Une seule lecture du fichier, mais injection à chaque run
if "base_css_content" not in st.session_state:
with open("assets/styles/base.css") as f:
st.session_state["base_css_content"] = f.read()
st.markdown(f"", unsafe_allow_html=True)
# Chargement initial des thèmes (variables CSS uniquement)
if "theme_css_content_clair" not in st.session_state:
with open("assets/styles/theme-light.css") as f:
st.session_state["theme_css_content_clair"] = f.read()
if "theme_css_content_sombre" not in st.session_state:
with open("assets/styles/theme-dark.css") as f:
st.session_state["theme_css_content_sombre"] = f.read()
# Thème en cours
current_theme = st.session_state.get("theme_mode", "Clair").lower()
theme_css = st.session_state[f"theme_css_content_{current_theme}"]
# Injection des variables du thème
st.markdown(f"", unsafe_allow_html=True)
# Chargement unique du CSS principal (base.css)
if "base_css_content" not in st.session_state:
with open("assets/styles/base.css") as f:
st.session_state["base_css_content"] = f.read()
# Injection du style principal basé sur les variables
st.markdown(f"", unsafe_allow_html=True)
def ouvrir_page():
charger_theme()
afficher_entete()
afficher_menu()
st.markdown("""
""", unsafe_allow_html=True)
def fermer_page():
st.markdown("", unsafe_allow_html=True)
st.markdown("""""", unsafe_allow_html=True)
st.markdown("", unsafe_allow_html=True)
total_bytes = get_total_bytes_for_session(session_id)
afficher_pied_de_page()
afficher_impact(total_bytes)
ouvrir_page()
dot_file_path = None
if st.session_state.onglet == "Instructions":
markdown_content = charger_instructions_depuis_gitea(INSTRUCTIONS)
if markdown_content:
afficher_instructions_avec_expanders(markdown_content)
elif st.session_state.onglet == "Fiches":
interface_fiches()
else:
# Charger le graphe une seule fois
# Le graphe n'est pas nécessaire pour Instructions ou Fiches
G_temp, G_temp_ivc, dot_file_path = charger_graphe()
if dot_file_path and st.session_state.onglet == "Analyse":
interface_analyse(G_temp)
elif dot_file_path and st.session_state.onglet == "Visualisations":
interface_visualisations(G_temp, G_temp_ivc)
elif dot_file_path and st.session_state.onglet == "Personnalisation":
G_temp = interface_personnalisation(G_temp)
fermer_page()