Kanbante 0.45.6 : barre commune v0.2.0 — onglet ShaarIt + garde data-theme (comportement visible) #78

Merged
bruno merged 6 commits from barre-v020-0-45-6 into main 2026-11-04 11:16:59 -05:00
9 changed files with 208 additions and 21 deletions
+2
View File
@@ -12,12 +12,14 @@ KANBANTE_PUBLIC_URL=https://kanbante.dracodev.net
DRACO_SSO_URL=https://og.dracodev.net DRACO_SSO_URL=https://og.dracodev.net
DRACO_FLOWDECK_URL=https://flowdeck.dracodev.net DRACO_FLOWDECK_URL=https://flowdeck.dracodev.net
DRACO_TIKTAK_URL=https://tiktak.dracodev.net DRACO_TIKTAK_URL=https://tiktak.dracodev.net
DRACO_SHAARIT_URL=https://shaarit.dracodev.net
AGENT_URL=https://agent.dracodev.net AGENT_URL=https://agent.dracodev.net
# Exemples dev (à décommenter sur l'hôte dev) : # Exemples dev (à décommenter sur l'hôte dev) :
# KANBANTE_PUBLIC_URL=https://kanbante-dev.dracodev.net # KANBANTE_PUBLIC_URL=https://kanbante-dev.dracodev.net
# DRACO_SSO_URL=https://og-dev.dracodev.net # DRACO_SSO_URL=https://og-dev.dracodev.net
# DRACO_FLOWDECK_URL=https://flowdeck-dev.dracodev.net # DRACO_FLOWDECK_URL=https://flowdeck-dev.dracodev.net
# DRACO_TIKTAK_URL=https://tiktak-dev.dracodev.net # DRACO_TIKTAK_URL=https://tiktak-dev.dracodev.net
# DRACO_SHAARIT_URL=https://shaarit-dev.dracodev.net
# AGENT_URL=https://agent-dev.dracodev.net # AGENT_URL=https://agent-dev.dracodev.net
# Journal d'événements du service d'agents (signé HMAC) # Journal d'événements du service d'agents (signé HMAC)
# AGENT_EVENEMENTS_URL= # vide = dérivé de AGENT_URL (/api/v1/evenements) # AGENT_EVENEMENTS_URL= # vide = dérivé de AGENT_URL (/api/v1/evenements)
+8
View File
@@ -1,3 +1,11 @@
## 0.45.6 — 2026-11-03 — Barre commune v0.2.0 : onglet ShaarIt + garde data-theme (phase 3 ShaarIt)
- **⚠ CHANGEMENT DE COMPORTEMENT VISIBLE — garde `data-theme` (arbitrage à la fusion)** : le CSS de barre vendangé jusqu'ici (v0.1.11) appliquait les couleurs **sombres dès que le système était en mode sombre**, sans tenir compte du thème clair choisi dans l'app — sur un poste en sombre système, la barre restait sombre alors que Kanbante était en clair. La v0.2.0 de commons corrige ce piège **dans la source** : les deux blocs `@media (prefers-color-scheme: dark)` sont gardés par `html:not([data-theme])` (le sombre système ne s'applique que si `<html>` n'a **aucun** `data-theme`). Kanbante posant toujours `html[data-theme]` (sombre par défaut, bascule mémorisée `kanbante-theme`), sa barre suivra désormais **toujours le thème de l'app**, jamais celui du système contre son choix. Aucune surcharge `style.css` ajoutée : le correctif est entièrement dans le CSS vendangé verbatim.
- **Barre d'apps v0.2.0 vendangée (dracodev-commons @70c837a, PR commons #7)** : `static/css/draco-barre.css` et `static/js/draco-barre.js` remplacés **verbatim** — SHA-256 CSS `abc0c3b2…e05fab`, JS `24efe399…6e50e1`, identiques à la source `ui/barre-apps/` @70c837a (preuve aussi dans `tests/test_barre_v020.py`). Fragment `_draco_bar.html` porté à la v0.2.0 selon le mécanisme d'adaptation Kanbante existant (URL Jinja `draco_urls` / `agent_url`, `onAction` complet inchangé).
- **Nouvel onglet ShaarIt** (5e app, bookmarks) : `data-app="shaarit"`, **après Kanbante, avant Console Spark** ; couleur émeraude `#059669` ; logo `static/img/logos/shaarit.svg` copié verbatim de commons (SHA-256 `faf0c8a1…316db34`). Le menu de la marque, construit depuis les onglets, l'inclut automatiquement ; le palier mobile du CSS gagne la règle `data-current="shaarit"` (sans effet chez Kanbante, hôte `kanbante`).
- **URL ShaarIt par le même mécanisme que les autres apps** (`app.config` : nouveau champ `shaarit_url` dans `Settings` et `UrlsDraco`) : explicite `DRACO_SHAARIT_URL` > hôte public de la requête (motif fermé étendu à `shaarit<SUFFIXE>.dracodev.net`) > dérivation depuis les adresses de l'agent connues > défaut officiel `https://shaarit.dracodev.net` (dev : `https://shaarit-dev.dracodev.net`). Aucune URL codée en dur dans le gabarit ; le JS vendangé résout aussi `urls.shaarit` (défaut officiel + dérivation `-dev`). `app/main.py` expose `draco_urls.shaarit` au gabarit.
- **Cache** : le bump 0.45.5 → 0.45.6 change aussi le `?v=` des CSS/JS de la barre.
## 0.45.5 — 2026-10-30 — Panneau d'alertes unifiées lisible en thème clair ## 0.45.5 — 2026-10-30 — Panneau d'alertes unifiées lisible en thème clair
- **Retour de Bruno (capture)** : en mode clair, le panneau « Alertes unifiées » s'affichait sombre et illisible — titre invisible, onglets vides. Cause : le CSS neutre `draco-alertes.css` (Fusion #69) attend des variables d'hôte (`--bg-primary`, `--text-dim`, `--text-tertiary`) que Kanbante ne définissait pas ; le panneau retombait sur ses replis sombres pendant que `--text` suivait le thème clair → texte sombre sur fond sombre. - **Retour de Bruno (capture)** : en mode clair, le panneau « Alertes unifiées » s'affichait sombre et illisible — titre invisible, onglets vides. Cause : le CSS neutre `draco-alertes.css` (Fusion #69) attend des variables d'hôte (`--bg-primary`, `--text-dim`, `--text-tertiary`) que Kanbante ne définissait pas ; le panneau retombait sur ses replis sombres pendant que `--text` suivait le thème clair → texte sombre sur fond sombre.
+20 -5
View File
@@ -130,6 +130,10 @@ Environment variables:
DRACO_TIKTAK_URL Public base URL of TikTak for the DRACO_TIKTAK_URL Public base URL of TikTak for the
common app bar. Default (official) common app bar. Default (official)
https://tiktak.dracodev.net. https://tiktak.dracodev.net.
DRACO_SHAARIT_URL Public base URL of ShaarIt for the
common app bar (barre v0.2.0).
Default (official)
https://shaarit.dracodev.net.
ObsiGate's bar link reuses DRACO_SSO_URL ObsiGate's bar link reuses DRACO_SSO_URL
(the SSO emitter IS ObsiGate). (the SSO emitter IS ObsiGate).
Résolution d'une URL rendue à une Résolution d'une URL rendue à une
@@ -139,7 +143,7 @@ Environment variables:
ci-dessus (prioritaire, contrat ci-dessus (prioritaire, contrat
inchangé) ; 2) l'hôte public de la inchangé) ; 2) l'hôte public de la
requête, motif fermé requête, motif fermé
``(og|flowdeck|tiktak|kanbante|agent) ``(og|flowdeck|tiktak|kanbante|shaarit|agent)
<SUFFIXE>.dracodev.net`` (suffixe vide <SUFFIXE>.dracodev.net`` (suffixe vide
en prod, ``-dev`` en dev) appliqué à en prod, ``-dev`` en dev) appliqué à
toutes les sœurs et à l'agent — jamais toutes les sœurs et à l'agent — jamais
@@ -152,7 +156,7 @@ Environment variables:
l'URL sœur devient l'URL sœur devient
``https://<slug><SUFFIXE>. ``https://<slug><SUFFIXE>.
dracodev.net`` (slugs : og, flowdeck, dracodev.net`` (slugs : og, flowdeck,
tiktak, kanbante, agent) ; hôte hors tiktak, kanbante, shaarit, agent) ; hôte hors
motif (autre domaine, LAN, IP) = motif (autre domaine, LAN, IP) =
aucune dérivation, jamais de lien aucune dérivation, jamais de lien
deviné ; 4) le défaut officiel (prod). deviné ; 4) le défaut officiel (prod).
@@ -177,7 +181,7 @@ from urllib.parse import urlparse
BASE_DIR = Path(__file__).resolve().parent.parent BASE_DIR = Path(__file__).resolve().parent.parent
APP_VERSION = "0.45.5" APP_VERSION = "0.45.6"
def _env_bool(name: str, default: bool) -> bool: def _env_bool(name: str, default: bool) -> bool:
@@ -232,7 +236,7 @@ def _env_wip_limits(name: str) -> dict[str, int]:
# du service (élargie en 0.32.2) ; 4) défaut officiel. # du service (élargie en 0.32.2) ; 4) défaut officiel.
_MOTIF_HOTE_AGENT = re.compile(r"agent([a-z0-9-]*)\.dracodev\.net") _MOTIF_HOTE_AGENT = re.compile(r"agent([a-z0-9-]*)\.dracodev\.net")
_MOTIF_HOTE_PUBLIC = re.compile( _MOTIF_HOTE_PUBLIC = re.compile(
r"(?:og|flowdeck|tiktak|kanbante|agent)([a-z0-9-]*)\.dracodev\.net" r"(?:og|flowdeck|tiktak|kanbante|shaarit|agent)([a-z0-9-]*)\.dracodev\.net"
) )
@@ -265,7 +269,7 @@ def _suffixe_environnement_agent(url_agent: str) -> str | None:
def suffixe_environnement_requete(hote_requete: str | None) -> str | None: def suffixe_environnement_requete(hote_requete: str | None) -> str | None:
"""Suffixe lu sur l'hôte public de la requête entrante. """Suffixe lu sur l'hôte public de la requête entrante.
Motif fermé ``^(og|flowdeck|tiktak|kanbante|agent)<SUFFIXE> Motif fermé ``^(og|flowdeck|tiktak|kanbante|shaarit|agent)<SUFFIXE>
\\.dracodev\\.net$`` (suffixe optionnel : vide en prod, \\.dracodev\\.net$`` (suffixe optionnel : vide en prod,
``-dev`` en dev) ; un port éventuel est toléré et retiré. ``-dev`` en dev) ; un port éventuel est toléré et retiré.
Hors motif (LAN, IP, autre domaine) : ``None`` — l'appelant Hors motif (LAN, IP, autre domaine) : ``None`` — l'appelant
@@ -306,6 +310,7 @@ class UrlsDraco:
sso_url: str # ObsiGate (lien de barre ; explicite = DRACO_SSO_URL) sso_url: str # ObsiGate (lien de barre ; explicite = DRACO_SSO_URL)
flowdeck_url: str flowdeck_url: str
tiktak_url: str tiktak_url: str
shaarit_url: str # ShaarIt (barre v0.2.0 ; explicite = DRACO_SHAARIT_URL)
public_url: str # Kanbante elle-même (KANBANTE_PUBLIC_URL) public_url: str # Kanbante elle-même (KANBANTE_PUBLIC_URL)
agent_url: str # base du service d'agents (panneau + CSP) agent_url: str # base du service d'agents (panneau + CSP)
@@ -344,6 +349,9 @@ def resoudre_urls_draco(
"DRACO_FLOWDECK_URL", "flowdeck", base.flowdeck_url "DRACO_FLOWDECK_URL", "flowdeck", base.flowdeck_url
), ),
tiktak_url=resoudre("DRACO_TIKTAK_URL", "tiktak", base.tiktak_url), tiktak_url=resoudre("DRACO_TIKTAK_URL", "tiktak", base.tiktak_url),
shaarit_url=resoudre(
"DRACO_SHAARIT_URL", "shaarit", base.shaarit_url
),
public_url=resoudre( public_url=resoudre(
"KANBANTE_PUBLIC_URL", "kanbante", base.public_url "KANBANTE_PUBLIC_URL", "kanbante", base.public_url
), ),
@@ -393,6 +401,7 @@ class Settings:
public_url: str = "https://kanbante.dracodev.net" public_url: str = "https://kanbante.dracodev.net"
flowdeck_url: str = "https://flowdeck.dracodev.net" flowdeck_url: str = "https://flowdeck.dracodev.net"
tiktak_url: str = "https://tiktak.dracodev.net" tiktak_url: str = "https://tiktak.dracodev.net"
shaarit_url: str = "https://shaarit.dracodev.net"
agent_url: str = "https://agent.dracodev.net" agent_url: str = "https://agent.dracodev.net"
archive_suggest_days: int = 180 archive_suggest_days: int = 180
agent_evenements_url: str = "https://agent.dracodev.net/api/v1/evenements" agent_evenements_url: str = "https://agent.dracodev.net/api/v1/evenements"
@@ -497,6 +506,12 @@ def _env_settings() -> Settings:
"https://tiktak.dracodev.net", "https://tiktak.dracodev.net",
suffixe_agent, suffixe_agent,
), ),
shaarit_url=_url_soeur_draco(
"DRACO_SHAARIT_URL",
"shaarit",
"https://shaarit.dracodev.net",
suffixe_agent,
),
agent_url=agent_url, agent_url=agent_url,
archive_suggest_days=_env_int("KANBANTE_ARCHIVE_SUGGEST_DAYS", 180), archive_suggest_days=_env_int("KANBANTE_ARCHIVE_SUGGEST_DAYS", 180),
agent_evenements_url=agent_evenements_url, agent_evenements_url=agent_evenements_url,
+1
View File
@@ -2250,6 +2250,7 @@ def render(
"flowdeck": _urls.flowdeck_url, "flowdeck": _urls.flowdeck_url,
"tiktak": _urls.tiktak_url, "tiktak": _urls.tiktak_url,
"kanbante": _urls.public_url, "kanbante": _urls.public_url,
"shaarit": _urls.shaarit_url,
}, },
) )
context.setdefault("agent_url", _urls.agent_url) context.setdefault("agent_url", _urls.agent_url)
+22 -7
View File
@@ -1,17 +1,28 @@
{# Barre d'apps commune dracodev — Fusion ACC-1 (issue kanbante#28). {# Barre d'apps commune dracodev — Fusion ACC-1 (issue kanbante#28).
Snippet vendangé depuis Projets/dracodev-commons v0.1.10 Snippet vendangé depuis Projets/dracodev-commons v0.2.0
(ui/barre-apps/) : structure inchangée ; seule adaptation locale (ui/barre-apps/ @70c837a, PR commons #7) : structure du fragment
(0.32.0, dev/prod) = les URL des apps et l'adresse du service commons portée ici ; seule adaptation locale (0.32.0, dev/prod)
d'agents sont INJECTÉES par l'hôte depuis app.config = les URL des apps et l'adresse du service d'agents sont
(draco_urls / agent_url, défauts = noms officiels) — aucun nom INJECTÉES par l'hôte depuis app.config (draco_urls / agent_url,
public codé en dur dans ce gabarit ni dans draco-panneau.js. défauts = noms officiels) — aucun nom public codé en dur dans
ce gabarit ni dans draco-panneau.js. Le CSS et le JS, eux, sont
vendangés VERBATIM (static/css/draco-barre.css,
static/js/draco-barre.js — voir CHANGELOG 0.45.6).
v0.2.0 (phase 3 ShaarIt) : nouvel onglet ShaarIt
(data-app="shaarit", draco_urls.shaarit), APRÈS Kanbante et
AVANT l'onglet agent ; couleur émeraude #059669, logo
static/img/logos/shaarit.svg (copie verbatim de commons) ;
GARDE data-theme : le CSS v0.2.0 conditionne les blocs
prefers-color-scheme à html:not([data-theme]) — la barre ne
force plus le sombre système quand l'app est en thème clair
explicite (voir CHANGELOG 0.45.6, en tête).
Chantier 5 (fusion #69/#71, sans bump) : 5e onglet Console Spark Chantier 5 (fusion #69/#71, sans bump) : 5e onglet Console Spark
(data-app="agent", agent_url), après Kanbante ; l'entrée (data-app="agent", agent_url), après Kanbante ; l'entrée
« Console Spark » du menu de la marque est conservée. « Console Spark » du menu de la marque est conservée.
CSS/JS : /static/css/draco-barre.css, /static/js/draco-barre.js. CSS/JS : /static/css/draco-barre.css, /static/js/draco-barre.js.
Inclus par _header.html (toutes les pages applicatives ; ni le Inclus par _header.html (toutes les pages applicatives ; ni le
wallboard ni l'écran de connexion, volontaires). wallboard ni l'écran de connexion, volontaires).
Icônes logos v0.1.9 (2026-10-29) : les 5 tuiles sont les logos Icônes logos v0.1.9 (2026-10-29) : les tuiles sont les logos
fournis, tels quels, servis depuis /static/img/logos/ (copie de fournis, tels quels, servis depuis /static/img/logos/ (copie de
ui/barre-apps/logos/ de dracodev-commons) — jamais de glyphe ui/barre-apps/logos/ de dracodev-commons) — jamais de glyphe
texte, jamais de redessin ; l'entrée « Console Spark » du menu texte, jamais de redessin ; l'entrée « Console Spark » du menu
@@ -58,6 +69,10 @@
<span class="draco-apptab-txt"><strong>Kanbante</strong><small>Kanban</small></span> <span class="draco-apptab-txt"><strong>Kanbante</strong><small>Kanban</small></span>
<span class="draco-badge" data-badge="kanbante" hidden>0</span> <span class="draco-badge" data-badge="kanbante" hidden>0</span>
</a> </a>
<a class="draco-apptab" data-app="shaarit" href="{{ draco_urls.shaarit }}/">
<span class="draco-apptab-ico" style="--app:#059669"><img src="/static/img/logos/shaarit.svg" alt="ShaarIt" width="30" height="30"></span>
<span class="draco-apptab-txt"><strong>ShaarIt</strong><small>Bookmarks</small></span>
</a>
<a class="draco-apptab" data-app="agent" href="{{ agent_url }}/"> <a class="draco-apptab" data-app="agent" href="{{ agent_url }}/">
<span class="draco-apptab-ico" style="--app:#c00000"><img src="/static/img/logos/spark.png" alt="Console Spark" width="30" height="30"></span> <span class="draco-apptab-ico" style="--app:#c00000"><img src="/static/img/logos/spark.png" alt="Console Spark" width="30" height="30"></span>
<span class="draco-apptab-txt"><strong>Console Spark</strong><small>Agent commun</small></span> <span class="draco-apptab-txt"><strong>Console Spark</strong><small>Agent commun</small></span>
+19 -3
View File
@@ -12,9 +12,18 @@
Alertes icône seule. Alertes icône seule.
v0.1.11 : marque = étoile Spark monochrome (blanche barre foncée, v0.1.11 : marque = étoile Spark monochrome (blanche barre foncée,
noire barre claire) ; anneau rouge #c00000 autour de l'avatar flottant. noire barre claire) ; anneau rouge #c00000 autour de l'avatar flottant.
v0.2.0 : nouvel onglet « ShaarIt » (data-app="shaarit", --app émeraude
#059669, logo logos/shaarit.svg via {{LOGO_SHAARIT}}) avant l'onglet
agent ; GARDE data-theme : les blocs prefers-color-scheme ne
s'appliquent que si <html> n'a AUCUN attribut data-theme
(html:not([data-theme])) — avant ce correctif, un hôte ayant choisi
le clair via data-theme="light" héritait quand même du sombre
système (piège constaté dans les copies vendangées de
Kanbante/Flowdeck ; les re-vendanges de la v0.2.0 le corrigent).
Jetons repris du prototype validé Console v7.2. Jetons repris du prototype validé Console v7.2.
Thème : clair par défaut, sombre via [data-theme="dark"] sur <html> Thème : clair par défaut, sombre via [data-theme="dark"] sur <html>
ou prefers-color-scheme si l'app intégratrice ne force rien. */ ou prefers-color-scheme si l'app intégratrice ne force rien
(aucun attribut data-theme sur <html>). */
.draco-bar { .draco-bar {
--bg: #f2f2f0; --surface: #ffffff; --surface-2: #e9eae6; --surface-3: #f6f6f3; --bg: #f2f2f0; --surface: #ffffff; --surface-2: #e9eae6; --surface-3: #f6f6f3;
@@ -27,8 +36,12 @@
background: var(--surface); border-bottom: 1px solid var(--line); background: var(--surface); border-bottom: 1px solid var(--line);
font: 500 14px/1.3 system-ui, "Segoe UI", sans-serif; color: var(--ink); font: 500 14px/1.3 system-ui, "Segoe UI", sans-serif; color: var(--ink);
} }
/* Garde data-theme (v0.2.0) : le sombre système ne s'applique QUE si
* l'hôte n'a posé aucun data-theme sur <html>. Sans cette garde, un
* hôte en data-theme="light" sur un système sombre affichait la barre
* sombre malgré son choix explicite. */
@media (prefers-color-scheme: dark) { @media (prefers-color-scheme: dark) {
.draco-bar { --bg:#101211; --surface:#1a1c1a; --surface-2:#242624; --surface-3:#20221f; html:not([data-theme]) .draco-bar { --bg:#101211; --surface:#1a1c1a; --surface-2:#242624; --surface-3:#20221f;
--ink:#eceee9; --ink-2:#a6aba2; --ink-3:#8b9089; --line:#2e302c; } --ink:#eceee9; --ink-2:#a6aba2; --ink-3:#8b9089; --line:#2e302c; }
} }
[data-theme="dark"] .draco-bar { --bg:#101211; --surface:#1a1c1a; --surface-2:#242624; --surface-3:#20221f; [data-theme="dark"] .draco-bar { --bg:#101211; --surface:#1a1c1a; --surface-2:#242624; --surface-3:#20221f;
@@ -48,7 +61,7 @@
barre foncée (filtre annulé par les règles thème ci-dessous). */ barre foncée (filtre annulé par les règles thème ci-dessous). */
.draco-brand-mark img { width: 26px; height: 26px; object-fit: cover; display: block; filter: brightness(0); } .draco-brand-mark img { width: 26px; height: 26px; object-fit: cover; display: block; filter: brightness(0); }
@media (prefers-color-scheme: dark) { @media (prefers-color-scheme: dark) {
.draco-bar .draco-brand-mark img { filter: none; } html:not([data-theme]) .draco-bar .draco-brand-mark img { filter: none; }
} }
[data-theme="dark"] .draco-bar .draco-brand-mark img { filter: none; } [data-theme="dark"] .draco-bar .draco-brand-mark img { filter: none; }
@@ -218,6 +231,9 @@
.draco-bar[data-current="flowdeck"] .draco-apptab[data-app="flowdeck"], .draco-bar[data-current="flowdeck"] .draco-apptab[data-app="flowdeck"],
.draco-bar[data-current="tiktak"] .draco-apptab[data-app="tiktak"], .draco-bar[data-current="tiktak"] .draco-apptab[data-app="tiktak"],
.draco-bar[data-current="kanbante"] .draco-apptab[data-app="kanbante"], .draco-bar[data-current="kanbante"] .draco-apptab[data-app="kanbante"],
/* v0.2.0 : sur ShaarIt elle-même (data-current="shaarit"), c'est
l'onglet ShaarIt qui reste visible en mobile. */
.draco-bar[data-current="shaarit"] .draco-apptab[data-app="shaarit"],
/* Chantier 5 : sur la console elle-même (data-current="agent", /* Chantier 5 : sur la console elle-même (data-current="agent",
programme console #71), c'est l'onglet Console Spark qui reste programme console #71), c'est l'onglet Console Spark qui reste
visible en mobile — les 4 hôtes gardent leur propre courant. */ visible en mobile — les 4 hôtes gardent leur propre courant. */
+9
View File
@@ -0,0 +1,9 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 240 240">
<!-- ShaarIt — signet (bookmark) blanc sur fond émeraude #059669,
couleur signature de l'app dans la barre (#059669, distincte du
teal Kanbante #0d9488). Fond arrondi comme les logos PNG 180 px
des autres apps ; géométrie simple, aucun redessin d'un logo
existant : le signet EST le symbole de l'app (bookmarks). -->
<rect x="8" y="8" width="224" height="224" rx="48" fill="#059669"/>
<path d="M 82 52 L 158 52 L 158 190 L 120 152 L 82 190 Z" fill="#ffffff"/>
</svg>

After

Width:  |  Height:  |  Size: 569 B

+18 -6
View File
@@ -8,7 +8,12 @@
* correctif fusion #70 (SANS bump de version, publication séparée) : * correctif fusion #70 (SANS bump de version, publication séparée) :
* bouton trois points et son menu par défaut SUPPRIMÉS, « Console Spark » * bouton trois points et son menu par défaut SUPPRIMÉS, « Console Spark »
* ajoutée au menu de la marque, fermeture/focus corrigés (voir * ajoutée au menu de la marque, fermeture/focus corrigés (voir
* « Menu des applications », « Focus » et « Écouteurs globaux »). * « Menu des applications », « Focus » et « Écouteurs globaux ») ;
* v0.2.0 : 5e application ShaarIt — clé urls.shaarit, défaut officiel
* https://shaarit.dracodev.net/, dérivation -dev shaarit-dev (même
* contrat que les autres apps), entrée APP_LABELS ; l'onglet
* (data-app="shaarit", après Kanbante, avant agent) est repris
* automatiquement par la construction du menu de la marque.
* *
* 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
@@ -26,6 +31,7 @@
* flowdeck: "https://flowdeck.dracodev.net/", * flowdeck: "https://flowdeck.dracodev.net/",
* tiktak: "https://tiktak.dracodev.net/", * tiktak: "https://tiktak.dracodev.net/",
* kanbante: "https://kanbante.dracodev.net/", * kanbante: "https://kanbante.dracodev.net/",
* shaarit: "https://shaarit.dracodev.net/",
* agent: "https://agent.dracodev.net/", * agent: "https://agent.dracodev.net/",
* spark: "https://spark.dracodev.net/" * spark: "https://spark.dracodev.net/"
* }, * },
@@ -54,10 +60,13 @@
* La clé spark ne correspond à aucun onglet de la barre : elle est * La clé spark ne correspond à aucun onglet de la barre : elle est
* résolue et exposée via DRACO_BAR.urls pour le panneau Spark * résolue et exposée via DRACO_BAR.urls pour le panneau Spark
* (panneau-agent), qui suit le même contrat d'injection. La clé agent, * (panneau-agent), qui suit le même contrat d'injection. La clé agent,
* elle, a un onglet depuis le chantier 5 (ordre : ObsiGate, Flowdeck, * elle, a un onglet depuis le chantier 5 (ordre, v0.2.0 : ObsiGate,
* TikTak, Kanbante, Console Spark) : elle suit donc l'étape « href * Flowdeck, TikTak, Kanbante, ShaarIt, Console Spark) : elle suit
* donc l'étape « href
* rendu » comme les autres onglets, en plus d'alimenter le menu de * rendu » comme les autres onglets, en plus d'alimenter le menu de
* la marque et DRACO_BAR.urls. * la marque et DRACO_BAR.urls. Même résolution pour shaarit (v0.2.0) :
* explicite > dérivation -dev shaarit-dev > href rendu
* ({{URL_SHAARIT}}) > défaut officiel.
* Actions émises (data-act) : rail, palette, domaine (data-dom), * Actions émises (data-act) : rail, palette, domaine (data-dom),
* alertes, spark, rappel-entete. L'app intégratrice décide de chacune * alertes, spark, rappel-entete. L'app intégratrice décide de chacune
* (ouvrir la palette, le panneau Spark, changer de domaine…). * (ouvrir la palette, le panneau Spark, changer de domaine…).
@@ -144,6 +153,7 @@
flowdeck: "https://flowdeck.dracodev.net/", flowdeck: "https://flowdeck.dracodev.net/",
tiktak: "https://tiktak.dracodev.net/", tiktak: "https://tiktak.dracodev.net/",
kanbante: "https://kanbante.dracodev.net/", kanbante: "https://kanbante.dracodev.net/",
shaarit: "https://shaarit.dracodev.net/",
agent: "https://agent.dracodev.net/", agent: "https://agent.dracodev.net/",
spark: "https://spark.dracodev.net/" spark: "https://spark.dracodev.net/"
}; };
@@ -157,12 +167,13 @@
flowdeck: "https://flowdeck-dev.dracodev.net/", flowdeck: "https://flowdeck-dev.dracodev.net/",
tiktak: "https://tiktak-dev.dracodev.net/", tiktak: "https://tiktak-dev.dracodev.net/",
kanbante: "https://kanbante-dev.dracodev.net/", kanbante: "https://kanbante-dev.dracodev.net/",
shaarit: "https://shaarit-dev.dracodev.net/",
agent: "https://agent-dev.dracodev.net/" agent: "https://agent-dev.dracodev.net/"
}; };
var APP_LABELS = { var APP_LABELS = {
obsigate: "ObsiGate", flowdeck: "Flowdeck", obsigate: "ObsiGate", flowdeck: "Flowdeck",
tiktak: "TikTak", kanbante: "Kanbante" tiktak: "TikTak", kanbante: "Kanbante", shaarit: "ShaarIt"
}; };
/* Vrai si hostname est un hôte -dev dracodev.net : première étiquette /* Vrai si hostname est un hôte -dev dracodev.net : première étiquette
@@ -365,7 +376,8 @@
if (badge) a.appendChild(badge.cloneNode(true)); if (badge) a.appendChild(badge.cloneNode(true));
appsMenu.appendChild(a); appsMenu.appendChild(a);
}); });
/* Entrée « Console Spark » (#70) : après Kanbante, vers la console /* Entrée « Console Spark » (#70) : après les onglets d'apps
* (ObsiGate…ShaarIt, v0.2.0), vers la console
* de l'agent commun (URL agent résolue — explicite > -dev > * de l'agent commun (URL agent résolue — explicite > -dev >
* défaut prod ; aucun hôte spark-dev inventé). data-app="agent" * défaut prod ; aucun hôte spark-dev inventé). data-app="agent"
* l'intègre à refreshMenuHrefs/applyUrls/setCurrent comme les * l'intègre à refreshMenuHrefs/applyUrls/setCurrent comme les
+109
View File
@@ -0,0 +1,109 @@
"""Barre commune v0.2.0 (phase 3 ShaarIt) — re-vendange 0.45.6.
- CSS/JS vendangés VERBATIM depuis dracodev-commons @70c837a
(ui/barre-apps/barre-apps.css / .js) ; logo shaarit.svg idem.
- GARDE data-theme (changement de comportement visible) : avant
la v0.2.0, le CSS vendangé appliquait le sombre système dès
``prefers-color-scheme: dark``, même avec un thème clair
explicite (html[data-theme="light"]) ; la v0.2.0 conditionne
les deux blocs à ``html:not([data-theme])``.
- Onglet ShaarIt : présent dans le rendu, APRÈS Kanbante et
AVANT l'agent, URL résolue par le même mécanisme que les
autres apps (explicite DRACO_SHAARIT_URL > hôte de la
requête > dérivation par l'agent > défaut officiel).
"""
import hashlib
from pathlib import Path
R = Path(__file__).resolve().parents[1]
SHA256_CSS_V020 = "abc0c3b2a282566013bd121b0c46b133700f20be78cf44128bebdf19b7e05fab"
SHA256_JS_V020 = "24efe399823eed21add535c081ea153ae97afe128744aed9b628cf855e6b50e1"
SHA256_LOGO_SHAARIT = "faf0c8a17e7cb82d0884f598eadf2c4fee7a603bfdc3a2ecfdac1e750316db34"
_ENV_BARRE = (
"DRACO_SSO_URL", "DRACO_FLOWDECK_URL", "DRACO_TIKTAK_URL",
"DRACO_SHAARIT_URL", "KANBANTE_PUBLIC_URL", "AGENT_URL",
"AGENT_EVENEMENTS_URL",
)
def _sha256(chemin):
return hashlib.sha256((R / chemin).read_bytes()).hexdigest()
def _nettoyer(monkeypatch):
for nom in _ENV_BARRE:
monkeypatch.delenv(nom, raising=False)
def test_barre_css_js_verbatim_commons_v020():
assert _sha256("static/css/draco-barre.css") == SHA256_CSS_V020
assert _sha256("static/js/draco-barre.js") == SHA256_JS_V020
def test_logo_shaarit_verbatim():
assert _sha256("static/img/logos/shaarit.svg") == SHA256_LOGO_SHAARIT
def test_garde_data_theme_apportee_par_la_v020():
css = (R / "static/css/draco-barre.css").read_text(encoding="utf-8")
# Les deux blocs système sont gardés ; le sombre forcé reste.
assert "html:not([data-theme]) .draco-bar" in css
assert "html:not([data-theme]) .draco-bar .draco-brand-mark img" in css
assert '[data-theme="dark"] .draco-bar' in css
assert "@media (prefers-color-scheme: dark) {\n .draco-bar" not in css
def test_url_shaarit_defaut_officiel(monkeypatch):
from app.config import _env_settings, resoudre_urls_draco
_nettoyer(monkeypatch)
assert _env_settings().shaarit_url == "https://shaarit.dracodev.net"
assert resoudre_urls_draco().shaarit_url == "https://shaarit.dracodev.net"
def test_url_shaarit_derivee_du_seul_agent_evenements(monkeypatch):
from app.config import _env_settings
_nettoyer(monkeypatch)
monkeypatch.setenv(
"AGENT_EVENEMENTS_URL",
"https://agent-dev.dracodev.net/api/v1/evenements",
)
assert _env_settings().shaarit_url == "https://shaarit-dev.dracodev.net"
def test_url_shaarit_explicite_prioritaire(monkeypatch):
from app.config import _env_settings
_nettoyer(monkeypatch)
monkeypatch.setenv(
"AGENT_EVENEMENTS_URL",
"https://agent-dev.dracodev.net/api/v1/evenements",
)
monkeypatch.setenv("DRACO_SHAARIT_URL", "https://signets.example.test")
assert _env_settings().shaarit_url == "https://signets.example.test"
def test_url_shaarit_par_hote_de_requete(monkeypatch):
from app.config import resoudre_urls_draco, suffixe_environnement_requete
_nettoyer(monkeypatch)
assert suffixe_environnement_requete("shaarit-dev.dracodev.net") == "-dev"
urls = resoudre_urls_draco("kanbante-dev.dracodev.net")
assert urls.shaarit_url == "https://shaarit-dev.dracodev.net"
urls = resoudre_urls_draco("kanbante.dracodev.net")
assert urls.shaarit_url == "https://shaarit.dracodev.net"
def test_onglet_shaarit_dans_le_rendu(client):
r = client.get("/")
assert r.status_code == 200
assert 'data-app="shaarit"' in r.text
assert "https://shaarit.dracodev.net/" in r.text
assert "/static/img/logos/shaarit.svg" in r.text
# Ordre : Kanbante < ShaarIt < Console Spark (agent).
assert r.text.index('data-app="kanbante"') < r.text.index('data-app="shaarit"')
assert r.text.index('data-app="shaarit"') < r.text.index('data-app="agent"')
assert client.get("/static/img/logos/shaarit.svg").status_code == 200