# === Constantes et imports ===
import streamlit as st
import requests
import re
import os
import yaml
import markdown
from bs4 import BeautifulSoup
from datetime import datetime, timezone
from latex2mathml.converter import convert as latex_to_mathml
from utils.tickets.display import afficher_tickets_par_fiche
from utils.tickets.creation import formulaire_creation_ticket_dynamique
from utils.tickets.core import rechercher_tickets_gitea
from config import GITEA_TOKEN, GITEA_URL, ORGANISATION, DEPOT_FICHES, ENV, FICHES_CRITICITE
from utils.gitea import charger_arborescence_fiches, recuperer_date_dernier_commit
from utils.fiche_utils import load_seuils, render_fiche_markdown
from utils.dynamic import (
build_dynamic_sections,
build_ivc_sections,
build_ihh_sections,
build_isg_sections,
build_production_sections,
build_minerai_sections
)
# === Logique métier ===
def fichier_plus_recent(chemin_fichier, reference):
try:
modif = datetime.fromtimestamp(os.path.getmtime(chemin_fichier), tz=timezone.utc)
return modif > reference
except Exception:
return False
def doit_regenerer_fiche(html_path, fiche_type, fiche_choisie, commit_url, fichiers_criticite):
if not os.path.exists(html_path):
return True
local_mtime = datetime.fromtimestamp(os.path.getmtime(html_path), tz=timezone.utc)
remote_mtime = recuperer_date_dernier_commit(commit_url)
if remote_mtime is None or remote_mtime > local_mtime:
return True
if fichier_plus_recent(fichiers_criticite.get("IHH"), local_mtime):
return True
if fiche_type == "minerai" or "minerai" in fiche_choisie.lower():
if fichier_plus_recent(fichiers_criticite.get("IVC"), local_mtime):
return True
if fichier_plus_recent(fichiers_criticite.get("ICS"), local_mtime):
return True
return False
# === Fonctions de transformation ===
def remplacer_latex_par_mathml(markdown_text):
def remplacer_bloc_display(match):
formule_latex = match.group(1).strip()
try:
mathml = latex_to_mathml(formule_latex, display='block')
return f'
{mathml}
'
except Exception as e:
return f"Erreur LaTeX block: {e}"
def remplacer_bloc_inline(match):
formule_latex = match.group(1).strip()
try:
mathml = latex_to_mathml(formule_latex, display='inline')
return f'{mathml}'
except Exception as e:
return f"Erreur LaTeX inline: {e}"
markdown_text = re.sub(r"\$\$(.*?)\$\$", remplacer_bloc_display, markdown_text, flags=re.DOTALL)
markdown_text = re.sub(r"(?', f'{bloc_titre}
']
for bloc in sections_n1:
if bloc["titre"] and bloc["titre"] != bloc_titre:
html_output.append(f"{bloc['titre']}
")
if bloc["intro"]:
intro_md = remplacer_latex_par_mathml("\n".join(bloc["intro"]))
html_intro = markdown_to_html_rgaa(intro_md)
html_output.append(html_intro)
for sous_titre, contenu in bloc["sections_n2"].items():
contenu_md = remplacer_latex_par_mathml("\n".join(contenu))
contenu_html = markdown_to_html_rgaa(contenu_md, caption_text=sous_titre)
html_output.append(f"{sous_titre}
{contenu_html} ")
html_output.append("")
html_dir = os.path.join("HTML", dossier)
os.makedirs(html_dir, exist_ok=True)
html_path = os.path.join(html_dir, os.path.splitext(nom_fichier)[0] + ".html")
with open(html_path, "w", encoding="utf-8") as f:
f.write("\n".join(html_output))
return html_path
def afficher_fiches():
if "fiches_arbo" not in st.session_state:
st.session_state["fiches_arbo"] = charger_arborescence_fiches()
arbo = st.session_state.get("fiches_arbo", {})
if not arbo:
st.warning("Aucune fiche disponible pour le moment.")
return
dossiers = sorted(arbo.keys(), key=lambda x: x.lower())
dossier_choisi = st.selectbox("Choisissez un dossier", ["-- Sélectionner un dossier --"] + dossiers)
if dossier_choisi and dossier_choisi != "-- Sélectionner un dossier --":
fiches = arbo.get(dossier_choisi, [])
noms_fiches = [f['nom'] for f in fiches]
fiche_choisie = st.selectbox("Choisissez une fiche", ["-- Sélectionner une fiche --"] + noms_fiches)
if fiche_choisie and fiche_choisie != "-- Sélectionner une fiche --":
fiche_info = next((f for f in fiches if f["nom"] == fiche_choisie), None)
if fiche_info:
try:
headers = {"Authorization": f"token {GITEA_TOKEN}"}
reponse_fiche = requests.get(fiche_info["download_url"], headers=headers)
reponse_fiche.raise_for_status()
md_source = reponse_fiche.text
if "seuils" not in st.session_state:
SEUILS = load_seuils("assets/config.yaml")
st.session_state["seuils"] = SEUILS
else:
SEUILS = st.session_state["seuils"]
html_path = os.path.join("HTML", dossier_choisi, os.path.splitext(fiche_choisie)[0] + ".html")
path_relative = f"Documents/{dossier_choisi}/{fiche_choisie}"
commits_url = f"{GITEA_URL}/repos/{ORGANISATION}/{DEPOT_FICHES}/commits?path={path_relative}&sha={ENV}"
regenerate = doit_regenerer_fiche(
html_path=html_path,
fiche_type=fiche_info.get("type", ""),
fiche_choisie=fiche_choisie,
commit_url=commits_url,
fichiers_criticite=FICHES_CRITICITE
)
if regenerate:
st.info("DEBUG : Régénération de la fiche")
html_path = creer_fiche(md_source, dossier_choisi, fiche_choisie, SEUILS)
else:
st.info("DEBUG : Pas de régénération")
with open(html_path, "r", encoding="utf-8") as f:
st.markdown(f.read(), unsafe_allow_html=True)
st.markdown("
", unsafe_allow_html=True)
st.markdown("## Gestion des tickets pour cette fiche")
afficher_tickets_par_fiche(rechercher_tickets_gitea(fiche_choisie))
formulaire_creation_ticket_dynamique(fiche_choisie)
except Exception as e:
st.error(f"Erreur lors du chargement de la fiche : {e}")