Public Access
Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d6b94e7cf3 | ||
|
|
5f6802a3ab |
@@ -9,6 +9,62 @@
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## v2026.5.48 — Notification par email des déplacements, onglet Email, fiches réservation fiables entre postes, recherche et reconnexion durcies
|
||||||
|
|
||||||
|
> Cette version apporte une vraie nouveauté : après le déplacement d'une intervention (autre jour ou autre technicien), l'extension peut ouvrir un **brouillon d'email pré-rempli** dans votre application mail pour prévenir les techniciens concernés — l'envoi reste un geste manuel. Elle corrige aussi en profondeur la circulation des informations de réservation entre postes, le bouton de reconnexion quand il n'y a aucun cache, et plusieurs comportements de la recherche.
|
||||||
|
|
||||||
|
### Email après un déplacement (nouveau)
|
||||||
|
|
||||||
|
- **Brouillon automatique** : après un déplacement vers un **autre jour** ou un **autre technicien** (fenêtre de modification ou glisser-déposer), un brouillon pré-adressé aux deux techniciens s'ouvre dans l'application mail (ex. Outlook). Un simple ajustement d'heures n'ouvre rien. **Rien n'est envoyé automatiquement.**
|
||||||
|
- **Case « Prévenir les techniciens par email »** dans les fenêtres de déplacement : quand l'option est active, la décocher ne vaut que pour **ce déplacement-là** — le prochain déplacement la retrouve cochée. L'option ne se désactive durablement que dans les Paramètres.
|
||||||
|
- **Destinataires** séparés par « ; » (compatibilité Outlook) ; si une adresse manque, le brouillon s'ouvre quand même, à compléter directement dans l'email (une notification indique qui manque).
|
||||||
|
- **Nouvel onglet « Email »** dans les Paramètres : option, et **modèle du message** entièrement personnalisable (sujet + texte), avec **variables cliquables** rangées par thème (Intervention / Avant / Après) et **aperçu en direct** sur un exemple. Le modèle de base présente le déplacement en deux blocs AVANT / APRÈS bien lisibles.
|
||||||
|
- **Adresses des techniciens** dans l'onglet Équipe (colonne Email, boutons au-dessus de la liste) : bouton « **Récupérer les emails** » qui remplit les adresses manquantes depuis l'annuaire EasyVista — et **complète au passage un nom affiché tronqué** (ex. « Martins » → « De Almeida Martins »), avec un garde-fou contre les homonymes. Une adresse saisie à la main n'est jamais écrasée. Champ vide = adresse proposée `prenom.nom@domaine` (domaine réglable au même endroit, appliqué à tous).
|
||||||
|
|
||||||
|
### Informations de réservation fiables entre postes
|
||||||
|
|
||||||
|
- Les informations saisies sur une réservation (n° d'intervention, ville, rue, catégorie) **voyagent désormais avec la réservation** dans le dossier partagé, horodatées : la modification la plus récente gagne, sur tous les postes.
|
||||||
|
- Fin des « fuites » d'informations : une réservation posée par un autre coordinateur ne récupère plus les infos d'une réservation précédente au même créneau, un identifiant recyclé par EasyVista ne fait plus hériter les infos d'un autre technicien, et un champ volontairement vidé ne « ressuscite » plus.
|
||||||
|
- Une réservation **re-planifiée directement dans EasyVista** conserve ses informations quand le rapprochement est sans ambiguïté.
|
||||||
|
- Divers : le pompier du jour n'est plus compté en double dans les statistiques ; « réservé toute la journée » se calcule sur les heures affichées ; les champs pré-remplis du formulaire ne sont plus écrasés par le remplissage automatique.
|
||||||
|
|
||||||
|
### Reconnexion et recherche
|
||||||
|
|
||||||
|
- **Bouton « Ouvrir EasyVista »** (écran « Session expirée » sans aucun cache) : après la reconnexion, l'écran se ferme réellement et le planning s'affiche ; re-cliquer relance le chargement au lieu d'être ignoré.
|
||||||
|
- **Recherche** : la recherche part de façon fiable quand on arrête de taper (les relances au survol ne l'interrompent plus), **Entrée** lance la recherche immédiatement, la roue de chargement est visible dès le début, déplier « Planifiée (passé) » ne ferme plus la zone de résultats, et seuls les statuts **Clôturé / Fait** sont affichés sur les résultats.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## v2026.5.47 — Vue « échelle de temps exacte » : aide à la saisie, erreurs mises en évidence, corrections de fiabilité
|
||||||
|
|
||||||
|
> Cette version peaufine la vue horizontale « échelle de temps exacte » : un vrai retour visuel accompagne la pose d'un rendez-vous ou d'une absence, et les erreurs de saisie (rendez-vous dont le début est égal à la fin) sont désormais bien visibles et signalées. Elle corrige aussi plusieurs problèmes de navigation entre dates et de synchronisation du dossier partagé, réorganise le panneau de synchronisation, et ajoute un bouton de test de la communication avec le script du poste.
|
||||||
|
|
||||||
|
### Vue « échelle de temps exacte » — aide à la saisie
|
||||||
|
|
||||||
|
- **Retour visuel au survol d'un créneau libre** : une zone surlignée suit la souris et affiche **l'heure exacte** (début → fin) du rendez-vous ou de l'absence qu'un clic droit poserait. Une bulle fixe, en haut de la ligne, rappelle la **plage libre et la durée disponible** du créneau (« Libre 12:00–18:00 / 6 h disponible »). Elle se place toujours sur un espace libre — jamais par-dessus un rendez-vous — et ne masque pas l'heure choisie.
|
||||||
|
- **Erreurs de saisie mises en évidence** : un rendez-vous dont le **début est égal à la fin** (ex. 10:00 → 10:00) est désormais affiché en **rouge** et reste **visible** (avant, il disparaissait sur l'échelle exacte). Survoler une telle zone pour en poser un autre affiche un **avertissement** et **empêche** la création tant que l'erreur n'est pas corrigée.
|
||||||
|
- **Interventions courtes visibles** : une intervention de 1 à 5 minutes garde une largeur minimale et reste visible.
|
||||||
|
- **Zone du nom** : le fond du nom du technicien remplit toute la hauteur de la ligne (nom centré).
|
||||||
|
- **Barre des heures** : reste collée en haut au défilement et passe sous la banderole de reconnexion (au lieu de disparaître derrière).
|
||||||
|
|
||||||
|
### Corrections de fiabilité
|
||||||
|
|
||||||
|
- **Navigation rapide entre dates** : le jour que l'on quitte ne peut plus écraser le jour qui vient de s'afficher.
|
||||||
|
- **Technicien retiré de l'équipe** : n'apparaît plus sur les jours relus depuis le dossier partagé.
|
||||||
|
- **Synchronisation du dossier partagé** : correction d'un blocage où l'écriture n'aboutissait jamais (conflit permanent entre l'index et le fichier relu) ; l'index se répare de lui-même.
|
||||||
|
- **Jour présent au dossier mais pas en local** : lu depuis le dossier d'emblée — plus de re-remplissage visible inutile.
|
||||||
|
- **Absences** : plus de doublon « absence récurrente » + « vraie absence » le même jour ; le fond des cartes d'absence remplit toute la carte en échelle exacte.
|
||||||
|
- **Réservations multiples le même jour** : les deux créneaux coexistent ; saisir le n° d'intervention dans le formulaire remplit automatiquement ville, rue et catégorie.
|
||||||
|
- **Barre de progression** et **message de reconnexion** : bien positionnés en vue horizontale (barre en haut de la sidebar, message centré dans le contenu).
|
||||||
|
|
||||||
|
### Synchronisation multi-postes
|
||||||
|
|
||||||
|
- **Nouveau bouton « Tester la communication »** (onglet Synchro) : diagnostic de bout en bout extension → script du poste → dossier partagé.
|
||||||
|
- **Panneau Synchro réorganisé** en sections claires : état de la synchro, dossier partagé, script sur le poste, journal d'activité.
|
||||||
|
- **Script du poste (native messaging host) 2026.1.8** : verrou dédié sur l'index du dossier partagé (protège l'écriture simultanée par plusieurs postes ou onglets) et icône de la zone de notification ré-affichée au redémarrage de l'explorateur Windows. Le bouton « Télécharger le script » récupère cette version.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## v2026.5.46 — Refonte de la couche données, vue « échelle de temps exacte », session fiabilisée, réservations enrichies
|
## v2026.5.46 — Refonte de la couche données, vue « échelle de temps exacte », session fiabilisée, réservations enrichies
|
||||||
|
|
||||||
> Version majeure par son contenu : la couche données est entièrement refondue (store unifié par jour, un seul verdict par intervention, synchronisation du dossier partagé en sous-dossier `v2`), une nouvelle disposition « échelle de temps exacte » s'ajoute à la vue horizontale, la détection de session EasyVista est fiabilisée de bout en bout, et les réservations portent enfin leurs informations (n°, lieu, catégorie) sur tous les postes. Le script PowerShell du dossier partagé est désormais publié avec l'extension et téléchargeable depuis les Paramètres.
|
> Version majeure par son contenu : la couche données est entièrement refondue (store unifié par jour, un seul verdict par intervention, synchronisation du dossier partagé en sous-dossier `v2`), une nouvelle disposition « échelle de temps exacte » s'ajoute à la vue horizontale, la détection de session EasyVista est fiabilisée de bout en bout, et les réservations portent enfin leurs informations (n°, lieu, catégorie) sur tous les postes. Le script PowerShell du dossier partagé est désormais publié avec l'extension et téléchargeable depuis les Paramètres.
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ Extension Chrome / Firefox pour visualiser de manière claire et rapide le plann
|
|||||||
- **Auteur** : Quentin Rouiller (QRO), Technicien DGNSI — Canton de Vaud
|
- **Auteur** : Quentin Rouiller (QRO), Technicien DGNSI — Canton de Vaud
|
||||||
- **Public cible** : coordinateurs DGNSI qui pilotent dans EasyVista (`itsma.etat-de-vaud.ch` / `itsma.vd.ch`) le planning de l'équipe technicienne
|
- **Public cible** : coordinateurs DGNSI qui pilotent dans EasyVista (`itsma.etat-de-vaud.ch` / `itsma.vd.ch`) le planning de l'équipe technicienne
|
||||||
- **Démarrage projet** : jeudi 16 avril 2026
|
- **Démarrage projet** : jeudi 16 avril 2026
|
||||||
- **Version actuelle** : [`v2026.5.45`](https://gitea.netaplaid.ch/FroSteel/Planification/releases/tag/v2026.5.45) (latest)
|
- **Version actuelle** : [`v2026.5.48`](https://gitea.netaplaid.ch/FroSteel/Planification/releases/tag/v2026.5.48) (latest)
|
||||||
- **Contact** : voir [page wiki Contact](https://gitea.netaplaid.ch/FroSteel/Planification/wiki/Contact) ou [ouvrir une issue](https://gitea.netaplaid.ch/FroSteel/Planification/issues/new)
|
- **Contact** : voir [page wiki Contact](https://gitea.netaplaid.ch/FroSteel/Planification/wiki/Contact) ou [ouvrir une issue](https://gitea.netaplaid.ch/FroSteel/Planification/issues/new)
|
||||||
- **Manifest** : V3 (Chrome/Edge/Firefox 140+)
|
- **Manifest** : V3 (Chrome/Edge/Firefox 140+)
|
||||||
- **Format** : `.zip` (Chromium) + `.xpi` signé Mozilla (Firefox)
|
- **Format** : `.zip` (Chromium) + `.xpi` signé Mozilla (Firefox)
|
||||||
@@ -66,6 +66,12 @@ Les mises à jour sont **manuelles** : à chaque nouvelle release, retélécharg
|
|||||||
- Badge + barre gauche colorée + dégradé fond
|
- Badge + barre gauche colorée + dégradé fond
|
||||||
- Absences récurrentes (configurées par tech) : cyan (depuis v2026.5.30)
|
- Absences récurrentes (configurées par tech) : cyan (depuis v2026.5.30)
|
||||||
|
|
||||||
|
### Email après un déplacement (depuis v2026.5.48)
|
||||||
|
- Brouillon d'email pré-adressé aux deux techniciens après un déplacement vers un autre jour ou un autre technicien (fenêtre de modification ou glisser-déposer) — l'envoi reste manuel, rien ne part automatiquement
|
||||||
|
- Case « Prévenir les techniciens par email » dans les fenêtres de déplacement : la décocher ne vaut que pour ce déplacement-là
|
||||||
|
- Onglet Paramètres → Email : option et modèle du message personnalisable (variables cliquables par thème, aperçu en direct)
|
||||||
|
- Adresses des techniciens dans l'onglet Équipe : récupération depuis l'annuaire EasyVista (complète aussi un nom affiché tronqué), déduction `prenom.nom@domaine` sinon
|
||||||
|
|
||||||
### User et session
|
### User et session
|
||||||
- Badge user avec photo/initiales en topbar
|
- Badge user avec photo/initiales en topbar
|
||||||
- Badge cliquable (depuis v2026.5.26) : popup avec ⚙ Paramètres + ⊞ Vue + compteur session MM:SS
|
- Badge cliquable (depuis v2026.5.26) : popup avec ⚙ Paramètres + ⊞ Vue + compteur session MM:SS
|
||||||
@@ -115,7 +121,20 @@ Le numéro de **majeure** n'est **pas** un mois et **pas** un chiffre lié au ca
|
|||||||
|
|
||||||
## Versions notables
|
## Versions notables
|
||||||
|
|
||||||
### `v2026.5.46` (latest, 9 juillet 2026) — Couche données v2, vue « échelle de temps exacte », session fiabilisée, réservations partagées
|
### `v2026.5.48` (latest, 24 juillet 2026) — Notification par email des déplacements, onglet Email, fiches réservation fiables entre postes
|
||||||
|
|
||||||
|
- Brouillon d'email pré-rempli après un déplacement (autre jour ou autre technicien), modèle personnalisable avec variables et aperçu, case par déplacement
|
||||||
|
- Adresses des techniciens depuis l'annuaire EasyVista, noms tronqués complétés, domaine configurable
|
||||||
|
- Les informations de réservation voyagent avec la réservation entre les postes (horodatées, plus de fuites entre créneaux ou techniciens)
|
||||||
|
- Bouton « Ouvrir EasyVista » fiable sans cache ; recherche durcie (Entrée immédiate, plus d'interruptions au survol, statuts finals seulement)
|
||||||
|
|
||||||
|
### `v2026.5.47` (18 juillet 2026) — Vue « échelle de temps exacte » : aide à la saisie, erreurs mises en évidence
|
||||||
|
|
||||||
|
- Retour visuel de pose (zone + heure choisie + bulle « temps disponible »), rendez-vous à durée nulle visibles en rouge et bloquants, interventions courtes visibles
|
||||||
|
- Corrections : navigation rapide entre dates, synchro du dossier partagé (conflit d'index), doublons d'absences, réservations multiples le même jour
|
||||||
|
- Panneau Synchro réorganisé + bouton « Tester la communication » ; script du poste 2026.1.8
|
||||||
|
|
||||||
|
### `v2026.5.46` (9 juillet 2026) — Couche données v2, vue « échelle de temps exacte », session fiabilisée, réservations partagées
|
||||||
|
|
||||||
- Refonte complète de la couche données : store unifié par jour, un seul verdict par intervention, synchronisation du dossier partagé en sous-dossier v2
|
- Refonte complète de la couche données : store unifié par jour, un seul verdict par intervention, synchronisation du dossier partagé en sous-dossier v2
|
||||||
- Nouvelle disposition « échelle de temps exacte » pour la vue horizontale (option Apparence)
|
- Nouvelle disposition « échelle de temps exacte » pour la vue horizontale (option Apparence)
|
||||||
|
|||||||
+11
-1
@@ -2,10 +2,20 @@
|
|||||||
"addons": {
|
"addons": {
|
||||||
"[email protected]": {
|
"[email protected]": {
|
||||||
"updates": [
|
"updates": [
|
||||||
|
{
|
||||||
|
"version": "2026.5.48",
|
||||||
|
"update_link": "https://gitea.netaplaid.ch/FroSteel/Planification/releases/download/v2026.5.48/planification-v2026.5.48-firefox.xpi",
|
||||||
|
"update_hash": "sha256:be687aa2795649d7f1f9883f3384365bd224e0ab94987ff852b0901f5554a51a"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"version": "2026.5.47",
|
||||||
|
"update_link": "https://gitea.netaplaid.ch/FroSteel/Planification/releases/download/v2026.5.47/planification-v2026.5.47-firefox.xpi",
|
||||||
|
"update_hash": "sha256:0418062357b7c29bdd7a01b6d6e06eeb20e2ee419c67684a84855862af113cc2"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"version": "2026.5.46",
|
"version": "2026.5.46",
|
||||||
"update_link": "https://gitea.netaplaid.ch/FroSteel/Planification/releases/download/v2026.5.46/planification-v2026.5.46-firefox.xpi",
|
"update_link": "https://gitea.netaplaid.ch/FroSteel/Planification/releases/download/v2026.5.46/planification-v2026.5.46-firefox.xpi",
|
||||||
"update_hash": "sha256:052cac5d79a8ec9f1eeb7172e8491f2e2a82b5937622131905cfcaa3eba4737b"
|
"update_hash": "sha256:673dc0527073523750de348414ae1d3b5c0cb42cc8128a7839bbb09bffb6242c"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"version": "2026.5.45",
|
"version": "2026.5.45",
|
||||||
|
|||||||
+38
-12
@@ -30,7 +30,7 @@
|
|||||||
$ErrorActionPreference = 'Stop'
|
$ErrorActionPreference = 'Stop'
|
||||||
$ProgressPreference = 'SilentlyContinue'
|
$ProgressPreference = 'SilentlyContinue'
|
||||||
|
|
||||||
$HOST_VERSION = '2026.1.7'
|
$HOST_VERSION = '2026.1.8'
|
||||||
# v2026.1.7 - le host n'est plus persistant a vie : s'il ne recoit AUCUN message
|
# v2026.1.7 - le host n'est plus persistant a vie : s'il ne recoit AUCUN message
|
||||||
# pendant ce delai, il se ferme proprement (le navigateur le relance a la
|
# pendant ce delai, il se ferme proprement (le navigateur le relance a la
|
||||||
# prochaine activite de l'extension). Il lance aussi le tray a la demande.
|
# prochaine activite de l'extension). Il lance aussi le tray a la demande.
|
||||||
@@ -155,18 +155,44 @@ function Read-Index([string]$share) {
|
|||||||
|
|
||||||
function Update-Index([string]$share, [string]$date, [long]$savedAt) {
|
function Update-Index([string]$share, [string]$date, [long]$savedAt) {
|
||||||
$idx = Join-Path $share $INDEX_NAME
|
$idx = Join-Path $share $INDEX_NAME
|
||||||
$map = @{}
|
# v2026.1.8 - verrou DEDIE a l'index. Plusieurs hotes (plusieurs onglets
|
||||||
if (Test-Path -LiteralPath $idx) {
|
# Planification ouverts, ou plusieurs postes) font un read-modify-write
|
||||||
try {
|
# concurrent sur _index.json ; sans verrou, deux Move-Item se recouvrent et la
|
||||||
$existing = Get-Content -LiteralPath $idx -Raw -Encoding UTF8 | ConvertFrom-Json
|
# maj d'un hote est perdue (lost update) -> l'index prend du retard sur les
|
||||||
foreach ($p in $existing.PSObject.Properties) { $map[$p.Name] = $p.Value }
|
# fichiers-jour -> conflits CAS a repetition ("refusion" en boucle). On
|
||||||
} catch {}
|
# serialise donc la sequence lecture->modif->ecriture. Vol du verrou perime
|
||||||
|
# (> 10 s) comme pour les fichiers-jour. Best-effort : si on n'obtient pas le
|
||||||
|
# verrou, on renonce (la prochaine ecriture reussie remettra l'index a jour).
|
||||||
|
$lock = $idx + '.lock'
|
||||||
|
$haveLock = $false
|
||||||
|
for ($i = 0; $i -lt 20 -and -not $haveLock; $i++) {
|
||||||
|
try { [System.IO.File]::Open($lock, [System.IO.FileMode]::CreateNew, [System.IO.FileAccess]::Write).Close(); $haveLock = $true }
|
||||||
|
catch {
|
||||||
|
try {
|
||||||
|
$age = ((Get-Date) - (Get-Item -LiteralPath $lock).LastWriteTime).TotalSeconds
|
||||||
|
if ($age -gt 10) { Remove-Item -LiteralPath $lock -Force -ErrorAction SilentlyContinue }
|
||||||
|
else { Start-Sleep -Milliseconds 50 }
|
||||||
|
} catch { Start-Sleep -Milliseconds 50 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (-not $haveLock) { Write-Activity 'DEBUG' "Index non mis a jour pour le $(Format-DateFR $date) (verrou index indisponible)"; return }
|
||||||
|
try {
|
||||||
|
# lecture DANS le verrou -> on part toujours de la derniere version.
|
||||||
|
$map = @{}
|
||||||
|
if (Test-Path -LiteralPath $idx) {
|
||||||
|
try {
|
||||||
|
$existing = Get-Content -LiteralPath $idx -Raw -Encoding UTF8 | ConvertFrom-Json
|
||||||
|
foreach ($p in $existing.PSObject.Properties) { $map[$p.Name] = $p.Value }
|
||||||
|
} catch {}
|
||||||
|
}
|
||||||
|
$map[$date] = $savedAt
|
||||||
|
$tmp = $idx + '.tmp'
|
||||||
|
[System.IO.File]::WriteAllText($tmp, ($map | ConvertTo-Json -Compress -Depth 5), $Utf8NoBom)
|
||||||
|
Move-Item -LiteralPath $tmp -Destination $idx -Force
|
||||||
|
Write-Activity 'DEBUG' "Index du dossier mis a jour pour le $(Format-DateFR $date)"
|
||||||
|
} finally {
|
||||||
|
Remove-Item -LiteralPath $lock -Force -ErrorAction SilentlyContinue
|
||||||
}
|
}
|
||||||
$map[$date] = $savedAt
|
|
||||||
$tmp = $idx + '.tmp'
|
|
||||||
[System.IO.File]::WriteAllText($tmp, ($map | ConvertTo-Json -Compress -Depth 5), $Utf8NoBom)
|
|
||||||
Move-Item -LiteralPath $tmp -Destination $idx -Force
|
|
||||||
Write-Activity 'DEBUG' "Index du dossier mis a jour pour le $(Format-DateFR $date)"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function Get-SavedAt([string]$share, [string]$date, [string]$file) {
|
function Get-SavedAt([string]$share, [string]$date, [string]$file) {
|
||||||
|
|||||||
@@ -160,6 +160,35 @@ $ni.Icon = Get-TrayIcon
|
|||||||
$ni.Text = 'Planification - synchronisation active'
|
$ni.Text = 'Planification - synchronisation active'
|
||||||
$ni.Visible = $true
|
$ni.Visible = $true
|
||||||
|
|
||||||
|
# v2026.1.8 - "toujours present si actif" : le NotifyIcon disparait quand
|
||||||
|
# explorer.exe redemarre (Windows rediffuse alors le message "TaskbarCreated").
|
||||||
|
# Sans le traiter, l'icone ne revient JAMAIS tant que le tray tourne. On ecoute
|
||||||
|
# ce message via une petite fenetre native et on re-affiche l'icone.
|
||||||
|
try {
|
||||||
|
Add-Type -ReferencedAssemblies System.Windows.Forms -TypeDefinition @'
|
||||||
|
using System;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
public class PlanifTrayWatcher : NativeWindow {
|
||||||
|
[DllImport("user32.dll", CharSet = CharSet.Auto)]
|
||||||
|
static extern uint RegisterWindowMessage(string lpString);
|
||||||
|
public static readonly uint TaskbarCreated = RegisterWindowMessage("TaskbarCreated");
|
||||||
|
private NotifyIcon _icon;
|
||||||
|
public PlanifTrayWatcher(NotifyIcon icon) {
|
||||||
|
_icon = icon;
|
||||||
|
this.CreateHandle(new CreateParams());
|
||||||
|
}
|
||||||
|
protected override void WndProc(ref Message m) {
|
||||||
|
if (m.Msg == TaskbarCreated && _icon != null) {
|
||||||
|
try { _icon.Visible = false; _icon.Visible = true; } catch {}
|
||||||
|
}
|
||||||
|
base.WndProc(ref m);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
'@ -ErrorAction Stop
|
||||||
|
$script:trayWatcher = New-Object PlanifTrayWatcher($ni)
|
||||||
|
} catch {}
|
||||||
|
|
||||||
$menu = New-Object System.Windows.Forms.ContextMenuStrip
|
$menu = New-Object System.Windows.Forms.ContextMenuStrip
|
||||||
$miLog = $menu.Items.Add('Voir le journal de synchronisation')
|
$miLog = $menu.Items.Add('Voir le journal de synchronisation')
|
||||||
$miLog.add_Click({ Show-LogWindow })
|
$miLog.add_Click({ Show-LogWindow })
|
||||||
|
|||||||
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"manifest_version": 3,
|
"manifest_version": 3,
|
||||||
"name": "Planification",
|
"name": "Planification",
|
||||||
"version": "2026.5.46",
|
"version": "2026.5.48",
|
||||||
"description": "Vue claire et rapide du planning des techniciens EasyVista. Développé par Quentin Rouiller — DGNSI, Canton de Vaud.",
|
"description": "Vue claire et rapide du planning des techniciens EasyVista. Développé par Quentin Rouiller — DGNSI, Canton de Vaud.",
|
||||||
"key": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAl/El4I9gxcZkp5bnheg4ZBCKxckRLt9xQ5x+i6phEPYlydl6NapWlkbOyycUaeTZcpoEh/tKQnpMpoEc5jY8zCoRTwh/vfejVBZE6ANDG/dc3iix/1Z8OhRI4zMaRYQ+DQTjS5Q6l6wkcwzbQB85HZNhke/k1qIW6RCuBjeJYmES5WVDwzfCNVvaF6uQvdOCpLjrA3+LI6vUBEwaMg1hM42mC3dU0z9p7qzAby/dH3XpZD9HTFXLJL9/1zryN9rXNDpvZwYWnJ0hLTu5tfmURkvgKOwquX1KJy9vupmhUALRtS08Fplx/e3kUH3LD+coS1ExLwoOZ+1ORBUE9JCB8wIDAQAB",
|
"key": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAl/El4I9gxcZkp5bnheg4ZBCKxckRLt9xQ5x+i6phEPYlydl6NapWlkbOyycUaeTZcpoEh/tKQnpMpoEc5jY8zCoRTwh/vfejVBZE6ANDG/dc3iix/1Z8OhRI4zMaRYQ+DQTjS5Q6l6wkcwzbQB85HZNhke/k1qIW6RCuBjeJYmES5WVDwzfCNVvaF6uQvdOCpLjrA3+LI6vUBEwaMg1hM42mC3dU0z9p7qzAby/dH3XpZD9HTFXLJL9/1zryN9rXNDpvZwYWnJ0hLTu5tfmURkvgKOwquX1KJy9vupmhUALRtS08Fplx/e3kUH3LD+coS1ExLwoOZ+1ORBUE9JCB8wIDAQAB",
|
||||||
"permissions": [
|
"permissions": [
|
||||||
|
|||||||
+181
-14
@@ -1130,6 +1130,18 @@ html.view-classic .error-box.error-box-centered {
|
|||||||
box-shadow: var(--shadow);
|
box-shadow: var(--shadow);
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
/* v2026.5.47 — message de reconnexion EasyVista (#session-needed /
|
||||||
|
#ev-unreachable) CENTRÉ dans la zone de contenu en vue horizontale (avant :
|
||||||
|
posé en haut, comme un item flex de main#main). main#main est
|
||||||
|
position:relative en horizontal ; on centre dans le contenu (à droite de la
|
||||||
|
sidebar) via left = 50% + --sidebar-w/2. */
|
||||||
|
html.view-horizontal .session-needed {
|
||||||
|
position: absolute !important;
|
||||||
|
top: 50% !important;
|
||||||
|
left: calc(50% + var(--sidebar-w, 200px) / 2) !important;
|
||||||
|
transform: translate(-50%, -50%) !important;
|
||||||
|
margin: 0 !important;
|
||||||
|
}
|
||||||
.session-needed h2 {
|
.session-needed h2 {
|
||||||
margin: 0 0 12px 0;
|
margin: 0 0 12px 0;
|
||||||
color: var(--text);
|
color: var(--text);
|
||||||
@@ -1549,6 +1561,35 @@ html.view-horizontal .timeline-noon {
|
|||||||
background: #c44040 !important;
|
background: #c44040 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* v2026.5.47 — intervention à DURÉE NULLE (début == fin, ex. 10:00→10:00 :
|
||||||
|
erreur de saisie EV). Même rouge plein que les conflits ci-dessus, pour la
|
||||||
|
repérer d'un coup d'oeil dans toutes les vues. */
|
||||||
|
.iv-mini-card.iv-zero-duration {
|
||||||
|
background: #b03030 !important;
|
||||||
|
color: #ffffff !important;
|
||||||
|
border-color: #7a1f1f !important;
|
||||||
|
}
|
||||||
|
.iv-mini-card.iv-zero-duration .iv-mini-card-bar,
|
||||||
|
.iv-mini-card.iv-zero-duration .iv-mini-time-vertical,
|
||||||
|
.iv-mini-card.iv-zero-duration .iv-mini-card-text {
|
||||||
|
color: #ffffff !important;
|
||||||
|
background: transparent !important;
|
||||||
|
}
|
||||||
|
/* Vue exacte : la bulle est très fine (min-width) → le bord gauche (poignée)
|
||||||
|
doit être rouge lui aussi, sinon on ne verrait que sa couleur de catégorie. */
|
||||||
|
html.view-horizontal .iv-exact-card.iv-zero-duration .iv-exact-handle {
|
||||||
|
background-color: #7a1f1f !important;
|
||||||
|
background-image: none !important;
|
||||||
|
}
|
||||||
|
/* v2026.5.47 — durée nulle PLUS VISIBLE en vue exacte : un peu plus large
|
||||||
|
que les interventions courtes (11 px vs 6 px) + hachures rouges pour attirer
|
||||||
|
l'oeil sur l'erreur. */
|
||||||
|
html.view-horizontal .iv-exact-card.iv-zero-duration {
|
||||||
|
min-width: 11px !important;
|
||||||
|
background-image: repeating-linear-gradient(
|
||||||
|
45deg, #b03030 0 4px, #7a1f1f 4px 8px) !important;
|
||||||
|
}
|
||||||
|
|
||||||
/* ==========================================================================
|
/* ==========================================================================
|
||||||
Interventions — layout v2 (heures verticales)
|
Interventions — layout v2 (heures verticales)
|
||||||
========================================================================== */
|
========================================================================== */
|
||||||
@@ -4352,6 +4393,16 @@ html.theme-dark .card.absence-cat-recurring {
|
|||||||
background: linear-gradient(to bottom, rgba(6, 182, 212, 0.12) 0%, var(--bg-elevated) 40%);
|
background: linear-gradient(to bottom, rgba(6, 182, 212, 0.12) 0%, var(--bg-elevated) 40%);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* v2026.5.46 — vue horizontale : en échelle exacte, la carte d'un tech
|
||||||
|
absent est HAUTE (elle s'étire sur toute la frise) alors que son contenu est
|
||||||
|
court. Le dégradé « couleur → neutre à 40 % » (pensé pour les cartes courtes
|
||||||
|
de la vue classique) laissait tout le bas de la carte en neutre. En vue
|
||||||
|
horizontale on remplit donc TOUTE la carte de la couleur douce (theme-aware
|
||||||
|
via --c-*-soft) ; la vue classique garde le dégradé. */
|
||||||
|
html.view-horizontal .card.absence-cat-maladie { background: var(--c-maladie-soft); }
|
||||||
|
html.view-horizontal .card.absence-cat-conge,
|
||||||
|
html.view-horizontal .card.absence-cat-recurring { background: var(--c-conge-soft); }
|
||||||
|
|
||||||
/* Message "Absent le vendredi" (ou autre récurrence) en cyan.
|
/* Message "Absent le vendredi" (ou autre récurrence) en cyan.
|
||||||
Règle UNIQUE — les bordures haut/bas (qui venaient d'un 2e bloc plus
|
Règle UNIQUE — les bordures haut/bas (qui venaient d'un 2e bloc plus
|
||||||
haut, v4.1.20) sont repliées ici ; le bloc dupliqué a été retiré. */
|
haut, v4.1.20) sont repliées ici ; le bloc dupliqué a été retiré. */
|
||||||
@@ -4521,6 +4572,14 @@ html.view-horizontal .card-header {
|
|||||||
padding: 6px 10px !important;
|
padding: 6px 10px !important;
|
||||||
gap: 3px !important;
|
gap: 3px !important;
|
||||||
flex: 0 0 auto;
|
flex: 0 0 auto;
|
||||||
|
/* v2026.5.47 — le fond de la zone nom remplit TOUTE la hauteur de la
|
||||||
|
ligne (nom toujours centré via justify-content:center). En mode normal le
|
||||||
|
parent .card est déjà align-items:stretch, mais en mode heure exacte il
|
||||||
|
passe à align-items:center (pour centrer les bulles du corps), ce qui
|
||||||
|
laissait le header en bandeau fixe plus court que la ligne, avec du fond de
|
||||||
|
carte visible au-dessus/en dessous. align-self:stretch force le header à
|
||||||
|
s'étirer dans les deux modes ; le corps garde son propre centrage. */
|
||||||
|
align-self: stretch !important;
|
||||||
}
|
}
|
||||||
/* v2026.5.40 : nom du tech complet (jusqu'à 3 lignes). Si vraiment
|
/* v2026.5.40 : nom du tech complet (jusqu'à 3 lignes). Si vraiment
|
||||||
trop long, .card-tech-name-tight est appliqué dynamiquement par le JS
|
trop long, .card-tech-name-tight est appliqué dynamiquement par le JS
|
||||||
@@ -5199,23 +5258,29 @@ html.view-horizontal .horizontal-sidebar .date-custom {
|
|||||||
justify-content: center !important;
|
justify-content: center !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 13. Barre de rafraîchissement en vue horizontale : overlay par-dessus
|
/* 13. Barre de rafraîchissement en vue horizontale.
|
||||||
user-badge + titre (zone haut de sidebar). */
|
v2026.5.47 — Quentin : la barre doit RESTER dans la barre de gauche,
|
||||||
|
AU-DESSUS des initiales — pas dans le contenu où elle couvrait
|
||||||
|
les heures du mode « échelle exacte ». Elle repasse donc en overlay sur la
|
||||||
|
SIDEBAR (left:0, width = --sidebar-w) ; top suit --stack-top (sous la
|
||||||
|
banderole de session/reco si présente). Pour NE PAS recouvrir les
|
||||||
|
initiales, le contenu de la sidebar est poussé vers le bas pendant le
|
||||||
|
rafraîchissement (classe .planif-refreshing sur <html>, cf. showProgressBar). */
|
||||||
html.view-horizontal #progress-bar {
|
html.view-horizontal #progress-bar {
|
||||||
position: fixed !important;
|
position: fixed !important;
|
||||||
top: 0 !important;
|
top: var(--stack-top, 0px) !important;
|
||||||
left: 0 !important;
|
left: 0 !important;
|
||||||
width: 200px !important; /* largeur de la sidebar */
|
width: var(--sidebar-w, 200px) !important;
|
||||||
|
right: auto !important;
|
||||||
z-index: 9999 !important;
|
z-index: 9999 !important;
|
||||||
border-radius: 0 !important;
|
border-radius: 0 !important;
|
||||||
margin: 0 !important;
|
margin: 0 !important;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
/* Sur breakpoint étroit (sidebar 170px) */
|
/* Réserve la hauteur de la barre en haut de la sidebar pendant un
|
||||||
@media (max-width: 1400px) {
|
rafraîchissement → les initiales / le titre passent SOUS la barre. */
|
||||||
html.view-horizontal #progress-bar {
|
html.planif-refreshing.view-horizontal .horizontal-sidebar {
|
||||||
width: 170px !important;
|
padding-top: 34px !important;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* v2026.5.40 : banderole "En pompier du..." en vue HORIZONTALE
|
/* v2026.5.40 : banderole "En pompier du..." en vue HORIZONTALE
|
||||||
@@ -7017,6 +7082,76 @@ html.view-horizontal .iv-exact-lane + .iv-exact-lane {
|
|||||||
outline-offset: -2px;
|
outline-offset: -2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* v2026.5.47 — surbrillance de survol : la ZONE (1 h par défaut) qu'un clic
|
||||||
|
droit poserait en rendez-vous/absence, calée sous la souris à l'heure snappée
|
||||||
|
(créneau libre, mode heure exacte). Plus marquée que le survol gris du trou,
|
||||||
|
pour qu'on VOIE clairement la zone visée. Purement visuelle. */
|
||||||
|
.iv-exact-selpreview {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
pointer-events: none;
|
||||||
|
z-index: 0;
|
||||||
|
box-sizing: border-box;
|
||||||
|
border-radius: 4px;
|
||||||
|
border: 2px solid var(--accent, #3b82f6);
|
||||||
|
background: rgba(94, 168, 232, 0.28);
|
||||||
|
background: color-mix(in srgb, var(--accent, #3b82f6) 28%, transparent);
|
||||||
|
}
|
||||||
|
/* v2026.5.47 — bulle « temps disponible » FIXE en haut de la bande (elle ne
|
||||||
|
suit PLUS la souris) : plage libre du créneau survolé, ou avertissement rouge
|
||||||
|
si erreur. Seule la zone de sélection (.iv-exact-selpreview) suit le curseur. */
|
||||||
|
.iv-exact-selinfo {
|
||||||
|
position: absolute;
|
||||||
|
top: 3px;
|
||||||
|
left: 50%;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
white-space: nowrap;
|
||||||
|
text-align: center;
|
||||||
|
line-height: 1.25;
|
||||||
|
font-size: calc(11px * var(--text-scale, 1));
|
||||||
|
padding: 3px 10px;
|
||||||
|
border-radius: 6px;
|
||||||
|
background: var(--bg-elevated, #21242b);
|
||||||
|
color: var(--text, #e8eaed);
|
||||||
|
border: 1px solid var(--accent, #3b82f6);
|
||||||
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.35);
|
||||||
|
pointer-events: none;
|
||||||
|
z-index: 3;
|
||||||
|
}
|
||||||
|
.iv-exact-selinfo-main { font-weight: 700; }
|
||||||
|
.iv-exact-selinfo-sub { font-size: 0.9em; opacity: 0.8; font-weight: 500; }
|
||||||
|
.iv-exact-selinfo.danger .iv-exact-selinfo-sub { opacity: 0.95; }
|
||||||
|
/* v2026.5.47 — heure choisie (début–fin) affichée DANS le rectangle de
|
||||||
|
sélection mobile ; suit le curseur, lisible sur le fond translucide.
|
||||||
|
v2026.5.47 — placée EN BAS du rectangle (la bulle fixe est en haut) → la
|
||||||
|
bulle ne cache jamais l'heure quand la souris passe dessous. */
|
||||||
|
.iv-exact-selpreview-hour {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 3px;
|
||||||
|
left: 50%;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
white-space: nowrap;
|
||||||
|
font-size: calc(10.5px * var(--text-scale, 1));
|
||||||
|
font-weight: 700;
|
||||||
|
color: #ffffff;
|
||||||
|
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.75);
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
/* v2026.5.47 — un rendez-vous en ERREUR (début == fin) tombe dans la zone
|
||||||
|
qu'on créerait : surbrillance ET bulle passent en rouge (le clic droit est
|
||||||
|
par ailleurs bloqué, cf. disabledReason). */
|
||||||
|
.iv-exact-selpreview.danger {
|
||||||
|
border-color: #b03030;
|
||||||
|
background: rgba(176, 48, 48, 0.30);
|
||||||
|
background: color-mix(in srgb, #b03030 32%, transparent);
|
||||||
|
}
|
||||||
|
.iv-exact-selinfo.danger {
|
||||||
|
background: #b03030;
|
||||||
|
color: #ffffff;
|
||||||
|
border-color: #7a1f1f;
|
||||||
|
}
|
||||||
|
|
||||||
/* ── Les cartes posées (héritent de .iv-mini-card : anatomie, conflits
|
/* ── Les cartes posées (héritent de .iv-mini-card : anatomie, conflits
|
||||||
rouges !important, liseré clos/résolu, tooltips, reschedule) ────────── */
|
rouges !important, liseré clos/résolu, tooltips, reschedule) ────────── */
|
||||||
html.view-horizontal .iv-exact-card {
|
html.view-horizontal .iv-exact-card {
|
||||||
@@ -7035,7 +7170,11 @@ html.view-horizontal .iv-exact-card {
|
|||||||
height: auto !important;
|
height: auto !important;
|
||||||
pointer-events: auto;
|
pointer-events: auto;
|
||||||
flex: none;
|
flex: none;
|
||||||
min-width: 0;
|
/* v2026.5.47 — largeur MINIMALE visible : une intervention très courte
|
||||||
|
(1-5 min) ou à durée nulle (10:00→10:00) a une largeur proportionnelle
|
||||||
|
quasi nulle → elle disparaissait. Ce plancher la garde visible (très fine),
|
||||||
|
sans élargir les bulles normales (plus larges que ce plancher). */
|
||||||
|
min-width: 6px;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
container-type: inline-size;
|
container-type: inline-size;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
@@ -7155,10 +7294,12 @@ html.view-horizontal .iv-exact-card .iv-mini-card-text-mini .iv-mini-mini-ville
|
|||||||
html.view-horizontal.horizontal-exact .exact-hours-ruler {
|
html.view-horizontal.horizontal-exact .exact-hours-ruler {
|
||||||
display: block;
|
display: block;
|
||||||
position: sticky;
|
position: sticky;
|
||||||
/* v2026.5.46 — top:0 : en vue horizontale la barre du haut est
|
/* v2026.5.47 — top suit --stack-top : la règle des heures reste collée en
|
||||||
masquée, donc --stack-top (calé sur elle) envoyait la règle hors écran.
|
haut au scroll, ET passe SOUS la banderole de session/reconnexion quand il y
|
||||||
La sidebar utilise déjà top:0 dans la même structure et tient. */
|
en a une (au lieu de disparaître derrière), 0 sinon. (--stack-top = topbar
|
||||||
top: 0;
|
masquée en horizontal + hauteur des banderoles visibles ; corrigé depuis
|
||||||
|
des ajustements précédents, il ne sort plus la règle de l'écran.) */
|
||||||
|
top: var(--stack-top, 0px);
|
||||||
z-index: 20;
|
z-index: 20;
|
||||||
background: var(--bg);
|
background: var(--bg);
|
||||||
/* v2026.5.46 — l'alignement n'est PLUS un calcul théorique (faux au
|
/* v2026.5.46 — l'alignement n'est PLUS un calcul théorique (faux au
|
||||||
@@ -7205,3 +7346,29 @@ html.view-horizontal.horizontal-exact .cards {
|
|||||||
.reschedule-timeline-mark.reschedule-exact-mark {
|
.reschedule-timeline-mark.reschedule-exact-mark {
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ── Puces de variables du modèle d'email (v2026.5.48) ─────────────── */
|
||||||
|
/* Interactives : grossissent au survol, s'enfoncent au clic (demande
|
||||||
|
Quentin). Le style de base vit ici (plus d'inline) pour que :hover et
|
||||||
|
:active puissent surcharger la bordure. */
|
||||||
|
.admin-var-chip {
|
||||||
|
font-family: monospace;
|
||||||
|
font-size: 12px;
|
||||||
|
padding: 2px 8px;
|
||||||
|
align-self: flex-start;
|
||||||
|
border: 1px solid var(--border, #888);
|
||||||
|
border-radius: 6px;
|
||||||
|
background: transparent;
|
||||||
|
color: inherit;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: transform 0.09s ease, border-color 0.09s ease,
|
||||||
|
background-color 0.09s ease;
|
||||||
|
}
|
||||||
|
.admin-var-chip:hover {
|
||||||
|
transform: scale(1.07);
|
||||||
|
border-color: var(--accent, #4a90d9);
|
||||||
|
background: rgba(127, 127, 127, 0.12);
|
||||||
|
}
|
||||||
|
.admin-var-chip:active {
|
||||||
|
transform: scale(0.92);
|
||||||
|
}
|
||||||
|
|||||||
+1907
-311
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user