Flowdeck 7.85.4 — barre v0.6.0 re-vendangée : entrée « Administration » (fusion #142) #56
@@ -1,3 +1,9 @@
|
|||||||
|
## v7.85.4 (2026-11-06) — Barre commune v0.6.0 re-vendangée : entrée « Administration » (fusion #142)
|
||||||
|
|
||||||
|
- **Re-vendange verbatim** de la barre commons v0.6.0 (PR dracodev-commons #14) : `static/js/vendor/draco-barre.js` + `static/css/draco-barre.css`. Le menu compte gagne l'entrée **Administration** → `<hub>/admin` (le Hub redirige vers `/admin/utilisateurs`), à **visibilité conditionnelle** (affirmée par l'hôte via `cfg.admin` / `DRACO_BAR.setAdmin`, jamais déduite par la barre).
|
||||||
|
- **Pas de drapeau chez Flowdeck** : Flowdeck ne connaît que le rôle du registre du Hub pour sa propre application (consulté au pont draco avant le JIT) — pas le rôle global de suite (rôle du compte chez ObsiGate, la définition de la garde du Hub). À défaut de certitude, le contrat v0.6.0 impose de ne pas affirmer : l'entrée reste masquée dans Flowdeck (elle apparaît chez ObsiGate et dans la console, qui peuvent l'établir). Commentaire posé dans le gabarit `_draco_bar.html`.
|
||||||
|
- **Test** : `tests/test_draco_bar_texte.py::test_barre_v060_entree_administration_vendangee` (marqueurs de la vendange dans les assets servis).
|
||||||
|
|
||||||
## v7.85.3 (2026-11-06) — Déconnexion du menu compte branchée (fusion #141)
|
## v7.85.3 (2026-11-06) — Déconnexion du menu compte branchée (fusion #141)
|
||||||
|
|
||||||
- **Défaut corrigé** : le bouton « Déconnexion » du menu compte de la barre commune ne faisait rien — la barre relaie l'action `deconnexion` à l'hôte et le `onAction` du gabarit (`app/templates/_draco_bar.html`) n'avait aucune branche pour elle (même défaut que la console Spark, l'hôte du signalement de Bruno).
|
- **Défaut corrigé** : le bouton « Déconnexion » du menu compte de la barre commune ne faisait rien — la barre relaie l'action `deconnexion` à l'hôte et le `onAction` du gabarit (`app/templates/_draco_bar.html`) n'avait aucune branche pour elle (même défaut que la console Spark, l'hôte du signalement de Bruno).
|
||||||
|
|||||||
@@ -113,6 +113,14 @@
|
|||||||
dérivation par l'agent, défaut officiel) alimente les
|
dérivation par l'agent, défaut officiel) alimente les
|
||||||
liens du menu compte (Télécharger, À Propos, Aides,
|
liens du menu compte (Télécharger, À Propos, Aides,
|
||||||
Profil) via urls.hub. */
|
Profil) via urls.hub. */
|
||||||
|
/* Barre v0.6.0 (fusion #142) : JS/CSS re-vendangés verbatim
|
||||||
|
— le menu compte gagne l'entrée « Administration »
|
||||||
|
(lien Hub <hub>/admin) à visibilité conditionnelle.
|
||||||
|
Flowdeck ne passe PAS le drapeau admin : il ne connaît
|
||||||
|
que le rôle du registre du Hub pour sa propre app
|
||||||
|
(consulté au pont draco), pas le rôle global de suite
|
||||||
|
(rôle du compte chez ObsiGate) — à défaut de certitude,
|
||||||
|
l'entrée reste masquée ici, comme le contrat l'exige. */
|
||||||
urls: { hub: "{{ draco_urls().hub }}/" },
|
urls: { hub: "{{ draco_urls().hub }}/" },
|
||||||
domain: (function () { try { return localStorage.getItem("draco_domain") || "pro"; } catch (e) { return "pro"; } })(),
|
domain: (function () { try { return localStorage.getItem("draco_domain") || "pro"; } catch (e) { return "pro"; } })(),
|
||||||
counts: {},
|
counts: {},
|
||||||
|
|||||||
@@ -101,6 +101,11 @@
|
|||||||
text-decoration: none; cursor: pointer;
|
text-decoration: none; cursor: pointer;
|
||||||
}
|
}
|
||||||
.draco-menu-item:hover, .draco-menu-item:focus-visible { background: var(--surface-2); }
|
.draco-menu-item:hover, .draco-menu-item:focus-visible { background: var(--surface-2); }
|
||||||
|
/* Item conditionnel masqué (v0.6.0 : « Administration » tant que
|
||||||
|
l'hôte n'a pas affirmé le statut d'administrateur) — le
|
||||||
|
display:flex ci-dessus écraserait l'attribut hidden sans cette
|
||||||
|
règle, même patron que .draco-compte-menu[hidden]. */
|
||||||
|
.draco-menu-item[hidden] { display: none; }
|
||||||
/* Icônes monoline du menu compte (v0.4.0) : appendues après le
|
/* Icônes monoline du menu compte (v0.4.0) : appendues après le
|
||||||
libellé dans le DOM, replacées à gauche par order: -1. */
|
libellé dans le DOM, replacées à gauche par order: -1. */
|
||||||
.draco-menu-icone {
|
.draco-menu-icone {
|
||||||
|
|||||||
Vendored
+67
@@ -42,6 +42,22 @@
|
|||||||
* l'ouverture par le mécanisme data-theme des hôtes, avec cache
|
* l'ouverture par le mécanisme data-theme des hôtes, avec cache
|
||||||
* local court et repli intégral sur le comportement actuel de
|
* local court et repli intégral sur le comportement actuel de
|
||||||
* l'hôte si le Hub ne répond pas. Voir « Thème commun » plus bas.
|
* l'hôte si le Hub ne répond pas. Voir « Thème commun » plus bas.
|
||||||
|
* v0.6.0 (demande de Bruno, 2026-11-06) : le menu compte gagne un
|
||||||
|
* cinquième lien Hub, « Administration » → <hub>/admin (le Hub y
|
||||||
|
* redirige vers /admin/utilisateurs), placé après le séparateur,
|
||||||
|
* avant « Déconnexion », avec son icône monoline (curseurs de
|
||||||
|
* réglage). AFFICHAGE CONDITIONNEL : l'entrée n'apparaît que si
|
||||||
|
* l'hôte AFFIRME que le compte courant est administrateur de
|
||||||
|
* suite — cfg.admin === true à la configuration, ou
|
||||||
|
* DRACO_BAR.setAdmin(true) quand l'hôte l'apprend après coup
|
||||||
|
* (patron setUrls). L'hôte ne passe le drapeau que s'il l'a établi
|
||||||
|
* depuis SA source d'autorité (rôle global du compte chez
|
||||||
|
* ObsiGate, niveau du registre des rôles du Hub pour son app…) ;
|
||||||
|
* à défaut de certitude, pas de drapeau et l'entrée reste masquée.
|
||||||
|
* La barre ne devine jamais : le jeton draco ne porte aucun rôle
|
||||||
|
* (claims minimaux, par design). La vraie protection reste la
|
||||||
|
* garde serveur du Hub (/admin/*), pas ce masquage d'affichage.
|
||||||
|
* Voir le README, « Administration » — contrat de visibilité.
|
||||||
*
|
*
|
||||||
* Aucun gestionnaire inline : un seul écouteur délégué sur le document
|
* Aucun gestionnaire inline : un seul écouteur délégué sur le document
|
||||||
* (patron validé par le prototype — les onclick du HTML généré sont
|
* (patron validé par le prototype — les onclick du HTML généré sont
|
||||||
@@ -54,6 +70,11 @@
|
|||||||
* counts: { tiktak: 3, kanbante: 3, alertes: 3, spark: 0 },
|
* counts: { tiktak: 3, kanbante: 3, alertes: 3, spark: 0 },
|
||||||
* user: "Bruno", // nom affiché (v0.1.6) ;
|
* user: "Bruno", // nom affiché (v0.1.6) ;
|
||||||
* // ou { display_name: "Bruno", username: "bruno" }
|
* // ou { display_name: "Bruno", username: "bruno" }
|
||||||
|
* admin: true, // (v0.6.0, optionnel)
|
||||||
|
* // administrateur de suite ÉTABLI par l'hôte : démasque
|
||||||
|
* // l'entrée « Administration » du menu compte. Absent ou
|
||||||
|
* // non-strictement-true → entrée masquée. Peut aussi être
|
||||||
|
* // posé après coup via DRACO_BAR.setAdmin(true).
|
||||||
* urls: { // bases des applications
|
* urls: { // bases des applications
|
||||||
* obsigate: "https://og.dracodev.net/",
|
* obsigate: "https://og.dracodev.net/",
|
||||||
* flowdeck: "https://flowdeck.dracodev.net/",
|
* flowdeck: "https://flowdeck.dracodev.net/",
|
||||||
@@ -653,6 +674,18 @@
|
|||||||
["path", { d: "M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2" }],
|
["path", { d: "M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2" }],
|
||||||
["circle", { cx: "12", cy: "7", r: "4" }]
|
["circle", { cx: "12", cy: "7", r: "4" }]
|
||||||
],
|
],
|
||||||
|
/* Curseurs de réglage (trois axes, trois boutons) — v0.6.0. */
|
||||||
|
"admin": [
|
||||||
|
["line", { x1: "4", y1: "21", x2: "4", y2: "14" }],
|
||||||
|
["line", { x1: "4", y1: "10", x2: "4", y2: "3" }],
|
||||||
|
["line", { x1: "12", y1: "21", x2: "12", y2: "12" }],
|
||||||
|
["line", { x1: "12", y1: "8", x2: "12", y2: "3" }],
|
||||||
|
["line", { x1: "20", y1: "21", x2: "20", y2: "16" }],
|
||||||
|
["line", { x1: "20", y1: "12", x2: "20", y2: "3" }],
|
||||||
|
["line", { x1: "1", y1: "14", x2: "7", y2: "14" }],
|
||||||
|
["line", { x1: "9", y1: "8", x2: "15", y2: "8" }],
|
||||||
|
["line", { x1: "17", y1: "16", x2: "23", y2: "16" }]
|
||||||
|
],
|
||||||
/* Flèche sortant d'un cadre (porte). */
|
/* Flèche sortant d'un cadre (porte). */
|
||||||
"deconnexion": [
|
"deconnexion": [
|
||||||
["path", { d: "M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4" }],
|
["path", { d: "M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4" }],
|
||||||
@@ -687,6 +720,15 @@
|
|||||||
return span;
|
return span;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Visibilité de l'entrée « Administration » (v0.6.0) : vraie
|
||||||
|
* seulement si l'hôte l'a AFFIRMÉE — cfg.admin === true à la
|
||||||
|
* configuration, ou DRACO_BAR.setAdmin(true) après coup. La
|
||||||
|
* barre ne déduit jamais ce statut (le jeton draco ne porte
|
||||||
|
* aucun rôle) ; à défaut, l'entrée reste masquée et la garde
|
||||||
|
* serveur du Hub reste la vraie protection. */
|
||||||
|
var compteAdmin = cfg.admin === true;
|
||||||
|
var adminItem = null;
|
||||||
|
|
||||||
/* Menu compte (v0.1.6 ; v0.3.0 pour les liens) — en-tête
|
/* Menu compte (v0.1.6 ; v0.3.0 pour les liens) — en-tête
|
||||||
* d'identité, puis les liens du Hub (Télécharger, À Propos,
|
* d'identité, puis les liens du Hub (Télécharger, À Propos,
|
||||||
* Aides, Profil — vrais <a href>, même patron que le menu des
|
* Aides, Profil — vrais <a href>, même patron que le menu des
|
||||||
@@ -719,6 +761,22 @@
|
|||||||
sep.className = "draco-menu-sep";
|
sep.className = "draco-menu-sep";
|
||||||
sep.setAttribute("aria-hidden", "true");
|
sep.setAttribute("aria-hidden", "true");
|
||||||
compteMenu.appendChild(sep);
|
compteMenu.appendChild(sep);
|
||||||
|
/* « Administration » (v0.6.0) : cinquième lien Hub
|
||||||
|
* (<hub>/admin, où le Hub redirige vers /admin/utilisateurs).
|
||||||
|
* data-hub-link="admin" : son href est resynchronisé par
|
||||||
|
* refreshCompteHrefs / setUrls comme les quatre autres liens.
|
||||||
|
* Toujours construit ; masqué tant que l'hôte n'a pas affirmé
|
||||||
|
* le statut d'administrateur (compteAdmin). */
|
||||||
|
var adm = document.createElement("a");
|
||||||
|
adm.className = "draco-menu-item";
|
||||||
|
adm.href = hubHref("admin");
|
||||||
|
adm.setAttribute("data-hub-link", "admin");
|
||||||
|
adm.setAttribute("role", "menuitem");
|
||||||
|
adm.textContent = "Administration";
|
||||||
|
adm.appendChild(menuIcone("admin"));
|
||||||
|
adm.hidden = !compteAdmin;
|
||||||
|
compteMenu.appendChild(adm);
|
||||||
|
adminItem = adm;
|
||||||
var b = document.createElement("button");
|
var b = document.createElement("button");
|
||||||
b.type = "button";
|
b.type = "button";
|
||||||
b.className = "draco-menu-item";
|
b.className = "draco-menu-item";
|
||||||
@@ -734,6 +792,7 @@
|
|||||||
var head = compteMenu.querySelector(".draco-compte-nom");
|
var head = compteMenu.querySelector(".draco-compte-nom");
|
||||||
var name = displayName();
|
var name = displayName();
|
||||||
if (head) head.textContent = name || "Compte";
|
if (head) head.textContent = name || "Compte";
|
||||||
|
if (adminItem) adminItem.hidden = !compteAdmin;
|
||||||
refreshCompteHrefs();
|
refreshCompteHrefs();
|
||||||
}
|
}
|
||||||
function toggleCompteMenu(force) {
|
function toggleCompteMenu(force) {
|
||||||
@@ -835,6 +894,14 @@
|
|||||||
window.DRACO_BAR.urls = resolvedUrls;
|
window.DRACO_BAR.urls = resolvedUrls;
|
||||||
applyUrls(resolvedUrls);
|
applyUrls(resolvedUrls);
|
||||||
refreshCompteHrefs();
|
refreshCompteHrefs();
|
||||||
|
},
|
||||||
|
/* Administration (v0.6.0) : l'hôte pose le drapeau quand il a
|
||||||
|
* ÉTABLI que le compte courant est administrateur de suite
|
||||||
|
* (sa source d'autorité — voir l'en-tête et le README). Toute
|
||||||
|
* valeur autre que le booléen true masque l'entrée. */
|
||||||
|
setAdmin: function (v) {
|
||||||
|
compteAdmin = v === true;
|
||||||
|
if (adminItem) adminItem.hidden = !compteAdmin;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -45,6 +45,23 @@ def test_barre_deconnexion_branchee_globale():
|
|||||||
assert '{{ draco_urls().obsigate }}/sso/logout?return_to=' in gabarit
|
assert '{{ draco_urls().obsigate }}/sso/logout?return_to=' in gabarit
|
||||||
|
|
||||||
|
|
||||||
|
def test_barre_v060_entree_administration_vendangee():
|
||||||
|
"""Barre v0.6.0 (fusion #142) : JS/CSS vendangés portent l'entrée
|
||||||
|
« Administration » du menu compte (lien Hub data-hub-link
|
||||||
|
« admin », setAdmin, règle CSS [hidden]) ; le gabarit documente
|
||||||
|
pourquoi Flowdeck ne passe pas le drapeau (pas de rôle global
|
||||||
|
connu) — aucun « admin: true » dans la configuration servie."""
|
||||||
|
js = (ROOT / "static/js/vendor/draco-barre.js").read_text()
|
||||||
|
assert 'setAttribute("data-hub-link", "admin")' in js
|
||||||
|
assert '"Administration"' in js
|
||||||
|
assert "setAdmin" in js
|
||||||
|
css = (ROOT / "static/css/draco-barre.css").read_text()
|
||||||
|
assert ".draco-menu-item[hidden]" in css
|
||||||
|
gabarit = (ROOT / "app/templates/_draco_bar.html").read_text()
|
||||||
|
assert "v0.6.0" in gabarit
|
||||||
|
assert "admin: true" not in gabarit
|
||||||
|
|
||||||
|
|
||||||
def test_barre_v020_onglet_shaarit_et_garde_data_theme():
|
def test_barre_v020_onglet_shaarit_et_garde_data_theme():
|
||||||
"""Barre v0.2.0 (commons @70c837a) : onglet ShaarIt entre Kanbante
|
"""Barre v0.2.0 (commons @70c837a) : onglet ShaarIt entre Kanbante
|
||||||
et l'onglet agent, logo fourni tel quel, CSS vendangé verbatim
|
et l'onglet agent, logo fourni tel quel, CSS vendangé verbatim
|
||||||
|
|||||||
Reference in New Issue
Block a user