# === 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}")