Merge pull request 'feat: threshold modal with range sliders and card-based layout' (#75) from feat/server-thresholds into master

Reviewed-on: #75
Reviewed-by: rafaga21 <rafaelminaya20@hotmail.com>
This commit was merged in pull request #75.
This commit is contained in:
2026-06-13 16:33:41 -04:00
2 changed files with 81 additions and 32 deletions

View File

@@ -3134,3 +3134,39 @@ textarea.form-input {
background: var(--bg-hover, #e9ecef); background: var(--bg-hover, #e9ecef);
border-color: var(--text-muted, #888); border-color: var(--text-muted, #888);
} }
input[type="range"]::-webkit-slider-thumb {
-webkit-appearance: none;
appearance: none;
width: 18px;
height: 18px;
border-radius: 50%;
background: var(--text-primary);
border: 2px solid var(--bg-card);
box-shadow: 0 1px 4px rgba(0,0,0,0.4);
cursor: pointer;
transition: transform 0.1s;
}
input[type="range"]::-webkit-slider-thumb:hover {
transform: scale(1.15);
}
input[type="range"]::-moz-range-thumb {
width: 18px;
height: 18px;
border-radius: 50%;
background: var(--text-primary);
border: 2px solid var(--bg-card);
box-shadow: 0 1px 4px rgba(0,0,0,0.4);
cursor: pointer;
}
input[type="range"]:focus {
outline: none;
}
input[type="range"]::-moz-range-track {
height: 6px;
border-radius: 3px;
}

View File

@@ -304,49 +304,62 @@ $canManage = $server_role === 'owner' || $server_role === 'manager';
</div> </div>
<div id="thresholdModal" class="modal"> <div id="thresholdModal" class="modal">
<div class="modal-dialog"> <div class="modal-dialog" style="max-width:560px">
<div class="modal-header"> <div class="modal-header">
<h3><i class="fas fa-bell"></i> Notification Thresholds</h3> <h3><i class="fas fa-bell"></i> Notification Thresholds</h3>
<button type="button" class="modal-close" onclick="closeThresholdModal()">&times;</button> <button type="button" class="modal-close" onclick="closeThresholdModal()">&times;</button>
</div> </div>
<div class="modal-body"> <div class="modal-body">
<p class="text-muted" style="margin-bottom:20px"> <p class="text-muted" style="margin-bottom:24px;font-size:0.9em;line-height:1.5">
Notifications are sent to all users with access to this server when the agent reports values When the agent reports values above these thresholds, all users with access to this server
exceeding these thresholds. Only the server owner can modify them. receive a notification and push alert. Only the server owner can modify them.
</p> </p>
<form id="thresholdForm" onsubmit="return false"> <form id="thresholdForm" onsubmit="return false">
<div class="table-responsive"> <?php $resources = [
<table class="table"> 'cpu' => ['label' => 'CPU', 'icon' => 'fas fa-microchip', 'color' => 'var(--info)'],
<thead> 'ram' => ['label' => 'RAM', 'icon' => 'fas fa-memory', 'color' => 'var(--purple)'],
<tr> 'disk' => ['label' => 'Disk', 'icon' => 'fas fa-hdd', 'color' => 'var(--warning)'],
<th>Resource</th> ]; ?>
<th>Warning (%)</th> <?php foreach ($resources as $key => $res): ?>
<th>Critical (%)</th> <div style="background:var(--card-bg);border:1px solid var(--border);border-radius:10px;padding:16px 20px;margin-bottom:12px">
</tr> <div style="display:flex;align-items:center;gap:10px;margin-bottom:16px">
</thead> <i class="<?= $res['icon'] ?>" style="color:<?= $res['color'] ?>;font-size:1.2em;width:20px;text-align:center"></i>
<tbody> <strong style="font-size:1em"><?= $res['label'] ?></strong>
<?php foreach (['cpu' => 'CPU', 'ram' => 'RAM', 'disk' => 'Disk'] as $key => $label): ?>
<tr>
<td><strong><?= $label ?></strong></td>
<td>
<input type="number" name="<?= $key ?>_warning"
value="<?= htmlspecialchars((string)($server["threshold_{$key}_warning"] ?? 80)) ?>"
min="0" max="100" step="0.01" class="form-control" style="width:120px">
</td>
<td>
<input type="number" name="<?= $key ?>_critical"
value="<?= htmlspecialchars((string)($server["threshold_{$key}_critical"] ?? 95)) ?>"
min="0" max="100" step="0.01" class="form-control" style="width:120px">
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div> </div>
<div style="display:flex;gap:24px;align-items:flex-start">
<div style="flex:1">
<label style="display:flex;align-items:center;gap:6px;font-size:0.82em;color:var(--warning);margin-bottom:6px;font-weight:600">
<i class="fas fa-exclamation-triangle" style="font-size:0.85em"></i> Warning
</label>
<div style="display:flex;align-items:center;gap:10px">
<input type="range" name="<?= $key ?>_warning"
value="<?= htmlspecialchars((string)($server["threshold_{$key}_warning"] ?? 80)) ?>"
min="0" max="100" step="0.5"
oninput="document.getElementById('<?= $key ?>_warn_val').textContent = this.value + '%'"
style="flex:1;height:6px;-webkit-appearance:none;appearance:none;border-radius:3px;background:linear-gradient(to right, var(--success), var(--warning) 50%, var(--danger) 80%);outline:none;cursor:pointer">
<span id="<?= $key ?>_warn_val" style="min-width:52px;font-size:0.95em;font-weight:700;color:var(--warning);text-align:right"><?= htmlspecialchars((string)($server["threshold_{$key}_warning"] ?? 80)) ?>%</span>
</div>
</div>
<div style="flex:1">
<label style="display:flex;align-items:center;gap:6px;font-size:0.82em;color:var(--danger);margin-bottom:6px;font-weight:600">
<i class="fas fa-bolt" style="font-size:0.85em"></i> Critical
</label>
<div style="display:flex;align-items:center;gap:10px">
<input type="range" name="<?= $key ?>_critical"
value="<?= htmlspecialchars((string)($server["threshold_{$key}_critical"] ?? 95)) ?>"
min="0" max="100" step="0.5"
oninput="document.getElementById('<?= $key ?>_crit_val').textContent = this.value + '%'"
style="flex:1;height:6px;-webkit-appearance:none;appearance:none;border-radius:3px;background:linear-gradient(to right, var(--success), var(--warning) 50%, var(--danger) 80%);outline:none;cursor:pointer">
<span id="<?= $key ?>_crit_val" style="min-width:52px;font-size:0.95em;font-weight:700;color:var(--danger);text-align:right"><?= htmlspecialchars((string)($server["threshold_{$key}_critical"] ?? 95)) ?>%</span>
</div>
</div>
</div>
</div>
<?php endforeach; ?>
</form> </form>
</div> </div>
<div class="modal-footer"> <div class="modal-footer">
<button class="btn btn-primary" onclick="saveThresholds()"><i class="fas fa-save"></i> Save</button> <button class="btn btn-primary" onclick="saveThresholds()"><i class="fas fa-save"></i> Save Thresholds</button>
<button class="btn btn-secondary" onclick="closeThresholdModal()">Cancel</button> <button class="btn btn-secondary" onclick="closeThresholdModal()">Cancel</button>
</div> </div>
</div> </div>