Skip to content

Commit e5e9407

Browse files
committed
refactor: remove entire live resource system (frontend, CSS, backend route, permission)
1 parent 55d6f85 commit e5e9407

4 files changed

Lines changed: 0 additions & 213 deletions

File tree

middleware/permissions.js

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ export const PERMISSIONS = {
1414
SERVER_LIST: 'server:list',
1515
SERVER_DETAILS: 'server:details',
1616
SERVER_OVERVIEW: 'server:overview',
17-
SERVER_RESOURCES: 'server:resources',
1817

1918
// API key actions
2019
API_KEY_READ: 'api_key:read',
@@ -72,7 +71,6 @@ export const ROLE_PERMISSIONS = {
7271
PERMISSIONS.SERVER_LIST,
7372
PERMISSIONS.SERVER_DETAILS,
7473
PERMISSIONS.SERVER_OVERVIEW,
75-
PERMISSIONS.SERVER_RESOURCES,
7674
PERMISSIONS.API_KEY_READ,
7775
PERMISSIONS.API_KEY_WRITE,
7876
PERMISSIONS.API_KEY_DELETE,

public/css/style.css

Lines changed: 0 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -2053,20 +2053,6 @@ tbody tr:hover {
20532053
word-break: break-all;
20542054
}
20552055

2056-
/* Resource gauges */
2057-
.resource-gauges {
2058-
grid-template-columns: 1fr;
2059-
gap: 12px;
2060-
}
2061-
2062-
.resource-gauge {
2063-
padding: 16px 12px;
2064-
}
2065-
2066-
.resource-gauge-value {
2067-
font-size: 1.4rem;
2068-
}
2069-
20702056
/* Servers toolbar */
20712057
.servers-toolbar {
20722058
flex-direction: column;
@@ -2798,18 +2784,6 @@ tbody tr:hover {
27982784
padding-bottom: 6px;
27992785
}
28002786

2801-
.resource-gauge-value {
2802-
font-size: 1.2rem;
2803-
}
2804-
2805-
.resource-gauge-label {
2806-
font-size: 0.68rem;
2807-
}
2808-
2809-
.resource-gauge-sub {
2810-
font-size: 0.6rem;
2811-
}
2812-
28132787
.modal {
28142788
padding: 20px 16px;
28152789
}
@@ -3531,60 +3505,6 @@ tbody tr:hover {
35313505

35323506

35333507

3534-
/* Resource gauges for server detail */
3535-
.resource-gauges {
3536-
display: grid;
3537-
grid-template-columns: repeat(3, 1fr);
3538-
gap: 20px;
3539-
margin-top: 8px;
3540-
}
3541-
3542-
.resource-gauge {
3543-
text-align: center;
3544-
padding: 20px 12px;
3545-
background: rgba(255,255,255,0.02);
3546-
border: 1px solid var(--border);
3547-
border-radius: var(--radius-md);
3548-
position: relative;
3549-
overflow: hidden;
3550-
}
3551-
3552-
.resource-gauge-value {
3553-
font-size: 1.8rem;
3554-
font-weight: 800;
3555-
letter-spacing: -0.03em;
3556-
margin-bottom: 4px;
3557-
}
3558-
3559-
.resource-gauge-label {
3560-
font-size: 0.75rem;
3561-
color: var(--text-muted);
3562-
text-transform: uppercase;
3563-
letter-spacing: 0.06em;
3564-
font-weight: 600;
3565-
}
3566-
3567-
.resource-gauge-bar {
3568-
margin-top: 12px;
3569-
height: 4px;
3570-
background: rgba(255,255,255,0.06);
3571-
border-radius: 99px;
3572-
overflow: hidden;
3573-
}
3574-
3575-
.resource-gauge-fill {
3576-
height: 100%;
3577-
border-radius: 99px;
3578-
transition: width 1s cubic-bezier(0.4, 0, 0.2, 1);
3579-
}
3580-
3581-
.resource-gauge-sub {
3582-
font-size: 0.68rem;
3583-
color: var(--text-muted);
3584-
margin-top: 6px;
3585-
font-family: 'JetBrains Mono', monospace;
3586-
}
3587-
35883508
/* Account API key section */
35893509
.api-key-input-group {
35903510
display: flex;
@@ -3596,8 +3516,6 @@ tbody tr:hover {
35963516
flex: 1;
35973517
}
35983518

3599-
/* servers-toolbar + resource-gauges mobile: handled in RESPONSIVE section */
3600-
36013519
/* ===== ADMIN PANEL ===== */
36023520
.admin-layout {
36033521
min-height: 100vh;

public/js/app.js

Lines changed: 0 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -3273,10 +3273,6 @@ async function renderServerDetail(serverId) {
32733273
</div>
32743274
`;
32753275

3276-
if (activeTab === 'resources') {
3277-
fetchLiveResources(s.identifier);
3278-
}
3279-
32803276
// Disable transition for initial position to prevent sliding from 0
32813277
const indicator = $('#tab-indicator');
32823278
const activeTabEl = $('#server-detail-tabs .tab.active');
@@ -3305,89 +3301,6 @@ async function renderServerDetail(serverId) {
33053301
}
33063302
}
33073303

3308-
async function fetchLiveResources(identifier) {
3309-
const container = $('#live-resources-container');
3310-
if (!container) return;
3311-
3312-
try {
3313-
const data = await api(`/servers/resources/${identifier}`);
3314-
3315-
if (!data.resources) {
3316-
container.innerHTML = html`
3317-
<div class="empty-state" style="padding:24px">
3318-
<div class="empty-state-title" style="font-size:0.95rem">No live data</div>
3319-
<div class="empty-state-desc" style="font-size:0.82rem">
3320-
${data.error || 'Add your Pyrodactyl API key in Account → Account Info to enable live monitoring.'}
3321-
</div>
3322-
<button class="btn btn-primary btn-sm" onclick="navigateTo('account/info')" style="margin-top:8px;width:auto">Configure API Key</button>
3323-
</div>
3324-
`;
3325-
return;
3326-
}
3327-
3328-
const res = data.resources;
3329-
const currentState = data.current_state;
3330-
const cpuPct = Math.round(res.cpu_absolute || 0);
3331-
const memUsed = res.memory_bytes ? Math.round(res.memory_bytes / (1024 * 1024)) : 0;
3332-
const memLimit = res.memory_limit_bytes ? Math.round(res.memory_limit_bytes / (1024 * 1024)) : 512;
3333-
const memPct = memLimit > 0 ? Math.min(100, Math.round((memUsed / memLimit) * 100)) : 0;
3334-
const diskUsed = res.disk_bytes ? Math.round(res.disk_bytes / (1024 * 1024)) : 0;
3335-
const diskLimit = 3072;
3336-
const diskPct = diskLimit > 0 ? Math.min(100, Math.round((diskUsed / diskLimit) * 100)) : 0;
3337-
3338-
function usageClass(pct) {
3339-
if (pct >= 80) return 'usage-high';
3340-
if (pct >= 50) return 'usage-mid';
3341-
return 'usage-low';
3342-
}
3343-
3344-
container.innerHTML = html`
3345-
<div class="resource-gauges">
3346-
<div class="resource-gauge">
3347-
<div class="resource-gauge-value" style="color:${cpuPct >= 80 ? 'var(--accent-red)' : cpuPct >= 50 ? 'var(--accent-orange)' : 'var(--accent-cyan)'}">${cpuPct}%</div>
3348-
<div class="resource-gauge-label">CPU</div>
3349-
<div class="resource-gauge-bar"><div class="resource-gauge-fill ${usageClass(cpuPct)}" style="width:${cpuPct}%"></div></div>
3350-
<div class="resource-gauge-sub">${cpuPct >= 80 ? 'High load' : cpuPct >= 50 ? 'Moderate' : 'Idle'}</div>
3351-
</div>
3352-
<div class="resource-gauge">
3353-
<div class="resource-gauge-value" style="color:${memPct >= 80 ? 'var(--accent-red)' : memPct >= 50 ? 'var(--accent-orange)' : 'var(--accent-1)'}">${memUsed} / ${memLimit} MB</div>
3354-
<div class="resource-gauge-label">Memory</div>
3355-
<div class="resource-gauge-bar"><div class="resource-gauge-fill ${usageClass(memPct)}" style="width:${memPct}%"></div></div>
3356-
<div class="resource-gauge-sub">${memPct}% used</div>
3357-
</div>
3358-
<div class="resource-gauge">
3359-
<div class="resource-gauge-value" style="color:${diskPct >= 80 ? 'var(--accent-red)' : diskPct >= 50 ? 'var(--accent-orange)' : 'var(--accent-green)'}">${(diskUsed / 1024).toFixed(1)} / ${(diskLimit / 1024).toFixed(1)} GB</div>
3360-
<div class="resource-gauge-label">Disk</div>
3361-
<div class="resource-gauge-bar"><div class="resource-gauge-fill ${usageClass(diskPct)}" style="width:${diskPct}%"></div></div>
3362-
<div class="resource-gauge-sub">${diskPct}% used</div>
3363-
</div>
3364-
</div>
3365-
<div style="margin-top:12px;text-align:center;font-size:0.72rem;color:var(--text-muted)">
3366-
Updated ${formatRelativeTime(new Date().toISOString())} ·
3367-
${currentState ? html`Status: <strong>${currentState}</strong>` : ''}
3368-
</div>
3369-
`;
3370-
3371-
const refreshBtn = $('#refresh-resources-btn');
3372-
if (refreshBtn && !refreshBtn.dataset.listenerAttached) {
3373-
refreshBtn.dataset.listenerAttached = '1';
3374-
refreshBtn.addEventListener('click', () => {
3375-
container.innerHTML = '<div style="text-align:center;padding:32px;color:var(--text-secondary)" id="live-resources-loading"><span class="spinner"></span> Fetching live data...</div>';
3376-
fetchLiveResources(identifier);
3377-
});
3378-
}
3379-
3380-
} catch (err) {
3381-
if (container) {
3382-
container.innerHTML = html`
3383-
<div style="text-align:center;padding:24px;color:var(--text-muted);font-size:0.88rem">
3384-
Could not load live resources: ${err.message}
3385-
</div>
3386-
`;
3387-
}
3388-
}
3389-
}
3390-
33913304
// ===== TAB SWITCHING =====
33923305
function switchTab(tabBtn) {
33933306
if (!$('#tab-indicator')) return;
@@ -3407,13 +3320,6 @@ function switchTab(tabBtn) {
34073320
indicator.style.width = tabBtn.offsetWidth + 'px';
34083321
}
34093322

3410-
if (tabName === 'resources') {
3411-
const container = $('#live-resources-container');
3412-
if (container && container.querySelector('.resource-gauge') === null) {
3413-
fetchLiveResources(state.serverIdentifier);
3414-
}
3415-
}
3416-
34173323
const newUrl = `/server/${state.serverId}/${tabName}`;
34183324
history.pushState({ page: 'server', serverId: state.serverId, tab: tabName }, '', newUrl);
34193325
}

routes/servers.js

Lines changed: 0 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -540,41 +540,6 @@ async function verifyServerOwnership(userId, identifier) {
540540
}
541541
}
542542

543-
router.get('/resources/:identifier', authenticateToken, async (req, res) => {
544-
try {
545-
const { identifier } = req.params;
546-
const userId = req.user.userId;
547-
548-
if (!await verifyServerOwnership(userId, identifier)) {
549-
return res.status(403).json({ error: 'You do not own this server' });
550-
}
551-
552-
const users = await query('SELECT ptero_client_api_key FROM users WHERE id = ?', [userId]);
553-
if (users.length === 0 || !users[0].ptero_client_api_key) {
554-
return res.json({ resources: null, error: 'No Pyrodactyl API key configured. Set one in Account settings.' });
555-
}
556-
557-
const apiKey = users[0].ptero_client_api_key;
558-
const pteroRes = await fetch(`${PTERO_URL}/api/client/servers/${identifier}/resources`, {
559-
headers: {
560-
'Authorization': `Bearer ${apiKey}`,
561-
'Accept': 'application/json',
562-
},
563-
signal: AbortSignal.timeout(8000),
564-
});
565-
566-
if (!pteroRes.ok) {
567-
return res.status(502).json({ error: 'Failed to fetch resources from panel' });
568-
}
569-
570-
const data = await pteroRes.json();
571-
res.json({ resources: data.attributes.resources, current_state: data.attributes.current_state });
572-
} catch (err) {
573-
console.error('Resources error:', err.message);
574-
res.status(500).json({ error: 'Failed to fetch server resources' });
575-
}
576-
});
577-
578543
router.post('/power/:identifier', authenticateToken, powerLimiter, async (req, res) => {
579544
try {
580545
const { identifier } = req.params;

0 commit comments

Comments
 (0)