v2026.5.41 — Suppression des hardcodes runtime + UX admin + thème unifié
This commit is contained in:
+104
-26
@@ -115,11 +115,74 @@ self.addEventListener("unhandledrejection", (event) => {
|
||||
|
||||
LOG.info("boot", "service worker démarré", { version: LOG.version() });
|
||||
|
||||
// Domaines EasyVista reconnus (interne d'abord, externe en fallback)
|
||||
const EV_ORIGINS = [
|
||||
"https://itsma.etat-de-vaud.ch",
|
||||
"https://itsma.vd.ch"
|
||||
// ============================================================================
|
||||
// v2026.5.41 : Configuration runtime — lue depuis admin_config (chrome.storage.local).
|
||||
//
|
||||
// Les domaines EV et le group_id ont des défauts (filet de sécurité 1er install).
|
||||
// La liste de techniciens, elle, n'a AUCUN défaut : tant que l'utilisateur n'a
|
||||
// rien coché dans Paramètres → Équipe, l'extension ne fetche aucun planning et
|
||||
// invite à configurer.
|
||||
//
|
||||
// chrome.storage.local survit aux mises à jour d'extension → la sélection de
|
||||
// l'utilisateur est conservée d'une version à l'autre.
|
||||
// ============================================================================
|
||||
const DEFAULT_EV_ORIGINS = [
|
||||
"https://itsma.etat-de-vaud.ch", // interne DGNSI
|
||||
"https://itsma.vd.ch" // externe Internet
|
||||
];
|
||||
const DEFAULT_GROUP_ID = "191"; // SI-CSS
|
||||
|
||||
/**
|
||||
* Lit admin_config depuis chrome.storage.local. Retourne {} si absent ou
|
||||
* en cas d'erreur.
|
||||
*/
|
||||
async function getAdminConfig() {
|
||||
try {
|
||||
const stored = await chrome.storage.local.get("admin_config");
|
||||
return stored.admin_config || {};
|
||||
} catch (e) {
|
||||
LOG.warn("config", "getAdminConfig failed, using defaults", e);
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
/** Origines EV à surveiller, depuis admin_config ou défaut. */
|
||||
async function getEvOrigins() {
|
||||
const cfg = await getAdminConfig();
|
||||
const o = Array.isArray(cfg.evOrigins) ? cfg.evOrigins.filter(Boolean) : [];
|
||||
return o.length >= 1 ? o : DEFAULT_EV_ORIGINS;
|
||||
}
|
||||
|
||||
/** Group ID effectif (défaut SI-CSS). */
|
||||
async function getGroupId() {
|
||||
const cfg = await getAdminConfig();
|
||||
return cfg.groupId || DEFAULT_GROUP_ID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Support IDs effectifs (CSV des clés de cfg.team).
|
||||
* Retourne "" si aucun tech sélectionné — l'appelant doit alors signaler
|
||||
* à l'utilisateur d'aller configurer son équipe.
|
||||
*/
|
||||
async function getSupportIds() {
|
||||
const cfg = await getAdminConfig();
|
||||
const ids = Object.keys(cfg.team || {}).filter(Boolean);
|
||||
return ids.join(",");
|
||||
}
|
||||
|
||||
/**
|
||||
* Plage horaire d'affichage (heures pleines).
|
||||
* Lue depuis admin_config (Paramètres → Apparence → Heures de la journée),
|
||||
* défaut 8h-18h. Utilisée pour les paramètres day_start_hour / day_end_hour /
|
||||
* begin_hour / end_hour des requêtes EV. Le viewer utilise déjà ces mêmes
|
||||
* valeurs pour dessiner la timeline (cf. _initDayBoundsFromConfig dans viewer.js).
|
||||
*/
|
||||
async function getDayBounds() {
|
||||
const cfg = await getAdminConfig();
|
||||
const start = (typeof cfg.dayStart === "number" && cfg.dayStart >= 0 && cfg.dayStart <= 23) ? cfg.dayStart : 8;
|
||||
const end = (typeof cfg.dayEnd === "number" && cfg.dayEnd > start && cfg.dayEnd <= 24) ? cfg.dayEnd : 18;
|
||||
return { start, end };
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Clic sur l'icône → ouvrir le viewer
|
||||
@@ -147,8 +210,10 @@ chrome.action.onClicked.addListener(async () => {
|
||||
* @author Quentin Rouiller
|
||||
*/
|
||||
async function findEasyVistaSession() {
|
||||
// Chercher tous les onglets sur un domaine EasyVista
|
||||
for (const origin of EV_ORIGINS) {
|
||||
// v2026.5.41 : les origines EV viennent de admin_config (éditables dans
|
||||
// Paramètres → EasyVista), avec fallback sur DEFAULT_EV_ORIGINS.
|
||||
const origins = await getEvOrigins();
|
||||
for (const origin of origins) {
|
||||
const tabs = await chrome.tabs.query({ url: origin + "/*" });
|
||||
for (const tab of tabs) {
|
||||
const m = (tab.url || "").match(/[?&]PHPSESSID=([a-zA-Z0-9]+)/);
|
||||
@@ -175,8 +240,20 @@ async function findEasyVistaSession() {
|
||||
* @author Quentin Rouiller
|
||||
*/
|
||||
async function fetchPlanningXml(origin, phpsessid, unixDate) {
|
||||
const techIds = "76272,83725,66635,92235,90070,40944,72485,86874";
|
||||
const groupId = "191";
|
||||
// v2026.5.41 : groupId vient de admin_config (défaut SI-CSS).
|
||||
// techIds vient de admin_config — si vide, on lève une erreur claire pour
|
||||
// que le viewer affiche "Aucun technicien sélectionné" plutôt qu'un planning vide.
|
||||
const groupId = await getGroupId();
|
||||
const techIds = await getSupportIds();
|
||||
if (!techIds) {
|
||||
const err = new Error("no_team_configured");
|
||||
err.kind = "no_team_configured";
|
||||
throw err;
|
||||
}
|
||||
// v2026.5.41 : heures synchronisées avec admin_config (Paramètres → Apparence).
|
||||
// EV utilise day_end_hour exclusif (la plage rendue va jusqu'à end-1:59),
|
||||
// donc on envoie end+1 pour que la dernière heure pleine soit incluse.
|
||||
const { start, end } = await getDayBounds();
|
||||
const url =
|
||||
`${origin}/planning_xhr.php` +
|
||||
`?PHPSESSID=${encodeURIComponent(phpsessid)}` +
|
||||
@@ -190,8 +267,8 @@ async function fetchPlanningXml(origin, phpsessid, unixDate) {
|
||||
`&end_date_label=Date` +
|
||||
`&click_here_label=Ici` +
|
||||
`&mail_title=mail` +
|
||||
`&day_start_hour=8` +
|
||||
`&day_end_hour=19`;
|
||||
`&day_start_hour=${start}` +
|
||||
`&day_end_hour=${end + 1}`;
|
||||
// v2026.5.38 : on retire les logs verbose à chaque fetch (URL/status/taille).
|
||||
// En cas de souci, le throw plus bas porte assez d'info pour debug.
|
||||
const r = await evFetch(url, origin);
|
||||
@@ -714,6 +791,8 @@ async function submitAbsence(origin, phpsessid, opts) {
|
||||
const emplIds = (opts.techIds || []).join(",");
|
||||
if (!emplIds) throw new Error("Aucun technicien sélectionné");
|
||||
|
||||
// v2026.5.41 : heures synchronisées avec admin_config.
|
||||
const { start, end } = await getDayBounds();
|
||||
const internalurltime = Math.floor(Date.now() / 1000);
|
||||
const url = `${origin}/include/components/staff/planning/plan_set_holidays_popup.php`
|
||||
+ `?PHPSESSID=${encodeURIComponent(phpsessid)}`
|
||||
@@ -722,8 +801,8 @@ async function submitAbsence(origin, phpsessid, opts) {
|
||||
+ `&ROOT_DIRECTORY=${encodeURIComponent("/ccv/data/www/itsma/htdocs/")}`
|
||||
+ `¤t_date=${encodeURIComponent(opts.currentDate)}`
|
||||
+ `&empl_ids=${encodeURIComponent(emplIds)}`
|
||||
+ `&begin_hour=8`
|
||||
+ `&end_hour=18`
|
||||
+ `&begin_hour=${start}`
|
||||
+ `&end_hour=${end}`
|
||||
+ `&plagehoraire=0`;
|
||||
|
||||
const body = new URLSearchParams();
|
||||
@@ -785,6 +864,8 @@ async function submitDouchette(origin, phpsessid, opts) {
|
||||
const techIds = opts.techIds || [];
|
||||
if (techIds.length === 0) throw new Error("Aucun technicien sélectionné");
|
||||
|
||||
// v2026.5.41 : heures synchronisées avec admin_config.
|
||||
const { start, end } = await getDayBounds();
|
||||
const emplIds = techIds.join(",");
|
||||
const internalurltime = Math.floor(Date.now() / 1000);
|
||||
const url = `${origin}/include/components/staff/planning/plan_set_tech_planif_popup.php`
|
||||
@@ -794,8 +875,8 @@ async function submitDouchette(origin, phpsessid, opts) {
|
||||
+ `&ROOT_DIRECTORY=${encodeURIComponent("/ccv/data/www/itsma/htdocs/")}`
|
||||
+ `¤t_date=${encodeURIComponent(opts.currentDate)}`
|
||||
+ `&empl_ids=${encodeURIComponent(emplIds)}`
|
||||
+ `&begin_hour=8`
|
||||
+ `&end_hour=18`
|
||||
+ `&begin_hour=${start}`
|
||||
+ `&end_hour=${end}`
|
||||
+ `&plagehoraire=0`;
|
||||
|
||||
const body = new URLSearchParams();
|
||||
@@ -1034,18 +1115,14 @@ async function detectGroupsFromEV(origin, phpsessid) {
|
||||
* Retourne { ids: [{id, name, alreadyInTeam}], groupId }.
|
||||
*/
|
||||
async function detectTeamFromEV(origin, phpsessid, groupIdArg, supportIdsArg) {
|
||||
// v5.0.1 : valeurs par défaut (correspondent au groupe actuel).
|
||||
// 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 = groupIdArg || DEFAULT_GROUP_ID;
|
||||
// v2026.5.41 : groupId vient de l'argument, sinon de admin_config (défaut SI-CSS).
|
||||
// supportIds vient de l'argument, sinon de admin_config (vide tant que rien n'est
|
||||
// sélectionné). Le serveur retourne tous les membres du groupe quoi qu'il arrive ;
|
||||
// supportIds sert juste à pré-cocher les techs déjà inclus dans l'équipe.
|
||||
const groupId = groupIdArg || await getGroupId();
|
||||
const supportIds = (typeof supportIdsArg === "string")
|
||||
? supportIdsArg
|
||||
: (groupId === DEFAULT_GROUP_ID ? DEFAULT_SUPPORT_IDS : "");
|
||||
: await getSupportIds();
|
||||
console.log("[bg] detectTeamFromEV : group_id =", groupId, "| support_ids =", supportIds);
|
||||
|
||||
// Fetch la popup de sélection des intervenants du groupe
|
||||
@@ -1068,8 +1145,9 @@ async function detectTeamFromEV(origin, phpsessid, groupIdArg, supportIdsArg) {
|
||||
if (looksLikeLoginPage(popupHtml)) throw new Error("session_expired");
|
||||
} catch (e) {
|
||||
console.warn("[bg] detectTeam: fetch popup failed:", e);
|
||||
// Fallback : au moins on retourne les IDs connus avec noms vides
|
||||
const ids = DEFAULT_SUPPORT_IDS.split(",").filter(Boolean);
|
||||
// v2026.5.41 : on retourne les IDs déjà sélectionnés par l'user (s'il y en a)
|
||||
// plutôt qu'une liste hardcodée. Si vide, le viewer affichera juste 0 résultat.
|
||||
const ids = supportIds.split(",").filter(Boolean);
|
||||
return {
|
||||
ids: ids.map(id => ({ id, name: "? (" + id + ")", alreadyInTeam: true })),
|
||||
groupId
|
||||
|
||||
Reference in New Issue
Block a user