forked from FroSteel/Planification
v2026.5.40 — Sélection groupe EV + édition domaines + tri équipe + vue horizontale enrichie
Onglet Équipe : - Sélecteur de groupe EasyVista (SI-CSS, SI-EXT, …) en tête de section, détecté automatiquement à l'ouverture du panel via le <select id="plan_group_id"> de la page Planning EV. Robuste aux ajouts/renommages côté EV. - ID groupe affiché en italique (ex: ID groupe : 191). - Refresh auto de la liste d'équipe au changement de groupe. - Plus de bouton 'Détecter' : tout est auto à l'ouverture. - Tri double : inclus d'abord, puis exclus, alphabétique dans chaque sous-groupe. Onglet EasyVista : - Édition manuelle des deux domaines (interne DGNSI / externe Internet). - Bouton Réinitialiser, normalisation auto des URLs. - Les défauts restent codés en dur en fallback. Onglet Statuts retiré (placeholder lecture seule). Vue horizontale enrichie : - Barre couleur catégorie + référence + ville sur chaque segment. - Hauteur 22→32px. Coulisses : - Nouveau message 'detectGroups' + fonction detectGroupsFromEV() côté background.js. - detectTeamFromEV() accepte un groupId en argument. - Le fetch du planning continue d'utiliser group_id=191 codé en dur, branchement effectif dans une prochaine version.
This commit is contained in:
+133
-14
@@ -587,17 +587,26 @@ function watchReconnectTabForIamLogin(tabId) {
|
||||
*/
|
||||
async function fetchCurrentUser(origin, phpsessid) {
|
||||
const url = `${origin}/index.php?PHPSESSID=${encodeURIComponent(phpsessid)}`;
|
||||
const resp = await fetch(url, {
|
||||
// v2026.5.40 : on passe par evFetch() qui ajoute les headers Referer +
|
||||
// X-Requested-With attendus par EV. Sans ça, /index.php renvoyait une
|
||||
// page intermédiaire SSO sans le bloc .profile-info → user_null perpétuel.
|
||||
const resp = await evFetch(url, origin, {
|
||||
method: "GET",
|
||||
credentials: "include",
|
||||
headers: { "Accept": "text/html,*/*" }
|
||||
});
|
||||
// v4.2 : cette fonction est lancée en tâche de fond au démarrage. Si la
|
||||
// session est expirée ou EV inaccessible, on retourne juste null — le
|
||||
// planning lui-même déclenchera l'écran d'erreur approprié.
|
||||
if (!resp.ok) return null;
|
||||
if (!resp.ok) {
|
||||
LOG.warn("currentUser", "fetch /index.php non-OK", { status: resp.status });
|
||||
return null;
|
||||
}
|
||||
const html = await resp.text();
|
||||
if (looksLikeLoginPage(html)) return null;
|
||||
if (looksLikeLoginPage(html)) {
|
||||
LOG.warn("currentUser", "page de login detectee — session probablement intermediaire SSO");
|
||||
return null;
|
||||
}
|
||||
LOG.info("currentUser", "HTML index.php recu", { taille: html.length, hasProfileInfo: /class=["']profile-info["']/.test(html) });
|
||||
|
||||
// v4.2.2 : patterns spécifiques à la structure EasyVista réelle du Canton
|
||||
// de Vaud (identifiés à partir du HTML de la page d'accueil). L'user est
|
||||
@@ -669,7 +678,18 @@ async function fetchCurrentUser(origin, phpsessid) {
|
||||
}
|
||||
}
|
||||
|
||||
if (!name && !login && !service) return null;
|
||||
if (!name && !login && !service) {
|
||||
// v2026.5.40 : log diagnostic pour comprendre pourquoi l'extraction echoue
|
||||
LOG.warn("currentUser", "aucun nom/service/login extrait du HTML",
|
||||
{
|
||||
taille: html.length,
|
||||
hasH5: /class=["']h5["']/.test(html),
|
||||
hasProfileInfo: /class=["']profile-info["']/.test(html),
|
||||
hasEvDropdown: /class=["'][^"']*ev-employee-dropdown/.test(html),
|
||||
snippet: html.substring(0, 200).replace(/\s+/g, " ")
|
||||
});
|
||||
return null;
|
||||
}
|
||||
return { name, login, service };
|
||||
}
|
||||
|
||||
@@ -925,9 +945,80 @@ async function deletePlanningItem(origin, phpsessid, actionId, kind) {
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// v5.0.0 : Détection de la liste des techniciens depuis la page planning EV
|
||||
// v2026.5.41 : Détection des GROUPES EasyVista (SI-CSS, SI-EXT, …)
|
||||
// ============================================================================
|
||||
|
||||
/**
|
||||
* Fetch le HTML de la page planning et extrait la liste des groupes depuis
|
||||
* `<select id="plan_group_id">`. C'est la source autoritative : ce sont les
|
||||
* `group_id` exacts qu'EasyVista lui-même utilise pour le widget de
|
||||
* changement de groupe sur la page planning. Robuste aux ajouts/renommages :
|
||||
* si le DGNSI ajoute un 3e groupe ou renomme SI-CSS, ça apparaît tout seul.
|
||||
*
|
||||
* Retourne { groups: [{id, name}, ...] }. Liste vide si le fetch échoue ou
|
||||
* si EV renvoie une page de login / redirection JS.
|
||||
*
|
||||
* @author Quentin Rouiller
|
||||
*/
|
||||
async function detectGroupsFromEV(origin, phpsessid) {
|
||||
const url = `${origin}/index.php?eventName=HelpDesk_PlanningItem&PHPSESSID=${encodeURIComponent(phpsessid)}`;
|
||||
console.log("[bg] detectGroupsFromEV → fetch page planning");
|
||||
console.log("[bg] URL =", url);
|
||||
|
||||
const r = await evFetch(url, origin);
|
||||
if (!r.ok) {
|
||||
const err = new Error("HTTP " + r.status);
|
||||
err.kind = classifyHttpStatus(r.status);
|
||||
err.status = r.status;
|
||||
throw err;
|
||||
}
|
||||
const html = await r.text();
|
||||
console.log("[bg] page planning taille =", html.length);
|
||||
|
||||
if (looksLikeLoginPage(html)) {
|
||||
const err = new Error("session_expired");
|
||||
err.kind = "session_expired";
|
||||
throw err;
|
||||
}
|
||||
|
||||
// Parser le <select id="plan_group_id">…</select> et ses <option>.
|
||||
// On accepte plan_group_id avant ou après le name=, et on tolère les
|
||||
// attributs supplémentaires (onchange, class, etc.).
|
||||
const groups = [];
|
||||
const selectMatch = html.match(/<select[^>]*\bid=["']plan_group_id["'][^>]*>([\s\S]*?)<\/select>/i);
|
||||
if (selectMatch) {
|
||||
const inner = selectMatch[1];
|
||||
const rxOpt = /<option[^>]*\bvalue=["'](\d+)["'][^>]*>([^<]+)<\/option>/gi;
|
||||
let m;
|
||||
while ((m = rxOpt.exec(inner)) !== null) {
|
||||
const id = m[1];
|
||||
const name = (m[2] || "").trim();
|
||||
if (id && name && !groups.some(g => g.id === id)) {
|
||||
groups.push({ id, name });
|
||||
}
|
||||
}
|
||||
}
|
||||
console.log("[bg] " + groups.length + " groupes détectés :", groups);
|
||||
|
||||
// Fallback : si le <select> est absent (rendu côté client tardif), on
|
||||
// tente de lire les favoris menuGlobals.tech4 où les noms sont en base64.
|
||||
// Ces favoris listent les filtres "SI-CSS"/"SI-EXT" — utile si le HTML
|
||||
// initial ne contient pas encore le <select>.
|
||||
if (groups.length === 0) {
|
||||
const rxFav = /"TITLE"\s*:\s*"([^"]+)"[\s\S]{0,400}?"q2_value_selected"\s*:\s*"([A-Za-z0-9+/=]+)"/g;
|
||||
let mF;
|
||||
while ((mF = rxFav.exec(html)) !== null) {
|
||||
const title = mF[1];
|
||||
// On n'a pas l'ID dans les favoris : on garde au moins le nom pour
|
||||
// affichage info, mais sans ID ce groupe n'est pas sélectionnable
|
||||
// pour fetcher le planning. On ignore donc côté retour.
|
||||
console.log("[bg] fallback favoris : " + title + " (sans ID, ignoré)");
|
||||
}
|
||||
}
|
||||
|
||||
return { groups };
|
||||
}
|
||||
|
||||
/**
|
||||
* v5.0.1 : Détection de la liste complète des membres du groupe EasyVista.
|
||||
*
|
||||
@@ -942,14 +1033,19 @@ async function deletePlanningItem(origin, phpsessid, actionId, kind) {
|
||||
*
|
||||
* Retourne { ids: [{id, name, alreadyInTeam}], groupId }.
|
||||
*/
|
||||
async function detectTeamFromEV(origin, phpsessid) {
|
||||
async function detectTeamFromEV(origin, phpsessid, groupIdArg, supportIdsArg) {
|
||||
// v5.0.1 : valeurs par défaut (correspondent au groupe actuel).
|
||||
// À terme elles devraient venir de la config admin.
|
||||
// v2026.5.41 : on accepte un groupId en argument (ex: switch SI-CSS → SI-EXT).
|
||||
// Quand on change de groupe, on n'a pas la liste support_ids du nouveau
|
||||
// groupe → on passe une chaîne vide, le serveur retourne quand même tous
|
||||
// les membres, juste sans pré-cochage "alreadyInTeam".
|
||||
const DEFAULT_GROUP_ID = "191";
|
||||
const DEFAULT_SUPPORT_IDS = "76272,83725,66635,92235,90070,40944,72485,86874";
|
||||
|
||||
const groupId = DEFAULT_GROUP_ID;
|
||||
const supportIds = DEFAULT_SUPPORT_IDS;
|
||||
const groupId = groupIdArg || DEFAULT_GROUP_ID;
|
||||
const supportIds = (typeof supportIdsArg === "string")
|
||||
? supportIdsArg
|
||||
: (groupId === DEFAULT_GROUP_ID ? DEFAULT_SUPPORT_IDS : "");
|
||||
console.log("[bg] detectTeamFromEV : group_id =", groupId, "| support_ids =", supportIds);
|
||||
|
||||
// Fetch la popup de sélection des intervenants du groupe
|
||||
@@ -1228,16 +1324,39 @@ chrome.runtime.onMessage.addListener((msg, sender, sendResponse) => {
|
||||
return;
|
||||
}
|
||||
|
||||
if (msg.type === "detectTeam") {
|
||||
// v5.0.0 : détecte la liste des IDs de techniciens depuis le HTML
|
||||
// v5.0.1 : retourne aussi les noms via la popup group_supports
|
||||
if (msg.type === "detectGroups") {
|
||||
// v2026.5.41 : détecte la liste des groupes EV (SI-CSS, SI-EXT, …)
|
||||
// depuis le <select id="plan_group_id"> de la page planning.
|
||||
const session = await findEasyVistaSession();
|
||||
if (!session) {
|
||||
sendResponse({ ok: false, error: "no_session" });
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const result = await detectTeamFromEV(session.origin, session.phpsessid);
|
||||
const result = await detectGroupsFromEV(session.origin, session.phpsessid);
|
||||
sendResponse({ ok: true, groups: result.groups });
|
||||
} catch (err) {
|
||||
sendResponse({
|
||||
ok: false,
|
||||
error: err.kind || err.message || String(err)
|
||||
});
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (msg.type === "detectTeam") {
|
||||
// v5.0.0 : détecte la liste des IDs de techniciens depuis le HTML
|
||||
// v5.0.1 : retourne aussi les noms via la popup group_supports
|
||||
// v2026.5.41 : accepte msg.groupId pour basculer entre SI-CSS / SI-EXT
|
||||
const session = await findEasyVistaSession();
|
||||
if (!session) {
|
||||
sendResponse({ ok: false, error: "no_session" });
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const result = await detectTeamFromEV(
|
||||
session.origin, session.phpsessid, msg.groupId, msg.supportIds
|
||||
);
|
||||
// result = { ids: [{id,name,alreadyInTeam}, ...], groupId }
|
||||
sendResponse({ ok: true, members: result.ids, groupId: result.groupId });
|
||||
} catch (err) {
|
||||
|
||||
Reference in New Issue
Block a user