Remove test.php and enhance null safety and sorting across components

- Deleted `test.php` as it was no longer in use.
- Enhanced null safety checks in `Inventory.php`, `StdOut-detail.php`, `Backups.php`, and `SwitchsSAN.php` to prevent potential warnings.
- Refactored `SwitchsSAN.php` to improve sorting logic for ports based on errors, vFabric, and Port ID.
- Added seasonal snow effect script in `all.php` with toggle functionality for user engagement.
- Updated navigation bar (`navbar.html`) to include a new VIO page link.
- Introduced a new `VIO.php` page to display VIO monitoring details with table export and sorting features.
This commit is contained in:
e025532
2026-02-04 14:52:49 +01:00
parent b0c9cafc46
commit d5b45dbc22
9 changed files with 544 additions and 175 deletions

View File

@@ -79,69 +79,87 @@
<tbody> <!-- Body --> <tbody> <!-- Body -->
<?php <?php
// get all active servers
$today = date("Y-m-d");
$active = Invoke_Infra("SELECT name from cmdb_vms where LastInventory like'$today%'");
$active = array_column($active, 'name');
// NO Backup or Backup with Errors // NO Backup or Backup with Errors
$er = 0; $er = 0;
$answers = Invoke_infra("SELECT * FROM VMs_Backup where ( Owner like 'DUN-VMH%' or Owner like 'MDK-VMH%' ) and name not like 'WS%' and owner not like '%WKG%' and owner not like '%VMH-WM%' and Exclusion ='' and (LastResult <> 'OK' or lastresult is null) and policy is not null order by lastresult,name"); $answers = Invoke_infra("SELECT * FROM VMs_Backup where ( Owner like 'DUN-VMH%' or Owner like 'MDK-VMH%' ) and name not like 'WS%' and owner not like '%WKG%' and owner not like '%VMH-WM%' and Exclusion ='' and (LastResult <> 'OK' or lastresult is null) and policy is not null order by lastresult,name");
foreach ($answers as $row) { foreach ($answers as $row) {
if(in_array($row['Name'], $active)){
$er++; $er++;
$date1 = date_create($row['LastKnownGood']??'01/01/1970'); $diff = date_diff($date1, date_create(date("Y-m-d"))); $date1 = date_create($row['LastKnownGood'] ?? '01/01/1970');
if ($diff->format("%R%a") >= 2 || $row['LastKnownGood'] == ''){ $diff = date_diff($date1, date_create(date("Y-m-d")));
if ($diff->format("%R%a") >= 2 || $row['LastKnownGood'] == '') {
echo "<tr class='table-danger'>"; echo "<tr class='table-danger'>";
}else{ } else {
echo "<tr class='table-warning'>"; echo "<tr class='table-warning'>";
} }
if($diff->format("%R%a") == "-0"){$LastGood = "NEVER";}else{$LastGood = $row['LastKnownGood']." (".$diff->format("%R%a")."J)";} if ($diff->format("%R%a") == "-0") {
echo "<td><b>".$row['Name']."<b></td>"; $LastGood = "NEVER";
echo "<td>".$row['LastBackup']." ".$row['TimeStamp']."</td>"; } else {
echo "<td>".$row['LastResult']."</td>"; $LastGood = $row['LastKnownGood'] . " (" . $diff->format("%R%a") . "J)";
echo "<td>".$LastGood."</td>"; }
echo "<td>".$row['LastSize']."</td>"; echo "<td><b>" . $row['Name'] . "<b></td>";
echo "<td>".$row['Owner']."</td>"; echo "<td>" . $row['LastBackup'] . " " . $row['TimeStamp'] . "</td>";
echo "<td>".$row['Policy']."</td>"; echo "<td>" . $row['LastResult'] . "</td>";
echo "<td>" . $LastGood . "</td>";
echo "<td>" . $row['LastSize'] . "</td>";
echo "<td>" . $row['Owner'] . "</td>";
echo "<td>" . $row['Policy'] . "</td>";
echo "</tr>"; echo "</tr>";
} }
}
// Outdated // Outdated
$outdated = 0; $outdated = 0;
$answers = Invoke_infra("SELECT * FROM VMs_Backup where ( Owner like 'DUN-VMH%' or Owner like 'MDK-VMH%' ) and name not like 'WS%' and owner not like '%WKG%' and owner not like '%VMH-WM%' and Exclusion ='' and LastResult = 'OK' and TRY_CAST(lastknowngood AS DATE) < CAST(DATEADD(DAY, -2, GETDATE()) AS DATE) order by name"); $answers = Invoke_infra("SELECT * FROM VMs_Backup where ( Owner like 'DUN-VMH%' or Owner like 'MDK-VMH%' ) and name not like 'WS%' and owner not like '%WKG%' and owner not like '%VMH-WM%' and Exclusion ='' and LastResult = 'OK' and TRY_CAST(lastknowngood AS DATE) < CAST(DATEADD(DAY, -2, GETDATE()) AS DATE) order by name");
foreach ($answers as $row) { foreach ($answers as $row) {
$date1 = date_create($row['LastKnownGood']); $diff = date_diff($date1, date_create(date("Y-m-d"))); if (in_array($row['Name'], $active)) {
if(date('w') >= 2 && date('w') <= 6 ){ $date1 = date_create($row['LastKnownGood']);
if ($diff->format("%R%a") >= 2){ $diff = date_diff($date1, date_create(date("Y-m-d")));
if (date('w') >= 2 && date('w') <= 6) {
if ($diff->format("%R%a") >= 2) {
echo "<tr class='table-warning'>"; echo "<tr class='table-warning'>";
}else{ } else {
echo "<tr class='table-success'>"; echo "<tr class='table-success'>";
} }
}else{ } else {
if((date('w') < 2 || date('w') == 7)){ if ((date('w') < 2 || date('w') == 7)) {
if($diff->format("%R%a") <= 3){ if ($diff->format("%R%a") <= 3) {
echo "<tr class='table-success'>"; echo "<tr class='table-success'>";
}else{ } else {
echo "<tr class='table-warning'>"; echo "<tr class='table-warning'>";
} }
} }
} }
if($diff->format("%R%a") == "-0"){$LastGood = $row['LastKnownGood'];}else{$LastGood = $row['LastKnownGood']." (".$diff->format("%R%a")."J)";} if ($diff->format("%R%a") == "-0") {
echo "<td><b>".$row['Name']."<b></td>"; $LastGood = $row['LastKnownGood'];
echo "<td>".$row['LastBackup']." ".$row['TimeStamp']."</td>"; } else {
echo "<td>".$row['LastResult']."</td>"; $LastGood = $row['LastKnownGood'] . " (" . $diff->format("%R%a") . "J)";
if (date('w') >= 2 && date('w') <= 6 && $diff->format("%R%a") < 1){ }
echo "<td>".$LastGood."</td>"; echo "<td><b>" . $row['Name'] . "<b></td>";
}else{ echo "<td>" . $row['LastBackup'] . " " . $row['TimeStamp'] . "</td>";
if ((date('w') == 1 || date('w') == 7) && $diff->format("%R%a") <= 3){ echo "<td>" . $row['LastResult'] . "</td>";
echo "<td>".$LastGood."</td>"; if (date('w') >= 2 && date('w') <= 6 && $diff->format("%R%a") < 1) {
}else{ echo "<td>" . $LastGood . "</td>";
echo "<td class='table-warning'>".$LastGood."</td>"; } else {
if ((date('w') == 1 || date('w') == 7) && $diff->format("%R%a") <= 3) {
echo "<td>" . $LastGood . "</td>";
} else {
echo "<td class='table-warning'>" . $LastGood . "</td>";
$outdated++; $outdated++;
} }
} }
echo "<td>".$row['LastSize']."</td>"; echo "<td>" . $row['LastSize'] . "</td>";
echo "<td>".$row['Owner']."</td>"; echo "<td>" . $row['Owner'] . "</td>";
echo "<td>".$row['Policy']."</td>"; echo "<td>" . $row['Policy'] . "</td>";
echo "</tr>"; echo "</tr>";
} }
}
// Backup OK // Backup OK
$answers = Invoke_infra("SELECT * FROM VMs_Backup where ( Owner like 'DUN-VMH%' or Owner like 'MDK-VMH%' ) and name not like 'WS%' and owner not like '%WKG%' and owner not like '%VMH-WM%' and Exclusion ='' and LastResult = 'OK' and TRY_CAST(lastknowngood AS DATE) >= CAST(DATEADD(DAY, -2, GETDATE()) AS DATE) order by name"); $answers = Invoke_infra("SELECT * FROM VMs_Backup where ( Owner like 'DUN-VMH%' or Owner like 'MDK-VMH%' ) and name not like 'WS%' and owner not like '%WKG%' and owner not like '%VMH-WM%' and Exclusion ='' and LastResult = 'OK' and TRY_CAST(lastknowngood AS DATE) >= CAST(DATEADD(DAY, -2, GETDATE()) AS DATE) order by name");

View File

@@ -14,11 +14,11 @@
<link rel="stylesheet" href="/css/bootstrap-icons/bootstrap-icons.css"> <link rel="stylesheet" href="/css/bootstrap-icons/bootstrap-icons.css">
<script src="/js/bootstrap.bundle.min.js"></script> <script src="/js/bootstrap.bundle.min.js"></script>
<link rel="stylesheet" href="/css/bootstrap-table.min.css">
<script src="/js/bootstrap-table.min.js"></script>
<script src="/js/bootstrap-table-fr-FR.min.js"></script>
<style> <style>
/* Custom styles to match the previous JS rendering */
.table-danger { background-color: #f8d7da !important; }
.table-success { background-color: #d1e7dd !important; }
/* Ensure text is readable on colored headers */
.card-header a { text-decoration: none; color: white; display: block; width: 100%; } .card-header a { text-decoration: none; color: white; display: block; width: 100%; }
.card-header a:hover { color: #f0f0f0; } .card-header a:hover { color: #f0f0f0; }
</style> </style>
@@ -26,13 +26,12 @@
<body class="bg-light text-dark"> <body class="bg-light text-dark">
<?php <?php
// Include your existing libraries // Include global configurations
include $_SERVER['DOCUMENT_ROOT'] . "/include/all.php"; include $_SERVER['DOCUMENT_ROOT'] . "/include/all.php";
// --- PHP LOGIC START --- // --- PHP LOGIC START ---
// 1. Fetch JSON Data // 1. Fetch JSON Data
// Ensure the PostJson function returns a valid JSON string
$jsonString = PostJson("$bdnuss/Storage/BROCADE/PORT/BROCADE_PORT_LIST.php", ''); $jsonString = PostJson("$bdnuss/Storage/BROCADE/PORT/BROCADE_PORT_LIST.php", '');
// 2. Decode to PHP Array // 2. Decode to PHP Array
@@ -40,7 +39,7 @@
// Check if decode was successful // Check if decode was successful
if (json_last_error() !== JSON_ERROR_NONE) { if (json_last_error() !== JSON_ERROR_NONE) {
$sanData = []; // Fallback to empty array to avoid errors $sanData = [];
$errorMessage = "Error decoding JSON: " . json_last_error_msg(); $errorMessage = "Error decoding JSON: " . json_last_error_msg();
} }
?> ?>
@@ -62,42 +61,65 @@
<div id="accordion"> <div id="accordion">
<?php <?php
// 3. Loop through Switches // Loop through Switches
if (!empty($sanData)) { if (!empty($sanData)) {
$switchIndex = 0; // Iterator for unique IDs $switchIndex = 0;
foreach ($sanData as $switchName => $ports) { foreach ($sanData as $switchName => $ports) {
$switchIndex++; $switchIndex++;
$collapseId = "collapse_" . $switchIndex; // Unique ID for Bootstrap $collapseId = "collapse_" . $switchIndex;
// Initialize counters // Inject PortID into the array content for easier sorting
foreach ($ports as $k => $v) $ports[$k]['_PortID'] = $k;
// Custom Sort: Errors (Desc) > vFabric (Asc) > Port (Natural Asc)
uasort($ports, function ($a, $b) {
// Errors (Descending)
$errA = (int)$a['Errors'];
$errB = (int)$b['Errors'];
if ($errA !== $errB) {
return $errB <=> $errA;
}
// vFabric (Ascending / Case Insensitive)
$vfA = $a['vFabric'] ?? '';
$vfB = $b['vFabric'] ?? '';
$cmpVf = strcasecmp($vfA, $vfB);
if ($cmpVf !== 0) {
return $cmpVf;
}
// Port ID (Natural Sort, e.g. 2 comes before 10)
return strnatcmp($a['_PortID'], $b['_PortID']);
});
// Initialize counters & buffers
$upCount = 0; $upCount = 0;
$downCount = 0; $downCount = 0;
$errorCount = 0; $errorCount = 0;
$tableBody = "";
// Arrays to store HTML rows (for sorting logic) // Generate HTML Rows based on sorted data
$errorRows = [];
$normalRows = [];
// 4. Loop through Ports to calculate stats and build rows
foreach ($ports as $portId => $portData) { foreach ($ports as $portId => $portData) {
$state = $portData['State']; $state = $portData['State'];
$errors = (int)$portData['Errors']; // Cast to int for safety $errors = (int)$portData['Errors'];
if ($state === 'UP') { if ($state === 'UP') $upCount++;
$upCount++; elseif ($state === 'DN') $downCount++;
// Determine row color if ($errors > 0 && $state === 'UP') $errorCount++;
$rowClass = "table-success";
if ($errors > 0) { if ($state === 'DN') {
$errorCount++; continue;
$rowClass = "table-danger";
} }
// Build the HTML for this row // Determine Row CSS Class
// Note: Using variables in double quotes for cleaner syntax $rowClass = "table-success";
$rowHtml = " if ($errors > 0) $rowClass = "table-danger";
// Build Row HTML
$tableBody .= "
<tr class='{$rowClass}'> <tr class='{$rowClass}'>
<td>{$portData['vFabric']}</td>
<td>{$portId}</td> <td>{$portId}</td>
<td>{$portData['Status']}</td> <td>{$portData['Status']}</td>
<td>{$portData['State']}</td> <td>{$portData['State']}</td>
@@ -105,34 +127,13 @@
<td>{$portData['Nego']}</td> <td>{$portData['Nego']}</td>
<td>{$portData['FrameTX']}</td> <td>{$portData['FrameTX']}</td>
<td>{$portData['FrameRX']}</td> <td>{$portData['FrameRX']}</td>
<td><strong>{$portData['Errors']}</strong></td> <td data-value='{$errors}'><strong>{$portData['Errors']}</strong></td>
</tr>"; </tr>";
// Sort into appropriate array
if ($errors > 0) {
$errorRows[] = $rowHtml;
} else {
$normalRows[] = $rowHtml;
} }
} elseif ($state === 'DN') { // Determine Header Color
$downCount++; $headerColor = ($errorCount > 0) ? "DarkOrange" : "green";
} $msg = ($errorCount > 0) ? "<b> {$errorCount} issue(s)</b>" : "OK";
}
// 5. Merge rows: Errors first
$finalRows = array_merge($errorRows, $normalRows);
$tableBody = implode("\n", $finalRows);
// 6. Determine Header Style
$headerColor = "green";
$msg = "OK";
if ($errorCount > 0) {
$headerColor = "DarkOrange";
$msg = "<b> --> {$errorCount} issue(s)</b>";
}
// 7. Output the Accordion Item (Card)
?> ?>
<div class="card" style="background-color:<?php echo $headerColor; ?>;"> <div class="card" style="background-color:<?php echo $headerColor; ?>;">
@@ -142,20 +143,22 @@
</a> </a>
</h4> </h4>
</div> </div>
<div id="<?php echo $collapseId; ?>" class="collapse" data-bs-parent="#accordion"> <div id="<?php echo $collapseId; ?>" class="collapse" data-bs-parent="#accordion">
<div class="card-body bg-white border p-0"> <div class="card-body bg-white border p-0">
<div class="table-responsive"> <div class="table-responsive">
<table class="table table-bordered table-hover mb-0 text-center"> <table class="table table-bordered table-hover mb-0 text-center" data-toggle="table">
<thead class="table-light"> <thead class="table-light">
<tr> <tr>
<th>Port</th> <th data-sortable="true">vFabric</th>
<th>Status</th> <th data-sortable="true">Port</th>
<th>State</th> <th data-sortable="true">Status</th>
<th>Speed</th> <th data-sortable="true">State</th>
<th>Nego</th> <th data-sortable="true">Speed</th>
<th>FrameTX</th> <th data-sortable="true">Nego</th>
<th>FrameRX</th> <th data-sortable="true">FrameTX</th>
<th>Errors</th> <th data-sortable="true">FrameRX</th>
<th data-sortable="true">Errors</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
@@ -168,14 +171,16 @@
<br> <br>
<?php <?php
} // End foreach Switch }
} else { } else {
echo "<div class='alert alert-warning'>No data available via API.</div>"; echo "<div class='alert alert-warning'>No data available via API.</div>";
} }
?> ?>
</div> </div> </div>
</div>
</div> </div>
</div> </div>
</div> </div>
</body> </body>
<script src="/js/switch.js"></script>
</html> </html>

View File

@@ -82,7 +82,7 @@
foreach ($list as $s) { foreach ($list as $s) {
$name = $s['HOSTNAME']; $name = $s['HOSTNAME'];
$ts = $s['ts']; $ts = $s['ts'];
$lastBackup = (explode(".",$s['LastBackup']))[0]; $lastBackup = (explode(".",$s['LastBackup'] ?? ''))[0];
$location = $s['Location']; $location = $s['Location'];
$log = $s['Log']; $log = $s['Log'];
$backuptype = $s['BackupType']; $backuptype = $s['BackupType'];
@@ -135,19 +135,15 @@
</div> </div>
</div> </div>
</div> </div>
</div>
</body> </body>
<script src="/js/switch.js"></script> <script src="/js/switch.js"></script>
<script> <script>
$(function() { $(function() {
// Dès que le switch #showAll change d'état
$('#showAll').on('change', function() { $('#showAll').on('change', function() {
// On soumet le formulaire le plus proche (le parent)
$(this).closest('form').submit(); $(this).closest('form').submit();
}); });
$('#showSize').on('change', function() { $('#showSize').on('change', function() {
// On soumet le formulaire le plus proche (le parent)
$(this).closest('form').submit(); $(this).closest('form').submit();
}); });
}); });

View File

@@ -179,11 +179,11 @@
//LastBackup //LastBackup
$lr = explode(".", $s['backuplast'] ?? "")[0]; $lr = explode(".", $s['backuplast'] ?? "")[0];
if(str_contains(strtolower($s['backuplog']), 'progress')){ if(str_contains(strtolower($s['backuplog'] ?? ''), 'progress')){
$size = "<span class='text-warning'>In Progress</span>"; $size = "<span class='text-warning'>In Progress</span>";
}elseif (str_contains(strtolower($s['backuplog']), 'waiting')){ }elseif (str_contains(strtolower($s['backuplog'] ?? ''), 'waiting')){
$size = "<span class='text-warning'><br>".$s['backuplog']."</span>"; $size = "<span class='text-warning'><br>".$s['backuplog']."</span>";
}elseif (str_contains(strtolower($s['backuplog']), 'error')){ }elseif (str_contains(strtolower($s['backuplog'] ?? ''), 'error')){
$size = "<span class='text-danger'><b> ERROR !!!</b></span>"; $size = "<span class='text-danger'><b> ERROR !!!</b></span>";
}else { }else {
$size = 0; $size = 0;

View File

@@ -176,8 +176,8 @@
<tbody> <?php <tbody> <?php
foreach ($hosts as $h) { foreach ($hosts as $h) {
$host = strtoupper($h['HOSTNAME']); $host = strtoupper($h['HOSTNAME']);
$os = strtoupper($h['Type']); $os = strtoupper($h['Type'] ?? "");
$osver = strtoupper($h['OSVersion']); $osver = strtoupper($h['OSVersion'] ?? "");
if ($os == "AIX") { if ($os == "AIX") {
$taix++; $taix++;

191
X/VIO.php Normal file
View File

@@ -0,0 +1,191 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>Web Infra Reports IT</title>
<link rel="shortcut icon" type="image/png" href="/include/favicon-32x32.png">
<script src="/js/jquery-3.6.1.min.js"></script>
<link rel="stylesheet" href="/css/bootstrap.min.css">
<link rel="stylesheet" href="/css/bootstrap-icons/bootstrap-icons.css">
<link rel="stylesheet" href="/css/preloader.css">
<script src="/js/bootstrap.bundle.min.js"></script>
<link rel="stylesheet" href="/css/bootstrap-table.min.css">
<script src="/js/bootstrap-table.min.js"></script>
<script src="/js/bootstrap-table-fr-FR.min.js"></script>
<script src="/js/tableExport.min.js"></script>
<script src="/js/bootstrap-table-export.min.js"></script>
<script src="/js/libs/js-xlsx/xlsx.core.min.js"></script>
<style>
.cell-multiline {
white-space: nowrap;
}
/* Custom style for VIOErr badges */
.badge-err {
background-color: #dc3545 !important;
color: white;
}
</style>
</head>
<body class="bg-light text-dark">
<?php include $_SERVER['DOCUMENT_ROOT'] . "/include/all.php"; ?>
<?php
// ==========================================
// 1. DATA PROCESSING (PHP)
// ==========================================
$rawRows = Invoke_Infra("SELECT * FROM x_cmdb_VIO");
if (!$rawRows) $rawRows = [];
// Grouping
$groupedData = [];
foreach ($rawRows as $row) {
$key = $row['clintname'];
if (empty($key)) $key = "[No Client Name]";
if (!isset($groupedData[$key])) $groupedData[$key] = [];
$groupedData[$key][] = $row;
}
// Flattening for Display (1 Row per Client)
$displayRows = [];
foreach ($groupedData as $clientKey => $rows) {
// 1. Sort by date desc
usort($rows, function($a, $b) {
return strcmp($b['ts'], $a['ts']);
});
// 2. Keep max 2
if (count($rows) > 2) {
$rows = array_slice($rows, 0, 2);
}
$names = []; $inerrs = []; $vfcs = []; $vios = [];
$clintids = []; $fcnames = []; $tss = []; $vioerrs = [];
$hasError = false;
$maxVioErr = 0;
foreach ($rows as $r) {
if ($r['inerr'] != 0 && $r['inerr'] != '0') $hasError = true;
// Track VIOErr
$errVal = (int)($r['VIOErr'] ?? 0);
if ($errVal > $maxVioErr) $maxVioErr = $errVal;
// Format VIOErr for display (Red badge if > 0)
$vioerrs[] = ($errVal > 0) ? "<span class='badge badge-err'>$errVal</span>" : $errVal;
$names[] = $r['name'] ?? '-';
$inerrs[] = $r['inerr'] ?? '-';
$vfcs[] = $r['vfcclientname'] ?? '-';
$vios[] = $r['vio'] ?? '-';
$clintids[] = $r['clintid'] ?? '-';
$fcnames[] = $r['fcname'] ?? '-';
$tss[] = $r['ts'] ?? '-';
}
$displayRows[] = [
'clintname' => $clientKey,
'hasError' => $hasError,
'maxVioErr' => $maxVioErr,
'name' => implode('<br>', $names),
'inerr' => implode('<br>', $inerrs),
'vfc' => implode('<br>', $vfcs),
'vio' => implode('<br>', $vios),
'clintid' => implode('<br>', $clintids),
'fcname' => implode('<br>', $fcnames),
'ts' => implode('<br>', $tss),
'vioerr' => implode('<br>', $vioerrs),
];
}
// 4. Final Sort: 1. Warning (inerr), 2. VIOErr > 0, 3. Alpha
usort($displayRows, function($a, $b) {
// Priority 1: InErr (table-warning)
if ($a['hasError'] && !$b['hasError']) return -1;
if (!$a['hasError'] && $b['hasError']) return 1;
// Priority 2: VIOErr count
if ($a['maxVioErr'] > 0 && $b['maxVioErr'] == 0) return -1;
if ($a['maxVioErr'] == 0 && $b['maxVioErr'] > 0) return 1;
if ($a['maxVioErr'] != $b['maxVioErr']) return $b['maxVioErr'] - $a['maxVioErr'];
// Priority 3: Alphabetical
return strcasecmp($a['clintname'], $b['clintname']);
});
?>
<div class="container-fluid" id="content">
<div class="row flex-nowrap">
<div class="col-auto col-md-2 col-xl-2 px-sm-2 px-0 bg-dark vh-100 position-sticky top-0" style="flex: 0 0 230px;">
<?php include $_SERVER['DOCUMENT_ROOT'] . "/navbar.html"; ?>
</div>
<div class="col py-3">
<h1><span class="badge text-bg-secondary w-100">VIO Monitoring</span></h1>
<div class="container-fluid">
<div>
<table class='table table-bordered table-hover table-sm' id='t1'
data-toggle="table"
data-search="true"
data-show-columns="true"
data-export-types="['xlsx','csv','json']"
data-show-export="true"
data-sortable="true"> <thead>
<tr>
<th data-field="clintname" data-sortable="true">Clint Name</th>
<th data-field="name">Name</th>
<th data-field="vioerr">VIOErr</th>
<th data-field="inerr">InErr</th>
<th data-field="vfcclientname">VFC Client Name</th>
<th data-field="vio">VIO</th>
<th data-field="clintid">ClintID</th>
<th data-field="fcname">FC Name</th>
<th data-field="ts">Last Update</th>
</tr>
</thead>
<tbody>
<?php foreach ($displayRows as $row): ?>
<?php $class = $row['hasError'] ? 'table-warning' : ''; ?>
<tr class="<?php echo $class; ?>">
<td class="fw-bold align-middle"><?php echo htmlspecialchars($row['clintname']); ?></td>
<td class="cell-multiline"><?php echo $row['name']; ?></td>
<td class="cell-multiline text-center fw-bold"><?php echo $row['vioerr']; ?></td>
<td class="cell-multiline"><?php echo $row['inerr']; ?></td>
<td class="cell-multiline"><?php echo $row['vfc']; ?></td>
<td class="cell-multiline"><?php echo $row['vio']; ?></td>
<td class="cell-multiline"><?php echo $row['clintid']; ?></td>
<td class="cell-multiline"><?php echo $row['fcname']; ?></td>
<td class="cell-multiline small"><?php echo $row['ts']; ?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</body>
<script src="/js/switch.js"></script>
<script>
var $table = $('#t1');
function adjustTableHeight() {
let height = $(window).height() - 170;
$table.bootstrapTable('resetView', { height: height });
}
$(function () {
adjustTableHeight();
$(window).resize(function () { adjustTableHeight(); });
});
</script>
</html>

View File

@@ -335,6 +335,207 @@
?> ?>
<style>
/* 1. CONFIGURATION DES COULEURS */
:root {
/* Par défaut (Mode Clair / bg-light) : Gris visible sur blanc */
--snow-color: rgba(160, 160, 160, 0.9);
}
/* 2. DÉTECTION DU MODE SOMBRE BASÉE SUR TON SCRIPT */
/* Ton script ajoute la classe 'bg-dark' au body, on s'en sert ici */
body.bg-dark {
--snow-color: rgba(255, 255, 255, 0.9) !important;
}
/* Gestion des préférences système (OS) au cas où le script JS n'a pas encore chargé */
@media (prefers-color-scheme: dark) {
body:not(.bg-light) { /* Sauf si l'utilisateur a forcé le mode clair */
--snow-color: rgba(255, 255, 255, 0.9);
}
}
/* 3. STYLES DU CANVAS ET DU BOUTON */
#snow-canvas {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 9999; /* Au-dessus de tout */
pointer-events: none; /* LAISSE PASSER LES CLICS (Vital !) */
}
#snow-toggle-btn {
position: fixed;
/* Positionné un peu au-dessus du bas pour ne pas gêner d'autres footers */
bottom: 20px;
right: 20px;
z-index: 10000;
background: transparent;
color: var(--snow-color); /* Le bouton prend aussi la couleur du thème */
border: 1px solid var(--snow-color);
border-radius: 50%;
width: 35px;
height: 35px;
cursor: pointer;
font-size: 18px;
transition: all 0.3s;
display: flex;
align-items: center;
justify-content: center;
opacity: 0.5; /* Discret par défaut */
}
#snow-toggle-btn:hover {
opacity: 1;
background: rgba(128, 128, 128, 0.2);
}
</style>
<canvas id="snow-canvas"></canvas>
<button id="snow-toggle-btn" title="Activer/Désactiver la neige">❄️</button>
<script>
(function() {
// --- 1. GESTION DES DATES (15 Déc au 5 Jan) ---
const now = new Date();
const month = now.getMonth() + 1; // JS compte les mois de 0 à 11, donc on ajoute 1
const day = now.getDate();
// La condition : (Mois = 12 ET Jour >= 15) OU (Mois = 1 ET Jour <= 5)
const isSeason = (month === 12 && day >= 15) || (month === 1 && day <= 5);
const canvas = document.getElementById('snow-canvas');
const toggleBtn = document.getElementById('snow-toggle-btn');
// Si on n'est pas dans la période, on cache tout et on arrête le script.
if (!isSeason) {
if (canvas) canvas.style.display = 'none';
if (toggleBtn) toggleBtn.style.display = 'none';
return; // Arrêt immédiat du script
}
// --- 2. CONFIGURATION ---
const ctx = canvas.getContext('2d');
let width = window.innerWidth;
let height = window.innerHeight;
const maxFlakes = 80;
let flakes = [];
let animationId;
let isSnowing = false;
// Gestion du redimensionnement
canvas.width = width;
canvas.height = height;
window.addEventListener('resize', () => {
width = window.innerWidth;
height = window.innerHeight;
canvas.width = width;
canvas.height = height;
});
// --- 3. CLASSE FLOCON ---
class Snowflake {
constructor() {
this.reset(true);
}
reset(initial = false) {
this.x = Math.random() * width;
this.y = initial ? Math.random() * height : -10;
this.radius = Math.random() * 3 + 1;
this.speed = Math.random() * 1.5 + 0.5;
this.drift = Math.random() * 2 - 1;
}
update() {
this.y += this.speed;
this.x += this.drift;
if (this.y > height || this.x > width || this.x < 0) {
this.reset();
}
}
draw(color) {
ctx.beginPath();
ctx.fillStyle = color;
ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2, true);
ctx.fill();
}
}
// --- 4. ANIMATION ---
function initFlakes() {
flakes = [];
for (let i = 0; i < maxFlakes; i++) {
flakes.push(new Snowflake());
}
}
function animate() {
if (!isSnowing) {
ctx.clearRect(0, 0, width, height);
return;
}
ctx.clearRect(0, 0, width, height);
// Récupération dynamique de la couleur (compatible avec ton script Light Switch)
const style = getComputedStyle(document.body);
const currentColor = style.getPropertyValue('--snow-color').trim();
flakes.forEach(flake => {
flake.update();
flake.draw(currentColor);
});
animationId = requestAnimationFrame(animate);
}
// --- 5. BOUTON & INIT ---
function toggleSnow() {
isSnowing = !isSnowing;
updateButtonState();
if (isSnowing) {
initFlakes();
animate();
localStorage.setItem('snow-preference', 'on');
} else {
cancelAnimationFrame(animationId);
ctx.clearRect(0, 0, width, height);
localStorage.setItem('snow-preference', 'off');
}
}
function updateButtonState() {
if(isSnowing) {
toggleBtn.style.opacity = "1";
toggleBtn.style.background = "rgba(128, 128, 128, 0.3)";
} else {
toggleBtn.style.opacity = "0.5";
toggleBtn.style.background = "transparent";
}
}
toggleBtn.addEventListener('click', toggleSnow);
const savedPref = localStorage.getItem('snow-preference');
if (savedPref !== 'off') {
isSnowing = true;
initFlakes();
animate();
updateButtonState();
}
})();
</script>
<!-- MODAL WAIT --> <!-- MODAL WAIT -->
<div class="modal fade bs-example-modal-sm" id="wait" tabindex="-1" role="dialog" aria-hidden="true" data-backdrop="static" style="padding-top: 15%;"> <div class="modal fade bs-example-modal-sm" id="wait" tabindex="-1" role="dialog" aria-hidden="true" data-backdrop="static" style="padding-top: 15%;">
<div class="modal-dialog modal-sm"> <div class="modal-dialog modal-sm">
@@ -352,3 +553,6 @@
</div> </div>
</div> </div>
</div> </div>

View File

@@ -1,46 +0,0 @@
<?php
// Temporarily enable all error reporting to catch details from odbc_connect
// error_reporting(E_ALL); // Uncomment this line if you still don't get enough info
$conn_string = "DRIVER={IBM DB2 ODBC DRIVER - F_DB2_clidriver};" .
"DATABASE=AIXCMDB; " .
"HOSTNAME=db2_aixcmdb.appliarmony.net;" .
"PORT=50000; " .
"PROTOCOL=TCPIP; " .
"UID=aixcmdb;" .
"AUTHENTICATION=SERVER;" .
"PWD=aixcmdb;";
$conn = odbc_connect($conn_string, "", "");
if (!$conn) {
// --- IMPORTANT: Récupérer le message d'erreur ODBC détaillé ---
$error_message = "ODBC Connect Error: " . odbc_errormsg() . " (" . odbc_error() . ")";
echo "Pas de connexion : " . $error_message . "<br>";
// Pour débogage, tu peux aussi loguer cette erreur dans un fichier
// error_log($error_message);
return "ERROR: Could not connect to DB2. Check connection string and ODBC setup."; // Retourne une erreur pour éviter l'appel à odbc_exec
}
$rs = odbc_exec($conn, $request);
// Ton code existant après la connexion
if (strpos(strtoupper($request), "SELECT") !== false) { // strpos est plus robuste que instr ici en PHP
$answer = []; // Initialize array to prevent undefined variable warning
while ($row = odbc_fetch_array($rs)) {
$answer[] = $row;
}
}
if (isset($answer)) {
return $answer;
} else {
if ($rs) {
return "OK";
} else {
// If odbc_exec failed
error_reporting(E_ALL); // Re-enable for this specific error if needed
return "ERROR : " . odbc_errormsg($conn);
}
}

View File

@@ -48,6 +48,7 @@
<a href="/X/autoremediationlog.php" class="nav-link px-0"> <span class="d-none d-sm-inline text-white h7">- AutoRemediation Logs</span></a> <a href="/X/autoremediationlog.php" class="nav-link px-0"> <span class="d-none d-sm-inline text-white h7">- AutoRemediation Logs</span></a>
<a href="/X/stdout.php" class="nav-link px-0"> <span class="d-none d-sm-inline text-white h7">- Scripts Result</span></a> <a href="/X/stdout.php" class="nav-link px-0"> <span class="d-none d-sm-inline text-white h7">- Scripts Result</span></a>
<a href="/X/backups.php" class="nav-link px-0"> <span class="d-none d-sm-inline text-white h7">- Backups</span></a> <a href="/X/backups.php" class="nav-link px-0"> <span class="d-none d-sm-inline text-white h7">- Backups</span></a>
<a href="/X/VIO.php" class="nav-link px-0"> <span class="d-none d-sm-inline text-white h7">- VIO</span></a>
</li> </li>
</ul> </ul>
</li> </li>