fix(gui): complete V6 admin configuration mockup
This commit is contained in:
@@ -17,7 +17,44 @@ from gui_v6 import theme as theme_mod
|
||||
from gui_v6 import ui_kit
|
||||
from gui_v6.config_state import ConfigState, default_profile_key, list_profile_keys
|
||||
|
||||
_SUBTABS = [("reg", "⚙️ Réglages"), ("msk", "🎭 Masquage"), ("shr", "🔄 Partage"), ("rul", "🛡️ Règles")]
|
||||
_SUBTABS = [
|
||||
("reg", "⚙️ Réglages"),
|
||||
("msk", "🎭 Masquage"),
|
||||
("shr", "🔄 Partage"),
|
||||
("rul", "🛡️ Règles 2"),
|
||||
]
|
||||
|
||||
_DETECTION_OPTIONS = [
|
||||
("Noms et prénoms", "Gazetteers INSEE · CamemBERT"),
|
||||
("Dates de naissance", "Uniquement la date de naissance"),
|
||||
("Établissements", "Répertoire FINESS + contexte"),
|
||||
("Adresses et codes postaux", ""),
|
||||
("N° sécurité sociale", ""),
|
||||
("Téléphones et e-mails", ""),
|
||||
("N° adhérent mutuelle", ""),
|
||||
]
|
||||
|
||||
_PRESERVE_TERMS = ["FUROSEMIDE", "rééducation fonctionnelle", "classification internationale"]
|
||||
_MASK_TERMS = ["CHUXX"]
|
||||
|
||||
CONFIG_MOCKUP_SECTIONS = {
|
||||
"reglages": [
|
||||
"Profil métier",
|
||||
"Moteurs NER",
|
||||
"Données à détecter",
|
||||
"Termes à toujours conserver",
|
||||
"Termes à toujours masquer",
|
||||
],
|
||||
"masquage": [
|
||||
"Couleur de masquage (PDF)",
|
||||
"Style des marqueurs (texte)",
|
||||
"Épaisseur du masque",
|
||||
"Codes de remplacement",
|
||||
"Masques de zones fixes",
|
||||
],
|
||||
"partage": ["Exporter la configuration", "Importer une configuration"],
|
||||
"regles": ["Règles actives", "Testeur de règle"],
|
||||
}
|
||||
|
||||
|
||||
class ConfigTab(ctk.CTkFrame):
|
||||
@@ -68,9 +105,11 @@ class ConfigTab(ctk.CTkFrame):
|
||||
def _build_reglages(self) -> None:
|
||||
p = self._p
|
||||
|
||||
# Profil + sortie
|
||||
prof = ui_kit.Card(self._body, p, title="🗂️ Profil métier")
|
||||
prof.pack(fill="x", padx=14, pady=7)
|
||||
cols = self._two_columns(self._body)
|
||||
left, right = cols
|
||||
|
||||
prof = ui_kit.Card(left, p, title="🗂️ Profil métier")
|
||||
prof.pack(fill="x", pady=7)
|
||||
row = ctk.CTkFrame(prof, fg_color="transparent")
|
||||
row.pack(fill="x", padx=16, pady=(0, 10))
|
||||
profiles = list_profile_keys()
|
||||
@@ -89,65 +128,182 @@ class ConfigTab(ctk.CTkFrame):
|
||||
text_color=p["text_muted"], font=ui_kit.font(12))
|
||||
self._out_label.pack(side="left")
|
||||
|
||||
# Moteurs NER (câblé)
|
||||
ner = ui_kit.Card(self._body, p, title="🧠 Moteurs NER")
|
||||
ner.pack(fill="x", padx=14, pady=7)
|
||||
ner = ui_kit.Card(left, p, title="🧠 Moteurs NER")
|
||||
ner.pack(fill="x", pady=7)
|
||||
self._tog_ner = ui_kit.ToggleRow(ner, p, "CamemBERT-bio ⚡", "~10 ms/doc · F1 = 0.963", value=self._state.use_local_ner, command=self._on_ner)
|
||||
self._tog_ner.pack(fill="x", padx=16, pady=2)
|
||||
self._tog_eds = ui_kit.ToggleRow(ner, p, "EDS-Pseudo", "médical français (optionnel)", value=self._state.enable_eds, command=self._on_eds)
|
||||
self._tog_eds = ui_kit.ToggleRow(ner, p, "EDS-Pseudo PRÉCIS", "~200 ms/doc · médical français", value=self._state.enable_eds, command=self._on_eds)
|
||||
self._tog_eds.pack(fill="x", padx=16, pady=2)
|
||||
self._tog_gli = ui_kit.ToggleRow(ner, p, "GLiNER", "vote croisé (optionnel)", value=self._state.enable_gliner, command=self._on_gliner)
|
||||
self._tog_gli = ui_kit.ToggleRow(ner, p, "GLiNER OPTIONNEL", "~95 ms/doc · vote croisé", value=self._state.enable_gliner, command=self._on_gliner)
|
||||
self._tog_gli.pack(fill="x", padx=16, pady=(2, 14))
|
||||
|
||||
# Données à détecter (visuel)
|
||||
det = ui_kit.Card(self._body, p, title="🔍 Données à détecter")
|
||||
det.pack(fill="x", padx=14, pady=7)
|
||||
for label, hint in [
|
||||
("Noms et prénoms", "Gazetteers INSEE · CamemBERT"),
|
||||
("Dates de naissance", "Uniquement la date de naissance"),
|
||||
("Établissements", "Répertoire FINESS + contexte"),
|
||||
("Adresses et codes postaux", ""),
|
||||
("N° sécurité sociale", ""),
|
||||
("Téléphones et e-mails", ""),
|
||||
]:
|
||||
det = ui_kit.Card(right, p, title="🔍 Données à détecter")
|
||||
det.pack(fill="x", pady=7)
|
||||
for label, hint in _DETECTION_OPTIONS:
|
||||
ui_kit.ToggleRow(det, p, label, hint, value=True).pack(fill="x", padx=16, pady=2)
|
||||
ctk.CTkFrame(det, fg_color="transparent", height=8).pack()
|
||||
|
||||
keep = ui_kit.Card(right, p, title="✅ Termes à toujours conserver")
|
||||
keep.pack(fill="x", pady=7)
|
||||
self._note(keep, "Ces termes ne seront jamais masqués, même s'ils ressemblent à un nom propre.")
|
||||
self._tag_editor(keep, "Ex : FUROSEMIDE…", _PRESERVE_TERMS, "keep")
|
||||
|
||||
mask = ui_kit.Card(right, p, title="🚫 Termes à toujours masquer")
|
||||
mask.pack(fill="x", pady=7)
|
||||
self._note(mask, "Ces termes seront toujours masqués, même sans contexte médical autour.")
|
||||
self._tag_editor(mask, "Ex : CHUXX, Dr Dupont…", _MASK_TERMS, "mask")
|
||||
|
||||
def _build_masquage(self) -> None:
|
||||
p = self._p
|
||||
card = ui_kit.Card(self._body, p, title="🎭 Masquage")
|
||||
card.pack(fill="x", padx=14, pady=7)
|
||||
ctk.CTkLabel(card, text="Couleur, style des marqueurs et éditeur de masques PDF.",
|
||||
text_color=p["text_dim"], font=ui_kit.font(12), anchor="w", justify="left").pack(anchor="w", padx=16)
|
||||
codes = ui_kit.Card(self._body, p, title="🔒 Codes de remplacement")
|
||||
codes.pack(fill="x", padx=14, pady=7)
|
||||
for k, v in [("Nom/Prénom", "[NOM]"), ("Date naissance", "[DATE_NAISSANCE]"),
|
||||
("Établissement", "[ETABLISSEMENT]"), ("Adresse", "[ADRESSE]"), ("N° sécu", "[NIR]")]:
|
||||
cols = self._two_columns(self._body)
|
||||
left, right = cols
|
||||
|
||||
color = ui_kit.Card(left, p, title="⬛ Couleur de masquage (PDF)")
|
||||
color.pack(fill="x", pady=7)
|
||||
self._note(color, "Couleur des rectangles dans le PDF final.")
|
||||
swatches = ctk.CTkFrame(color, fg_color="transparent")
|
||||
swatches.pack(fill="x", padx=16, pady=(0, 14))
|
||||
for color_value in ["#000000", "#1a1a2e", "#374151", "#92400e", "#1e3a5f"]:
|
||||
ctk.CTkButton(
|
||||
swatches,
|
||||
text="",
|
||||
width=30,
|
||||
height=30,
|
||||
fg_color=color_value,
|
||||
hover_color=color_value,
|
||||
border_color=p["primary"] if color_value == "#000000" else p["card_border"],
|
||||
border_width=3 if color_value == "#000000" else 1,
|
||||
corner_radius=6,
|
||||
command=lambda: None,
|
||||
).pack(side="left", padx=(0, 8))
|
||||
|
||||
style = ui_kit.Card(left, p, title="🏷️ Style des marqueurs (texte)")
|
||||
style.pack(fill="x", pady=7)
|
||||
self._mask_style_var = ctk.StringVar(value="brackets")
|
||||
for label, value, preview in [
|
||||
("Crochets", "brackets", "[NOM]"),
|
||||
("Étoiles", "stars", "***"),
|
||||
("Noirci", "blackout", "████"),
|
||||
]:
|
||||
row = ctk.CTkFrame(style, fg_color="transparent")
|
||||
row.pack(fill="x", padx=16, pady=2)
|
||||
ctk.CTkRadioButton(
|
||||
row,
|
||||
text=f"{label} — {preview}",
|
||||
variable=self._mask_style_var,
|
||||
value=value,
|
||||
command=self._update_mask_preview,
|
||||
text_color=p["text"],
|
||||
fg_color=p["primary"],
|
||||
hover_color=p["primary_dim"],
|
||||
font=ui_kit.font(13),
|
||||
).pack(anchor="w")
|
||||
self._mask_preview = ctk.CTkLabel(
|
||||
style,
|
||||
text="Patient [NOM], né le [DATE_NAISSANCE]",
|
||||
text_color=p["text_dim"],
|
||||
fg_color=p["divider"],
|
||||
corner_radius=6,
|
||||
font=ui_kit.font(13),
|
||||
anchor="w",
|
||||
)
|
||||
self._mask_preview.pack(fill="x", padx=16, pady=(8, 14), ipady=8)
|
||||
|
||||
thick = ui_kit.Card(right, p, title="📐 Épaisseur du masque")
|
||||
thick.pack(fill="x", pady=7)
|
||||
self._note(thick, "Marge autour du texte masqué, en points.")
|
||||
self._slider_row(thick, "Marge horizontale", 2)
|
||||
self._slider_row(thick, "Marge verticale", 1)
|
||||
ui_kit.ToggleRow(thick, p, "Coins arrondis", "", value=False).pack(fill="x", padx=16, pady=(2, 14))
|
||||
|
||||
codes = ui_kit.Card(right, p, title="🔒 Codes de remplacement")
|
||||
codes.pack(fill="x", pady=7)
|
||||
for k, v in [
|
||||
("Nom/Prénom", "[NOM]"),
|
||||
("Date naissance", "[DATE_NAISSANCE]"),
|
||||
("Établissement", "[ETABLISSEMENT]"),
|
||||
("Adresse", "[ADRESSE]"),
|
||||
("Téléphone", "[TEL]"),
|
||||
("N° sécu", "[NIR]"),
|
||||
("IPP", "[IPP]"),
|
||||
("Email", "[EMAIL]"),
|
||||
]:
|
||||
r = ctk.CTkFrame(codes, fg_color="transparent")
|
||||
r.pack(fill="x", padx=16, pady=1)
|
||||
ctk.CTkLabel(r, text=k, text_color=p["text_muted"], font=ui_kit.font(12)).pack(side="left")
|
||||
ctk.CTkLabel(r, text=v, text_color=p["primary"], font=ui_kit.font(12, "bold")).pack(side="right")
|
||||
ctk.CTkFrame(codes, fg_color="transparent", height=8).pack()
|
||||
ctk.CTkLabel(self._body, text="Éditeur de masques PDF (zones fixes) : intégré au lot suivant.",
|
||||
text_color=p["text_muted"], font=ui_kit.font(11)).pack(anchor="w", padx=18, pady=6)
|
||||
|
||||
editor = ui_kit.Card(self._body, p, title="🏠 Masques de zones fixes (logos, en-têtes)")
|
||||
editor.pack(fill="x", padx=14, pady=7)
|
||||
top = ctk.CTkFrame(editor, fg_color="transparent")
|
||||
top.pack(fill="x", padx=16, pady=(0, 8))
|
||||
ctk.CTkLabel(
|
||||
top,
|
||||
text="Dessinez des rectangles sur un PDF modèle pour masquer systématiquement les logos, en-têtes ou zones fixes.",
|
||||
text_color=p["text_dim"],
|
||||
font=ui_kit.font(12),
|
||||
justify="left",
|
||||
wraplength=610,
|
||||
).pack(side="left", fill="x", expand=True)
|
||||
ui_kit.primary_button(top, p, "✏ Ouvrir l'éditeur de masques", command=lambda: None).pack(side="right", padx=(8, 0))
|
||||
toolbar = ctk.CTkFrame(editor, fg_color=p["divider"], border_color=p["card_border"], border_width=1, corner_radius=8)
|
||||
toolbar.pack(fill="x", padx=16, pady=(0, 10))
|
||||
for label in ["📄 Ouvrir PDF…", "−", "100%", "+", "💾 Sauver", "📁 Charger", "🗑 Effacer page"]:
|
||||
ui_kit.secondary_button(toolbar, p, label, command=lambda: None).pack(side="left", padx=4, pady=8)
|
||||
canvas = ctk.CTkFrame(editor, fg_color=p["divider"], border_color=p["card_border"], border_width=1, corner_radius=8, height=150)
|
||||
canvas.pack(fill="x", padx=16, pady=(0, 12))
|
||||
canvas.pack_propagate(False)
|
||||
ctk.CTkLabel(
|
||||
canvas,
|
||||
text="📄\nOuvrez un PDF pour commencer à dessiner des zones de masquage.\nCliquez-glissez pour tracer un rectangle.",
|
||||
text_color=p["text_muted"],
|
||||
font=ui_kit.font(12),
|
||||
justify="center",
|
||||
).pack(expand=True)
|
||||
|
||||
def _build_partage(self) -> None:
|
||||
p = self._p
|
||||
card = ui_kit.Card(self._body, p, title="🔄 Partage de configuration")
|
||||
card.pack(fill="x", padx=14, pady=7)
|
||||
ctk.CTkLabel(card, text="Exporter / importer la configuration (whitelist, blacklist, profils) par JSON.",
|
||||
text_color=p["text_dim"], font=ui_kit.font(12), anchor="w", justify="left").pack(anchor="w", padx=16, pady=(0, 8))
|
||||
actrow = ctk.CTkFrame(card, fg_color="transparent")
|
||||
actrow.pack(fill="x", padx=16, pady=(0, 14))
|
||||
ui_kit.secondary_button(actrow, p, "⬇ Exporter", command=lambda: None).pack(side="left", padx=(0, 8))
|
||||
ui_kit.secondary_button(actrow, p, "⬆ Importer", command=lambda: None).pack(side="left")
|
||||
export = ui_kit.Card(self._body, p, title="📤 Exporter la configuration")
|
||||
export.pack(fill="x", padx=14, pady=7)
|
||||
self._note(export, "Génère un fichier .json avec vos listes, à envoyer par e-mail à d'autres établissements.")
|
||||
ui_kit.secondary_button(export, p, "⬇ Exporter (.json)", command=lambda: None).pack(anchor="w", padx=16, pady=(0, 14))
|
||||
|
||||
import_card = ui_kit.Card(self._body, p, title="📥 Importer une configuration")
|
||||
import_card.pack(fill="x", padx=14, pady=7)
|
||||
self._note(import_card, "Importez un fichier reçu. Vos réglages locaux ne seront pas supprimés.")
|
||||
ui_kit.secondary_button(import_card, p, "⬆ Importer (.json)", command=lambda: None).pack(anchor="w", padx=16, pady=(0, 14))
|
||||
|
||||
def _build_regles(self) -> None:
|
||||
p = self._p
|
||||
card = ui_kit.Card(self._body, p, title="🛡️ Règles personnalisées")
|
||||
card = ui_kit.Card(self._body, p, title="🛡️ Règles actives")
|
||||
card.pack(fill="x", padx=14, pady=7)
|
||||
ctk.CTkLabel(card, text="Règles système (lecture seule) et règles personnalisées de l'établissement.",
|
||||
text_color=p["text_dim"], font=ui_kit.font(12), anchor="w", justify="left").pack(anchor="w", padx=16, pady=(0, 14))
|
||||
self._note(card, "Ces règles adaptent le moteur à votre établissement. Chaque règle est validée avant activation.")
|
||||
headers = ctk.CTkFrame(card, fg_color="transparent")
|
||||
headers.pack(fill="x", padx=16, pady=(0, 4))
|
||||
for text, width in [("Label", 190), ("Type", 80), ("Cible → Résultat", 210), ("Statut", 70), ("", 70)]:
|
||||
ctk.CTkLabel(headers, text=text.upper(), width=width, anchor="w", text_color=p["text_muted"], font=ui_kit.font(10, "bold")).pack(side="left")
|
||||
for row in [
|
||||
("Masquer le sigle CHUXX", "exact", "CHUXX → [MASK]", "Actif"),
|
||||
("Préserver “classification internationale”", "preserve", "conservé tel quel", "Actif"),
|
||||
("Identifier N° 1234567", "norm-id", "N° 1234567 → [NDA]", "Candidat"),
|
||||
]:
|
||||
self._rule_row(card, row)
|
||||
actions = ctk.CTkFrame(card, fg_color="transparent")
|
||||
actions.pack(fill="x", padx=16, pady=(10, 14))
|
||||
ui_kit.primary_button(actions, p, "+ Nouvelle règle", command=lambda: None).pack(side="left", padx=(0, 8))
|
||||
ui_kit.secondary_button(actions, p, "🔄 Recharger", command=lambda: None).pack(side="left")
|
||||
|
||||
sim = ui_kit.Card(self._body, p, title="🧪 Testeur de règle")
|
||||
sim.pack(fill="x", padx=14, pady=7)
|
||||
ctk.CTkLabel(sim, text="Texte de test", text_color=p["text_muted"], font=ui_kit.font(12)).pack(anchor="w", padx=16)
|
||||
txt = ctk.CTkTextbox(sim, height=78, fg_color=p["divider"], text_color=p["text"], border_color=p["card_border"], border_width=1)
|
||||
txt.pack(fill="x", padx=16, pady=(5, 10))
|
||||
txt.insert("1.0", "Compte rendu CHUXX, patient N° 1234567.")
|
||||
btns = ctk.CTkFrame(sim, fg_color="transparent")
|
||||
btns.pack(fill="x", padx=16, pady=(0, 14))
|
||||
ui_kit.primary_button(btns, p, "▶ Tester", command=lambda: None).pack(side="left", padx=(0, 8))
|
||||
ui_kit.secondary_button(btns, p, "✖ Fermer", command=lambda: None).pack(side="left")
|
||||
|
||||
# -- callbacks --------------------------------------------------------
|
||||
|
||||
@@ -168,3 +324,96 @@ class ConfigTab(ctk.CTkFrame):
|
||||
if path:
|
||||
self._state.output_dir = Path(path)
|
||||
self._out_label.configure(text=str(self._state.output_dir))
|
||||
|
||||
# -- helpers UI -------------------------------------------------------
|
||||
|
||||
def _two_columns(self, parent) -> tuple[ctk.CTkFrame, ctk.CTkFrame]:
|
||||
row = ctk.CTkFrame(parent, fg_color="transparent")
|
||||
row.pack(fill="both", expand=True, padx=14)
|
||||
left = ctk.CTkFrame(row, fg_color="transparent")
|
||||
right = ctk.CTkFrame(row, fg_color="transparent")
|
||||
left.pack(side="left", fill="both", expand=True, padx=(0, 7))
|
||||
right.pack(side="left", fill="both", expand=True, padx=(7, 0))
|
||||
return left, right
|
||||
|
||||
def _note(self, parent, text: str) -> None:
|
||||
p = self._p
|
||||
ctk.CTkLabel(
|
||||
parent,
|
||||
text=text,
|
||||
text_color=p["text_muted"],
|
||||
fg_color=p["divider"],
|
||||
corner_radius=4,
|
||||
font=ui_kit.font(11),
|
||||
anchor="w",
|
||||
justify="left",
|
||||
wraplength=330,
|
||||
).pack(fill="x", padx=16, pady=(0, 10), ipady=5)
|
||||
|
||||
def _tag_editor(self, parent, placeholder: str, terms: list[str], kind: str) -> None:
|
||||
p = self._p
|
||||
row = ctk.CTkFrame(parent, fg_color="transparent")
|
||||
row.pack(fill="x", padx=16, pady=(0, 8))
|
||||
entry = ctk.CTkEntry(
|
||||
row,
|
||||
placeholder_text=placeholder,
|
||||
fg_color=p["btn_sec_bg"],
|
||||
border_color=p["btn_sec_border"],
|
||||
text_color=p["text"],
|
||||
height=32,
|
||||
)
|
||||
entry.pack(side="left", fill="x", expand=True, padx=(0, 8))
|
||||
ui_kit.secondary_button(row, p, "+ Ajouter", command=lambda: None).pack(side="right")
|
||||
cloud = ctk.CTkFrame(parent, fg_color="transparent")
|
||||
cloud.pack(fill="x", padx=16, pady=(0, 14))
|
||||
tag_color = p["success"] if kind == "keep" else p["primary"]
|
||||
line = ctk.CTkFrame(cloud, fg_color="transparent")
|
||||
line.pack(fill="x", anchor="w")
|
||||
used_width = 0
|
||||
for term in terms:
|
||||
estimated_width = min(230, max(88, len(term) * 8 + 34))
|
||||
if used_width and used_width + estimated_width > 360:
|
||||
line = ctk.CTkFrame(cloud, fg_color="transparent")
|
||||
line.pack(fill="x", anchor="w")
|
||||
used_width = 0
|
||||
ctk.CTkLabel(
|
||||
line,
|
||||
text=f"{term[:30]}{'…' if len(term) > 30 else ''} ×",
|
||||
width=estimated_width,
|
||||
text_color=tag_color,
|
||||
fg_color=p["btn_sec_bg"],
|
||||
corner_radius=99,
|
||||
font=ui_kit.font(12),
|
||||
).pack(side="left", padx=(0, 6), pady=3, ipadx=4, ipady=3)
|
||||
used_width += estimated_width + 6
|
||||
|
||||
def _slider_row(self, parent, label: str, value: int) -> None:
|
||||
p = self._p
|
||||
row = ctk.CTkFrame(parent, fg_color="transparent")
|
||||
row.pack(fill="x", padx=16, pady=3)
|
||||
ctk.CTkLabel(row, text=label, text_color=p["text"], font=ui_kit.font(13)).pack(side="left")
|
||||
slider = ctk.CTkSlider(row, from_=0, to=6, number_of_steps=6, progress_color=p["primary"], width=125)
|
||||
slider.set(value)
|
||||
slider.pack(side="right")
|
||||
|
||||
def _update_mask_preview(self) -> None:
|
||||
value = self._mask_style_var.get()
|
||||
if value == "stars":
|
||||
text = "Patient ***, né le ***"
|
||||
elif value == "blackout":
|
||||
text = "Patient ████, né le ████"
|
||||
else:
|
||||
text = "Patient [NOM], né le [DATE_NAISSANCE]"
|
||||
self._mask_preview.configure(text=text)
|
||||
|
||||
def _rule_row(self, parent, values: tuple[str, str, str, str]) -> None:
|
||||
p = self._p
|
||||
label, rule_type, target, status = values
|
||||
row = ctk.CTkFrame(parent, fg_color="transparent")
|
||||
row.pack(fill="x", padx=16, pady=1)
|
||||
ctk.CTkLabel(row, text=label, width=190, anchor="w", text_color=p["text"], font=ui_kit.font(12)).pack(side="left")
|
||||
ctk.CTkLabel(row, text=rule_type, width=80, anchor="w", text_color=p["text_dim"], font=ui_kit.font(11)).pack(side="left")
|
||||
ctk.CTkLabel(row, text=target, width=210, anchor="w", text_color=p["primary"], font=ui_kit.font(12, "bold")).pack(side="left")
|
||||
color = p["success"] if status == "Actif" else p["warning"]
|
||||
ctk.CTkLabel(row, text=status, width=70, anchor="w", text_color=color, font=ui_kit.font(11, "bold")).pack(side="left")
|
||||
ui_kit.secondary_button(row, p, "▶ Tester", command=lambda: None).pack(side="left")
|
||||
|
||||
26
tests/unit/test_gui_v6_config_mockup_sections.py
Normal file
26
tests/unit/test_gui_v6_config_mockup_sections.py
Normal file
@@ -0,0 +1,26 @@
|
||||
"""Garde-fou : l'onglet Configuration doit couvrir les sections de la maquette V6."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from gui_v6.tabs.tab_config import CONFIG_MOCKUP_SECTIONS
|
||||
|
||||
|
||||
def test_config_mockup_sections_cover_admin_surface():
|
||||
assert CONFIG_MOCKUP_SECTIONS == {
|
||||
"reglages": [
|
||||
"Profil métier",
|
||||
"Moteurs NER",
|
||||
"Données à détecter",
|
||||
"Termes à toujours conserver",
|
||||
"Termes à toujours masquer",
|
||||
],
|
||||
"masquage": [
|
||||
"Couleur de masquage (PDF)",
|
||||
"Style des marqueurs (texte)",
|
||||
"Épaisseur du masque",
|
||||
"Codes de remplacement",
|
||||
"Masques de zones fixes",
|
||||
],
|
||||
"partage": ["Exporter la configuration", "Importer une configuration"],
|
||||
"regles": ["Règles actives", "Testeur de règle"],
|
||||
}
|
||||
Reference in New Issue
Block a user