update
This commit is contained in:
158
assets/js/agent-access.js
Normal file
158
assets/js/agent-access.js
Normal file
@@ -0,0 +1,158 @@
|
||||
/**
|
||||
* Compte d'accès depuis la fiche des agents (`PTA.modules.agentAccess`),
|
||||
* écran manage_agents.php — V7.28.
|
||||
*
|
||||
* Pose sur chaque ligne du tableau des agents un bouton qui COUPE ou RÉTABLIT
|
||||
* l'accès de l'agent à l'application. C'est le geste courant — un départ, un
|
||||
* arrêt long, un retour — là où l'écran Administration porte la distribution des
|
||||
* jetons elle-même.
|
||||
*
|
||||
* CE QUE LE BOUTON NE FAIT PAS : il ne touche ni au jeton (désactiver puis
|
||||
* réactiver rend le MÊME jeton valable), ni à la fiche de l'agent, qui reste
|
||||
* planifiable. Il ne crée pas non plus de compte : un agent qui n'en a pas
|
||||
* encore l'obtient depuis Administration, seul écran qui sache afficher un jeton
|
||||
* fraîchement produit.
|
||||
*
|
||||
* Il réutilise les endpoints de la délégation V7.27 (api/acces_comptes.php et
|
||||
* api/acces_compte_statut.php) : mêmes gardes serveur, même liste blanche de
|
||||
* rôles, même journalisation. Rien de neuf côté droits.
|
||||
*
|
||||
* L'état des comptes N'EST PAS rendu par PHP mais chargé par ce module : le HTML
|
||||
* servi ne porte ainsi aucune information sur les comptes, comme sur l'écran
|
||||
* DSI.
|
||||
*/
|
||||
(() => {
|
||||
'use strict';
|
||||
const PTA = window.PTA;
|
||||
if (!PTA) return;
|
||||
|
||||
const { readJsonResponse, apiErrorMessage } = PTA.utils;
|
||||
|
||||
const corps = () => document.querySelector('#agent-assignment-body');
|
||||
|
||||
/** Comptes d'accès des agents, indexés par identifiant d'agent. */
|
||||
let comptesParAgent = new Map();
|
||||
let chargement = false;
|
||||
|
||||
function message(texte, type = 'info') {
|
||||
const boite = document.querySelector('#assignment-message');
|
||||
if (!boite) return;
|
||||
boite.className = texte ? `message message-${type}` : 'message';
|
||||
boite.textContent = texte;
|
||||
}
|
||||
|
||||
/** Appel d'API mutualisé : toute réponse non-OK devient une exception. */
|
||||
async function api(url, options = {}) {
|
||||
const reponse = await fetch(url, options);
|
||||
const donnees = await readJsonResponse(reponse);
|
||||
if (!reponse.ok) throw new Error(apiErrorMessage(donnees, 'Opération impossible.'));
|
||||
return donnees;
|
||||
}
|
||||
|
||||
/**
|
||||
* Met un bouton de ligne à l'état du compte correspondant.
|
||||
*
|
||||
* Trois états, et un seul est actionnable :
|
||||
* - compte actif → « Couper l'accès » ;
|
||||
* - compte coupé → « Rétablir l'accès » ;
|
||||
* - aucun compte → bouton inerte, qui dit où en créer un.
|
||||
*/
|
||||
function decorerLigne(ligne) {
|
||||
const bouton = ligne.querySelector('.agent-access-toggle');
|
||||
if (!bouton) return;
|
||||
|
||||
const agentId = Number(ligne.dataset.agentId);
|
||||
const compte = comptesParAgent.get(agentId);
|
||||
|
||||
if (!compte) {
|
||||
bouton.disabled = true;
|
||||
bouton.textContent = 'Sans compte d’accès';
|
||||
bouton.title = 'Cet agent n’a pas encore de jeton. Créez son compte depuis l’onglet Administration, section « Jetons d’accès ».';
|
||||
delete bouton.dataset.compteId;
|
||||
delete bouton.dataset.actif;
|
||||
return;
|
||||
}
|
||||
|
||||
bouton.disabled = false;
|
||||
bouton.dataset.compteId = String(compte.id_compte);
|
||||
bouton.dataset.actif = compte.actif ? '1' : '0';
|
||||
bouton.textContent = compte.actif ? 'Couper l’accès' : 'Rétablir l’accès';
|
||||
bouton.title = compte.actif
|
||||
? 'Désactive le compte : l’agent ne pourra plus se connecter. Son jeton reste valable et resservira au rétablissement.'
|
||||
: 'Réactive le compte : l’agent pourra de nouveau se connecter avec le jeton qu’il détient déjà.';
|
||||
bouton.classList.toggle('button-danger', compte.actif);
|
||||
bouton.classList.toggle('button-secondary', !compte.actif);
|
||||
}
|
||||
|
||||
/** Applique l'état chargé à toutes les lignes présentes. */
|
||||
function decorerToutesLesLignes() {
|
||||
corps()?.querySelectorAll('tr[data-agent-id]').forEach(decorerLigne);
|
||||
}
|
||||
|
||||
/**
|
||||
* Recharge l'état des comptes agents.
|
||||
*
|
||||
* L'échec est SILENCIEUX sur le tableau : les boutons restent inertes avec
|
||||
* leur libellé d'attente, et la page des agents continue de fonctionner. Une
|
||||
* commodité ne doit pas empêcher de consulter ou de modifier une fiche.
|
||||
*/
|
||||
async function refresh() {
|
||||
if (!corps() || chargement) return;
|
||||
chargement = true;
|
||||
try {
|
||||
const donnees = await api('api/acces_comptes.php?role=AGENT');
|
||||
comptesParAgent = new Map(
|
||||
(donnees.comptes || [])
|
||||
.filter((compte) => compte.id_agent !== null)
|
||||
.map((compte) => [Number(compte.id_agent), compte])
|
||||
);
|
||||
decorerToutesLesLignes();
|
||||
} catch (erreur) {
|
||||
message(`État des comptes d’accès indisponible : ${erreur.message}`, 'warning');
|
||||
} finally {
|
||||
chargement = false;
|
||||
}
|
||||
}
|
||||
|
||||
/** Coupe ou rétablit l'accès de l'agent d'une ligne. */
|
||||
async function basculer(evenement) {
|
||||
const bouton = evenement.target.closest('.agent-access-toggle');
|
||||
if (!bouton || bouton.disabled) return;
|
||||
|
||||
const ligne = bouton.closest('tr[data-agent-id]');
|
||||
const compteId = Number(bouton.dataset.compteId);
|
||||
const actif = bouton.dataset.actif === '1';
|
||||
const titulaire = ligne?.querySelector('.agent-row-name')?.textContent?.trim() || 'cet agent';
|
||||
|
||||
if (actif && !window.confirm(`Couper l’accès de ${titulaire} ? Il ne pourra plus se connecter, et sa session en cours se refermera à sa prochaine action. Son jeton reste valable pour un rétablissement.`)) {
|
||||
return;
|
||||
}
|
||||
|
||||
bouton.disabled = true;
|
||||
try {
|
||||
const donnees = await api('api/acces_compte_statut.php', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
csrf_token: window.PTA_CONFIG.csrfToken,
|
||||
compte_id: compteId,
|
||||
action: actif ? 'DESACTIVER' : 'ACTIVER',
|
||||
}),
|
||||
});
|
||||
message(donnees.message, 'success');
|
||||
await refresh();
|
||||
} catch (erreur) {
|
||||
message(erreur.message, 'error');
|
||||
bouton.disabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
function init() {
|
||||
// Le module ne sert que sur l'écran des agents : ailleurs, il se retire.
|
||||
if (!corps()) return;
|
||||
corps().addEventListener('click', basculer);
|
||||
refresh();
|
||||
}
|
||||
|
||||
PTA.modules.agentAccess = { init, refresh };
|
||||
})();
|
||||
Reference in New Issue
Block a user