# display.py import streamlit as st import html import re from collections import defaultdict from dateutil import parser from utils.translations import _ 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", str(_("pages.fiches.tickets.status.awaiting")), str(_("pages.fiches.tickets.status.in_progress")), str(_("pages.fiches.tickets.status.completed")), str(_("pages.fiches.tickets.status.rejected"))]: if statut in labels: return statut return str(_("pages.fiches.tickets.status.others")) def afficher_tickets_par_fiche(tickets): if not tickets: st.info(str(_("pages.fiches.tickets.no_linked_tickets"))) return st.markdown(str(_("pages.fiches.tickets.associated_tickets"))) 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} {str(_('pages.fiches.tickets.moderation_notice'))}") ordre_statuts = [ str(_("pages.fiches.tickets.status.awaiting")), str(_("pages.fiches.tickets.status.in_progress")), str(_("pages.fiches.tickets.status.completed")), str(_("pages.fiches.tickets.status.rejected")), str(_("pages.fiches.tickets.status.others")) ] 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"{str(_('pages.fiches.tickets.comment_error'))} {e}") return [] def afficher_carte_ticket(ticket): titre = ticket.get("title", str(_("pages.fiches.tickets.no_title"))) url = ticket.get("html_url", "") user = ticket.get("user", {}).get("login", str(_("pages.fiches.tickets.unknown"))) 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"({str(_('pages.fiches.tickets.updated'))} {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', str(_("pages.fiches.tickets.unknown")))) contenu = html.escape(commentaire.get('body', '')) date = format_date(commentaire.get('created_at', '')) commentaires_html += f"""
{str(_("pages.fiches.tickets.opened_by"))} {html.escape(user)} {str(_("pages.fiches.tickets.on_date"))} {date_created_str} {maj_info}
{str(_("pages.fiches.tickets.subject_label"))} : {html.escape(sujet)}
Labels : {' • '.join(labels) if labels else str(_("pages.fiches.tickets.no_labels"))}
{auteur} ({date})
{contenu}