| <!doctype html> |
| <html lang="fr"> |
| <head> |
| <meta charset="utf-8" /> |
| <meta |
| name="viewport" |
| content="width=device-width, initial-scale=1, viewport-fit=cover, maximum-scale=1" |
| /> |
| <title>MSG MOTOC</title> |
| <meta name="description" content="Messagerie de groupe temps réel." /> |
| <meta name="theme-color" content="#071318" /> |
| <meta name="mobile-web-app-capable" content="yes" /> |
| <meta name="apple-mobile-web-app-capable" content="yes" /> |
| <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" /> |
| <meta name="apple-mobile-web-app-title" content="MOTOC" /> |
| <link rel="manifest" href="/manifest.webmanifest" /> |
| <link rel="icon" href="/static/icons/favicon-64.png" sizes="64x64" /> |
| <link rel="apple-touch-icon" href="/static/icons/apple-touch-icon.png" /> |
| <link rel="stylesheet" href="/static/styles.css" /> |
| </head> |
| <body> |
| |
| <svg style="display: none" xmlns="http://www.w3.org/2000/svg"> |
| <symbol id="i-back" viewBox="0 0 24 24"><path d="M15 18l-6-6 6-6" /></symbol> |
| <symbol id="i-settings" viewBox="0 0 24 24"> |
| <circle cx="12" cy="12" r="3" /> |
| <path d="M19.4 15a1.65 1.65 0 00.33 1.82l.06.06a2 2 0 11-2.83 2.83l-.06-.06a1.65 1.65 0 00-1.82-.33 1.65 1.65 0 00-1 1.51V21a2 2 0 11-4 0v-.09A1.65 1.65 0 008.6 19.4a1.65 1.65 0 00-1.82.33l-.06.06a2 2 0 11-2.83-2.83l.06-.06a1.65 1.65 0 00.33-1.82 1.65 1.65 0 00-1.51-1H3a2 2 0 110-4h.09A1.65 1.65 0 004.6 8.6a1.65 1.65 0 00-.33-1.82l-.06-.06a2 2 0 112.83-2.83l.06.06a1.65 1.65 0 001.82.33H9a1.65 1.65 0 001-1.51V3a2 2 0 114 0v.09a1.65 1.65 0 001 1.51 1.65 1.65 0 001.82-.33l.06-.06a2 2 0 112.83 2.83l-.06.06a1.65 1.65 0 00-.33 1.82V9a1.65 1.65 0 001.51 1H21a2 2 0 110 4h-.09a1.65 1.65 0 00-1.51 1z" /> |
| </symbol> |
| <symbol id="i-shield" viewBox="0 0 24 24"> |
| <path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z" /> |
| </symbol> |
| <symbol id="i-info" viewBox="0 0 24 24"> |
| <circle cx="12" cy="12" r="10" /><path d="M12 16v-4M12 8h.01" /> |
| </symbol> |
| <symbol id="i-image" viewBox="0 0 24 24"> |
| <rect x="3" y="3" width="18" height="18" rx="2" /> |
| <circle cx="8.5" cy="8.5" r="1.5" /><path d="M21 15l-5-5L5 21" /> |
| </symbol> |
| <symbol id="i-send" viewBox="0 0 24 24"><path d="M2 21l21-9L2 3v7l15 2-15 2v7z" /></symbol> |
| <symbol id="i-reply" viewBox="0 0 24 24"><path d="M9 17l-6-6 6-6M3 11h11a6 6 0 016 6v3" /></symbol> |
| <symbol id="i-pin" viewBox="0 0 24 24"> |
| <path d="M9 4h6l-1 6 4 3v2H6v-2l4-3-1-6zM12 15v5" /> |
| </symbol> |
| <symbol id="i-copy" viewBox="0 0 24 24"> |
| <rect x="9" y="9" width="13" height="13" rx="2" /> |
| <path d="M5 15H4a2 2 0 01-2-2V4a2 2 0 012-2h9a2 2 0 012 2v1" /> |
| </symbol> |
| <symbol id="i-trash" viewBox="0 0 24 24"> |
| <path d="M3 6h18M8 6V4a1 1 0 011-1h6a1 1 0 011 1v2M19 6l-1 14a2 2 0 01-2 2H8a2 2 0 01-2-2L5 6" /> |
| </symbol> |
| <symbol id="i-bell" viewBox="0 0 24 24"> |
| <path d="M18 8A6 6 0 006 8c0 7-3 9-3 9h18s-3-2-3-9M13.7 21a2 2 0 01-3.4 0" /> |
| </symbol> |
| <symbol id="i-logout" viewBox="0 0 24 24"> |
| <path d="M9 21H5a2 2 0 01-2-2V5a2 2 0 012-2h4M16 17l5-5-5-5M21 12H9" /> |
| </symbol> |
| <symbol id="i-users" viewBox="0 0 24 24"> |
| <path d="M17 21v-2a4 4 0 00-4-4H5a4 4 0 00-4 4v2" /> |
| <circle cx="9" cy="7" r="4" /><path d="M23 21v-2a4 4 0 00-3-3.87M16 3.13a4 4 0 010 7.75" /> |
| </symbol> |
| <symbol id="i-plus" viewBox="0 0 24 24"><path d="M12 5v14M5 12h14" /></symbol> |
| <symbol id="i-check" viewBox="0 0 24 24"><path d="M20 6L9 17l-5-5" /></symbol> |
| |
| <symbol id="i-check2" viewBox="0 0 30 24"> |
| <path d="M15 6L6.5 17 2 12" /> |
| <path d="M28 6l-11 11-2.2-2.4" /> |
| </symbol> |
| <symbol id="i-chat" viewBox="0 0 24 24"> |
| <path d="M21 11.5a8.38 8.38 0 01-.9 3.8 8.5 8.5 0 01-7.6 4.7 8.38 8.38 0 01-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 01-.9-3.8 8.5 8.5 0 014.7-7.6 8.38 8.38 0 013.8-.9h.5a8.48 8.48 0 018 8v.5z" /> |
| </symbol> |
| <symbol id="i-download" viewBox="0 0 24 24"> |
| <path d="M21 15v4a2 2 0 01-2 2H5a2 2 0 01-2-2v-4M7 10l5 5 5-5M12 15V3" /> |
| </symbol> |
| <symbol id="i-loader" viewBox="0 0 24 24"> |
| <path d="M21 12a9 9 0 11-6.2-8.6" /> |
| </symbol> |
| <symbol id="i-alert" viewBox="0 0 24 24"> |
| <circle cx="12" cy="12" r="10" /><path d="M12 8v4M12 16h.01" /> |
| </symbol> |
| <symbol id="i-key" viewBox="0 0 24 24"> |
| <path d="M21 2l-2 2m-7.6 7.6a5 5 0 11-7.1 7.1 5 5 0 017.1-7.1zm0 0L15.5 7.5m0 0l3 3L22 7l-3-3" /> |
| </symbol> |
| </svg> |
|
|
| <div id="app"> |
| |
| <section id="screen-auth" class="screen active"> |
| <div class="auth-inner"> |
| <div class="auth-mark"> |
| <img src="/static/icons/icon-192.png" alt="" /> |
| <h1>MSG Motoc</h1> |
| <p>Messagerie de groupe</p> |
| </div> |
| <div class="bolt-rule"></div> |
|
|
| <div class="auth-card"> |
| <div id="auth-error" class="form-error"></div> |
|
|
| |
| <div id="step-role" class="auth-step"> |
| <h2 class="auth-step-title">Vous êtes…</h2> |
| <p class="auth-step-sub">Choisissez votre profil pour continuer.</p> |
| <button class="role-card" data-role="admin"> |
| <svg><use href="#i-shield" /></svg> |
| <div> |
| <strong>Admin</strong> |
| <span>Groupes, membres, rôles et supervision</span> |
| </div> |
| </button> |
| <button class="role-card benevole" data-role="benevole"> |
| <svg><use href="#i-users" /></svg> |
| <div> |
| <strong>Bénévole</strong> |
| <span>Vos groupes et vos conversations</span> |
| </div> |
| </button> |
| </div> |
|
|
| |
| <div id="step-phone" class="auth-step" hidden> |
| <div id="role-pill-slot"></div> |
| <h2 class="auth-step-title">Votre numéro</h2> |
| <p class="auth-step-sub"> |
| Votre numéro de mobile est votre identifiant. Si vous n'avez jamais utilisé |
| l'application, vous créerez votre compte à l'étape suivante. |
| </p> |
| <div class="field"> |
| <label for="in-phone">Téléphone</label> |
| <input |
| id="in-phone" |
| class="input-phone" |
| type="tel" |
| inputmode="numeric" |
| autocomplete="tel" |
| placeholder="06 12 34 56 78" |
| maxlength="14" |
| /> |
| </div> |
| <button id="btn-phone" class="btn btn-primary">Continuer</button> |
| <button class="btn-link" data-back-to-role>Changer de profil</button> |
| </div> |
|
|
| |
| <div id="step-register" class="auth-step" hidden> |
| <h2 class="auth-step-title">Créer votre profil</h2> |
| <p class="auth-step-sub"> |
| Première connexion pour le <strong id="reg-phone"></strong>. |
| </p> |
| <p id="reg-newcomer" class="auth-note" hidden> |
| Votre numéro n'était pas encore connu : vous créez votre compte. Un administrateur |
| vous ajoutera ensuite à vos groupes — ils apparaîtront tout seuls. |
| </p> |
| <div class="field-row"> |
| <div class="field"> |
| <label for="in-first">Prénom</label> |
| <input id="in-first" type="text" autocomplete="given-name" maxlength="60" /> |
| </div> |
| <div class="field"> |
| <label for="in-last">Nom</label> |
| <input id="in-last" type="text" autocomplete="family-name" maxlength="60" /> |
| </div> |
| </div> |
| <div class="field"> |
| <label for="in-nick">Pseudo</label> |
| <input id="in-nick" type="text" maxlength="40" placeholder="Affiché dans les groupes" /> |
| <div class="hint">Laissez vide pour utiliser votre prénom.</div> |
| </div> |
| <div class="field"> |
| <label for="in-pin1">Code PIN (6 chiffres)</label> |
| <input |
| id="in-pin1" |
| class="input-pin" |
| type="password" |
| inputmode="numeric" |
| autocomplete="new-password" |
| maxlength="6" |
| /> |
| </div> |
| <div class="field"> |
| <label for="in-pin2">Confirmer le code PIN</label> |
| <input |
| id="in-pin2" |
| class="input-pin" |
| type="password" |
| inputmode="numeric" |
| autocomplete="new-password" |
| maxlength="6" |
| /> |
| <div class="hint">Il protège votre compte : ne le partagez pas.</div> |
| </div> |
| <button id="btn-register" class="btn btn-ember">Créer mon compte</button> |
| <button class="btn-link" data-back-to-phone>Changer de numéro</button> |
| <button class="btn-link" data-back-to-role>Changer de profil</button> |
| </div> |
|
|
| |
| <div id="step-login" class="auth-step" hidden> |
| <h2 class="auth-step-title">Bon retour</h2> |
| <p class="auth-step-sub"> |
| <strong id="login-name"></strong><br /><span id="login-phone"></span> |
| </p> |
| <div class="field"> |
| <label for="in-pin">Code PIN</label> |
| <input |
| id="in-pin" |
| class="input-pin" |
| type="password" |
| inputmode="numeric" |
| autocomplete="current-password" |
| maxlength="6" |
| /> |
| </div> |
| <button id="btn-login" class="btn btn-primary">Se connecter</button> |
| <button class="btn-link" data-open-help>Code oublié ou compte bloqué ?</button> |
| <button class="btn-link" data-back-to-phone>Changer de numéro</button> |
| <button class="btn-link" data-back-to-role>Changer de profil</button> |
| </div> |
|
|
| |
| <div id="step-help" class="auth-step" hidden> |
| <h2 class="auth-step-title">Contacter un administrateur</h2> |
| <p class="auth-step-sub"> |
| Votre demande part aux administrateurs de vos groupes. Ils pourront déverrouiller |
| votre compte ou réinitialiser votre code PIN. |
| </p> |
| <div class="field"> |
| <label for="in-help-reason">Motif</label> |
| <select id="in-help-reason"> |
| <option value="locked">Compte verrouillé après trop d'essais</option> |
| <option value="forgot_pin">J'ai oublié mon code PIN</option> |
| <option value="blocked">Mon compte est bloqué</option> |
| <option value="other">Autre</option> |
| </select> |
| </div> |
| <div class="field"> |
| <label for="in-help-msg">Message (facultatif)</label> |
| <textarea id="in-help-msg" rows="3" maxlength="400" placeholder="Précisez si besoin…"></textarea> |
| </div> |
| <button id="btn-help-send" class="btn btn-ember">Envoyer la demande</button> |
| <button class="btn-link" data-back-to-phone>Retour</button> |
| </div> |
| </div> |
| </div> |
| </section> |
|
|
| |
| <section id="screen-groups" class="screen"> |
| <header class="topbar"> |
| <div style="width: 8px"></div> |
| <h2> |
| MSG Motoc |
| <div class="sub" id="conn-state">Connexion…</div> |
| </h2> |
| <button class="icon-btn" id="btn-admin" hidden title="Administration"> |
| <svg><use href="#i-shield" /></svg> |
| </button> |
| <button class="icon-btn" id="btn-settings" title="Réglages"> |
| <svg><use href="#i-settings" /></svg> |
| </button> |
| </header> |
| <div class="search-wrap"> |
| <input id="in-search" type="search" placeholder="Rechercher un groupe…" /> |
| </div> |
| |
| |
| <div id="help-requests-inline" style="padding: 0 12px"></div> |
| <div class="list-body" id="groups-list"></div> |
| </section> |
|
|
| |
| |
| <div id="chat-placeholder"> |
| <svg><use href="#i-chat" /></svg> |
| <h3>Vos conversations</h3> |
| <p>Choisissez un groupe dans la liste pour l'ouvrir ici.</p> |
| </div> |
|
|
| |
| <section id="screen-chat" class="screen overlay"> |
| <header class="topbar"> |
| <button class="icon-btn" data-close-chat> |
| <svg><use href="#i-back" /></svg> |
| </button> |
| <h2> |
| <span id="chat-title">Groupe</span> |
| <div class="sub" id="chat-sub"></div> |
| </h2> |
| <button class="icon-btn" id="btn-group-info"> |
| <svg><use href="#i-info" /></svg> |
| </button> |
| </header> |
| <div class="pin-bar" id="pin-bar" hidden></div> |
| <div class="thread" id="thread"></div> |
| <div class="composer"> |
| <div class="typing-line" id="typing-line"></div> |
| <div class="reply-bar" id="reply-bar"> |
| <div><strong id="reply-author"></strong> <span id="reply-text"></span></div> |
| <button class="icon-btn" id="btn-cancel-reply" style="width: 30px; height: 30px"> |
| <svg viewBox="0 0 24 24" style="width: 16px; height: 16px"> |
| <path d="M18 6L6 18M6 6l12 12" /> |
| </svg> |
| </button> |
| </div> |
| <div class="composer-row"> |
| <button class="icon-btn" id="btn-image" title="Envoyer une photo (P2P)"> |
| <svg><use href="#i-image" /></svg> |
| </button> |
| <textarea |
| id="in-message" |
| rows="1" |
| placeholder="Message…" |
| enterkeyhint="send" |
| maxlength="4000" |
| ></textarea> |
| <button class="send-btn" id="btn-send" disabled> |
| <svg><use href="#i-send" /></svg> |
| </button> |
| </div> |
| </div> |
| <input type="file" id="file-image" accept="image/*" hidden /> |
| </section> |
|
|
| |
| <section id="screen-settings" class="screen overlay"> |
| <header class="topbar"> |
| <button class="icon-btn" data-close-overlay="screen-settings"> |
| <svg><use href="#i-back" /></svg> |
| </button> |
| <h2>Réglages</h2> |
| </header> |
| <div class="list-body" style="padding: 14px"> |
| <div class="panel-card"> |
| <h4>Profil</h4> |
| <div class="field-row"> |
| <div class="field"> |
| <label for="set-first">Prénom</label> |
| <input id="set-first" type="text" maxlength="60" /> |
| </div> |
| <div class="field"> |
| <label for="set-last">Nom</label> |
| <input id="set-last" type="text" maxlength="60" /> |
| </div> |
| </div> |
| <div class="field"> |
| <label for="set-nick">Pseudo</label> |
| <input id="set-nick" type="text" maxlength="40" /> |
| </div> |
| <div class="field"> |
| <label>Numéro (identifiant)</label> |
| <input id="set-phone" type="text" disabled /> |
| </div> |
| <button id="btn-save-profile" class="btn btn-primary btn-sm" style="width: 100%"> |
| Enregistrer |
| </button> |
| </div> |
|
|
| <div class="panel-card"> |
| <h4>Notifications</h4> |
| <div class="opt-row"> |
| <div> |
| <div class="label">Notifications système</div> |
| <div class="desc" id="push-desc">Recevoir les messages même application fermée.</div> |
| </div> |
| <button class="switch" id="sw-push" aria-label="Activer les notifications"></button> |
| </div> |
| <button id="btn-test-push" class="btn btn-ghost btn-sm" style="width: 100%; margin-top: 12px"> |
| Envoyer une notification test |
| </button> |
| </div> |
|
|
| <div class="panel-card"> |
| <h4>Sécurité</h4> |
| <div class="field"> |
| <label for="set-pin-old">Code PIN actuel</label> |
| <input id="set-pin-old" class="input-pin" type="password" inputmode="numeric" maxlength="6" /> |
| </div> |
| <div class="field"> |
| <label for="set-pin-new">Nouveau code PIN</label> |
| <input id="set-pin-new" class="input-pin" type="password" inputmode="numeric" maxlength="6" /> |
| </div> |
| <button id="btn-change-pin" class="btn btn-ghost btn-sm" style="width: 100%"> |
| Changer le code PIN |
| </button> |
| </div> |
|
|
| <button id="btn-logout" class="btn btn-danger" style="margin-top: 6px"> |
| Se déconnecter |
| </button> |
| <p style="text-align: center; color: var(--text-faint); font-size: 12px; margin-top: 18px"> |
| MSG MOTOC — les photos transitent directement entre appareils (P2P), jamais par le |
| serveur. |
| </p> |
| </div> |
| </section> |
|
|
| |
| <section id="screen-admin" class="screen overlay"> |
| <header class="topbar"> |
| <button class="icon-btn" data-close-overlay="screen-admin"> |
| <svg><use href="#i-back" /></svg> |
| </button> |
| <h2>Administration</h2> |
| </header> |
| <nav class="tabs"> |
| <button class="active" data-tab="tab-dash">Bord</button> |
| <button data-tab="tab-groups">Groupes</button> |
| <button data-tab="tab-users">Membres</button> |
| <button data-tab="tab-moderation"> |
| Modération <span class="tab-badge" id="moderation-badge" hidden>0</span> |
| </button> |
| <button data-tab="tab-system">Machine</button> |
| <button data-tab="tab-playground">Bac à sable</button> |
| <button data-tab="tab-stats">Système</button> |
| </nav> |
|
|
| |
| <div class="tab-panel active" id="tab-dash"> |
| <div id="help-requests-card"></div> |
|
|
| <div class="panel-card"> |
| <h4>Vue d'ensemble</h4> |
| <div class="kpi-grid" id="dash-kpis"></div> |
| </div> |
|
|
| <div class="panel-card"> |
| <div class="chart-head"> |
| <h4>Messages par jour</h4> |
| <span class="chart-note" id="daily-note"></span> |
| </div> |
| <div class="chart-scroll"><div id="chart-daily"></div></div> |
| </div> |
|
|
| <div class="panel-card"> |
| <div class="chart-head"> |
| <h4>Activité des dernières 24 h</h4> |
| <span class="chart-note" id="hourly-note"></span> |
| </div> |
| <div class="chart-scroll"><div id="chart-hourly"></div></div> |
| </div> |
|
|
| <div class="panel-card"> |
| <div class="chart-head"> |
| <h4>Groupes les plus actifs</h4> |
| <span class="chart-note">30 derniers jours</span> |
| </div> |
| <div id="chart-groups"></div> |
| </div> |
|
|
| <div class="panel-card"> |
| <div class="chart-head"> |
| <h4>Membres les plus actifs</h4> |
| <span class="chart-note">30 derniers jours</span> |
| </div> |
| <div id="chart-members"></div> |
| </div> |
|
|
| <div class="panel-card"> |
| <div class="chart-head"> |
| <h4>Journal d'audit</h4> |
| <button class="btn-link" id="btn-audit-all" style="width: auto; padding: 0"> |
| Tout voir |
| </button> |
| </div> |
| <div id="audit-list"></div> |
| </div> |
| </div> |
|
|
| <div class="tab-panel" id="tab-groups"> |
| <div class="panel-card"> |
| <h4>Nouveau groupe</h4> |
| <div class="field"> |
| <label for="ng-name">Nom</label> |
| <input id="ng-name" type="text" maxlength="80" placeholder="Ex. Bénévoles Scène 1" /> |
| </div> |
| <div class="field"> |
| <label for="ng-parent">Groupe parent</label> |
| <select id="ng-parent"> |
| <option value="">— Aucun (groupe principal) —</option> |
| </select> |
| <div class="hint">Choisir un parent crée un sous-groupe.</div> |
| </div> |
| <div class="field"> |
| <label for="ng-desc">Description</label> |
| <input id="ng-desc" type="text" maxlength="300" /> |
| </div> |
| <button id="btn-create-group" class="btn btn-ember btn-sm" style="width: 100%"> |
| Créer le groupe |
| </button> |
| </div> |
| <div class="panel-card"> |
| <h4>Groupes existants</h4> |
| <div id="admin-groups"></div> |
| </div> |
| </div> |
|
|
| <div class="tab-panel" id="tab-users"> |
| <div class="panel-card"> |
| <h4>Enregistrer des numéros</h4> |
| <div class="field"> |
| <label for="nu-phones">Numéros (un par ligne)</label> |
| <textarea |
| id="nu-phones" |
| rows="4" |
| placeholder="06 12 34 56 78 07 98 76 54 32" |
| ></textarea> |
| <div class="hint"> |
| Les personnes créeront elles-mêmes leur profil et leur code PIN. |
| </div> |
| </div> |
| <button id="btn-add-users" class="btn btn-ember btn-sm" style="width: 100%"> |
| Enregistrer |
| </button> |
| </div> |
|
|
| <div class="panel-card"> |
| <h4>Importer un fichier</h4> |
| <p class="panel-note"> |
| Excel (.xlsx) ou CSV. Les colonnes prénom, nom et téléphone sont retrouvées |
| automatiquement — vous pourrez vérifier avant d'importer. |
| </p> |
| <div class="field"> |
| <label for="in-import-group">Ajouter aussi à un groupe (facultatif)</label> |
| <select id="in-import-group"> |
| <option value="">Aucun groupe</option> |
| </select> |
| </div> |
| <input id="in-import-file" type="file" accept=".csv,.tsv,.txt,.xlsx,.xlsm" hidden /> |
| <button id="btn-pick-file" class="btn btn-ghost btn-sm" style="width: 100%"> |
| Choisir un fichier… |
| </button> |
| <div id="import-result" hidden></div> |
| </div> |
| <div class="panel-card"> |
| <h4>Annuaire</h4> |
| <div class="field"> |
| <input id="in-user-search" type="search" placeholder="Rechercher (nom, numéro)…" /> |
| </div> |
| <div id="admin-users"></div> |
| </div> |
| </div> |
|
|
| <div class="tab-panel" id="tab-stats"> |
| <div class="panel-card"> |
| <h4>Fréquentation</h4> |
| <div class="stat-grid" id="stat-grid"></div> |
| </div> |
| <div class="panel-card"> |
| <h4>Stockage</h4> |
| <div class="meter"><span id="storage-bar" style="width: 0%"></span></div> |
| <div id="storage-text" style="font-size: 13px; color: var(--text-dim)"></div> |
| <button id="btn-purge" class="btn btn-ghost btn-sm" style="width: 100%; margin-top: 14px"> |
| Lancer une purge maintenant |
| </button> |
| </div> |
| </div> |
|
|
| |
| <div class="tab-panel" id="tab-moderation"> |
| <div class="panel-card"> |
| <h4>Signalements</h4> |
| <p class="panel-note"> |
| Les messages surveillés sont <strong>livrés normalement</strong> — l'expéditeur voit |
| seulement une mention discrète. Un faux positif ne bloque jamais une consigne. |
| </p> |
| <div class="segmented" id="seg-moderation"> |
| <button data-status="pending" class="active">À traiter</button> |
| <button data-status="">Tout l'historique</button> |
| </div> |
| <div id="moderation-list"></div> |
| </div> |
| <div class="panel-card"> |
| <h4>Termes surveillés</h4> |
| <p class="panel-note"> |
| Un terme par ligne. Les accents, la casse, les espaces intercalaires |
| (« g r a t u i t »), les chiffres-substituts (« gr4tuit ») et les fautes de frappe |
| sont reconnus automatiquement. |
| </p> |
| <div id="terms-editor"></div> |
| <button id="btn-save-terms" class="btn btn-ember btn-sm" style="width: 100%"> |
| Enregistrer la liste |
| </button> |
| </div> |
| </div> |
|
|
| |
| <div class="tab-panel" id="tab-system"> |
| <div class="sys-live"> |
| <span class="sys-dot" id="sys-dot"></span> |
| <span id="sys-status">Mesure en cours…</span> |
| <button class="btn-link" id="btn-sys-toggle">Suspendre</button> |
| </div> |
| <div class="sys-grid" id="sys-grid"></div> |
| <div class="panel-card"> |
| <h4>Réseau</h4> |
| <div class="spark-row"> |
| <div class="spark-block"> |
| <div class="spark-label">Entrant <strong id="net-rx">—</strong></div> |
| <svg class="spark" id="spark-rx" viewBox="0 0 200 44" preserveAspectRatio="none"> |
| <polyline points="" /> |
| </svg> |
| </div> |
| <div class="spark-block"> |
| <div class="spark-label">Sortant <strong id="net-tx">—</strong></div> |
| <svg class="spark ember" id="spark-tx" viewBox="0 0 200 44" preserveAspectRatio="none"> |
| <polyline points="" /> |
| </svg> |
| </div> |
| </div> |
| </div> |
| <div class="panel-card"> |
| <h4>Processeur</h4> |
| <svg class="spark tall" id="spark-cpu" viewBox="0 0 200 70" preserveAspectRatio="none"> |
| <polyline points="" /> |
| </svg> |
| <div id="cpu-detail" class="sys-detail"></div> |
| </div> |
| </div> |
|
|
| |
| <div class="tab-panel" id="tab-playground"> |
| <div class="panel-card"> |
| <h4>Bac à sable</h4> |
| <p class="panel-note"> |
| Un festival fictif pour prendre l'application en main. Ces comptes |
| <strong>ne peuvent pas se connecter</strong> et n'apparaissent nulle part ailleurs : |
| ni dans l'annuaire, ni dans les statistiques, ni pour les bénévoles. |
| </p> |
| <div id="playground-groups"></div> |
| </div> |
| <div class="panel-card" id="playground-people-card"> |
| <h4>Comptes fictifs</h4> |
| <div id="playground-users"></div> |
| </div> |
| </div> |
| </section> |
| |
| <section id="screen-sandbox" class="screen overlay"> |
| <header class="topbar"> |
| <button class="icon-btn" data-close-overlay="screen-sandbox"> |
| <svg><use href="#i-back" /></svg> |
| </button> |
| <h2> |
| <span id="sandbox-title">Bac à sable</span> |
| <div class="sub" id="sandbox-sub"></div> |
| </h2> |
| <button class="icon-btn" id="btn-sandbox-menu" title="Options"> |
| <svg><use href="#i-info" /></svg> |
| </button> |
| </header> |
| <div class="sandbox-banner"> |
| Bac à sable — rien de ce qui est écrit ici n'est visible par les bénévoles. |
| </div> |
| <div class="thread" id="sandbox-thread"></div> |
| <div class="composer"> |
| <div class="field" style="margin: 0 0 8px"> |
| <label for="sandbox-as">Écrire en tant que</label> |
| <select id="sandbox-as"></select> |
| </div> |
| <div class="composer-row"> |
| <textarea id="sandbox-message" rows="1" placeholder="Message…" maxlength="4000"></textarea> |
| <button class="send-btn" id="btn-sandbox-send"> |
| <svg><use href="#i-send" /></svg> |
| </button> |
| </div> |
| </div> |
| </section> |
| </div> |
|
|
| |
| <div class="sheet-backdrop" id="sheet-backdrop"> |
| <div class="sheet" id="sheet"></div> |
| </div> |
|
|
| <div id="toasts"></div> |
|
|
| <script src="/static/app.js"></script> |
| </body> |
| </html> |
|
|