Update VM and DHCP management pages, optimize code

- Modified VM queries in `SYN-VMList.php` to remove unnecessary cluster filtering.
- Adjusted page titles for better context in `SYN-VMList.php`.
- Updated `dhcp_servers.php` with enhanced table export and added new JavaScript (`switch.js`).
- Extended French translations in `fr.php` with new VM-related terms.
- Enhanced KPI calculations in `Crossover-KPI.js` with improved checks and parameter handling.
- Refactored and streamlined `GlobalCrossover.php` for cleaner and more efficient code, improving readability and maintainability.
This commit is contained in:
e025532
2026-04-14 13:59:24 +02:00
parent e9cf3077fa
commit 1f1b7dcd22
9 changed files with 587 additions and 439 deletions

View File

@@ -30,7 +30,7 @@
<body class="bg-light text-dark">
<?php include $_SERVER['DOCUMENT_ROOT'] . "/include/all.php"; ?> <!-- Include All -->
<?php $answers = Invoke_Infra("select * from cmdb_vms where cluster like 'DMV-VMH-SYN%' and decomtime is null order by name"); ?>
<?php $answers = Invoke_Infra("select * from cmdb_vms where decomtime is null order by name"); ?>
<!-- HTML -->
<div class="container-fluid" id="content">
@@ -42,7 +42,7 @@
<!-- Display -->
<div class="col py-3">
<!-- Page Title -->
<h2><span class="badge text-bg-secondary " style="width:100%;" >Synergy VM List - <?php echo count($answers); ?> VMs</span></h2>
<h2><span class="badge text-bg-secondary " style="width:100%;" >VM List - <?php echo count($answers); ?> VMs</span></h2>
<!-- Main content -->
<div class="container-fluid">

186
Hyper-V/VMs.php Normal file
View File

@@ -0,0 +1,186 @@
<!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">
<!-- Page Title -->
<title>Web Infra Reports IT</title>
<link rel="shortcut icon" type="image/png" href="/include/favicon-32x32.png">
<!-- JQuery -->
<script src="/js/jquery-3.6.1.min.js"></script>
<!-- Bootstrap -->
<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>
<!-- Bootstrap-tables -->
<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>
</head>
<body class="bg-light text-dark">
<?php include $_SERVER['DOCUMENT_ROOT'] . "/include/all.php"; ?> <!-- Include All -->
<?php $answers = Invoke_Infra("select * from cmdb_vms where decomtime is null order by name"); ?>
<!-- HTML -->
<div class="container-fluid" id="content">
<div class="row flex-nowrap">
<!-- Left NAVBAR -->
<div class="col-auto col-md-2 col-xl-2 px-sm-2 px-0 bg-dark vh-100 position-sticky top-0" style="-ms-flex: 0 0 230px;flex: 0 0 230px;">
<?php include $_SERVER['DOCUMENT_ROOT'] . "/navbar.html"; ?>
</div>
<!-- Display -->
<div class="col py-3">
<!-- Page Title -->
<h2><span class="badge text-bg-secondary " style="width:100%;" ><?php echo $ti_19 . " - " . count($answers). " " .$w_VMs; ?></span></h2>
<!-- Main content -->
<div class="container-fluid">
<!-- 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-dialog modal-sm">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title mb-1 text-dark text-uppercase text-center">
<i class="bi bi-hourglass-split"></i><br> Work in progress ...
</h4>
</div>
<div class="modal-body">
<div class="progress">
<div class="progress-bar progress-bar-secondary progress-bar-striped progress-bar-animated" style="width: 100%"></div>
</div>
</div>
</div>
</div>
</div>
<!-- TABLE -->
<div>
<div id="result" class="text-center"></div>
<table class='table table-bordered table-hover table-sm' id='t1' data-height="620" data-toggle="table" data-search="true" data-show-columns="true" data-export-types="['xlsx','csv','json']" data-show-export="true" data-sortable="true" data-sort-name="vm">
<thead> <!-- Header -->
<tr>
<th data-field='vm' data-sortable='true'><?php echo $w_name; ?></th>
<th data-field='owner' data-sortable='true'><?php echo $w_owner; ?></th>
<th data-field='infos' data-sortable='true'>Infos</th>
<th data-field='PreferedOwner' data-sortable='true'><?php echo $w_prefferedNode; ?></th>
<th data-field='gen-ver' data-sortable='true'>Gen & Version</th>
<th data-field='LastInventory' data-sortable='true'><?php echo $w_lastUpdate; ?></th>
</tr>
</thead>
<tbody> <!-- Body -->
<?php
$wrongOwner = $unclustered = $v10 = 0 ; $msg ="" ; $CpuComp = 0; $DynVHD = 0;
foreach ($answers as $row) {
echo "<tr>";
# Name
$state = '<i class="bi bi-question-square-fill text-primary"></i> ';
if($row['State'] == "Running"){$state = '<i class="bi bi-play-btn-fill text-success"></i> ';}
if($row['State'] == "Off" || $row['State'] == "Stopping"){$state = '<i class="bi bi-stop-btn-fill text-danger"></i> ';}
if($row['State'] == "Paused"){$state = '<i class="bi bi-pause-btn-fill text-warning"></i> ';}
echo "<td>".$state." <b>".$row['Name']."</td>";
# Owner
echo "<td>".$row['Owner']."</td>";
# Infos
echo '<td><span class="badge rounded-pill bg-secondary text-light">'.$row['Memory'].'GB / '.$row['CPU'].' CPU</span> ';
echo '<span class="badge rounded-pill bg-secondary text-light">VHDx(s) : '.$row['TotalDiskSize'].' GB</span> ';
if($row['WWPNs'] != ""){
echo '<span class="badge rounded-pill bg-primary text-light">LUN(s)</span> ';
}
if($row['CPUcomp'] == "True"){
echo '<span class="badge rounded-pill bg-warning text-dark">CPU Comp.</span> '; $CpuComp++;
}
if($row['DynamicVHD'] == "Y"){
echo '<span class="badge rounded-pill bg-secondary text-warning">Dyn. VHDX</span> '; $DynVHD++;
}
echo "</td>";
# Prefered Owner
if($row['Owner'] == $row['PreferredOwner']){
echo '<td><span class="badge rounded-pill bg-success text-light">'.$row['Owner'].'</span></td> ';
}else{
if($row['IsClustered'] == 'True'){
echo '<td><span class="badge rounded-pill bg-warning text-dark">'.$row['Owner'].'</span></td> ';
$wrongOwner++;
}else{
echo '<td><span class="badge rounded-pill bg-danger text-dark">'.$w_unclustered.'</span></td> ';
$unclustered++;
}
}
# Gen & Ver
echo "<td>";
if($row['Generation'] == "2"){
echo '<span class="badge rounded-pill bg-success text-light">Gen '.$row['Generation'].'</span> ';
}else{
echo '<span class="badge rounded-pill bg-warning text-dark">Gen '.$row['Generation'].'</span> ';
}
if($row['Version'] == "10.0"){
echo '<span class="badge rounded-pill bg-success text-light">Ver '.$row['Version'].'</span> ';
}else{
echo '<span class="badge rounded-pill bg-warning text-dark">Ver '.$row['Version'].'</span> ';
$v10++;
}
echo "</td>";
# TS
echo "<td>".$row['LastInventory']."</td>";
echo "</tr>";
}
if($wrongOwner > 0){$msg = "<span class='badge bg-warning text-dark'>$wrongOwner $w_VMOnWrongOwner</span>";}
if($unclustered > 0){$msg .= "&nbsp;<span class='badge bg-danger'>$unclustered $w_unclusteredVMs</span>";}
if($v10 > 0){$msg .= "&nbsp;<span class='badge bg-warning text-dark'>$v10 $w_VMs < Ver 10.0</span>";}
if($CpuComp > 0){$msg .= "&nbsp;<span class='badge bg-warning text-dark'>$CpuComp $w_vmCpuChecked</span>";}
if($DynVHD > 0){$msg .= "&nbsp;<span class='badge bg-secondary text-warning'>$DynVHD $w_vmDynamicVHD</span>";}
?>
</tbody>
</table>
<br>
</div>
</div>
<!-- End of main content -->
</div>
</div>
</div>
</body>
<script src="/js/switch.js"></script>
</HTML>
<SCRIPT>
$(function() {
const table = $('#t1');
// Exécution initiale pour définir la hauteur
adjustTableHeight();
// Événement de redimensionnement
$(window).on('resize', function() {
adjustTableHeight();
});
function adjustTableHeight() {
const windowHeight = $(window).height();
const tableTop = table.offset().top;
const footerHeight = 50; // Hauteur estimée pour d'éventuels éléments en bas
let availableHeight = windowHeight - tableTop - footerHeight;
// Définir une hauteur minimale
availableHeight = Math.max(availableHeight, 400);
table.bootstrapTable('refreshOptions', {
height: availableHeight
});
}
});
document.getElementById("result").innerHTML = "<?php echo "<h4>".$msg."</h4>" ; ?>";
</script>

View File

@@ -51,7 +51,7 @@ foreach ($xml->xpath("//OptionDefinition") as $optDef) {
<script src="/js/libs/js-xlsx/xlsx.core.min.js"></script>
</head>
<body class="bg-light">
<body class="bg-light text-dark">
<div class="container-fluid">
<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">
@@ -59,14 +59,14 @@ foreach ($xml->xpath("//OptionDefinition") as $optDef) {
</div>
<div class="col py-3">
<h1><span class="badge text-bg-dark w-100"><?php echo htmlspecialchars($server); ?></span></h1>
<h1><span class="badge bg-secondary text-white w-100"><?php echo htmlspecialchars($server); ?></span></h1>
<div class="card mb-3">
<div class="card mb-3 bg-light text-dark">
<div class="card-header bg-info text-white">
<a class="text-white fw-bold" data-bs-toggle="collapse" href="#OptVal"><?php echo $w_globalOptionValues ; ?></a>
<a class="fw-bold text-black" data-bs-toggle="collapse" href="#OptVal"><?php echo $w_globalOptionValues ; ?></a>
</div>
<div id="OptVal" class="collapse show">
<div class="card-body">
<div class="card-body bg-white text-black">
<?php
$globalOptions = $xml->xpath("//IPv4/OptionValues/OptionValue");
foreach ($globalOptions as $opt):
@@ -97,8 +97,8 @@ foreach ($xml->xpath("//OptionDefinition") as $optDef) {
</a>
</div>
<div id="<?php echo $cleanId; ?>" class="collapse">
<div class="card-body">
<div class="row mb-3 text-center bg-light py-2">
<div class="card-body bg-white text-black">
<div class="row mb-3 text-center bg-secondary text-light py-2">
<div class="col-md-4"><strong><?php echo $w_start; ?>:</strong> <?php echo (string)$scope->StartRange; ?></div>
<div class="col-md-4"><strong><?php echo $w_end; ?>:</strong> <?php echo (string)$scope->EndRange; ?></div>
<div class="col-md-4"><strong><?php echo $w_mask; ?>:</strong> <?php echo (string)$scope->SubnetMask; ?></div>
@@ -151,4 +151,5 @@ foreach ($xml->xpath("//OptionDefinition") as $optDef) {
</div>
</div>
</body>
<script src="/js/switch.js"></script>
</html>

View File

@@ -40,7 +40,7 @@ $serversData = Invoke_Entry01("SELECT Server,TS FROM dump_dhcp where ts ='$ts' o
<h1><span class="badge text-bg-secondary w-100"><?php echo count($serversData); ?> DHCP <?php echo $w_server; ?></span></h1>
<div class="container mt-4">
<table class='table table-bordered table-hover table-sm' id='t1' data-height="620" data-toggle="table" data-search="true" data-show-columns="true" data-export-types="['xlsx','csv','json']" data-show-export="true" data-sortable="true">
<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 class="table-light">
<tr>
<th data-field="Server" data-sortable="true"><?php echo $w_server; ?></th>
@@ -66,4 +66,5 @@ $serversData = Invoke_Entry01("SELECT Server,TS FROM dump_dhcp where ts ='$ts' o
</div>
</div>
</body>
<script src="/js/switch.js"></script>
</html>

View File

@@ -1,28 +1,58 @@
function dateDiffInDays(a) {
if (!a || a === 'Missing' || a === '&nbsp;') return 999; // Sécurité
const _MS_PER_DAY = 1000 * 60 * 60 * 24;
return Math.floor((Date.now() - new Date(a)) / _MS_PER_DAY);
}
$(function() {
$button.click(function () {
$data = $table.bootstrapTable('getData')
$dl = $data.length
$nSCCM=0; $nAD=0; $nGLPI=0;$nEPO=0;$nNBU=0;$nOS=0;$nSCOM=0;$nZabbix=0;$nS1=0;
for( $i=0 ; $i < $dl ; $i++ ){
if ($data[$i]['AD'] !== 'Missing') { $nAD++ ; }
if ((dateDiffInDays($data[$i]['ADlu'].split(" ")[0]) > 45 || $data[$i]['ADlu'] == 'Missing') && $data[$i]['AD'] !== 'Missing'){ $nAD-- ;}
if ($data[$i]['SCCM'] !== 'Missing') { $nSCCM++ ; }
if ((dateDiffInDays($data[$i]['SCCMlu'].split(" ")[0]) > 7 || $data[$i]['SCCMlu'] == 'Missing') && $data[$i]['SCCM'] !== 'Missing'){ $nSCCM-- ;}
if ($data[$i]['GLPI'] !== 'Missing') { $nGLPI++ ; }
if ((dateDiffInDays($data[$i]['GLPIlu'].split(" ")[0]) > 7 || $data[$i]['GLPIlu'] == 'Missing') && $data[$i]['GLPI'] !== 'Missing'){ $nGLPI-- ;}
if ($data[$i]['NESSUS'] !== 'Missing') { $nEPO++ ; }
if ($data[$i]['Backup'] !== 'Missing') { $nNBU++ ; }
if ((dateDiffInDays($data[$i]['NBUlu'].split(" ")[0]) > 30 || $data[$i]['NBUlu'] == 'Missing') && $data[$i]['Backup'].split(" ")[0] !== 'Missing'){ $nNBU-- ;}
if (($data[$i]['OS'].includes('XP') || $data[$i]['OS'].includes('2000') || $data[$i]['OS'].includes('2003') || $data[$i]['OS'].includes('2008') || $data[$i]['OS'].includes('2012') || $data[$i]['OS'].includes('7') || $data[$i]['OS'].includes('Windows NT')) == false && $data[$i]['OS'] !=='&nbsp;') { $nOS++ ;}
if ($data[$i]['SCOM'] !== 'Missing') { $nSCOM++ ; }
if ($data[$i]['Zabbix'] !== 'Missing') { $nZabbix++ ; }
if ($data[$i]['S1'] !== 'Missing') { $nS1++ ; }
if ((dateDiffInDays($data[$i]['S1lu'].split(" ")[0]) > 7 || $data[$i]['S1lu'] == 'Missing') && $data[$i]['S1'] !== 'Missing'){ $nS1-- ;}
$('#button').click(function () {
var $data = $('#t1').bootstrapTable('getData');
var $dl = $data.length;
if ($dl === 0) return;
var $nSCCM=0, $nAD=0, $nGLPI=0, $nEPO=0, $nNBU=0, $nOS=0, $nSCOM=0, $nZabbix=0, $nS1=0;
for(var $i=0 ; $i < $dl ; $i++ ){
// Vérification AD
if ($data[$i]['AD'] !== 'Missing') {
$nAD++;
var adDate = ($data[$i]['ADlu'] || '').split(" ")[0];
if (dateDiffInDays(adDate) > 45 || adDate === '') { $nAD--; }
}
// Vérification SCCM
if ($data[$i]['SCCM'] !== 'Missing') {
$nSCCM++;
var sccmDate = ($data[$i]['SCCMlu'] || '').split(" ")[0];
if (dateDiffInDays(sccmDate) > 7 || sccmDate === '') { $nSCCM--; }
}
// Vérification GLPI
if ($data[$i]['GLPI'] !== 'Missing') {
$nGLPI++;
var glpiDate = ($data[$i]['GLPIlu'] || '').split(" ")[0];
if (dateDiffInDays(glpiDate) > 7 || glpiDate === '') { $nGLPI--; }
}
// NESSUS
if ($data[$i]['NESSUS'] !== 'Missing' && $data[$i]['NESSUS'] !== '&nbsp;') { $nEPO++; }
// BACKUP
if ($data[$i]['Backup'] !== 'Missing') {
$nNBU++;
var nbuDate = ($data[$i]['NBUlu'] || '').split(" ")[0];
if (dateDiffInDays(nbuDate) > 30 || nbuDate === '') { $nNBU--; }
}
// OS (Supporté)
var os = $data[$i]['OS'] || '';
if (!(os.includes('XP') || os.includes('2000') || os.includes('2003') || os.includes('2008') || os.includes('2012') || os.includes('7')) && os !== '&nbsp;') { $nOS++; }
// SCOM & Zabbix
if ($data[$i]['SCOM'] !== 'Missing') { $nSCOM++; }
if ($data[$i]['Zabbix'] !== 'Missing') { $nZabbix++; }
// S1
if ($data[$i]['S1'] !== 'Missing') {
$nS1++;
var s1Date = ($data[$i]['S1lu'] || '').split(" ")[0];
if (dateDiffInDays(s1Date) > 7 || s1Date === '') { $nS1--; }
}
}
document.getElementById("KPIAD").innerHTML = Math.round($nAD/$dl*1000)/10 + "%";

View File

@@ -6,42 +6,32 @@
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Page Title -->
<title>Web Infra Reports IT</title>
<link rel="shortcut icon" type="image/png" href="/include/favicon-32x32.png">
<!-- JQuery -->
<script src="/js/jquery-3.6.1.min.js"></script>
<!-- Bootstrap -->
<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>
<!-- Bootstrap-tables -->
<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>
<!-- test -->
</head>
<body class="bg-light text-dark">
<?php include $_SERVER['DOCUMENT_ROOT'] . "/include/all.php"; ?> <!-- Include All -->
<div class="container-fluid">
<?php include $_SERVER['DOCUMENT_ROOT'] . "/include/all.php"; ?>
<div class="container-fluid">
<div class="row flex-nowrap">
<!-- Left NAVBAR -->
<div class="col-auto col-md-2 col-xl-2 px-sm-2 px-0 bg-dark vh-100 position-sticky top-0" style="-ms-flex: 0 0 230px;flex: 0 0 230px;">
<?php include $_SERVER['DOCUMENT_ROOT'] . "/navbar.html"; ?> <!-- Left Navbar -->
<?php include $_SERVER['DOCUMENT_ROOT'] . "/navbar.html"; ?>
</div>
<!-- Display -->
<div class="col py-3">
<!-- Page Title -->
<h1><span class="badge text-bg-secondary font-weight-bold" style="width:100%;"><?php echo $ti_3; ?></span></h1>
<!-- Main content -->
<div class="row" style="zoom: 80%">
<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']"
@@ -69,229 +59,170 @@
</thead>
<tbody>
<!-- Display DATAs -->
<?php
$conn = DB_ENTRY02();
// Base query
$sql = "SELECT * FROM GlobalCrossover";
$whereClauses = ["server NOT LIKE 'WS%'"];
$params = [];
$types = "";
// Handle filters securely using prepared statements
if (isset($_GET['filter'])) {
$filter = $_GET['filter'];
$filterTitle = "$w_filter : " . htmlspecialchars($filter) . " $w_nonCompliant";
switch ($filter) {
case "AD":
$whereClauses[] = "AD IS NULL OR (ADlu IS NOT NULL AND DATEDIFF(now(), ADlu) > 45)";
break;
case "OS":
$whereClauses[] = "OS LIKE '%2003%' OR OS LIKE '%2008%'";
break;
case "GLPI":
$whereClauses[] = "GLPI IS NULL OR GLPIlu IS NULL OR DATEDIFF(now(), GLPIlu) > 7";
break;
case "SCCM":
$whereClauses[] = "SCCM IS NULL OR (SCCMlu IS NOT NULL AND DATEDIFF(now(), SCCMlu) > 7)";
break;
case "NESSUS":
$whereClauses[] = "EPO IS NULL";
break;
case "NBU":
$whereClauses[] = "NBU IS NULL OR (NBUlu IS NOT NULL AND DATEDIFF(now(), NBUlu) > 30)";
break;
case "SCOM":
$whereClauses[] = "SCOM IS NULL";
break;
case "zabbix":
$whereClauses[] = "zabbix IS NULL";
break;
case "S1":
$whereClauses[] = "S1 IS NULL OR (S1lu IS NOT NULL AND DATEDIFF(now(), S1lu) > 7)";
break;
default:
$filterTitle = null; // No valid filter
break;
case "AD": $whereClauses[] = "AD IS NULL OR (ADlu IS NOT NULL AND DATEDIFF(now(), ADlu) > 45)"; break;
case "OS": $whereClauses[] = "OS LIKE '%2003%' OR OS LIKE '%2008%'"; break;
case "GLPI": $whereClauses[] = "GLPI IS NULL OR GLPIlu IS NULL OR DATEDIFF(now(), GLPIlu) > 7"; break;
case "SCCM": $whereClauses[] = "SCCM IS NULL OR (SCCMlu IS NOT NULL AND DATEDIFF(now(), SCCMlu) > 7)"; break;
case "NESSUS": $whereClauses[] = "EPO IS NULL"; break;
case "NBU": $whereClauses[] = "NBU IS NULL OR (NBUlu IS NOT NULL AND DATEDIFF(now(), NBUlu) > 30)"; break;
case "SCOM": $whereClauses[] = "SCOM IS NULL"; break;
case "zabbix": $whereClauses[] = "zabbix IS NULL"; break;
case "S1": $whereClauses[] = "S1 IS NULL OR (S1lu IS NOT NULL AND DATEDIFF(now(), S1lu) > 7)"; break;
default: $filterTitle = null; break;
}
if ($filterTitle) {
echo "<h2><div style=\"text-align: center;\"><span class='badge text-bg-danger font-weight-bold'>$filterTitle</span></div></h2>";
}
}
// Combine all WHERE clauses
if (!empty($whereClauses)) {
$sql .= " WHERE " . implode(' AND ', $whereClauses);
}
if (!empty($whereClauses)) { $sql .= " WHERE " . implode(' AND ', $whereClauses); }
$sql .= " ORDER BY server";
// Prepare and execute the query
$stmt = $conn->prepare($sql);
// Note: If you had parameters, you would bind them here, e.g., $stmt->bind_param($types, ...$params);
$stmt->execute();
$result = $stmt->get_result();
// --- PART 2: HELPER FUNCTIONS FOR RENDERING ---
/**
* Renders a standard status cell based on a value and its last update date.
* @param string|null $status The status value (e.g., 'Y', 'N').
* @param string|null $lastUpdate The date of the last update.
* @param int $daysThreshold The number of days to be considered "out of date".
* @param string $okText Text to display for OK status (e.g., "OK", "OK (NBU)").
* @return string The generated HTML for two <td> cells.
*/
// --- PART 2: HELPER FUNCTIONS ---
function renderStatusCellWithDate(?string $status, ?string $lastUpdate, int $daysThreshold, string $okText = 'OK'): string {
// Sanitize output to prevent XSS
$status = htmlspecialchars($status ?? '', ENT_QUOTES, 'UTF-8');
$lastUpdate = htmlspecialchars($lastUpdate ?? '', ENT_QUOTES, 'UTF-8');
$okText = htmlspecialchars($okText, ENT_QUOTES, 'UTF-8');
if ($status === 'Y') {
if (empty($lastUpdate)) {
// Status is OK, but date is missing
return "<td class='text-white' style='background: linear-gradient(90deg, rgba(25,135,84,1) 50%, rgba(255,193,7,1) 100%);'>$okText</td>"
. "<td class='bg-warning text-black'>Missing</td>";
return "<td class='text-white' style='background: linear-gradient(90deg, rgba(25,135,84,1) 50%, rgba(255,193,7,1) 100%);'>$okText</td><td class='bg-warning text-black'>Missing</td>";
}
try {
$diff = date_diff(date_create($lastUpdate), date_create());
$days = (int) $diff->format("%R%a");
if ($days > $daysThreshold) {
// Out of date
return "<td class='text-white' style='background: linear-gradient(90deg, rgba(25,135,84,1) 50%, rgba(220,53,69,1) 100%);'>$okText</td>"
. "<td class='bg-danger text-white'>$lastUpdate ($days days)</td>";
return "<td class='text-white' style='background: linear-gradient(90deg, rgba(25,135,84,1) 50%, rgba(220,53,69,1) 100%);'>$okText</td><td class='bg-danger text-white'>$lastUpdate ($days days)</td>";
} else {
// Compliant
return "<td class='bg-success text-white'>$okText</td>"
. "<td class='bg-success text-white'>$lastUpdate</td>";
return "<td class='bg-success text-white'>$okText</td><td class='bg-success text-white'>$lastUpdate</td>";
}
} catch (Exception) {
// Handle invalid date format gracefully
return "<td class='bg-danger text-white'>Invalid Date</td><td class='bg-danger text-white'>$lastUpdate</td>";
}
}
if ($status !== '') {
// Not applicable, non-supported, etc.
return "<td class='bg-secondary'><small>$status</small></td><td class='bg-secondary text-secondary'>&nbsp;</td>";
}
// Missing
return "<td class='bg-warning text-black'>Missing</td><td class='bg-warning text-warning'>&nbsp;</td>";
}
// --- PART 3: CLEAN DATA DISPLAY LOOP ---
// Initialize counters
// --- PART 3: DATA PROCESSING & DISPLAY ---
$counters = [
'total' => 0, 'ok' => 0, 'nOS' => 0, 'nAD' => 0, 'nSCCM' => 0, 'nGLPI' => 0,
'nFI' => 0, 'nNESSUS' => 0, 'nNBU' => 0, 'nDPM' => 0, 'nS1' => 0
'nFI' => 0, 'nNESSUS' => 0, 'nNBU' => 0, 'nDPM' => 0, 'nS1' => 0,
'nzabbix' => 0, 'nSCOM' => 0
];
while ($row = $result->fetch_assoc()) {
$counters['total']++;
// Sanitize server name for URL and display
$serverName = htmlspecialchars($row['Server'], ENT_QUOTES, 'UTF-8');
$serverUrl = urlencode($row['Server']);
$maxS1Win = "0"; $maxS1Lin = "0";
$dataRows = [];
// Determine overall row status
while ($row = $result->fetch_assoc()) {
$dataRows[] = $row;
$currentV = $row['S1'] ?? '';
$os = $row['OS'] ?? '';
if (str_contains($currentV, '.')) {
if (stripos($os, 'Windows') !== false) {
if (version_compare($currentV, $maxS1Win, '>')) { $maxS1Win = $currentV; }
} else {
if (version_compare($currentV, $maxS1Lin, '>')) { $maxS1Lin = $currentV; }
}
}
}
foreach ($dataRows as $row) {
// KPI Calculation
$counters['total']++;
$isCompliant = isset($row['AD'], $row['GLPI'], $row['SCCM'], $row['EPO']) && (isset($row['NBU']) || isset($row['DPM'])) && isset($row['SCOM']);
if ($isCompliant) { $counters['ok']++; }
if (!empty($row['OS']) && !preg_match('(XP|2003|2000|2008|Windows 7|2012)', $row['OS'])) { $counters['nOS']++; }
if (!isset($row['AD'])) $counters['nAD']++;
if (!isset($row['SCCM'])) $counters['nSCCM']++;
if (!isset($row['GLPI'])) $counters['nGLPI']++;
if (!isset($row['EPO'])) $counters['nNESSUS']++;
if (!isset($row['NBU']) && !isset($row['DPM'])) $counters['nNBU']++;
if (!isset($row['SCOM'])) $counters['nSCOM']++;
if (!isset($row['zabbix'])) $counters['nzabbix']++;
if (!isset($row['S1'])) $counters['nS1']++;
// Row Rendering
$serverName = htmlspecialchars($row['Server'] ?? '', ENT_QUOTES, 'UTF-8');
$serverUrl = urlencode($row['Server'] ?? '');
if ($isCompliant) {
$counters['ok']++;
$serverCell = "<td class='bg-success text-white'><b><a href='/crossover/Detail.php?server=$serverUrl' target='_blank' class='link-light'>$serverName</a></b></td>";
} else {
$serverCell = "<td><b><a href='/crossover/Detail.php?server=$serverUrl' target='_blank'>$serverName</a></b></td>";
}
// OS Cell
$osCell = "<td class='bg-warning'>&nbsp;</td>";
if (!empty($row['OS'])) {
$os = htmlspecialchars($row['OS']);
if (preg_match('(XP|2003|2000|2008|Windows 7|2012)', $row['OS'])) {
$osCell = "<td class='bg-warning text-black'>$os</td>";
} else {
$counters['nOS']++;
$osCell = "<td>$os</td>";
}
$osCell = preg_match('(XP|2003|2000|2008|Windows 7|2012)', $row['OS']) ? "<td class='bg-warning text-black'>$os</td>" : "<td>$os</td>";
}
echo "<tr>";
echo $serverCell;
echo $osCell;
echo $serverCell . $osCell;
echo "<td>" . htmlspecialchars($row['crit'] ?? '') . "</td>";
// Use helper function for status columns
echo renderStatusCellWithDate($row['AD'], $row['ADlu'], 45);
echo renderStatusCellWithDate($row['GLPI'], $row['GLPIlu'], 7);
echo renderStatusCellWithDate($row['SCCM'], $row['SCCMlu'], 7);
// NESSUS (EPO) Cell - Custom logic
if (str_contains($row['EPO'] ?? '', '.')) {
echo "<td class='bg-success text-white'>" . htmlspecialchars($row['EPO']) . "</td>";
} elseif (isset($row['EPO']) && !in_array($row['EPO'], ['Y', 'N'])) {
echo "<td class='bg-secondary'><small>" . htmlspecialchars($row['EPO']) . "</small></td>";
} else {
echo "<td class='bg-warning text-black'>Missing</td>";
$counters['nNESSUS']++;
}
// NESSUS
if (str_contains($row['EPO'] ?? '', '.')) { echo "<td class='bg-success text-white'>".htmlspecialchars($row['EPO'])."</td>"; }
elseif (isset($row['EPO']) && !in_array($row['EPO'], ['Y', 'N'])) { echo "<td class='bg-secondary'><small>".htmlspecialchars($row['EPO'])."</small></td>"; }
else { echo "<td class='bg-warning text-black'>Missing</td>"; }
// BACKUP Cell - Custom logic for NBU/DPM
if ($row['NBU'] === 'Y') {
echo renderStatusCellWithDate($row['NBU'], $row['NBUlu'], 30, 'OK (NBU)');
} elseif ($row['DPM'] === 'Y') {
echo renderStatusCellWithDate($row['DPM'], $row['DPMlu'], 30, 'OK (DPM)');
} else {
// Handle non-Y cases for NBU or DPM, or missing
$backupStatus = $row['NBU'] ?? $row['DPM'] ?? null;
echo renderStatusCellWithDate($backupStatus, null, 30);
}
// BACKUP
if (($row['NBU'] ?? '') === 'Y') { echo renderStatusCellWithDate($row['NBU'], $row['NBUlu'], 30, 'OK (NBU)'); }
elseif (($row['DPM'] ?? '') === 'Y') { echo renderStatusCellWithDate($row['DPM'], $row['DPMlu'], 30, 'OK (DPM)'); }
else { echo renderStatusCellWithDate($row['NBU'] ?? $row['DPM'] ?? null, null, 30); }
// SCOM Cell - Simple logic
if ($row['SCOM'] === 'Y') {
echo "<td class='bg-success text-white'>OK</td>";
} elseif (isset($row['SCOM'])) {
echo "<td class='bg-secondary'><small>" . htmlspecialchars($row['SCOM']) . "</small></td>";
} else {
echo "<td class='bg-warning text-black'>Missing</td>";
}
// SCOM
if (($row['SCOM'] ?? '') === 'Y') { echo "<td class='bg-success text-white'>OK</td>"; }
elseif (isset($row['SCOM'])) { echo "<td class='bg-secondary'><small>".htmlspecialchars($row['SCOM'])."</small></td>"; }
else { echo "<td class='bg-warning text-black'>Missing</td>"; }
// Zabbix Cell - Simple logic
// Zabbix
$zabbixStatus = $row['zabbix'] ?? '';
if ($zabbixStatus === 'Y' || str_contains($zabbixStatus, '.')) {
echo "<td class='bg-success text-white'>" . htmlspecialchars(str_replace('Y', 'OK', $zabbixStatus)) . "</td>";
} elseif (isset($row['zabbix'])) {
echo "<td class='bg-secondary'><small>" . htmlspecialchars($zabbixStatus) . "</small></td>";
} else {
echo "<td class='bg-warning text-black'>Missing</td>";
}
if ($zabbixStatus === 'Y' || str_contains($zabbixStatus, '.')) { echo "<td class='bg-success text-white'>".htmlspecialchars(str_replace('Y', 'OK', $zabbixStatus))."</td>"; }
elseif (isset($row['zabbix'])) { echo "<td class='bg-secondary'><small>".htmlspecialchars($zabbixStatus)."</small></td>"; }
else { echo "<td class='bg-warning text-black'>Missing</td>"; }
// S1 Cell
// S1 (Comparison)
$s1Status = $row['S1'] ?? '';
$s1Text = ($s1Status === 'Y' || str_contains($s1Status, '.')) ? str_replace('Y', 'OK', $s1Status) : 'OK';
echo renderStatusCellWithDate($s1Status, $row['S1lu'], 7, $s1Text);
$osRaw = $row['OS'] ?? '';
$targetMax = (stripos($osRaw, 'Windows') !== false) ? $maxS1Win : $maxS1Lin;
if (!empty($s1Status) && $s1Status === $targetMax && $targetMax !== "0") {
echo "<td class='bg-success text-white'>" . htmlspecialchars($s1Status) . " <i class='bi bi-check-all'></i></td>";
} elseif (str_contains($s1Status, '.')) {
echo "<td class='bg-warning text-black'>" . htmlspecialchars($s1Status) . "</td>";
} else {
echo renderStatusCellWithDate($s1Status, $row['S1lu'] ?? null, 7, ($s1Status === 'Y' ? 'OK' : $s1Status));
}
echo "</tr>";
}
// You can now use the $counters array to pass data to your JS for the KPIs
// For example:
echo "<script>let kpiData = " . json_encode($counters) . ";</script>";
$stmt->close();
$conn->close();
//echo "<script>let kpiData = " . json_encode($counters) . ";</script>";
$stmt->close(); $conn->close();
?>
</tbody>
</table>
</div>
<button id="button" type="button" class="btn btn-primary btn-sm invisible"><i
class="bi bi-arrow-clockwise"></i><b> Generate KPI</b></button>
<button id="button" type="button" class="btn btn-primary btn-sm invisible"><i class="bi bi-arrow-clockwise"></i><b> Generate KPI</b></button>
<div class="row flex-nowrap text-center" style="zoom: 80%">
<div class="col"> <!-- CARTE Devices -->
<div class="card border-secondary mb-3">
@@ -394,58 +325,41 @@
</div>
</div>
</div>
<!-- End of main content -->
</div>
</div>
</div>
<script src="/js/switch.js"></script>
</div>
</div>
</div>
<script src="/js/switch.js"></script>
</body>
<script src="/crossover/Crossover-KPI.js"></script>
<script>
let $table = $('#t1');
const $button = $('#button');
$table.on('search.bs.table', function () {
let $button = $('#button');
$button.click();
})
$(window).on('load', function () {
$('.preloader').addClass('preloader-deactivate');
});
document.addEventListener("DOMContentLoaded", function () { setTimeout(function () { $('#button').click(); }, 1000); });
</script>
<SCRIPT>
$(function() {
// Exécution initiale pour définir la hauteur
adjustTableHeight();
// Événement de redimensionnement
$(window).on('resize', function() {
adjustTableHeight();
});
// 1. Déclenchement du calcul
setTimeout(function () {
$('#button').trigger('click');
}, 500);
// 2. Gestion du redimensionnement
function adjustTableHeight() {
const table = $('#t1');
const $table = $('#t1');
if ($table.length && $table.offset()) {
const windowHeight = $(window).height();
const tableTop = table.offset().top;
const footerHeight = -50; // Hauteur estimée pour d'éventuels éléments en bas
let availableHeight = windowHeight - tableTop - footerHeight;
// Définir une hauteur minimale
availableHeight = Math.max(availableHeight, 400);
table.bootstrapTable('refreshOptions', {
height: availableHeight
});
const tableTop = $table.offset().top;
$table.bootstrapTable('refreshOptions', { height: Math.max(windowHeight - tableTop - 50, 400) });
}
}
$table = $('#t1');
$table.on('search.bs.table', function () { $('#button').trigger('click'); });
adjustTableHeight();
$(window).on('resize', adjustTableHeight);
});
</script>
</HTML>
</html>

View File

@@ -13,6 +13,8 @@
$nav_3_2 = "VMs Backup";
$nav_3_3 = "VMs Mem hunt";
$nav_3_4 = "Hosts Mem hunt";
$nav_3_5 = "VMs List";
$nav_4 = "Shared Folders";
$nav_4_1 = "Projects & Teams";
@@ -61,6 +63,7 @@
$ti_16 = "Workstation Global Crossover";
$ti_17 = "HeartBeat Map for servers NOT in maintenance";
$ti_18 = "Cluster Resources";
$ti_19 = "Virtual Machines";
// words
$w_server = "Server";
@@ -149,3 +152,8 @@
$w_scopeOptions = "Scope Options";
$w_reservations = "Reservations";
$w_globalOptionValues = "Global Options Values";
$w_prefferedNode = "Preffered Node";
$w_VMOnWrongOwner = "VM(s) on Wrong Owner";
$w_unclusteredVMs = "Unclustered VM(s)";
$w_vmCpuChecked = "VM(s) With 'CPU Compatibility' checked";
$w_vmDynamicVHD = "VM(s) with dynamic VHD";

View File

@@ -13,6 +13,7 @@
$nav_3_2 = "Sauvegardes MVs";
$nav_3_3 = "Chasse Mem MVs";
$nav_3_4 = "Chasse Mem Hôtes";
$nav_3_5 = "Liste des MVs";
$nav_4 = "Dossiers Partagés";
$nav_4_1 = "Projets & Equipes";
@@ -61,6 +62,7 @@
$ti_16 = "Consolidation Multisources des Postes de Travail";
$ti_17 = "Carte des signes de présence pour les Serveurs qui ne sont pas en maintenance";
$ti_18 = "Ressources des Grappes de Serveurs";
$ti_19 = "Machines Virtuelles";
// words
$w_server = "Serveur";
@@ -149,3 +151,8 @@
$w_scopeOptions = "Options de portée";
$w_reservations = "Réservations";
$w_globalOptionValues = "Valeurs des Options Globales";
$w_prefferedNode = "Noeud préféré";
$w_VMOnWrongOwner = "MV(s) sur le mauvais noeud";
$w_unclusteredVMs = "MV(s) non en ressource";
$w_vmCpuChecked = "MV(s) avec 'Compatibilité CPU' coché";
$w_vmDynamicVHD = "MV(s) avec VHD dynamique";

View File

@@ -107,6 +107,7 @@
-->
<a href="/Hyper-V/memory-hunt-vms.php" class="nav-link px-0"> <span class="d-none d-sm-inline text-white h7">- <?php echo $nav_3_3 ;?></span></a>
<a href="/Hyper-V/memory-hunt-HV.php" class="nav-link px-0"> <span class="d-none d-sm-inline text-white h7">- <?php echo $nav_3_4 ;?></span></a>
<a href="/Hyper-V/VMs.php" class="nav-link px-0"> <span class="d-none d-sm-inline text-white h7">- <?php echo $nav_3_5 ;?></span></a>
</li>
</ul>
</li>
@@ -151,7 +152,7 @@
</li>
<li>
<a href="#cluster" data-bs-toggle="collapse" class="nav-link px-0 align-middle">
<i class="fs-6 bi bi-pc text-white"></i> <span class="ms-1 d-none d-sm-inline text-white h7"><small><?php echo $nav_9; ?></small></span><i class="bi bi-caret-down"></i> </a>
<i class="fs-6 bi bi-hdd-network text-white"></i> <span class="ms-1 d-none d-sm-inline text-white h7"><small><?php echo $nav_9; ?></small></span><i class="bi bi-caret-down"></i> </a>
<ul class="collapse nav flex-column ms-1" id="cluster" data-bs-parent="#menu">
<li class="w-100">
<a href="/Inventory/ClusterResource.php" class="nav-link px-0" > <span class="d-none d-sm-inline text-white h7">- <?php echo $nav_9_1; ?></span></a>
@@ -169,7 +170,7 @@
</li>
<li>
<a href="#secureboot" data-bs-toggle="collapse" class="nav-link px-0 align-middle">
<i class="fs-6 bi bi-pc text-white"></i> <span class="ms-1 d-none d-sm-inline text-white h7"><small><?php echo $nav_10; ?></small></span><i class="bi bi-caret-down"></i> </a>
<i class="fs-6 bi bi-shield-lock text-white"></i> <span class="ms-1 d-none d-sm-inline text-white h7"><small><?php echo $nav_10; ?></small></span><i class="bi bi-caret-down"></i> </a>
<ul class="collapse nav flex-column ms-1" id="secureboot" data-bs-parent="#menu">
<li class="w-100">
<a href="/SecureBoot/SecureBoot-SRV.php" class="nav-link px-0"> <span class="d-none d-sm-inline text-white h7">- <?php echo $nav_10_1; ?></span></a>