# display.py import streamlit as st import html import re from collections import defaultdict from dateutil import parser from .core import rechercher_tickets_gitea def extraire_statut_par_label(ticket): labels = [label.get('name', '') for label in ticket.get('labels', [])] for statut in ["Backlog", "En attente de traitement", "En cours", "Terminés", "Non retenus"]: if statut in labels: return statut return "Autres" def afficher_tickets_par_fiche(tickets): if not tickets: st.info("Aucun ticket lié à cette fiche.") return st.markdown("**Tickets associés à cette fiche**") tickets_groupes = defaultdict(list) for ticket in tickets: statut = extraire_statut_par_label(ticket) tickets_groupes[statut].append(ticket) nb_backlogs = len(tickets_groupes["Backlog"]) if nb_backlogs: st.info(f"⤇ {nb_backlogs} ticket(s) en attente de modération ne sont pas affichés.") ordre_statuts = ["En attente de traitement", "En cours", "Terminés", "Non retenus", "Autres"] for statut in ordre_statuts: if tickets_groupes[statut]: with st.expander(f"{statut} ({len(tickets_groupes[statut])})", expanded=(statut == "En cours")): for ticket in tickets_groupes[statut]: afficher_carte_ticket(ticket) def recuperer_commentaires_ticket(issue_index): from config import GITEA_URL, GITEA_TOKEN, ORGANISATION, DEPOT_FICHES import requests headers = {"Authorization": f"token {GITEA_TOKEN}"} url = f"{GITEA_URL}/repos/{ORGANISATION}/{DEPOT_FICHES}/issues/{issue_index}/comments" try: response = requests.get(url, headers=headers, timeout=10) response.raise_for_status() return response.json() except Exception as e: st.error(f"Erreur lors de la récupération des commentaires : {e}") return [] def afficher_carte_ticket(ticket): titre = ticket.get("title", "Sans titre") url = ticket.get("html_url", "") user = ticket.get("user", {}).get("login", "inconnu") created = ticket.get("created_at", "") updated = ticket.get("updated_at", "") body = ticket.get("body", "") labels = [l["name"] for l in ticket.get("labels", []) if "name" in l] sujet = "" match = re.search(r"## Sujet de la proposition\s+(.+?)(\n|$)", body, re.DOTALL) if match: sujet = match.group(1).strip() def format_date(iso): try: return parser.isoparse(iso).strftime("%d/%m/%Y") except: return "?" date_created_str = format_date(created) maj_info = f"(MAJ {format_date(updated)})" if updated and updated != created else "" commentaires = recuperer_commentaires_ticket(ticket.get("number")) commentaires_html = "" for commentaire in commentaires: auteur = html.escape(commentaire.get('user', {}).get('login', 'inconnu')) contenu = html.escape(commentaire.get('body', '')) date = format_date(commentaire.get('created_at', '')) commentaires_html += f"""
Ouvert par {html.escape(user)} le {date_created_str} {maj_info}
Sujet : {html.escape(sujet)}
Labels : {' • '.join(labels) if labels else 'aucun'}
{auteur} ({date})
{contenu}