Diverses modifications

This commit is contained in:
Fabrication du Numérique 2025-05-12 21:47:57 +02:00
parent 863cce5c68
commit 96682783b6
8 changed files with 287 additions and 291 deletions

View File

@ -2,6 +2,7 @@
import streamlit as st import streamlit as st
import requests import requests
import os import os
import pathlib
from .utils.tickets.display import afficher_tickets_par_fiche from .utils.tickets.display import afficher_tickets_par_fiche
from .utils.tickets.creation import formulaire_creation_ticket_dynamique from .utils.tickets.creation import formulaire_creation_ticket_dynamique
@ -64,7 +65,8 @@ def interface_fiches():
else: else:
SEUILS = st.session_state["seuils"] SEUILS = st.session_state["seuils"]
html_path = os.path.join("HTML", dossier_choisi, os.path.splitext(fiche_choisie)[0] + ".html") nom_fiche = os.path.splitext(fiche_choisie)[0]
html_path = os.path.join("HTML", dossier_choisi, nom_fiche + ".html")
path_relative = f"Documents/{dossier_choisi}/{fiche_choisie}" path_relative = f"Documents/{dossier_choisi}/{fiche_choisie}"
commits_url = f"{GITEA_URL}/repos/{ORGANISATION}/{DEPOT_FICHES}/commits?path={path_relative}&sha={ENV}" commits_url = f"{GITEA_URL}/repos/{ORGANISATION}/{DEPOT_FICHES}/commits?path={path_relative}&sha={ENV}"
@ -82,7 +84,24 @@ def interface_fiches():
with open(html_path, "r", encoding="utf-8") as f: with open(html_path, "r", encoding="utf-8") as f:
st.markdown(f.read(), unsafe_allow_html=True) st.markdown(f.read(), unsafe_allow_html=True)
st.markdown("<hr style='border: 1px solid #ccc; margin: 2rem 0;' />", unsafe_allow_html=True) if st.session_state.get("logged_in", False):
pdf_name = nom_fiche + ".pdf"
pdf_path = os.path.join("static", "Fiches", dossier_choisi, pdf_name)
# Bouton de téléchargement du PDF
if os.path.exists(pdf_path):
with open(pdf_path, "rb") as pdf_file:
st.download_button(
label="Télécharger cette fiche en PDF",
data=pdf_file,
file_name=pdf_name,
mime="application/pdf",
help="Télécharger la version PDF de cette fiche",
key="telecharger_fiche_pdf"
)
else:
st.warning("Le fichier PDF de cette fiche n'est pas disponible.")
st.markdown("## Gestion des tickets pour cette fiche") st.markdown("## Gestion des tickets pour cette fiche")
afficher_tickets_par_fiche(rechercher_tickets_gitea(fiche_choisie)) afficher_tickets_par_fiche(rechercher_tickets_gitea(fiche_choisie))
formulaire_creation_ticket_dynamique(fiche_choisie) formulaire_creation_ticket_dynamique(fiche_choisie)

View File

@ -23,7 +23,10 @@ def build_production_sections(md: str) -> str:
yaml_block = re.search(r"```yaml\n(.+?)\n```", md, re.DOTALL) yaml_block = re.search(r"```yaml\n(.+?)\n```", md, re.DOTALL)
if not yaml_block: if not yaml_block:
return md return md
# Capture le bloc YAML complet pour le supprimer plus tard
yaml_block_full = yaml_block.group(0)
try: try:
yaml_data = yaml.safe_load(yaml_block.group(1)) yaml_data = yaml.safe_load(yaml_block.group(1))
except Exception as e: except Exception as e:
@ -130,5 +133,8 @@ def build_production_sections(md: str) -> str:
st.warning(f"Aucune section IHH trouvée pour le schéma {schema} dans la fiche technique IHH.") st.warning(f"Aucune section IHH trouvée pour le schéma {schema} dans la fiche technique IHH.")
except Exception as e: except Exception as e:
st.error(f"Erreur lors de la lecture/traitement de la fiche IHH: {e}") st.error(f"Erreur lors de la lecture/traitement de la fiche IHH: {e}")
# Supprimer le bloc YAML du markdown final
md_modifie = md_modifie.replace(yaml_block_full, "")
return md_modifie return md_modifie

View File

@ -64,7 +64,7 @@ def rechercher_tickets_gitea(fiche_selectionnee):
if not cible: if not cible:
return [] return []
labels_cibles = set(cible["operations"] + [cible["item"]]) labels_cibles = set([cible["item"]])
tickets_associes = [] tickets_associes = []
for issue in issues: for issue in issues:

View File

@ -9,7 +9,7 @@ def interface_personnalisation(G):
st.markdown("# Personnalisation des produits finaux") st.markdown("# Personnalisation des produits finaux")
with st.expander("Comment utiliser cet onglet ?", expanded=False): with st.expander("Comment utiliser cet onglet ?", expanded=False):
st.markdown(""" st.markdown("""
1. Cliquez sur "Ajouter un produit final" pour créer un nouveau produit 1. Cliquez sur « Ajouter un produit final » pour créer un nouveau produit
2. Donnez un nom à votre produit 2. Donnez un nom à votre produit
3. Sélectionnez une opération d'assemblage appropriée (si pertinent) 3. Sélectionnez une opération d'assemblage appropriée (si pertinent)
4. Choisissez les composants qui constituent votre produit dans la liste proposée 4. Choisissez les composants qui constituent votre produit dans la liste proposée

View File

@ -36,15 +36,15 @@ Fiche minerai aluminium.md,Extraction/Traitement/Réserves,Aluminium
Fiche minerai antimoine.md,Extraction/Traitement/Réserves,Antimoine Fiche minerai antimoine.md,Extraction/Traitement/Réserves,Antimoine
Fiche minerai argent.md,Extraction/Traitement/Réserves,Argent Fiche minerai argent.md,Extraction/Traitement/Réserves,Argent
Fiche minerai arsenic.md,Extraction/Traitement/Réserves,Arsenic Fiche minerai arsenic.md,Extraction/Traitement/Réserves,Arsenic
Fiche minerai beryllium.md,Extraction/Traitement/Réserves,Beryllium Fiche minerai béryllium.md,Extraction/Traitement/Réserves,Beryllium
Fiche minerai ceramiques.md,Extraction/Traitement/Réserves,Ceramiques Fiche minerai céramiques.md,Extraction/Traitement/Réserves,Ceramiques
Fiche minerai cerium.md,Extraction/Traitement/Réserves,Cerium Fiche minerai cérium.md,Extraction/Traitement/Réserves,Cerium
Fiche minerai chrome.md,Extraction/Traitement/Réserves,Chrome Fiche minerai chrome.md,Extraction/Traitement/Réserves,Chrome
Fiche minerai cobalt.md,Extraction/Traitement/Réserves,Cobalt Fiche minerai cobalt.md,Extraction/Traitement/Réserves,Cobalt
Fiche minerai cuivre.md,Extraction/Traitement/Réserves,Cuivre Fiche minerai cuivre.md,Extraction/Traitement/Réserves,Cuivre
Fiche minerai dysprosium.md,Extraction/Traitement/Réserves,Dysprosium Fiche minerai dysprosium.md,Extraction/Traitement/Réserves,Dysprosium
Fiche minerai erbium.md,Extraction/Traitement/Réserves,Erbium Fiche minerai erbium.md,Extraction/Traitement/Réserves,Erbium
Fiche minerai etain.md,Extraction/Traitement/Réserves,Etain Fiche minerai étain.md,Extraction/Traitement/Réserves,Etain
Fiche minerai europium.md,Extraction/Traitement/Réserves,Europium Fiche minerai europium.md,Extraction/Traitement/Réserves,Europium
Fiche minerai fluorite.md,Extraction/Traitement/Réserves,Fluorite Fiche minerai fluorite.md,Extraction/Traitement/Réserves,Fluorite
Fiche minerai gadolinium.md,Extraction/Traitement/Réserves,Gadolinium Fiche minerai gadolinium.md,Extraction/Traitement/Réserves,Gadolinium
@ -56,9 +56,9 @@ Fiche minerai holmium.md,Extraction/Traitement/Réserves,Holmium
Fiche minerai indiumetain.md,Extraction/Traitement/Réserves,IndiumEtain Fiche minerai indiumetain.md,Extraction/Traitement/Réserves,IndiumEtain
Fiche minerai lanthane.md,Extraction/Traitement/Réserves,Lanthane Fiche minerai lanthane.md,Extraction/Traitement/Réserves,Lanthane
Fiche minerai lithium.md,Extraction/Traitement/Réserves,Lithium Fiche minerai lithium.md,Extraction/Traitement/Réserves,Lithium
Fiche minerai magnesium.md,Extraction/Traitement/Réserves,Magnesium Fiche minerai magnésium.md,Extraction/Traitement/Réserves,Magnesium
Fiche minerai manganese.md,Extraction/Traitement/Réserves,Manganese Fiche minerai manganèse.md,Extraction/Traitement/Réserves,Manganese
Fiche minerai neodyme.md,Extraction/Traitement/Réserves,Neodyme Fiche minerai néodyme.md,Extraction/Traitement/Réserves,Neodyme
Fiche minerai nickel.md,Extraction/Traitement/Réserves,Nickel Fiche minerai nickel.md,Extraction/Traitement/Réserves,Nickel
Fiche minerai or.md,Extraction/Traitement/Réserves,Or Fiche minerai or.md,Extraction/Traitement/Réserves,Or
Fiche minerai palladium.md,Extraction/Traitement/Réserves,Palladium Fiche minerai palladium.md,Extraction/Traitement/Réserves,Palladium
@ -67,8 +67,8 @@ Fiche minerai phosphore.md,Extraction/Traitement/Réserves,Phosphore
Fiche minerai plastiques.md,Extraction/Traitement/Réserves,Plastiques Fiche minerai plastiques.md,Extraction/Traitement/Réserves,Plastiques
Fiche minerai platine.md,Extraction/Traitement/Réserves,Platine Fiche minerai platine.md,Extraction/Traitement/Réserves,Platine
Fiche minerai plomb.md,Extraction/Traitement/Réserves,Plomb Fiche minerai plomb.md,Extraction/Traitement/Réserves,Plomb
Fiche minerai polystyrene.md,Extraction/Traitement/Réserves,Polystyrene Fiche minerai polystyrène.md,Extraction/Traitement/Réserves,Polystyrene
Fiche minerai praseodyme.md,Extraction/Traitement/Réserves,Praseodyme Fiche minerai praséodyme.md,Extraction/Traitement/Réserves,Praseodyme
Fiche minerai pvc.md,Extraction/Traitement/Réserves,PVC Fiche minerai pvc.md,Extraction/Traitement/Réserves,PVC
Fiche minerai quartz.md,Extraction/Traitement/Réserves,Quartz Fiche minerai quartz.md,Extraction/Traitement/Réserves,Quartz
Fiche minerai samarium.md,Extraction/Traitement/Réserves,Samarium Fiche minerai samarium.md,Extraction/Traitement/Réserves,Samarium
@ -77,7 +77,7 @@ Fiche minerai silicium.md,Extraction/Traitement/Réserves,Silicium
Fiche minerai tantale.md,Extraction/Traitement/Réserves,Tantale Fiche minerai tantale.md,Extraction/Traitement/Réserves,Tantale
Fiche minerai terbium.md,Extraction/Traitement/Réserves,Terbium Fiche minerai terbium.md,Extraction/Traitement/Réserves,Terbium
Fiche minerai titane.md,Extraction/Traitement/Réserves,Titane Fiche minerai titane.md,Extraction/Traitement/Réserves,Titane
Fiche minerai tungstene.md,Extraction/Traitement/Réserves,Tungstene Fiche minerai tungstène.md,Extraction/Traitement/Réserves,Tungstene
Fiche minerai verre.md,Extraction/Traitement/Réserves,Verre Fiche minerai verre.md,Extraction/Traitement/Réserves,Verre
Fiche minerai yttrium.md,Extraction/Traitement/Réserves,Yttrium Fiche minerai yttrium.md,Extraction/Traitement/Réserves,Yttrium
Fiche minerai zinc.md,Extraction/Traitement/Réserves,Zinc Fiche minerai zinc.md,Extraction/Traitement/Réserves,Zinc

1 Fiche Label opération Label item
36 Fiche minerai antimoine.md Extraction/Traitement/Réserves Antimoine
37 Fiche minerai argent.md Extraction/Traitement/Réserves Argent
38 Fiche minerai arsenic.md Extraction/Traitement/Réserves Arsenic
39 Fiche minerai beryllium.md Fiche minerai béryllium.md Extraction/Traitement/Réserves Beryllium
40 Fiche minerai ceramiques.md Fiche minerai céramiques.md Extraction/Traitement/Réserves Ceramiques
41 Fiche minerai cerium.md Fiche minerai cérium.md Extraction/Traitement/Réserves Cerium
42 Fiche minerai chrome.md Extraction/Traitement/Réserves Chrome
43 Fiche minerai cobalt.md Extraction/Traitement/Réserves Cobalt
44 Fiche minerai cuivre.md Extraction/Traitement/Réserves Cuivre
45 Fiche minerai dysprosium.md Extraction/Traitement/Réserves Dysprosium
46 Fiche minerai erbium.md Extraction/Traitement/Réserves Erbium
47 Fiche minerai etain.md Fiche minerai étain.md Extraction/Traitement/Réserves Etain
48 Fiche minerai europium.md Extraction/Traitement/Réserves Europium
49 Fiche minerai fluorite.md Extraction/Traitement/Réserves Fluorite
50 Fiche minerai gadolinium.md Extraction/Traitement/Réserves Gadolinium
56 Fiche minerai indiumetain.md Extraction/Traitement/Réserves IndiumEtain
57 Fiche minerai lanthane.md Extraction/Traitement/Réserves Lanthane
58 Fiche minerai lithium.md Extraction/Traitement/Réserves Lithium
59 Fiche minerai magnesium.md Fiche minerai magnésium.md Extraction/Traitement/Réserves Magnesium
60 Fiche minerai manganese.md Fiche minerai manganèse.md Extraction/Traitement/Réserves Manganese
61 Fiche minerai neodyme.md Fiche minerai néodyme.md Extraction/Traitement/Réserves Neodyme
62 Fiche minerai nickel.md Extraction/Traitement/Réserves Nickel
63 Fiche minerai or.md Extraction/Traitement/Réserves Or
64 Fiche minerai palladium.md Extraction/Traitement/Réserves Palladium
67 Fiche minerai plastiques.md Extraction/Traitement/Réserves Plastiques
68 Fiche minerai platine.md Extraction/Traitement/Réserves Platine
69 Fiche minerai plomb.md Extraction/Traitement/Réserves Plomb
70 Fiche minerai polystyrene.md Fiche minerai polystyrène.md Extraction/Traitement/Réserves Polystyrene
71 Fiche minerai praseodyme.md Fiche minerai praséodyme.md Extraction/Traitement/Réserves Praseodyme
72 Fiche minerai pvc.md Extraction/Traitement/Réserves PVC
73 Fiche minerai quartz.md Extraction/Traitement/Réserves Quartz
74 Fiche minerai samarium.md Extraction/Traitement/Réserves Samarium
77 Fiche minerai tantale.md Extraction/Traitement/Réserves Tantale
78 Fiche minerai terbium.md Extraction/Traitement/Réserves Terbium
79 Fiche minerai titane.md Extraction/Traitement/Réserves Titane
80 Fiche minerai tungstene.md Fiche minerai tungstène.md Extraction/Traitement/Réserves Tungstene
81 Fiche minerai verre.md Extraction/Traitement/Réserves Verre
82 Fiche minerai yttrium.md Extraction/Traitement/Réserves Yttrium
83 Fiche minerai zinc.md Extraction/Traitement/Réserves Zinc

View File

@ -1,185 +1,60 @@
/* --- Base.css --- */ /* --- Base.css --- */
/* ==========================================
1. Reset et base
========================================== */
.stAppHeader { .stAppHeader {
visibility: hidden; visibility: hidden;
} }
/* Conteneur principal */ body, html {
.block-container { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
max-width: 1024px !important;
padding-left: 2rem;
padding-right: 2rem;
padding: 0rem 1rem 10rem;
} }
.stVerticalBlock { body, .stApp, .block-container {
gap: 0.5rem !important; background-color: var(--bg-color) !important;
color: var(--text-color) !important;
} }
/* Typographie & structure */ /* ==========================================
body, 2. Layout et containers
html { ========================================== */
font-family:
-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial,
sans-serif;
}
.block-container { .block-container {
max-width: 1024px !important; max-width: 1024px !important;
padding: 0 1rem 10rem; padding: 0 1rem 10rem;
} }
.stVerticalBlock { .stVerticalBlock {
gap: 0.5rem !important; gap: 0.5rem !important;
} }
/* Boutons & sliders */ /* ==========================================
3. Composants d'interface
========================================== */
/* --- 3.1 Boutons --- */
.stButton > button, .stButton > button,
.stDownloadButton > button, .stDownloadButton > button,
.stFormSubmitButton > button,
.stSlider > div > div { .stSlider > div > div {
background-color: darkgreen !important; background-color: darkgreen !important;
color: white !important; color: white !important;
border: 1px solid grey; border: 1px solid grey;
} }
/* Sidebar (style fixe) */ .st-key-FormSubmitter-auth_form-Se-connecter {
section[data-testid="stSidebar"] { margin-left: auto;
background-color: #ccc !important; margin-right: auto;
color: #111 !important;
} }
section[data-testid="stSidebar"] .stButton > button { section:not([data-testid="stSidebar"]) button[data-testid="stBaseButton-primary"],
background-color: darkgreen !important; section:not([data-testid="stSidebar"]) button[data-testid="stBaseButton-secondary"] {
color: white !important; color: white !important;
font-weight: bold; background: darkgreen !important;
border: 1px solid #ccc !important;
} }
/* Footer commun */ section:not([data-testid="stSidebar"]) button[data-testid="stBaseButton-primary"] p,
.wide-footer { section:not([data-testid="stSidebar"]) button[data-testid="stBaseButton-secondary"] p {
width: 100vw;
margin-left: calc(-50vw + 50%);
margin-top: 3rem;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
border-top: 1px solid #ddd;
text-align: center;
padding-top: 1rem;
}
.info-footer {
font-size: 1rem !important;
font-weight: 800;
}
/* En-tête large */
.wide-header {
width: 100vw;
margin-left: calc(-50vw + 50%);
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
border-bottom: 1px solid #ddd;
text-align: center;
padding-top: 1rem;
margin-top: -1.25em;
}
.titre-header {
font-size: 2rem !important;
font-weight: bolder !important;
}
/* Accessibilité RGAA pour les onglets */
div[role="radiogroup"] > label {
padding: 0.5em 1em;
border-radius: 0.4em;
margin-right: 0.5em;
cursor: pointer;
border: 1px solid #fff;
}
div[role="radiogroup"] > label[data-selected="true"] {
font-weight: bold;
border: 2px solid #145a1a;
}
/* Styles pour les éléments décoratifs */
section[data-testid="stSidebar"] .decorative-heading {
font-size: 1.25rem;
font-weight: bold;
margin-bottom: 0.5rem;
text-align: center;
color: #145a1a;
}
section[data-testid="stSidebar"] div[role="radiogroup"] {
justify-content: center !important;
display: flex !important;
gap: 1rem; /* Optionnel : espace entre les boutons */
}
/* Corrige la couleur du texte des boutons de la sidebar - identique en light ou en dark */
section[data-testid="stSidebar"] .stButton > button {
background-color: darkgreen !important;
color: white !important;
font-weight: bold !important;
border: 1px solid #ccc !important;
width: 100%;
}
/* Translate Drag and drop and Browse files */
/* Hide original "Drag and drop file here" text */
div[data-testid="stFileUploaderDropzoneInstructions"]
.st-emotion-cache-j7qwjs
> span:nth-of-type(1) {
visibility: hidden;
}
/* Insert French translation */
div[data-testid="stFileUploaderDropzoneInstructions"]
.st-emotion-cache-j7qwjs
> span:nth-of-type(1)::after {
content: "Glissez-déposez votre fichier ici";
visibility: visible;
display: block;
font-size: inherit;
color: inherit;
}
/* Hide original "Browse files" button text */
/* Target the button within the dropzone container for uploader */
div[data-testid="stFileUploaderDropzone"]
button[data-testid="stBaseButton-secondary"] {
color: transparent !important;
position: relative;
}
/* Insert French translation for button */
div[data-testid="stFileUploaderDropzone"]
button[data-testid="stBaseButton-secondary"]::after {
content: "Parcourir les fichiers";
visibility: visible !important;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
display: block;
font-size: inherit;
color: inherit !important;
}
/* Override Streamlit file uploader limit text to 100 Ko */
div[data-testid="stFileUploaderDropzoneInstructions"] small {
visibility: hidden;
}
div[data-testid="stFileUploaderDropzoneInstructions"] small::after {
content: "Limite 100 Ko par fichier • JSON";
visibility: visible;
display: block;
font-size: inherit;
color: inherit;
margin-top: 0.25em;
}
button[data-testid="stBaseButton-primary"],
button[data-testid="stBaseButton-secondary"] {
color: white !important;
}
button[data-testid="stBaseButton-primary"] p,
,
button[data-testid="stBaseButton-secondary"] p {
color: white !important; color: white !important;
} }
@ -206,59 +81,35 @@ button[data-testid="stBaseButton-secondary"] p {
letter-spacing: 0.2em; letter-spacing: 0.2em;
} }
/* Utilisation des variables CSS définies dans les fichiers de thème */ button[data-testid="stBaseButton-headerNoPadding"] svg {
fill: var(--text-color) !important;
body,
.stApp,
.block-container {
background-color: var(--bg-color) !important;
color: var(--text-color) !important;
} }
/* En-tête large */ /* --- 3.2 Onglets et radiogroup --- */
.wide-header { div[role="radiogroup"] > label {
background-color: var(--header-bg); padding: 0.5em 1em;
border-radius: 0.4em;
margin-right: 0.5em;
cursor: pointer;
border: 1px solid #fff;
} }
.titre-header { div[role="radiogroup"] > label[data-selected="true"] {
color: var(--header-title); font-weight: bold;
border: 2px solid #145a1a;
} }
/* Footer commun */
.wide-footer {
background-color: var(--footer-bg);
}
.info-footer {
color: var(--footer-text);
}
/* Accessibilité RGAA pour les onglets */
section:not([data-testid="stSidebar"]) div[role="radiogroup"] > label p { section:not([data-testid="stSidebar"]) div[role="radiogroup"] > label p {
background-color: var(--radio-bg) !important; background-color: var(--radio-bg) !important;
color: var(--radio-text) !important; color: var(--radio-text) !important;
} }
section:not([data-testid="stSidebar"]) section:not([data-testid="stSidebar"]) div[role="radiogroup"] > label[data-selected="true"] {
div[role="radiogroup"]
> label[data-selected="true"] {
background-color: var(--radio-selected-bg) !important; background-color: var(--radio-selected-bg) !important;
color: var(--radio-selected-text) !important; color: var(--radio-selected-text) !important;
} }
/* Graphiques */ /* --- 3.3 Champs de formulaire --- */
.stPlotlyChart text {
fill: var(--plot-text) !important;
}
/* Paragraphes */
section:not([data-testid="stSidebar"])
div:not[data-testid="stElementContainer"]
p:not(#Authentification):not(#Theme) {
color: var(--paragraph-color) !important;
}
/* Champs de formulaire */
div[data-baseweb="select"], div[data-baseweb="select"],
section:not([data-testid="stSidebar"]) div[data-baseweb="base-input"], section:not([data-testid="stSidebar"]) div[data-baseweb="base-input"],
section[data-testid="stFileUploaderDropzone"] { section[data-testid="stFileUploaderDropzone"] {
@ -267,12 +118,89 @@ section[data-testid="stFileUploaderDropzone"] {
padding: 4px; padding: 4px;
} }
/* Détails */ section:not([data-testid="stSidebar"]) div[data-testid="stSelectbox"] p,
details { section:not([data-testid="stSidebar"]) div[data-testid="stMultiSelect"] p,
border-color: var(--details-border) !important; section:not([data-testid="stSidebar"]) div[data-testid="stRadio"] p,
section:not([data-testid="stSidebar"]) div[data-testid="stCheckbox"] p,
section:not([data-testid="stSidebar"]) div[data-testid="stTextInput"] p,
section:not([data-testid="stSidebar"]) div[data-testid="stTextArea"] p,
section:not([data-testid="stSidebar"]) div[data-testid="stAlertContentInfo"] p {
color: var(--text-color) !important;
} }
/* Tables */ /* ==========================================
4. Header et Footer
========================================== */
/* --- 4.1 Header --- */
.wide-header {
width: 100vw;
margin-left: calc(-50vw + 50%);
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
border-bottom: 1px solid #ddd;
text-align: center;
padding-top: 1rem;
margin-top: -1.25em;
background-color: var(--header-bg);
}
.titre-header {
font-size: 2rem !important;
font-weight: bolder !important;
color: var(--header-title);
}
/* --- 4.2 Footer --- */
.wide-footer {
width: 100vw;
margin-left: calc(-50vw + 50%);
margin-top: 3rem;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
border-top: 1px solid #ddd;
text-align: center;
padding-top: 1rem;
background-color: var(--footer-bg);
}
.info-footer {
font-size: 1rem !important;
font-weight: 800;
color: var(--footer-text);
}
/* ==========================================
5. Sidebar
========================================== */
section[data-testid="stSidebar"] {
background-color: #ccc !important;
color: #111 !important;
}
section[data-testid="stSidebar"] .stButton > button {
background-color: darkgreen !important;
color: white !important;
font-weight: bold !important;
border: 1px solid #ccc !important;
width: 100%;
}
section[data-testid="stSidebar"] .decorative-heading {
font-size: 1.25rem;
font-weight: bold;
margin-bottom: 0.5rem;
text-align: center;
color: #145a1a;
}
section[data-testid="stSidebar"] div[role="radiogroup"] {
justify-content: center !important;
display: flex !important;
gap: 1rem;
}
/* ==========================================
6. Tables
========================================== */
table { table {
border: 1px solid var(--table-border) !important; border: 1px solid var(--table-border) !important;
border-collapse: collapse; border-collapse: collapse;
@ -280,14 +208,12 @@ table {
margin-bottom: 1.5em; margin-bottom: 1.5em;
} }
th, th, td {
td {
border: 1px solid var(--table-border) !important; border: 1px solid var(--table-border) !important;
padding: 8px; padding: 8px;
text-align: left; text-align: left;
} }
/* Accessibilité RGAA */
caption { caption {
caption-side: top; caption-side: top;
font-weight: bold; font-weight: bold;
@ -301,20 +227,61 @@ table[role="table"] th[scope="col"] {
background-color: var(--background-color); background-color: var(--background-color);
} }
/* Fin de Tables */ /* ==========================================
7. Composants spécifiques
========================================== */
section:not([data-testid="stSidebar"]) div[data-testid="stSelectbox"] p, /* --- 7.1 File Uploader (traductions) --- */
section:not([data-testid="stSidebar"]) div[data-testid="stMultiSelect"] p, /* Hide original "Drag and drop file here" text */
section:not([data-testid="stSidebar"]) div[data-testid="stRadio"] p, div[data-testid="stFileUploaderDropzoneInstructions"] span:nth-of-type(1) {
section:not([data-testid="stSidebar"]) div[data-testid="stCheckbox"] p, visibility: hidden;
section:not([data-testid="stSidebar"]) div[data-testid="stTextInput"] p,
section:not([data-testid="stSidebar"]) div[data-testid="stTextArea"] p,
section:not([data-testid="stSidebar"]) div[data-testid="stAlertContentInfo"] p {
color: var(--text-color) !important;
} }
section:not([data-testid="stSidebar"]) hr { /* Insert French translation */
background-color: var(--hr-color) !important; div[data-testid="stFileUploaderDropzoneInstructions"] span:nth-of-type(1)::after {
content: "Glissez-déposez votre fichier ici";
visibility: visible;
display: block;
font-size: inherit;
color: inherit;
}
/* Hide original "Browse files" button text */
div[data-testid="stFileUploaderDropzone"] button[data-testid="stBaseButton-secondary"] {
color: transparent !important;
position: relative;
}
/* Insert French translation for button */
div[data-testid="stFileUploaderDropzone"] button[data-testid="stBaseButton-secondary"]::after {
content: "Parcourir les fichiers";
visibility: visible !important;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
display: block;
font-size: inherit;
color: inherit !important;
}
/* Override Streamlit file uploader limit text */
div[data-testid="stFileUploaderDropzoneInstructions"] small {
visibility: hidden;
}
div[data-testid="stFileUploaderDropzoneInstructions"] small::after {
content: "Limite 100 Ko par fichier • JSON";
visibility: visible;
display: block;
font-size: inherit;
color: inherit;
margin-top: 0.25em;
}
/* --- 7.2 Graphiques --- */
.stPlotlyChart text {
fill: var(--plot-text) !important;
} }
.stPlotlyChart text { .stPlotlyChart text {
@ -325,60 +292,54 @@ section:not([data-testid="stSidebar"]) hr {
font-family: Verdana, sans-serif !important; font-family: Verdana, sans-serif !important;
} }
.conteneur_commentaire { /* Cache complètement la section d'actions Vega */
background: var(--background-color); .vega-actions {
padding: 0.5rem; display: none !important;
border-radius: 8px;
margin-bottom: 0.5rem;
border: 1px solid #ccc;
border-radius: 8px;
padding: 1em;
margin-bottom: 1em;
} }
.commentaire_auteur { /* Et aussi le <details> parent, s'il faut tout masquer */
color: var(--text-color) !important; details[title="Click to view actions"] {
margin: 0; display: none !important;
}
.commentaire_contenu {
color: var(--text-color) !important;
margin: 0.5rem 0 0;
}
.conteneur_ticket {
background: var(--background-color);
padding: 0.5rem;
border-radius: 8px;
margin-bottom: 0.5rem;
border: 1px solid #ccc;
border-radius: 8px;
padding: 1em;
margin-bottom: 1em;
}
.ticket_auteur {
color: var(--text-color) !important;
margin: 0;
}
.ticket_contenu {
color: var(--text-color) !important;
margin: 0.5rem 0 0;
}
button[data-testid="stBaseButton-headerNoPadding"] svg {
fill: var(--text-color) !important;
} }
/* --- 7.3 Détails et paragraphes --- */
details { details {
border: 1px solid #ccc; border: 1px solid #ccc;
border-radius: 6px; border-radius: 6px;
padding: 0.5em; padding: 0.5em;
margin-bottom: 0.5em; margin-bottom: 0.5em;
background-color: var(--background-color); background-color: var(--background-color);
border-color: var(--details-border) !important;
} }
section:not([data-testid="stSidebar"]) div:not[data-testid="stElementContainer"] p:not(#Authentification):not(#Theme) {
color: var(--paragraph-color) !important;
}
section:not([data-testid="stSidebar"]) hr {
background-color: var(--hr-color) !important;
}
/* --- 7.4 Conteneurs de commentaires et tickets --- */
.conteneur_commentaire, .conteneur_ticket {
background: var(--background-color);
padding: 1em;
border-radius: 8px;
margin-bottom: 1em;
border: 1px solid #ccc;
}
.commentaire_auteur, .ticket_auteur {
color: var(--text-color) !important;
margin: 0;
}
.commentaire_contenu, .ticket_contenu {
color: var(--text-color) !important;
margin: 0.5rem 0 0;
}
/* --- 7.5 Blocs mathématiques --- */
.math-block { .math-block {
display: block; display: block;
text-align: center; text-align: center;
@ -394,16 +355,15 @@ details {
display: inline-block; display: inline-block;
} }
/* Cache complètement la section dactions Vega */ /* ==========================================
.vega-actions { 8. Éléments spécifiques
display: none !important; ========================================== */
}
/* Et aussi le <details> parent, sil faut tout masquer */
details[title="Click to view actions"] {
display: none !important;
}
div.stElementContainer.element-container.st-key-nom_utilisateur { div.stElementContainer.element-container.st-key-nom_utilisateur {
display: none !important; display: none !important;
} }
.st-key-telecharger_fiche_pdf {
margin-left: auto;
margin-right: auto;
margin-top: 1rem;
}

View File

@ -38,20 +38,11 @@ def connexion():
if not st.session_state.logged_in: if not st.session_state.logged_in:
with st.form("auth_form"): with st.form("auth_form"):
# 🧠 Ajout d'un champ identifiant fictif pour activer l'autocomplétion navigateur # Ajout d'un champ identifiant fictif pour activer l'autocomplétion navigateur
# et permettre de stocker le token comme un mot de passe par le navigateur
identifiant = st.text_input("Identifiant_token", value="fabnum-connexion", key="nom_utilisateur") identifiant = st.text_input("Identifiant_token", value="fabnum-connexion", key="nom_utilisateur")
token = st.text_input("Token d'accès personnel Gitea", type="password") token = st.text_input("Token d'accès personnel Gitea", type="password")
submitted = st.form_submit_button("Se connecter") submitted = st.form_submit_button("Se connecter")
st.markdown("""
<script>
const containers = [...document.querySelectorAll('.stElementContainer')];
containers.forEach(el => {
if (el.innerText.includes("Identifiant_token")) {
el.style.display = "none";
}
});
</script>
""", unsafe_allow_html=True)
if submitted and token: if submitted and token:
erreur = True erreur = True

View File

@ -1,24 +1,44 @@
import base64 import base64
import requests import requests
import os import os
import streamlit as st
from dateutil import parser from dateutil import parser
from datetime import datetime, timezone from datetime import datetime, timezone
import logging import logging
from config import GITEA_URL, GITEA_TOKEN, ORGANISATION, DEPOT_FICHES, DEPOT_CODE, ENV, ENV_CODE, DOT_FILE from config import GITEA_URL, GITEA_TOKEN, ORGANISATION, DEPOT_FICHES, DEPOT_CODE, ENV, ENV_CODE, DOT_FILE
def lire_fichier_local(nom_fichier):
with open(nom_fichier, "r", encoding="utf-8") as f:
contenu_md = f.read()
return contenu_md
def charger_instructions_depuis_gitea(nom_fichier="Instructions.md"): def charger_instructions_depuis_gitea(nom_fichier="Instructions.md"):
headers = {"Authorization": f"token {GITEA_TOKEN}"} headers = {"Authorization": f"token {GITEA_TOKEN}"}
url = f"{GITEA_URL}/repos/{ORGANISATION}/{DEPOT_FICHES}/contents/{nom_fichier}?ref={ENV}" url = f"{GITEA_URL}/repos/{ORGANISATION}/{DEPOT_FICHES}/contents/{nom_fichier}?ref={ENV}"
try: try:
response = requests.get(url, headers=headers) # Vérifier si une version plus récente existe sur le dépôt
response.raise_for_status() remote_last_modified = recuperer_date_dernier_commit(f"{GITEA_URL}/repos/{ORGANISATION}/{DEPOT_FICHES}/commits?path={nom_fichier}&sha={ENV}")
data = response.json() local_last_modified = datetime.fromtimestamp(os.path.getmtime(nom_fichier), tz=timezone.utc) if os.path.exists(nom_fichier) else None
contenu_md = base64.b64decode(data["content"]).decode("utf-8")
return contenu_md # Si le fichier local n'existe pas ou si la version distante est plus récente
if not local_last_modified or (remote_last_modified and remote_last_modified > local_last_modified):
response = requests.get(url, headers=headers)
response.raise_for_status()
data = response.json()
contenu_md = base64.b64decode(data["content"]).decode("utf-8")
# Sauvegarder en local
with open(nom_fichier, "w", encoding="utf-8") as f:
f.write(contenu_md)
return contenu_md
else:
# Lire depuis le cache local
return lire_fichier_local(nom_fichier)
except Exception as e: except Exception as e:
logging.error(f"Erreur chargement instructions Gitea : {e}") st.error(f"Erreur chargement instructions Gitea : {e}")
# Essayer de charger depuis le cache local en cas d'erreur
if os.path.exists(nom_fichier):
return lire_fichier_local(nom_fichier)
return None return None