SPB Git forge

spb/api-ka

Public

API-KA — plateforme centrale : collecte quotidienne des 8 services KA, historisation append-only et API publique sur www.api-ka.com

48commits 1branches 0releases
5.9 MBsize
maindefault branch
19 days agolast push
Python 60.9% HTML 21% TypeScript 7.3% JavaScript 5.2% CSS 4.8% Shell 0.8%
4.2 KB · 107 lines javascript
Raw Blame History
1/* ============================================2   Projet   : API-KA3   Fichier  : src/api/web/ka/ka-shell.js4   Node     : m3u96b5   Author   : Simon-Pierre Boucher6   Contact  : contact@spboucher.ai7   Date     : 2026-08-178   ============================================9   Coquille commune Groupe KA pour les pages statiques d'API-KA :10   · footer commun .ka-footer (équivalent vanilla de ka-ui/KaFooter.tsx),11     alimenté par /ka/ecosystem.json (source de vérité unique) ;12   · cartes contact (page /contact, conteneur #ka-contacts) ;13   · état de connexion KA ID dans le header (conteneur #ka-auth). */14"use strict";1516const KA_SITE_ID = "api-ka";1718async function kaEco() {19  const r = await fetch("/ka/ecosystem.json");20  return r.json();21}2223function el(tag, cls, html) {24  const e = document.createElement(tag);25  if (cls) e.className = cls;26  if (html !== undefined) e.innerHTML = html;27  return e;28}2930function esc(s) {31  return String(s).replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");32}3334/* ---------- footer commun (structure .ka-footer de tokens.css) ---------- */35function kaRenderFooter(eco) {36  const root = document.getElementById("ka-footer-root");37  if (!root) return;38  const site = eco.sites.find((s) => s.id === KA_SITE_ID);39  const others = eco.sites.filter((s) => s.id !== KA_SITE_ID);40  const year = new Date().getFullYear();41  root.innerHTML = `42    <a class="wordmark" href="${eco.hub.url}" target="_blank" rel="noopener noreferrer"43       aria-label="Groupe KA — le portail de l'écosystème">Groupe <span class="ka">KA</span></a>44    <p class="desc">${esc(eco.org.tagline)} Des centaines de connecteurs lisent les sites à la45      source, normalisent la donnée et se resynchronisent seuls.46      ${site ? `<b style="color:var(--paper)">${esc(site.wordmark)}</b> — ${esc(site.tagline)} — est un service Groupe KA.` : ""}</p>47    <p class="notice"><b>${esc(eco.org.disclaimer)}</b></p>48    <ul class="sites">49      ${others.map((s) => `<li><a href="https://${s.domain}" target="_blank" rel="noopener noreferrer">${esc(s.wordmark)}</a></li>`).join("")}50      ${(eco.extraFooterLinks || []).map((l) => `<li><a href="${l.href}" target="_blank" rel="noopener noreferrer">${esc(l.label)}</a></li>`).join("")}51    </ul>52    <div class="contacts">53      ${eco.contacts.map((c) => `<p style="margin:0"><a href="mailto:${c.email}">${c.email}</a><span>${esc(c.role)}</span></p>`).join("")}54    </div>55    <p class="legal">© ${year} ${esc(eco.org.copyrightHolder)}56       · <a href="/doc/">Documentation</a>57      ${eco.legal.map((l) => ` · <a href="${l.href}" target="_blank" rel="noopener noreferrer">${esc(l.label)}</a>`).join("")}58    </p>`;59}6061/* ---------- cartes contact (page /contact) ---------- */62function kaRenderContacts(eco) {63  const zone = document.getElementById("ka-contacts");64  if (!zone) return;65  zone.innerHTML = eco.contacts66    .map(67      (c) => `<div class="card contact-card">68        <span class="klabel">${esc(c.role)}</span>69        <a class="contact-mail" href="mailto:${c.email}">${c.email}</a>70      </div>`71    )72    .join("");73  const hub = document.getElementById("ka-hub-link");74  if (hub) hub.href = eco.hub.url + eco.hub.loginPath;75}7677/* ---------- connexion KA ID dans le header (#ka-auth) ---------- */78async function kaRenderAuth() {79  const zone = document.getElementById("ka-auth");80  if (!zone) return;81  try {82    const r = await fetch("/api/auth/me", { headers: { Accept: "application/json" } });83    if (r.ok) {84      const u = await r.json();85      zone.innerHTML = `<span class="ka-user" title="${esc(u.email || "")}">86          ${u.picture ? `<img src="${u.picture}" alt="" class="ka-avatar">` : ""}87          <b>${esc(u.name || "membre")}</b></span>88        <button class="btn btn-ghost ka-logout" type="button">Déconnexion</button>`;89      zone.querySelector(".ka-logout").addEventListener("click", async () => {90        await fetch("/api/auth/logout", { method: "POST" });91        location.reload();92      });93      return;94    }95  } catch {}96  zone.innerHTML = `<a class="btn btn-accent ka-login" href="/api/auth/ka/login">Se connecter avec KA</a>`;97}9899(async () => {100  kaRenderAuth();101  try {102    const eco = await kaEco();103    kaRenderFooter(eco);104    kaRenderContacts(eco);105  } catch {}106})();107