Compare commits

..
2 Commits
8 changed files with 408 additions and 10 deletions
BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 MiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 MiB

+12
View File
@@ -123,6 +123,18 @@ try {
exit; exit;
} }
// Comptage seul (?compte=1), ajouté le 2 septembre 2026 pour la
// pastille du classeur "Contacts" sur l'écran de fond (voir
// journal section 28) : le nombre de contacts actifs, sans
// charger la liste complète juste pour ça. Volontairement
// indépendant des filtres f_* (le classeur affiche le total réel
// de la table, pas le résultat d'une recherche en cours).
if (isset($_GET['compte'])) {
$total = (int)$pdo->query('SELECT COUNT(*) FROM ASP_Contacts WHERE CNT_Actif = 1')->fetchColumn();
echo json_encode(['total' => $total]);
exit;
}
$tri = $_GET['tri'] ?? 'CNT_Nom'; $tri = $_GET['tri'] ?? 'CNT_Nom';
if (!in_array($tri, COLONNES_TRI_AUTORISEES, true)) { if (!in_array($tri, COLONNES_TRI_AUTORISEES, true)) {
$tri = 'CNT_Nom'; $tri = 'CNT_Nom';
+263
View File
@@ -177,6 +177,47 @@
opaque (au lieu d'une transparence à 62%) à la demande de Jean-Marc — opaque (au lieu d'une transparence à 62%) à la demande de Jean-Marc —
reste plus sobre que les objets fonctionnels, mais plus affirmée reste plus sobre que les objets fonctionnels, mais plus affirmée
qu'avant. */ qu'avant. */
/* Pastille "nombre de contacts" sur le classeur Contacts (2 septembre
2026, essai). Idée de Jean-Marc : au fur et à mesure que chaque classeur
sera branché à sa table, afficher une petite pastille collée dessous le
trou cerclé de métal, avec un chiffre — pour donner une indication
immédiate du contenu sans avoir à ouvrir le classeur. Couleur de fond
mesurée sur ecran_fond.jpg (teinte réelle du classeur "Contacts",
rgb≈3,79,99, plus sombre en photo qu'à l'écran) puis assombrie d'un
facteur ~0.55 pour que le chiffre blanc ressorte sans jurer avec le
classeur — pas une couleur arbitraire. Liseré blanc autour de la
pastille (2 fichiers/gris clair, cohérent avec le liseré déjà utilisé
sur les étiquettes de tous les classeurs sur la photo) + légère ombre
portée pour la détacher visuellement, plutôt qu'un anneau de couleur :
Jean-Marc n'avait pas de préférence tranchée sur la couleur de l'anneau,
le blanc a été choisi pour rester cohérent avec l'habillage existant
(à changer facilement si Jean-Marc préfère une autre couleur après test
réel). pointer-events:none : la pastille est purement informative, le
clic doit continuer à passer à travers vers #classeur-contacts en
dessous (même logique que #micro-icone au-dessus de #micro-desk). Le
pattern (variables IMG, positionnement dans positionner(), chargement
via un endpoint réel) est pensé pour être répliqué sur les prochains
classeurs au fur et à mesure de leur branchement — voir commentaire de
PASTILLE_CONTACTS_* plus bas dans le script. Retouchée le même jour
après premier test réel de Jean-Marc ("trop présente, liseré trop
pétant") : diamètre réduit (22px de référence → 17px) et liseré blanc
assoupli (opacité .85→.4, épaisseur 2px→1.5px) pour rester une
indication discrète plutôt qu'un élément qui attire l'œil en premier. */
#pastille-contacts{
position:fixed;
border-radius:50%;
background:#022b36;
box-shadow:0 0 0 1.5px rgba(255,255,255,.4), 0 1px 2px rgba(0,0,0,.45);
display:flex;align-items:center;justify-content:center;
pointer-events:none;
user-select:none;
}
#pastille-contacts span{
color:#fff;
font-family:"Segoe UI","Arial",sans-serif;
font-weight:700;
line-height:1;
}
#version-desk{ #version-desk{
position:fixed; position:fixed;
color:#3a2712; color:#3a2712;
@@ -188,6 +229,65 @@
pointer-events:none; pointer-events:none;
user-select:none; user-select:none;
} }
/* Post-its de la ToDoList personnelle (2 septembre 2026, premier
affichage réel — voir journal section 28). Posés dans la zone décrite
par ZONE_POSTITS_* plus bas dans le script : une bande occupant 30% de
la largeur de l'écran depuis le bord droit, juste au-dessus du chevalet
— décision de Jean-Marc ("le vilain petit canard sera l'humain", donc
plus de place que chaque assistant, dont la ToDoList n'est pas encore
gérée — voir Réflexions stratégiques section 11 et le fil du 2-3
septembre). Grille à 4 colonnes × 5 lignes = 20 cases, volontairement
alignée sur CAPACITE_TABLEAU_PAR_UTILISATEUR (todolist.php) pour cette
première version — les deux devront évoluer ensemble si la capacité
change. Chaque post-it reçoit une légère rotation/décalage à
l'intérieur de sa propre case (jamais à cheval sur la case voisine,
donc jamais de chevauchement ce soir — Jean-Marc a autorisé le
chevauchement partiel mais a refusé l'empilement en tas ; rester dans
sa case est la façon la plus simple de garantir qu'on ne recrée jamais
ce tas). Décalage/rotation calculés de façon déterministe à partir de
TDL_Incr (voir hashDeterministe() dans le script) : la disposition ne
"saute" pas à chaque rechargement de l'écran.
Couleur jaune classique pour l'utilisateur (--postit-jaune) — les
couleurs par assistant restent à faire le jour où leur ToDoList sera
gérée (AGN_Couleur, voir Réflexions stratégiques section 11).
Punaise ronde en haut (photo confirmée comme du vrai liège par
Jean-Marc le 2 septembre) plutôt qu'un simple post-it posé — cohérent
avec la matière réelle du fond d'écran. Pastille d'urgence toujours
dans le coin haut-droit, jamais recouverte par du jitter (voir calcul
de bornes dans positionnerPostits()) : c'est le repère visuel ET la
garantie d'une zone de clic non ambiguë même si deux post-its finissent
visuellement proches. Pas de texte sur le post-it (choix explicite de
Jean-Marc) : le titre de la tâche n'apparaît qu'au survol (title natif),
le clic ne fait rien pour l'instant (voir journal — navigation vers
liste_todolist.html volontairement pas encore branchée). */
.postit{
position:fixed;
box-shadow:2px 4px 8px rgba(0,0,0,.35);
background:
linear-gradient(135deg, transparent 50%, rgba(0,0,0,.12) 50%, rgba(0,0,0,.12) 62%, transparent 62%) bottom right / 22% 22% no-repeat,
var(--couleur-postit, #fbe14a);
cursor:default;
}
.postit::before{
content:'';
position:absolute;
top:-9px; left:50%;
transform:translateX(-50%);
width:13%; height:13%;
min-width:8px; min-height:8px;
border-radius:50%;
background:radial-gradient(circle at 35% 30%, #fff8, transparent 40%), #8a3b12;
box-shadow:0 2px 3px rgba(0,0,0,.5);
}
.postit .pastille-urgence-postit{
position:absolute;
top:-15%; right:-15%;
width:32%; height:32%;
border-radius:50%;
box-shadow:0 0 0 2px rgba(255,255,255,.9), 0 1px 2px rgba(0,0,0,.4);
}
.postit .pastille-urgence-postit.rouge{ background:#c0392b; }
.postit .pastille-urgence-postit.orange{ background:#ff5a1f; }
</style> </style>
</head> </head>
<body> <body>
@@ -210,6 +310,7 @@
<rect class="barre" x="20" y="11" width="3.5" height="10" rx="1"/> <rect class="barre" x="20" y="11" width="3.5" height="10" rx="1"/>
</svg> </svg>
</div> </div>
<div id="pastille-contacts"><span id="pastille-contacts-nombre">…</span></div>
<div id="version-desk"></div> <div id="version-desk"></div>
<script> <script>
@@ -264,6 +365,45 @@
// calé pour se terminer avant, vers y=436. // calé pour se terminer avant, vers y=436.
const VERSION_X = 1012, VERSION_Y = 424; const VERSION_X = 1012, VERSION_Y = 424;
const VERSION_POLICE_FRAC = 11 / IMG_W; const VERSION_POLICE_FRAC = 11 / IMG_W;
// Pastille "nombre de contacts", sous le trou cerclé de métal du classeur
// Contacts. Trou mesuré sur ecran_fond.jpg : centre (58, 354), anneau
// métallique jusqu'à y≈365. Pastille centrée sur le même axe X que le
// trou (cohérence visuelle), posée juste en dessous, avant la fin du
// classeur (bas de la tranche à y=397, voir CLASSEUR_Y2). Diamètre réduit
// de 22 à 17 le 2 septembre 2026 (retour de Jean-Marc : "trop présente") —
// centre recalé à (58, 381) pour rester au milieu de l'espace disponible
// entre l'anneau et le bas du classeur avec la nouvelle taille.
const PASTILLE_CONTACTS_CENTRE_X = 58, PASTILLE_CONTACTS_CENTRE_Y = 381;
const PASTILLE_CONTACTS_DIAM_FRAC = 17 / IMG_W;
// Zone des post-its personnels (2 septembre 2026, premier affichage réel
// — voir commentaire CSS .postit ci-dessus pour le détail des décisions).
// 30% de la largeur de l'écran depuis le bord droit (1024 × 0.30 ≈ 307),
// du haut de l'image jusqu'à juste au-dessus du chevalet (CHEVALET_Y1 =
// 362, marge de 10px). Grille 4 colonnes × 5 lignes = 20 cases, alignée
// sur CAPACITE_TABLEAU_PAR_UTILISATEUR (todolist.php) — à faire évoluer
// ensemble le jour où cette capacité changera.
const ZONE_POSTITS_X1 = 717, ZONE_POSTITS_X2 = 1024;
const ZONE_POSTITS_Y1 = 6, ZONE_POSTITS_Y2 = 352;
const GRILLE_POSTITS_COLONNES = 4, GRILLE_POSTITS_LIGNES = 5;
// Taille d'un post-it : ~60% de la plus petite dimension de case, pour
// laisser de la marge au jitter sans jamais déborder sur la case voisine
// (voir positionnerPostits()).
const POSTIT_RATIO_CASE = 0.6;
/**
* Petit générateur pseudo-aléatoire déterministe (0..1), à partir d'un
* entier (TDL_Incr) — pour que le jitter (rotation/décalage) d'un post-it
* donné reste toujours le même d'un rechargement à l'autre de l'écran,
* plutôt que de "sauter" à chaque fois (mulberry32, implémentation
* minimale, largement suffisante ici — pas besoin de qualité crypto).
*/
function pseudoAleatoire(graine) {
let t = (graine + 0x6D2B79F5) | 0;
t = Math.imul(t ^ (t >>> 15), t | 1);
t ^= t + Math.imul(t ^ (t >>> 7), t | 61);
return ((t ^ (t >>> 14)) >>> 0) / 4294967296;
}
function positionner() { function positionner() {
const vw = window.innerWidth, vh = window.innerHeight; const vw = window.innerWidth, vh = window.innerHeight;
@@ -313,6 +453,49 @@
versionDesk.style.width = '200px'; versionDesk.style.width = '200px';
versionDesk.style.top = (offY + (VERSION_Y / IMG_H) * dispH) + 'px'; versionDesk.style.top = (offY + (VERSION_Y / IMG_H) * dispH) + 'px';
versionDesk.style.fontSize = (VERSION_POLICE_FRAC * dispW) + 'px'; versionDesk.style.fontSize = (VERSION_POLICE_FRAC * dispW) + 'px';
const pastilleContacts = document.getElementById('pastille-contacts');
const pastilleDiam = PASTILLE_CONTACTS_DIAM_FRAC * dispW;
pastilleContacts.style.left = (offX + (PASTILLE_CONTACTS_CENTRE_X / IMG_W) * dispW - pastilleDiam / 2) + 'px';
pastilleContacts.style.top = (offY + (PASTILLE_CONTACTS_CENTRE_Y / IMG_H) * dispH - pastilleDiam / 2) + 'px';
pastilleContacts.style.width = pastilleDiam + 'px';
pastilleContacts.style.height = pastilleDiam + 'px';
// Taille de police proportionnelle au diamètre, réduite si le nombre a
// 3 chiffres ou plus pour continuer à tenir dans le rond sans déborder.
const nbChiffres = document.getElementById('pastille-contacts-nombre').textContent.length;
const facteurPolice = nbChiffres >= 4 ? 0.34 : (nbChiffres === 3 ? 0.42 : 0.52);
document.getElementById('pastille-contacts-nombre').style.fontSize = (pastilleDiam * facteurPolice) + 'px';
// Post-its personnels : chaque .postit porte sa case (data-colonne/
// data-ligne, attribuées au chargement — voir creerPostits()) et une
// graine (data-graine = TDL_Incr) pour un jitter stable d'un
// rechargement à l'autre. Le jitter reste borné à l'intérieur de la
// case (marge × 0.8, jamais 1) pour ne jamais déborder sur la case
// voisine — c'est ce qui garantit l'absence d'empilement.
const zoneW = ((ZONE_POSTITS_X2 - ZONE_POSTITS_X1) / IMG_W) * dispW;
const zoneH = ((ZONE_POSTITS_Y2 - ZONE_POSTITS_Y1) / IMG_H) * dispH;
const caseW = zoneW / GRILLE_POSTITS_COLONNES;
const caseH = zoneH / GRILLE_POSTITS_LIGNES;
const postitTaille = Math.min(caseW, caseH) * POSTIT_RATIO_CASE;
const zoneLeft = offX + (ZONE_POSTITS_X1 / IMG_W) * dispW;
const zoneTop = offY + (ZONE_POSTITS_Y1 / IMG_H) * dispH;
const margeX = (caseW - postitTaille) / 2 * 0.8;
const margeY = (caseH - postitTaille) / 2 * 0.8;
document.querySelectorAll('.postit').forEach(function (postit) {
const col = Number(postit.dataset.colonne);
const ligne = Number(postit.dataset.ligne);
const graine = Number(postit.dataset.graine);
const caseLeft = zoneLeft + col * caseW;
const caseTop = zoneTop + ligne * caseH;
const decalageX = (pseudoAleatoire(graine) * 2 - 1) * margeX;
const decalageY = (pseudoAleatoire(graine + 1) * 2 - 1) * margeY;
const rotation = (pseudoAleatoire(graine + 2) * 2 - 1) * 7; // ±7°
postit.style.width = postitTaille + 'px';
postit.style.height = postitTaille + 'px';
postit.style.left = (caseLeft + (caseW - postitTaille) / 2 + decalageX) + 'px';
postit.style.top = (caseTop + (caseH - postitTaille) / 2 + decalageY) + 'px';
postit.style.transform = 'rotate(' + rotation.toFixed(1) + 'deg)';
});
} }
window.addEventListener('resize', positionner); window.addEventListener('resize', positionner);
positionner(); positionner();
@@ -381,6 +564,86 @@
} }
chargerVersionDesk(); chargerVersionDesk();
// Pastille "nombre de contacts" du classeur Contacts : total réel de la
// table (contacts.php?compte=1, voir journal section 28 et commentaire
// ajouté dans contacts.php), jamais un chiffre figé. Repli visuel "—" en
// cas d'échec (même logique que chargerIdentiteChevalet), pour ne jamais
// laisser une pastille vide sans explication. Le pattern (constantes
// PASTILLE_*, positionnement dans positionner(), chargement ici) est
// pensé pour être dupliqué sur les prochains classeurs à mesure qu'ils
// seront branchés à leur table.
async function chargerCompteContacts() {
const elNombre = document.getElementById('pastille-contacts-nombre');
try {
const reponse = await fetch('contacts.php?compte=1');
if (!reponse.ok) throw new Error('HTTP ' + reponse.status);
const data = await reponse.json();
elNombre.textContent = (typeof data.total === 'number') ? String(data.total) : '—';
} catch (erreur) {
console.error('Erreur de chargement de contacts.php?compte=1 (pastille classeur) :', erreur);
elNombre.textContent = '—';
}
positionner(); // recalcule la taille de police selon le nombre réel de chiffres
}
chargerCompteContacts();
// Post-its personnels (2 septembre 2026, premier affichage réel — voir
// commentaire CSS .postit et constantes ZONE_POSTITS_*/GRILLE_POSTITS_*
// plus haut). Source : todolist.php (déjà utilisé par liste_todolist.html,
// voir journal section 26), filtré ici côté client sur l'utilisateur
// connecté (TDL_ToDoUser) et sur les tâches non réalisées (TDL_RealDate
// vide) — l'endpoint reste volontairement non filtré par utilisateur
// (voir son commentaire d'en-tête), donc le tri "c'est MES post-its" se
// fait ici. L'API renvoie déjà les tâches triées par urgence (rouge avant
// orange avant vert, voir calculerGroupe()) : cet ordre est conservé pour
// remplir la grille case par case, donc les plus urgentes arrivent
// toujours en premier (en haut à gauche de la zone). Une tâche déjà
// réalisée ne crée jamais de post-it : elle libère sa place sur le
// tableau dès qu'elle est marquée faite (voir aussi CAPACITE_TABLEAU_
// PAR_UTILISATEUR dans todolist.php — même logique des deux côtés).
// Coupé à la capacité de la grille par sécurité (ne devrait normalement
// jamais arriver, la capacité étant déjà appliquée à la création côté
// todolist.php).
async function chargerMesPostits() {
try {
const [reponsePrefs, reponseTaches] = await Promise.all([
fetch('preferences.php'),
fetch('todolist.php'),
]);
if (!reponsePrefs.ok) throw new Error('HTTP ' + reponsePrefs.status + ' (preferences.php)');
if (!reponseTaches.ok) throw new Error('HTTP ' + reponseTaches.status + ' (todolist.php)');
const prefs = await reponsePrefs.json();
const dataTaches = await reponseTaches.json();
const capacite = GRILLE_POSTITS_COLONNES * GRILLE_POSTITS_LIGNES;
const mesTaches = (dataTaches.taches || [])
.filter(t => t.TDL_ToDoUser === prefs.USR_Code && !t.TDL_RealDate)
.slice(0, capacite);
mesTaches.forEach((tache, index) => {
const postit = document.createElement('div');
postit.className = 'postit';
postit.style.setProperty('--couleur-postit', '#fbe14a'); // jaune classique, toujours pour l'humain
postit.title = tache.TDL_ToDoTxt || '';
postit.dataset.colonne = index % GRILLE_POSTITS_COLONNES;
postit.dataset.ligne = Math.floor(index / GRILLE_POSTITS_COLONNES);
postit.dataset.graine = tache.TDL_Incr;
const pastille = document.createElement('div');
// TDL_Groupe 0 = rouge, 1 = orange (le vert n'atteint jamais cet
// écran, voir filtre ci-dessus sur TDL_RealDate).
pastille.className = 'pastille-urgence-postit ' + (tache.TDL_Groupe === 0 ? 'rouge' : 'orange');
postit.appendChild(pastille);
document.body.appendChild(postit);
});
positionner(); // place les post-its qui viennent d'être créés
} catch (erreur) {
console.error('Erreur de chargement des post-its personnels (todolist.php/preferences.php) :', erreur);
}
}
chargerMesPostits();
// Lien visible "→ Liste des tâches" retiré le 2 septembre 2026 à la // Lien visible "→ Liste des tâches" retiré le 2 septembre 2026 à la
// demande de Jean-Marc. Échap conservé comme échappatoire silencieuse // demande de Jean-Marc. Échap conservé comme échappatoire silencieuse
// (même logique que le reste de l'appli), pour ne pas rester bloqué sur // (même logique que le reste de l'appli), pour ne pas rester bloqué sur
+28 -4
View File
@@ -12,6 +12,8 @@ Pour les trois documents de ce projet (ce journal — résumé/index —, les R
**Précision du 2 septembre 2026 (fin de session) sur les exports SQL transmis par Jean-Marc :** un `CREATE TABLE`/`INSERT` envoyé par Jean-Marc est le compte-rendu d'une modification déjà faite à la main côté base (il travaille en éditant directement, puis exporte pour informer Claude) — jamais une commande à exécuter côté Claude. Claude peut donc lire ces exports comme l'état réel de la base au moment de l'envoi, sans jamais chercher à les "lancer". **Précision du 2 septembre 2026 (fin de session) sur les exports SQL transmis par Jean-Marc :** un `CREATE TABLE`/`INSERT` envoyé par Jean-Marc est le compte-rendu d'une modification déjà faite à la main côté base (il travaille en éditant directement, puis exporte pour informer Claude) — jamais une commande à exécuter côté Claude. Claude peut donc lire ces exports comme l'état réel de la base au moment de l'envoi, sans jamais chercher à les "lancer".
**Précision du 2 septembre 2026 (soir) sur la continuité entre fenêtres de conversation :** chaque nouvelle fenêtre de conversation démarre un environnement cloud entièrement neuf, sans mémoire du fil précédent ni accès aux fichiers de travail locaux de la session précédente (ex. le clonage temporaire du dépôt GitHub fait dans `/tmp` pour éditer du code) — seuls les documents de ce projet (ce journal, les Réflexions stratégiques, la Documentation utilisateur) traversent d'une fenêtre à l'autre. C'est pour cette raison que la consigne ci-dessus (mise à jour en fin de session, pas au fil de l'eau) compte particulièrement : c'est le seul filet de continuité entre deux sessions. Point déjà noté dans les Réflexions stratégiques, section 2. Un résumé automatique de conversation trop longue (fait par Claude Code en cours de fil, différent d'un changement de fenêtre) est en revanche censé préserver les faits essentiels de la session en cours — dans les faits, une erreur de mesure de pixels a bien eu lieu le 2 septembre après un tel résumé, mais elle provenait d'une méthode de mesure imprécise, pas d'une perte d'information liée au résumé lui-même (voir section 28, le centrage de l'étiquette "Contacts").
## Sommaire des sections (`/journal` sur GitHub) ## Sommaire des sections (`/journal` sur GitHub)
- 00. Présentation - 00. Présentation
@@ -44,9 +46,9 @@ Pour les trois documents de ce projet (ce journal — résumé/index —, les R
- 27. Pilotage vocal - 27. Pilotage vocal
- 28. Écran de fond - 28. Écran de fond
*(Numérotation et titres repris du découpage fait par Jean-Marc le 31 août 2026, légèrement reformulés par lui à cette occasion — se référer aux fichiers eux-mêmes pour le libellé exact. Section 27 (Pilotage vocal) validée de bout en bout et son fichier définitif déposé dans `/journal` le 2 septembre 2026 — le nom "(Lilou)" porté un temps par cette section a été abandonné le même jour, l'assistante n'étant plus qu'un des agents disponibles parmi d'autres, voir Statut actuel ci-dessous. Section 28 (Écran de fond) ouverte le 2 septembre 2026 mais **non validée** — maquette graphique exploratoire en pause, voir Statut actuel.)* *(Numérotation et titres repris du découpage fait par Jean-Marc le 31 août 2026, légèrement reformulés par lui à cette occasion — se référer aux fichiers eux-mêmes pour le libellé exact. Section 27 (Pilotage vocal) validée de bout en bout et son fichier définitif déposé dans `/journal` le 2 septembre 2026. Section 28 (Écran de fond) ouverte le 2 septembre 2026, toujours **en cours** — passée d'une maquette graphique exploratoire à un premier essai fonctionnel réel, puis (soirée du 2 au 3 septembre) à une pastille de comptage sur le classeur Contacts et à un premier affichage réel des post-its personnels sur le tableau de liège ; fichier de section mis à jour à déposer par Jean-Marc, voir Statut actuel.)*
## Statut actuel (2 septembre 2026) ## Statut actuel (2-3 septembre 2026)
**Écrans "Identification" et "Liste des contacts"** (avec panneau détail intégré) : aboutis depuis le 25 août 2026, testés en production. **Prospection** (formulaire externe, vérification mail, envoi de doc) : livrée et testée en conditions réelles le 26 août 2026 (section 18). **Dépôt Git** en place depuis le 27-28 août (section 20), avec circuit de livraison FileZilla → SSH VPS → `git push` (section 23) — l'écriture directe par Claude reste bloquée côté proxy Anthropic, contournement adopté sans gêne. **MIRADOR** (authentification centralisée multi-bases, identifiant = email) branché et validé à deux utilisateurs le 30 août 2026, déployé sur `aspic.mvl-tls.fr` (développement) et `crm.aspic.bzh` (test), chacun avec son propre environnement Docker (sections 21, 24, 25). **Écrans "Identification" et "Liste des contacts"** (avec panneau détail intégré) : aboutis depuis le 25 août 2026, testés en production. **Prospection** (formulaire externe, vérification mail, envoi de doc) : livrée et testée en conditions réelles le 26 août 2026 (section 18). **Dépôt Git** en place depuis le 27-28 août (section 20), avec circuit de livraison FileZilla → SSH VPS → `git push` (section 23) — l'écriture directe par Claude reste bloquée côté proxy Anthropic, contournement adopté sans gêne. **MIRADOR** (authentification centralisée multi-bases, identifiant = email) branché et validé à deux utilisateurs le 30 août 2026, déployé sur `aspic.mvl-tls.fr` (développement) et `crm.aspic.bzh` (test), chacun avec son propre environnement Docker (sections 21, 24, 25).
@@ -58,11 +60,33 @@ Pour les trois documents de ce projet (ce journal — résumé/index —, les R
Le système, initialement à agent unique ("Lilou"), a été généralisé le 2 septembre à plusieurs assistants IA nommés (table `ASP_Agents`, endpoint `agents.php`, `lilou_notes.php` renommé `agent_notes.php`) — chaque agent portant ses propres graphies alternatives tolérées (`AGN_Variantes`, pilotable en base sans code) et un agent par défaut (`AGN_Defaut`) pour ne plus jamais figer un nom précis dans le code. Un incident de confidentialité (bribes d'un appel téléphonique captées par un traçage de débogage resté actif) a conduit au retrait immédiat de ce traçage et à l'ajout d'une coupure automatique du micro après quelques minutes d'inactivité. Après plusieurs essais réels montrant des confusions de reconnaissance récurrentes, Jean-Marc a retiré deux agents (Lilou, Karl) plutôt que d'empiler des tolérances risquant de créer de faux déclenchements ou de mal vieillir face à la diversité des accents/prononciations — liste active : Viktor, Matilda (par défaut), Léon, Nikita. Version incrémentée une fois pour cette session, **V1.006**. Le système, initialement à agent unique ("Lilou"), a été généralisé le 2 septembre à plusieurs assistants IA nommés (table `ASP_Agents`, endpoint `agents.php`, `lilou_notes.php` renommé `agent_notes.php`) — chaque agent portant ses propres graphies alternatives tolérées (`AGN_Variantes`, pilotable en base sans code) et un agent par défaut (`AGN_Defaut`) pour ne plus jamais figer un nom précis dans le code. Un incident de confidentialité (bribes d'un appel téléphonique captées par un traçage de débogage resté actif) a conduit au retrait immédiat de ce traçage et à l'ajout d'une coupure automatique du micro après quelques minutes d'inactivité. Après plusieurs essais réels montrant des confusions de reconnaissance récurrentes, Jean-Marc a retiré deux agents (Lilou, Karl) plutôt que d'empiler des tolérances risquant de créer de faux déclenchements ou de mal vieillir face à la diversité des accents/prononciations — liste active : Viktor, Matilda (par défaut), Léon, Nikita. Version incrémentée une fois pour cette session, **V1.006**.
**2 septembre 2026 (suite) : écran de fond — nouvel écran d'accueil "bureau à l'ancienne" (maquette graphique uniquement, pas de code).** Détail complet en section 28 du journal (`/journal` sur GitHub, fichier à déposer par Jean-Marc). Résumé : dans le prolongement de la réflexion "bureau à l'ancienne" (Réflexions stratégiques, section 11), Jean-Marc a engagé la conception visuelle du futur écran d'accueil d'ASPIC, appelé à remplacer la ToDoList/liste des contacts comme premier écran après connexion. Composition retenue à ce stade : un tableau en liège en arrière-plan avec un post-it par agent IA nommé (Viktor, Matilda, Léon, Nikita — couleur destinée à correspondre au futur champ couleur que Jean-Marc ajoute à `ASP_Agents` en parallèle), et un bureau au premier plan portant les objets/raccourcis fonctionnels : boîte à archives, enveloppes (logo Gmail), agenda (logo Google Agenda), téléphone portable écran éteint (explicitement **sans écran d'ordinateur représenté**), un micro physique avec voyant d'activité pulsé (pour matérialiser le pilotage vocal déjà fonctionnel), et une rangée de classeurs à levier (trou de préhension, pochette d'étiquette) portant les grandes sections de l'application — "Contacts", "Catalogue", "Affaires en cours" et un 4ᵉ "À faire" proposé par Claude à confirmer. Plusieurs itérations réalisées avec l'outil de canevas de design de Claude (maquette éditable, publiée en Artifact privé) à partir de croquis papier et de photos de référence fournis par Jean-Marc. **Mis en pause à la demande de Jean-Marc** : les allers-retours par description ont montré leurs limites pour ce type de rendu graphique — il va faire réaliser une meilleure représentation visuelle par une connaissance, à apporter dans une prochaine session pour reprendre le travail à partir de ce nouveau support. Aucun impact sur l'écran d'accueil actuellement en production. **2 septembre 2026 (suite) : écran de fond — d'une maquette graphique à un premier essai fonctionnel (V1.007).** Dans le prolongement de la réflexion "bureau à l'ancienne" (Réflexions stratégiques, section 11), Jean-Marc a d'abord engagé une maquette graphique (tableau en liège, post-it par agent IA, outil Claude Design) — non tranchée, jamais codée. En reprise de session le même jour, changement de cap : plutôt qu'une maquette stylisée, un premier **essai fonctionnel réel** ("c'est juste un test"), bâti sur une photo de scène de bureau fournie et recadrée par Jean-Marc lui-même (`ecran_fond.jpg`, 1024×457), affichée en plein écran juste après l'identification (`background-size:contain`). Un système de coordonnées calé sur l'image de référence (converties en position réelle par une fonction `positionner()`) permet de superposer des éléments interactifs précisément sur les objets photographiés. Livré dans ce premier essai : classeur "Contacts" cliquable, étiquette tournée, chevalet avec le prénom réel de l'utilisateur (`USR_Prenom`), micro cliquable en test d'affichage seul, numéro de version affiché. Version **V1.007**.
**2-3 septembre 2026 (nuit) : pastille du classeur, conception et premier affichage réel du tableau de post-its (V1.008).** Session enchaînée sur la même soirée, au départ pour une petite correction avant d'ouvrir le vrai chantier du tableau de liège.
*Pastille de comptage sur le classeur Contacts.* À la demande de Jean-Marc, une pastille ronde affiche désormais, sous le trou cerclé de métal du classeur "Contacts", le nombre réel de contacts actifs de la table (nouveau paramètre `contacts.php?compte=1`, comptage seul sans charger la liste complète). Couleur de fond calculée par assombrissement (×0,55) de la teinte réelle du classeur mesurée sur la photo, chiffre blanc gras, liseré blanc. Réduite en taille et le liseré adouci après premier retour de Jean-Marc sur son écran ("trop présente") — diamètre 22→17px (référentiel image), liseré 2px/85%→1,5px/40% d'opacité.
*Conception du tableau de liège (vision actée, partiellement codée).* Reprise du principe "bureau à l'ancienne" : le mur de la photo est confirmé être du **vrai liège** (texture visible au zoom, pas une couleur unie) — ça a orienté le choix graphique des post-its vers une punaise ronde en haut, cohérente avec la matière réelle. Principe de répartition de l'écran retenu : 70% de la largeur pour les assistants IA (Viktor, Matilda, Léon, Nikita), 30% fixe pour Jean-Marc lui-même — logique assumée : les assistants traitent vite (peu de post-its en attente à tout instant), l'humain accumule davantage avant de traiter, donc plus de place. Règles actées pour la part "assistants" (**non codées ce soir**, la ToDoList des assistants n'existant pas encore réellement) : part de chacun = (ses tâches en attente ÷ total tâches en attente tous assistants) × 70% ; l'assistant par défaut (Matilda) toujours le plus à gauche s'il a des tâches, puis les autres classés par charge décroissante ; un assistant sans tâche en attente disparaît entièrement du tableau (pas de colonne vide) ; couleur de post-it personnalisée par assistant (`AGN_Couleur`, à faire). Jean-Marc a fait remarquer, et Claude a vérifié dans le code, que la gestion de tâches par assistant n'est pas une nouvelle architecture à inventer : `TDL_ToDoUser`/`TDL_RealUser` dans `ASP_ToDoList` sont déjà des champs génériques non restreints à un humain (le commentaire d'en-tête de `todolist.php` anticipait déjà qu'un agent IA puisse assigner une tâche à un autre utilisateur) — il suffira d'ajouter un discriminant humain/agent le jour venu. Les écrans de gestion actuels (`liste_todolist.html`, `todolist.php`) sont conservés tels quels et **pas encore reliés à la navigation** depuis l'écran de fond (clic sur un post-it actuellement sans effet).
Nouveau besoin identifié en cours de réflexion, non traité ce soir : un écran "journalier" traçant ce qui a été réalisé par chacun (humain + assistants) — repéré comme déjà largement couvert par les champs existants `TDL_RealDate`/`TDL_RealUser`/`TDL_RealText` de `ASP_ToDoList` (une tâche marquée faite porte déjà qui, quand, avec quel commentaire), donc pas besoin a priori d'une nouvelle table pour un premier jet, seulement d'un écran de consultation à construire un jour.
*Capacité du tableau — refus explicite d'un ascenseur.* Jean-Marc a explicitement écarté toute idée de défilement/ascenseur sur le tableau ("ça casserait la logique du vrai bureau, et surtout m'inciterait à cumuler les post-its") au profit d'une capacité finie avec message de blocage. Ajout dans `todolist.php` : constante `CAPACITE_TABLEAU_PAR_UTILISATEUR = 20` (valeur provisoire, posée avant d'avoir les vrais pixels, à faire évoluer) et vérification à la création (POST) — au-delà de la capacité, refus (HTTP 409) avec le message exact demandé par Jean-Marc : *"Ton tableau est plein, tu ne peux plus ajouter de post-it !"*. Une tâche créée déjà réalisée n'est jamais bloquée (elle n'occupe pas de post-it). Posée dans `todolist.php` plutôt que côté écran, donc valable aussi le jour où la voix créera des tâches directement.
*Premier affichage réel des post-its personnels.* Dans `ecran_fond.html` : zone occupant 30% de la largeur depuis le bord droit de l'écran, du haut de l'image jusqu'à juste au-dessus du chevalet, avec une grille de 4 colonnes × 5 lignes = 20 cases — volontairement alignée sur `CAPACITE_TABLEAU_PAR_UTILISATEUR`. Données réelles de `todolist.php`, filtrées côté client sur l'utilisateur connecté (`TDL_ToDoUser`) et sur les tâches non réalisées (une tâche marquée faite libère sa place immédiatement). Chaque post-it reste dans sa propre case (léger jitter de rotation/décalage calculé de façon déterministe à partir de `TDL_Incr`, donc stable d'un rechargement à l'autre) — Jean-Marc a autorisé un chevauchement partiel entre post-its mais a explicitement refusé tout empilement en tas (illisible, imprécis au clic) ; rester dans sa case garantit qu'on ne recrée jamais ce cas. Punaise ronde, pastille d'urgence rouge/orange bien visible en coin haut-droit (jamais verte : le vert quitte le tableau dès qu'une tâche est réalisée), infobulle au survol avec le texte de la tâche, pas de texte visible sur le post-it lui-même, clic sans effet pour l'instant. Testé avec des données simulées (9 puis 23 tâches, plusieurs groupes d'urgence, tâches d'un autre utilisateur et déjà réalisées pour vérifier le filtrage) — rendu confirmé conforme par Jean-Marc sur image de synthèse avant dépôt.
Point relevé par Jean-Marc en toute fin de session, à traiter plus tard : les règles actuelles de calcul des pastilles rouge/orange/vert (`calculerGroupe()` dans `todolist.php`) risquent de donner un tableau surchargé de rouge/orange puisque le vert disparaît désormais immédiatement du tableau — à revoir, non traité ce soir.
Version incrémentée une seule fois pour l'ensemble de cette session (pastille classeur + capacité tableau + affichage post-its), conformément à la règle d'une incrémentation par session : **V1.008**.
**Reste à faire, noté au passage :** **Reste à faire, noté au passage :**
- Vérifier concrètement que le `.htaccess` du dossier `/journal` bloque bien l'accès direct (`curl -I` sur un fichier du dossier doit répondre `403`, pas `200` — point en suspens depuis le 31 août). - Vérifier concrètement que le `.htaccess` du dossier `/journal` bloque bien l'accès direct (`curl -I` sur un fichier du dossier doit répondre `403`, pas `200` — point en suspens depuis le 31 août).
- Pilotage vocal, étape 2 : définir les règles d'interprétation du contenu dicté (aujourd'hui stocké tel quel), envisagée via n8n avec des règles modifiables par l'utilisateur. - Pilotage vocal, étape 2 : définir les règles d'interprétation du contenu dicté (aujourd'hui stocké tel quel), envisagée via n8n avec des règles modifiables par l'utilisateur.
- Continuer à observer les agents actifs (Viktor, Matilda, Léon, Nikita) en usage réel ; ajuster `AGN_Variantes` en base si de nouvelles confusions apparaissent. - Continuer à observer les agents actifs (Viktor, Matilda, Léon, Nikita) en usage réel ; ajuster `AGN_Variantes` en base si de nouvelles confusions apparaissent.
- Documentation utilisateur du pilotage vocal : pas encore rédigée, fonctionnalité encore en phase d'essais techniques. - Documentation utilisateur du pilotage vocal : pas encore rédigée, fonctionnalité encore en phase d'essais techniques.
- Écran de fond (nouvel écran d'accueil "bureau à l'ancienne") : maquette en pause, en attente d'une meilleure représentation visuelle fournie par une connaissance de Jean-Marc — reprendre à partir de ce nouveau support dans une prochaine session (voir section 28). - Écran de fond : revoir un jour le sujet de la "tranche du bureau" non visible chez Jean-Marc ; décider si les autres objets photographiés (carnet, téléphone) doivent devenir cliquables ; brancher le micro du bureau sur la reconnaissance vocale réelle ; trancher un jour le sort de la piste "maquette liège + post-its par agent" (Claude Design, mise de côté pour cet essai, pas explicitement abandonnée).
- Tableau de liège : coder la répartition dynamique des 70% entre assistants par charge de tâches (formule actée, voir Statut actuel) — bloqué tant que la ToDoList des assistants n'existe pas réellement.
- Étendre `ASP_ToDoList`/`todolist.php` pour qu'un assistant puisse être attributaire d'une tâche (discriminant humain/agent à définir) — préalable à la répartition dynamique et aux couleurs de post-it par assistant (`AGN_Couleur`, à ajouter).
- Écran "journalier" (trace des réalisations, humain + assistants) — donnée déjà quasi disponible (`TDL_RealDate`/`TDL_RealUser`/`TDL_RealText`), écran de consultation à construire.
- Revoir les règles de calcul des pastilles rouge/orange/vert (`calculerGroupe()`) pour éviter un tableau trop chargé en rouge/orange maintenant que le vert quitte le tableau immédiatement.
- Décider du comportement du clic sur un post-it (aujourd'hui inerte) : ouvrir `liste_todolist.html` sur la tâche précise, ou afficher un détail directement sur l'écran de fond.
- Capacité du tableau (20) et taille de la grille (4×5) dans `ecran_fond.html`/`todolist.php` sont des valeurs provisoires posées avant d'avoir les vrais pixels de la version finale — à ajuster ensemble après usage réel prolongé.
+66 -5
View File
@@ -25,7 +25,7 @@ Une troisième itération, dans la même session, s'appuie sur une image trouvé
### Choix techniques retenus ### Choix techniques retenus
- **`background-size:contain`, pas `cover`.** Premier essai en `cover` : sur l'écran réel de Jean-Marc (proportions différentes de l'image), le bas de l'image était rogné. Passage à `contain` : l'image entière reste toujours visible quelle que soit la proportion d'écran, quitte à laisser une bande de la couleur du mur (échantillonnée sur la photo) de part et d'autre plutôt que de rogner. - **`background-size:contain`, pas `cover`.** Premier essai en `cover` : sur l'écran réel de Jean-Marc (proportions différentes de l'image), le bas de l'image était rogné. Passage à `contain` : l'image entière reste toujours visible quelle que soit la proportion d'écran, quitte à laisser une bande de la couleur du mur (échantillonnée sur la photo) de part et d'autre plutôt que de rogner.
- **Système de coordonnées calé sur l'image de référence.** Chaque élément cliquable/affiché est positionné en pixels de l'image de référence (`IMG_W`/`IMG_H`, constantes en tête de script), puis converti en position/taille réelle à l'écran par une fonction `positionner()` qui refait à la main le calcul de `background-size:contain` (comparaison du ratio image/fenêtre, calcul de la zone réellement affichée et des bandes vides). Appelée au chargement et à chaque redimensionnement. Ce pattern est appelé à être réutilisé pour tout futur objet ajouté sur ce bureau. - **Système de coordonnées calé sur l'image de référence.** Chaque élément cliquable/affiché est positionné en pixels de l'image de référence (`IMG_W`/`IMG_H`, constantes en tête de script), puis converti en position/taille réelle à l'écran par une fonction `positionner()` qui refait à la main le calcul de `background-size:contain` (comparaison du ratio image/fenêtre, calcul de la zone réellement affichée et des bandes vides). Appelée au chargement et à chaque redimensionnement. Ce pattern est appelé à être réutilisé pour tout futur objet ajouté sur ce bureau — et l'a effectivement été dès la nuit suivante pour la pastille du classeur et la grille de post-its (voir plus bas).
- **Zone cliquable large, séparée de l'icône visuelle précisément positionnée** (cas du micro, voir plus bas) : un premier essai avec une seule zone cliquable de la taille de l'icône s'est révélé trop étroit à l'usage réel (infobulle qui ne se déclenchait qu'en survolant précisément quelques pixels) — le pattern retenu sépare un grand bouton invisible (toute la silhouette de l'objet, pour le survol/clic/infobulle) d'un petit élément visuel `pointer-events:none` posé par-dessus, calé sur le détail précis à afficher (ici le rond noir du micro), reliés par un sélecteur de fratrie CSS (`~`) pour l'effet visuel au survol. - **Zone cliquable large, séparée de l'icône visuelle précisément positionnée** (cas du micro, voir plus bas) : un premier essai avec une seule zone cliquable de la taille de l'icône s'est révélé trop étroit à l'usage réel (infobulle qui ne se déclenchait qu'en survolant précisément quelques pixels) — le pattern retenu sépare un grand bouton invisible (toute la silhouette de l'objet, pour le survol/clic/infobulle) d'un petit élément visuel `pointer-events:none` posé par-dessus, calé sur le détail précis à afficher (ici le rond noir du micro), reliés par un sélecteur de fratrie CSS (`~`) pour l'effet visuel au survol.
- **Aucune donnée figée en dur** : tout ce qui s'affiche vient d'un endpoint PHP réel de la session en cours (`preferences.php`, `version.php`), jamais de texte statique. - **Aucune donnée figée en dur** : tout ce qui s'affiche vient d'un endpoint PHP réel de la session en cours (`preferences.php`, `version.php`), jamais de texte statique.
@@ -39,23 +39,84 @@ Une troisième itération, dans la même session, s'appuie sur une image trouvé
- **Touche Échap** conservée comme échappatoire silencieuse vers `liste_todolist.html`, le temps que cet écran ne porte pas encore d'objet fonctionnel complet. - **Touche Échap** conservée comme échappatoire silencieuse vers `liste_todolist.html`, le temps que cet écran ne porte pas encore d'objet fonctionnel complet.
- **Version applicative incrémentée à `V1.007`** pour l'ensemble de ce lot (première modification livrée dans cette étape du travail). - **Version applicative incrémentée à `V1.007`** pour l'ensemble de ce lot (première modification livrée dans cette étape du travail).
### Fichiers touchés ### Fichiers touchés (essai initial)
`identification.html` (redirection post-connexion), `ecran_fond.html` (nouveau), `ecran_fond.jpg` (nouveau, image de référence 1024×457 fournie et recadrée par Jean-Marc), `preferences.php` (ajout de `USR_Prenom` en lecture), `version.php` (`V1.007`). Côté base : colonne `USR_Prenom` ajoutée à `ASP_Users` par Jean-Marc directement (voir convention actée en tête de journal sur les exports SQL transmis). `identification.html` (redirection post-connexion), `ecran_fond.html` (nouveau), `ecran_fond.jpg` (nouveau, image de référence 1024×457 fournie et recadrée par Jean-Marc), `preferences.php` (ajout de `USR_Prenom` en lecture), `version.php` (`V1.007`). Côté base : colonne `USR_Prenom` ajoutée à `ASP_Users` par Jean-Marc directement (voir convention actée en tête de journal sur les exports SQL transmis).
## Nuit du 2 au 3 septembre 2026 : pastille du classeur, conception et premier affichage du tableau de post-its (V1.008)
Session enchaînée directement après l'essai initial ci-dessus (même soirée, Jean-Marc n'a pas fermé la fenêtre), à l'aide du token GitHub transmis en session pour relire l'état réel du dépôt avant de reprendre — token utilisé uniquement pour cloner/consulter, jamais stocké, conformément à la consigne en tête de journal.
### Pastille "nombre de contacts" sur le classeur
Avant d'ouvrir le chantier du tableau de liège, petite demande de Jean-Marc : afficher, sous le trou cerclé de métal du classeur "Contacts", une pastille ronde avec le nombre réel de contacts de la table, dans un esprit "collée sur le classeur" — couleur homogène avec le classeur (plus foncée), chiffre blanc, liseré pour ressortir.
Mesure précise du trou et de son anneau métallique sur `ecran_fond.jpg` (centre à x=58, y=354 dans le référentiel image, anneau jusqu'à y≈365) pour caler la pastille juste en dessous, sur le même axe. Couleur de fond calculée par assombrissement (×0,55) de la teinte réelle du classeur mesurée sur la photo (rgb≈3,79,99, plus sombre en photo qu'à l'écran) plutôt que choisie arbitrairement — donne `#022b36`. Nouveau paramètre `?compte=1` sur `contacts.php` : renvoie `{"total": N}` (comptage seul, `COUNT(*)` sur `ASP_Contacts` actifs) sans charger la liste complète, pour ne pas gaspiller un appel lourd juste pour une pastille. Taille de police du chiffre adaptative selon le nombre de chiffres (2/3/4+), pour continuer à tenir dans le rond si la table grossit.
Premier rendu jugé "un peu trop présent" par Jean-Marc à l'usage réel sur son écran : diamètre réduit de 22 à 17px (référentiel image 1024×457), liseré blanc adouci (épaisseur 2px→1,5px, opacité 85%→40%). Centre de la pastille recalé à (58, 381) pour rester au milieu de l'espace disponible entre l'anneau et le bas du classeur avec la nouvelle taille, plutôt que de garder l'ancien centrage. Validé ensuite par Jean-Marc ("c'est parfait").
### Conception du tableau de liège — vision actée, partiellement codée
Confirmation importante de Jean-Marc en cours de discussion : le mur représenté sur `ecran_fond.jpg` est bien du **vrai liège** (vérifié par Claude en zoomant sur la photo — texture organique/granuleuse nette, pas une couleur unie comme l'écran le laissait presque penser à taille normale). Ce point a tranché en faveur d'un post-it avec punaise ronde plutôt qu'un simple carré posé : sur du vrai liège, la punaise est l'objet qui va avec la matière, pas une fantaisie graphique.
**Répartition de l'écran, principe retenu :** 70% de la largeur pour les 4 assistants IA (Viktor, Matilda, Léon, Nikita — voir section 27), 30% fixe pour Jean-Marc lui-même, en bande verticale partant du bord droit de l'écran (juste au-dessus du chevalet, qui porte déjà son prénom — cohérence visuelle du "coin" qui le représente). Logique assumée par Jean-Marc : les assistants doivent traiter leurs tâches très rapidement (donc peu de post-its en attente à un instant T), l'humain — "le vilain petit canard" — accumule davantage avant de traiter, donc mérite plus de place. Jean-Marc a explicitement refusé d'appliquer à lui-même une répartition dynamique par charge, préférant garder ses 30% fixes pour l'instant.
**Règles actées pour la part "assistants" (70%), non codées ce soir faute de ToDoList assistants réelle :**
- Part de chaque assistant affiché = (ses tâches en attente ÷ somme des tâches en attente de tous les assistants) × 70%.
- L'assistant par défaut (`AGN_Defaut`, aujourd'hui Matilda) est toujours le plus à gauche parmi les colonnes affichées, s'il a au moins une tâche en attente.
- Les autres assistants ayant des tâches sont classés à sa suite par charge décroissante (le plus chargé juste après le défaut).
- Un assistant sans tâche en attente **disparaît entièrement** du tableau (pas de colonne vide) — permet d'intégrer les assistants un par un sans "zone vide" frustrante à l'écran.
- Chaque assistant aura une couleur de post-it personnalisée (`AGN_Couleur`, champ déjà en cours d'ajout par Jean-Marc à `ASP_Agents` en parallèle du pilotage vocal — voir section 27). Jean-Marc, lui, garde toujours le jaune classique du post-it, jamais personnalisé.
**Clarification importante actée en discussion, vérifiée dans le code par Claude :** Jean-Marc a fait remarquer que la gestion de tâches par assistant n'est pas une nouvelle mécanique à inventer — le champ `TDL_ToDoUser` de `ASP_ToDoList` (et `TDL_RealUser`) n'a jamais été restreint à un humain ; le commentaire d'en-tête de `todolist.php` anticipait déjà qu'un agent IA puisse ajouter une tâche pour un autre utilisateur, et l'endpoint renvoie déjà toutes les tâches actives quel que soit `TDL_ToDoUser`. Il suffira, le jour venu, d'ajouter un discriminant humain/agent (pour savoir quel nom et quelle couleur afficher) plutôt que de reconstruire un système. Les écrans de gestion actuels (`liste_todolist.html`, `todolist.php` pour la consultation/ajout/modification) sont conservés tels quels — pensés pour un usage humain (formulaire), pas forcément adaptés tels quels à un usage agent le jour venu, mais ce sujet est explicitement remis à plus tard. Ils ne sont **pas reliés à la navigation** depuis l'écran de fond pour l'instant (clic sur un post-it sans effet, voir plus bas).
**Nouveau besoin identifié en cours de réflexion (non traité ce soir) :** un écran "journalier", traçant ce qui a été réalisé par chacun (humain et assistants), une fois plusieurs acteurs actifs sur la même ToDoList. Repéré par Claude comme déjà largement couvert par les champs existants de `ASP_ToDoList` — `TDL_RealDate`/`TDL_RealUser`/`TDL_RealText` donnent déjà, pour chaque tâche réalisée, qui l'a faite, quand, et un commentaire de réalisation. Une première version de ce journalier pourrait donc être une simple requête "tâches où `TDL_RealDate` n'est pas vide, triées par date décroissante", sans nouvelle table. À noter : le commentaire d'en-tête de `todolist.php` mentionnait explicitement qu'un système d'audit avait été volontairement écarté à l'origine ("non demandé à ce stade... pas de sur-ingénierie") — le besoin de ce soir est justement le moment où ce choix mérite d'être révisité, ce qui valide plutôt bien le principe.
**Conception visuelle du post-it.** Deux options proposées par Claude (image de synthèse envoyée à Jean-Marc) : carré simple avec coin corné, ou même carré avec punaise ronde en haut. La confirmation que le fond est du vrai liège a tranché en faveur de la punaise. Première proposition d'agencement en petit tas chevauché, explicitement rejetée par Jean-Marc — pas pour le principe de chevauchement (qu'il n'a jamais exclu), mais pour l'empilement en tas qui rend le survol/clic imprécis ("il faudrait une précision de tireur d'élite"). Solution retenue : chaque post-it reste dans une case de grille qui lui est propre, avec un léger jitter de rotation/décalage à l'intérieur de sa case (jamais à cheval sur la case voisine) — donne un rendu "punaisé à la main" sans jamais recréer un tas ambigu au clic.
**Capacité du tableau — refus explicite d'un ascenseur.** En discutant de ce qui se passerait si le nombre de post-its dépassait la place disponible (taille fixe, pas de plafond souhaité par Jean-Marc au départ), Claude a proposé un défilement vertical à l'intérieur de la seule bande personnelle. Jean-Marc s'y est fermement opposé : un ascenseur casserait la métaphore du vrai bureau et, pire, l'inciterait lui-même à cumuler les post-its sans jamais être poussé à les traiter ("je me connais"). Décision retenue à la place : une capacité finie et un message de blocage à la création, une fois le tableau plein — la contrainte physique du vrai bureau étant vue comme une qualité (elle force à traiter), pas un défaut à contourner.
Implémentation dans `todolist.php` : constante `CAPACITE_TABLEAU_PAR_UTILISATEUR = 20` (valeur ronde provisoire, posée avant d'avoir les vrais pixels de la grille codée — "mets-le où tu veux, il faudra le faire évoluer", dixit Jean-Marc), et vérification au POST : si le nombre de tâches actives non réalisées de l'attributaire (`TDL_ToDoUser`) atteint cette capacité, la création est refusée (HTTP 409) avec le message exact demandé par Jean-Marc : *"Ton tableau est plein, tu ne peux plus ajouter de post-it !"*. Une tâche créée déjà réalisée (cas de la journalisation rétroactive d'une tâche déjà faite, prévu de longue date dans `todolist.php`) n'est jamais bloquée — elle n'occupe jamais de post-it sur le tableau. Posée dans `todolist.php` plutôt que dans l'écran de fond : la règle vaudra donc aussi le jour où la voix créera des tâches directement, sans rien à reprendre.
### Premier affichage réel des post-its personnels
Implémenté dans `ecran_fond.html`, en s'appuyant sur le pattern `positionner()` déjà en place pour les autres éléments (voir plus haut).
- **Zone :** 30% de la largeur de l'écran depuis le bord droit (soit x:[717,1024] sur l'image de référence 1024×457), du haut de l'image (y=6) jusqu'à juste au-dessus du chevalet (y=352, chevalet à partir de y=362).
- **Grille :** 4 colonnes × 5 lignes = 20 cases, volontairement alignée sur `CAPACITE_TABLEAU_PAR_UTILISATEUR` de `todolist.php` — les deux constantes devront évoluer ensemble si l'une change. Taille d'un post-it : ~60% de la plus petite dimension de case, pour laisser de la marge au jitter.
- **Source des données :** `todolist.php` (déjà utilisé par `liste_todolist.html`), filtré côté client sur l'utilisateur connecté (`TDL_ToDoUser` comparé au `USR_Code` renvoyé par `preferences.php`) et sur les tâches non réalisées (`TDL_RealDate` vide) — l'API elle-même reste volontairement non filtrée par utilisateur (voir plus haut), le tri "ce sont MES post-its" se fait donc à l'affichage. L'ordre renvoyé par l'API (rouge avant orange, sous-trié par échéance) est conservé pour remplir la grille case par case : les tâches les plus urgentes arrivent toujours en premier, en haut à gauche de la zone.
- **Jitter déterministe :** rotation et décalage d'un post-it calculés à partir de son `TDL_Incr` (petit générateur pseudo-aléatoire "mulberry32" simplifié), et non d'un hasard pur — la disposition reste stable d'un rechargement de l'écran à l'autre, pas de "saut" visuel à chaque retour sur l'écran de fond.
- **Habillage du post-it :** punaise ronde en haut, coin corné bas-droit (léger dégradé simulant le papier qui se soulève), pastille d'urgence rouge/orange bien visible en coin haut-droit (jamais verte : une tâche réalisée quitte immédiatement le tableau, voir filtre ci-dessus), jaune classique fixe pour Jean-Marc. Pas de texte visible sur le post-it (choix explicite de Jean-Marc) : le texte de la tâche (`TDL_ToDoTxt`) n'apparaît qu'en infobulle au survol. Clic sans effet pour l'instant — navigation vers `liste_todolist.html` volontairement pas encore branchée (voir plus haut).
- **Test :** rendu vérifié par Claude avec des jeux de données simulés (9 puis 23 tâches, groupes rouge/orange mélangés, une tâche appartenant à un autre utilisateur et une tâche déjà réalisée pour confirmer que le filtrage fonctionne bien) avant envoi à Jean-Marc. Rendu confirmé "conforme à la réalité" par Jean-Marc sur les images envoyées.
**Point relevé par Jean-Marc en toute fin de session, à traiter plus tard :** les règles actuelles de calcul du groupe d'urgence (`calculerGroupe()` dans `todolist.php` — rouge/orange/vert) risquent de donner un tableau surchargé de rouge et d'orange, puisque le vert (réalisé) quitte désormais le tableau immédiatement. Pas retouché ce soir, noté pour une prochaine session.
### Fichiers touchés (nuit du 2-3 septembre)
`contacts.php` (paramètre `?compte=1`), `ecran_fond.html` (pastille classeur + zone et grille de post-its), `todolist.php` (constante et vérification de capacité), `version.php` (`V1.008`).
## Point ouvert, non tranché ## Point ouvert, non tranché
- La question enveloppes/Gmail (voir plus haut) portait sur la maquette liège/post-its, mise de côté par le changement de cap ci-dessus — à retrancher le jour où cette piste sera reprise, pas urgent pour l'essai en cours. - La question enveloppes/Gmail (voir plus haut) portait sur la maquette liège/post-its, mise de côté par le changement de cap ci-dessus — à retrancher le jour où cette piste sera reprise, pas urgent pour l'essai en cours.
- Confirmer un jour le libellé du 4ᵉ classeur envisagé dans la maquette liège ("À faire" / ToDoList) — question qui ne se pose plus dans l'immédiat : l'essai en cours n'a pour l'instant qu'un seul classeur fonctionnel ("Contacts"). - Confirmer un jour le libellé du 4ᵉ classeur envisagé dans la maquette liège ("À faire" / ToDoList) — question qui ne se pose plus dans l'immédiat : l'essai en cours n'a pour l'instant qu'un seul classeur fonctionnel ("Contacts").
- **Nouveau (2 septembre 2026, remonté par Jean-Marc) : la "tranche du bureau" (bord avant du plan de travail, en bas de l'image) n'est pas visible à l'écran chez lui.** Jean-Marc précise que ça ne le gêne pas dans l'immédiat, mais que ça pourrait poser problème plus tard — à revoir un jour. Cause non investiguée à ce stade (a priori liée à la proportion réelle de son écran par rapport à l'image, malgré le passage en `background-size:contain` qui garantit que l'image entière reste visible — reste à vérifier si la bande en question est simplement hors du cadre visible dans son cas, ou une autre cause). - La "tranche du bureau" (bord avant du plan de travail, en bas de l'image) n'est pas visible à l'écran chez Jean-Marc. Il précise que ça ne le gêne pas dans l'immédiat, mais que ça pourrait poser problème plus tard — à revoir un jour. Cause non investiguée à ce stade.
- Répartition dynamique des 70% entre assistants par charge de tâches (formule actée, voir ci-dessus) — pas codée, bloquée tant que la ToDoList des assistants n'existe pas réellement.
- Discriminant humain/agent à ajouter à `ASP_ToDoList`/`todolist.php` pour qu'un assistant puisse être attributaire d'une tâche — préalable à la répartition dynamique et aux couleurs de post-it par assistant (`AGN_Couleur`).
- Écran "journalier" (trace des réalisations, humain + assistants) — donnée déjà quasi disponible, écran à construire.
- Règles de calcul des pastilles rouge/orange/vert à revoir (voir remarque de Jean-Marc ci-dessus).
- Comportement du clic sur un post-it à décider (aujourd'hui inerte) : ouvrir `liste_todolist.html` sur la tâche précise, ou détail affiché directement sur l'écran de fond.
- Capacité du tableau (20) et taille de la grille (4×5) sont des valeurs provisoires posées avant d'avoir les vrais pixels de la version aboutie — à ajuster ensemble après usage réel prolongé.
## Statut et suite ## Statut et suite
**Essai fonctionnel en cours de test réel par Jean-Marc, sur son environnement de développement** (redirection post-identification vers `ecran_fond.html`, activée). Plusieurs allers-retours de correction fine déjà effectués dans la session (centrage de l'étiquette, position de l'icône micro, couleur/position du numéro de version) à partir des retours directs de Jean-Marc sur son propre écran — plusieurs points ont nécessité plus d'une itération, la mesure de position sur une photo réelle (plutôt que sur un dessin vectoriel) demandant une vérification fine à chaque retour. Fin de session actée le 2 septembre 2026 à la demande de Jean-Marc (changement de fenêtre de conversation) — pas de blocage, juste une pause volontaire. **Deux livraisons réelles sur la même soirée du 2 septembre, la seconde se prolongeant après minuit (3 septembre) :** l'essai fonctionnel initial (classeur Contacts, chevalet, micro test d'affichage, version — V1.007), puis la pastille de comptage sur le classeur et un premier affichage réel, fonctionnel et testé, du tableau de post-its personnels de Jean-Marc (V1.008). Plusieurs allers-retours de correction fine à chaque étape, à partir des retours directs de Jean-Marc sur son propre écran ou sur des rendus envoyés par Claude — la mesure de position sur une photo réelle (plutôt que sur un dessin vectoriel) continue de demander une vérification fine à chaque retour.
Séance close sur un bilan explicitement positif de Jean-Marc ("très satisfait du travail accompli"), après une séance précédente terminée sur une note plus mitigée. Fin de session actée à sa demande, sans blocage — dépôt des fichiers sur GitHub prévu par ses soins le lendemain matin.
**Reste à faire, noté au passage :** **Reste à faire, noté au passage :**
- Revoir un jour le sujet de la "tranche du bureau" non visible chez Jean-Marc (voir ci-dessus). - Revoir un jour le sujet de la "tranche du bureau" non visible chez Jean-Marc (voir ci-dessus).
- Décider si les autres objets photographiés sur le bureau (carnet, téléphone) doivent devenir cliquables/fonctionnels dans une prochaine étape, ou rester un habillage visuel statique pour l'instant. - Décider si les autres objets photographiés sur le bureau (carnet, téléphone) doivent devenir cliquables/fonctionnels dans une prochaine étape, ou rester un habillage visuel statique pour l'instant.
- Brancher réellement le micro du bureau sur la reconnaissance vocale de `micro.js` (aujourd'hui : bascule d'affichage seule, sans effet sur l'écoute réelle). - Brancher réellement le micro du bureau sur la reconnaissance vocale de `micro.js` (aujourd'hui : bascule d'affichage seule, sans effet sur l'écoute réelle).
- Trancher, un jour, le sort de la piste "maquette liège + post-its par agent" (Claude Design) : abandonnée pour cet essai, mais pas explicitement enterrée pour une version plus aboutie. - Trancher, un jour, le sort de la piste "maquette liège + post-its par agent" (Claude Design) : mise de côté pour les essais en cours, mais pas explicitement enterrée pour une version plus aboutie.
- Artifact de travail de la maquette liège (dernière version, non utilisée dans l'essai actuel) : https://claude.ai/code/artifact/a647369f-d320-4b21-9f8c-11b20f2ad353 — lien privé à Jean-Marc, à ne pas considérer comme un livrable définitif. - Artifact de travail de la maquette liège (dernière version, non utilisée dans l'essai actuel) : https://claude.ai/code/artifact/a647369f-d320-4b21-9f8c-11b20f2ad353 — lien privé à Jean-Marc, à ne pas considérer comme un livrable définitif.
- Répartition dynamique par charge, discriminant humain/agent, écran journalier, règles de pastilles, comportement du clic sur un post-it, calibrage capacité/grille : voir "Point ouvert, non tranché" ci-dessus.
+38
View File
@@ -105,6 +105,25 @@ function comparerDateNullEnPremier(?string $a, ?string $b): int
return strcmp($a, $b); return strcmp($a, $b);
} }
/**
* Capacité maximale de post-its "en attente" affichables sur le tableau de
* liège de l'écran de fond, par attributaire (voir journal de développement,
* section 28 — "bureau à l'ancienne"). Ajoutée le 2 septembre 2026, en amont
* du code réel du tableau : Jean-Marc a posé le principe avant d'avoir les
* pixels pour le calculer précisément ("mets-le où tu veux, il faudra le
* faire évoluer") — valeur ronde provisoire, à corriger dès que la taille
* réelle de la zone et celle d'un post-it seront posées à l'écran.
*
* Choix de principe explicite de Jean-Marc : PAS d'ascenseur/défilement sur
* le tableau, même si ça permettrait d'accepter plus de post-its — un vrai
* bureau a une capacité finie, et c'est justement cette contrainte physique
* qui pousse à traiter ses tâches plutôt qu'à les empiler indéfiniment. Une
* fois cette capacité atteinte, la création est refusée avec un message
* clair (voir POST ci-dessous) plutôt que de trouver un moyen d'entasser
* plus de post-its ou de faire défiler le tableau.
*/
const CAPACITE_TABLEAU_PAR_UTILISATEUR = 20;
try { try {
switch ($method) { switch ($method) {
case 'GET': case 'GET':
@@ -167,6 +186,25 @@ try {
$todoUser = $_SESSION['USR_Code']; $todoUser = $_SESSION['USR_Code'];
} }
// Capacité du tableau (voir CAPACITE_TABLEAU_PAR_UTILISATEUR
// ci-dessus) : ne s'applique qu'aux tâches qui vont réellement
// occuper un post-it "en attente" sur le bureau de $todoUser.
// Une tâche créée déjà réalisée (TDL_RealDate fourni dès la
// création, voir doc d'en-tête — permet de journaliser une tâche
// déjà faite) n'occupe jamais de place sur le tableau, donc
// n'est jamais bloquée par cette limite.
if (empty($data['TDL_RealDate'])) {
$stmtCompte = $pdo->prepare(
'SELECT COUNT(*) FROM ASP_ToDoList WHERE TDL_Actif = 1 AND TDL_ToDoUser = ? AND TDL_RealDate IS NULL'
);
$stmtCompte->execute([$todoUser]);
if ((int)$stmtCompte->fetchColumn() >= CAPACITE_TABLEAU_PAR_UTILISATEUR) {
http_response_code(409);
echo json_encode(['error' => 'Ton tableau est plein, tu ne peux plus ajouter de post-it !']);
exit;
}
}
// TDL_ToDoDate : incluse dans l'INSERT seulement si fournie par le // TDL_ToDoDate : incluse dans l'INSERT seulement si fournie par le
// client (permet de dater rétroactivement une tâche oubliée) — // client (permet de dater rétroactivement une tâche oubliée) —
// sinon on laisse MySQL appliquer DEFAULT CURRENT_TIMESTAMP // sinon on laisse MySQL appliquer DEFAULT CURRENT_TIMESTAMP
+1 -1
View File
@@ -24,7 +24,7 @@
* d'identification, avant toute connexion. * d'identification, avant toute connexion.
*/ */
const ASPIC_VERSION = 'V1.007'; const ASPIC_VERSION = 'V1.008';
if (basename($_SERVER['SCRIPT_NAME']) === 'version.php') { if (basename($_SERVER['SCRIPT_NAME']) === 'version.php') {
header('Content-Type: application/json; charset=utf-8'); header('Content-Type: application/json; charset=utf-8');