Public Access
v2026.5.46 — Couche données v2, vue « échelle de temps exacte », session fiabilisée, réservations partagées
This commit is contained in:
@@ -0,0 +1,196 @@
|
||||
# Planification - icone barre des taches (best-effort, optionnel) // 2026.1.4 - QRO
|
||||
# Developpe par Quentin Rouiller (QRO) - DGNSI, Canton de Vaud.
|
||||
# Licence MIT - voir le fichier LICENSE.
|
||||
#
|
||||
# Indique que le helper de sync est installe. Clic / menu -> fenetre du journal
|
||||
# (aspect application : journal colore par niveau, auto-rafraichi, bouton
|
||||
# "Tout afficher"). Lance par tray.vbs (fenetre masquee), au login.
|
||||
|
||||
$ErrorActionPreference = 'SilentlyContinue'
|
||||
|
||||
# Instance unique.
|
||||
$mutex = New-Object System.Threading.Mutex($false, 'Local\PlanificationTraySingleton')
|
||||
if (-not $mutex.WaitOne(0)) { exit }
|
||||
|
||||
Add-Type -AssemblyName System.Windows.Forms
|
||||
Add-Type -AssemblyName System.Drawing
|
||||
|
||||
# tray.ps1 vit dans <install>\bin -> racine = parent ; assets et log a la racine.
|
||||
$root = if ($PSScriptRoot) { Split-Path -Parent $PSScriptRoot } else { Join-Path $env:LOCALAPPDATA 'Planification' }
|
||||
$logFile = Join-Path $root 'activity.log'
|
||||
$iconPng = Join-Path (Join-Path $root 'assets') 'icon.png'
|
||||
|
||||
function Get-TrayIcon {
|
||||
try {
|
||||
if (Test-Path -LiteralPath $iconPng) {
|
||||
$bmp = New-Object System.Drawing.Bitmap($iconPng)
|
||||
return [System.Drawing.Icon]::FromHandle($bmp.GetHicon())
|
||||
}
|
||||
} catch {}
|
||||
return [System.Drawing.SystemIcons]::Information
|
||||
}
|
||||
|
||||
$script:logForm = $null
|
||||
$script:logRtb = $null
|
||||
$script:logChk = $null
|
||||
$script:logSig = ''
|
||||
|
||||
$colInfo = [System.Drawing.Color]::FromArgb(40, 70, 120)
|
||||
$colDebug = [System.Drawing.Color]::FromArgb(150, 150, 150)
|
||||
$colErr = [System.Drawing.Color]::FromArgb(200, 40, 40)
|
||||
$colTs = [System.Drawing.Color]::FromArgb(120, 120, 120)
|
||||
|
||||
function Update-LogText {
|
||||
if (-not $script:logRtb -or $script:logRtb.IsDisposed) { return }
|
||||
$lines = @()
|
||||
if (Test-Path -LiteralPath $logFile) {
|
||||
try {
|
||||
$all = Get-Content -LiteralPath $logFile -Encoding UTF8 -ErrorAction SilentlyContinue
|
||||
if ($all) {
|
||||
if ($script:logChk -and -not $script:logChk.Checked) {
|
||||
$all = $all | Where-Object { $_ -notmatch '\[DEBUG\]' }
|
||||
}
|
||||
$lines = @($all | Select-Object -Last 500)
|
||||
}
|
||||
} catch {}
|
||||
}
|
||||
$sig = ($lines -join "`n")
|
||||
if ($sig -eq $script:logSig) { return }
|
||||
$script:logSig = $sig
|
||||
|
||||
$rtb = $script:logRtb
|
||||
$rtb.SuspendLayout()
|
||||
$rtb.Clear()
|
||||
if ($lines.Count -eq 0) {
|
||||
$rtb.SelectionColor = $colDebug
|
||||
$rtb.AppendText("(aucune activite de synchronisation pour le moment)")
|
||||
} else {
|
||||
foreach ($line in $lines) {
|
||||
$col = $colInfo
|
||||
if ($line -match '\[ERREUR\]') { $col = $colErr }
|
||||
elseif ($line -match '\[DEBUG\]') { $col = $colDebug }
|
||||
if ($line -match '^(\d{2}/\d{2}/\d{4} \d{2}:\d{2}:\d{2})(.*)$') {
|
||||
$rtb.SelectionStart = $rtb.TextLength; $rtb.SelectionColor = $colTs
|
||||
$rtb.AppendText($Matches[1])
|
||||
$rtb.SelectionStart = $rtb.TextLength; $rtb.SelectionColor = $col
|
||||
$rtb.AppendText($Matches[2] + "`n")
|
||||
} else {
|
||||
$rtb.SelectionStart = $rtb.TextLength; $rtb.SelectionColor = $col
|
||||
$rtb.AppendText($line + "`n")
|
||||
}
|
||||
}
|
||||
}
|
||||
$rtb.ResumeLayout()
|
||||
$rtb.SelectionStart = $rtb.TextLength; $rtb.ScrollToCaret()
|
||||
}
|
||||
|
||||
function Show-LogWindow {
|
||||
if ($script:logForm -and -not $script:logForm.IsDisposed) {
|
||||
$script:logForm.WindowState = 'Normal'; $script:logForm.Activate(); return
|
||||
}
|
||||
$form = New-Object System.Windows.Forms.Form
|
||||
$form.Text = 'Planification - journal de synchronisation'
|
||||
$form.Size = New-Object System.Drawing.Size(760, 540)
|
||||
$form.StartPosition = 'CenterScreen'
|
||||
$form.BackColor = [System.Drawing.Color]::FromArgb(245, 246, 248)
|
||||
try { $form.Icon = Get-TrayIcon } catch {}
|
||||
|
||||
# 1) zone de texte (Fill) ajoutee en premier
|
||||
$rtb = New-Object System.Windows.Forms.RichTextBox
|
||||
$rtb.Dock = 'Fill'
|
||||
$rtb.ReadOnly = $true
|
||||
$rtb.BorderStyle = 'None'
|
||||
$rtb.BackColor = [System.Drawing.Color]::White
|
||||
$rtb.Font = New-Object System.Drawing.Font('Consolas', 9.5)
|
||||
$rtb.DetectUrls = $false
|
||||
$form.Controls.Add($rtb)
|
||||
|
||||
# 2) barre d'outils claire avec le BOUTON bascule "Tout afficher" bien visible
|
||||
$bar = New-Object System.Windows.Forms.Panel
|
||||
$bar.Dock = 'Top'; $bar.Height = 40
|
||||
$bar.BackColor = [System.Drawing.Color]::FromArgb(238, 240, 243)
|
||||
$chk = New-Object System.Windows.Forms.CheckBox
|
||||
$chk.Appearance = 'Button'
|
||||
$chk.Text = 'Tout afficher (mode detaille)'
|
||||
$chk.TextAlign = 'MiddleCenter'
|
||||
$chk.AutoSize = $false
|
||||
$chk.Size = New-Object System.Drawing.Size(200, 28)
|
||||
$chk.Location = New-Object System.Drawing.Point(10, 6)
|
||||
$chk.FlatStyle = 'System'
|
||||
$chk.add_CheckedChanged({ $script:logSig = '~'; Update-LogText })
|
||||
$bar.Controls.Add($chk)
|
||||
$hint = New-Object System.Windows.Forms.Label
|
||||
$hint.Text = 'Par defaut : l''essentiel. Activez pour voir tout le detail technique.'
|
||||
$hint.ForeColor = [System.Drawing.Color]::FromArgb(90, 90, 90)
|
||||
$hint.AutoSize = $true
|
||||
$hint.Location = New-Object System.Drawing.Point(220, 12)
|
||||
$bar.Controls.Add($hint)
|
||||
$form.Controls.Add($bar)
|
||||
|
||||
# 3) bandeau titre (bleu) ajoute en dernier -> tout en haut
|
||||
$hdrBar = New-Object System.Windows.Forms.Panel
|
||||
$hdrBar.Dock = 'Top'; $hdrBar.Height = 32
|
||||
$hdrBar.BackColor = [System.Drawing.Color]::FromArgb(40, 70, 120)
|
||||
$hdr = New-Object System.Windows.Forms.Label
|
||||
$hdr.Text = 'Activite de synchronisation - Planification'
|
||||
$hdr.ForeColor = [System.Drawing.Color]::White
|
||||
$hdr.Font = New-Object System.Drawing.Font('Segoe UI', 10, [System.Drawing.FontStyle]::Bold)
|
||||
$hdr.AutoSize = $true
|
||||
$hdr.Location = New-Object System.Drawing.Point(10, 7)
|
||||
$hdrBar.Controls.Add($hdr)
|
||||
$form.Controls.Add($hdrBar)
|
||||
|
||||
$script:logForm = $form
|
||||
$script:logRtb = $rtb
|
||||
$script:logChk = $chk
|
||||
$script:logSig = ''
|
||||
Update-LogText
|
||||
|
||||
$timer = New-Object System.Windows.Forms.Timer
|
||||
$timer.Interval = 2000
|
||||
$timer.add_Tick({ Update-LogText })
|
||||
$timer.Start()
|
||||
$form.add_FormClosed({ $timer.Stop(); $timer.Dispose() })
|
||||
|
||||
$form.Show(); $form.Activate()
|
||||
}
|
||||
|
||||
$ni = New-Object System.Windows.Forms.NotifyIcon
|
||||
$ni.Icon = Get-TrayIcon
|
||||
$ni.Text = 'Planification - synchronisation active'
|
||||
$ni.Visible = $true
|
||||
|
||||
$menu = New-Object System.Windows.Forms.ContextMenuStrip
|
||||
$miLog = $menu.Items.Add('Voir le journal de synchronisation')
|
||||
$miLog.add_Click({ Show-LogWindow })
|
||||
$miQuit = $menu.Items.Add('Quitter')
|
||||
$miQuit.add_Click({ $ni.Visible = $false; $ni.Dispose(); [System.Windows.Forms.Application]::Exit() })
|
||||
$ni.ContextMenuStrip = $menu
|
||||
$ni.add_MouseClick({ param($s, $e) if ($e.Button -eq [System.Windows.Forms.MouseButtons]::Left) { Show-LogWindow } })
|
||||
|
||||
# v2026.1.7 - auto-extinction apres 2 h SANS activite de synchronisation. On se
|
||||
# base sur la date de derniere ecriture du journal (le host y ecrit a chaque
|
||||
# operation). Le navigateur relancera le host a la prochaine activite, qui
|
||||
# relancera ce tray. -> "de base eteint, s'active a l'usage, se ferme au repos".
|
||||
$IDLE_LIMIT_MIN = 120
|
||||
$idleTimer = New-Object System.Windows.Forms.Timer
|
||||
$idleTimer.Interval = 300000 # verifie toutes les 5 min
|
||||
$idleTimer.add_Tick({
|
||||
try {
|
||||
$age = $null
|
||||
if (Test-Path -LiteralPath $logFile) {
|
||||
$age = ((Get-Date) - (Get-Item -LiteralPath $logFile).LastWriteTime).TotalMinutes
|
||||
}
|
||||
# Pas de journal, ou journal inactif depuis >= 2 h -> on s'eteint.
|
||||
if (($null -eq $age) -or ($age -ge $IDLE_LIMIT_MIN)) {
|
||||
$ni.Visible = $false; $ni.Dispose()
|
||||
[System.Windows.Forms.Application]::Exit()
|
||||
}
|
||||
} catch {}
|
||||
})
|
||||
$idleTimer.Start()
|
||||
|
||||
[System.Windows.Forms.Application]::EnableVisualStyles()
|
||||
[System.Windows.Forms.Application]::Run()
|
||||
$idleTimer.Stop()
|
||||
$ni.Dispose()
|
||||
Reference in New Issue
Block a user