95 lines
3.0 KiB
JavaScript
95 lines
3.0 KiB
JavaScript
|
|
/**
|
||
|
|
* Common Utilities for OpenVPN Monitor
|
||
|
|
*/
|
||
|
|
|
||
|
|
// --- Global Variables ---
|
||
|
|
var currentTheme = localStorage.getItem('theme') || 'light';
|
||
|
|
|
||
|
|
// --- Theme Functions ---
|
||
|
|
function initTheme() {
|
||
|
|
document.documentElement.setAttribute('data-theme', currentTheme);
|
||
|
|
const icon = document.getElementById('themeIcon');
|
||
|
|
if (icon) {
|
||
|
|
if (currentTheme === 'dark') {
|
||
|
|
// In dark mode we want Sun icon (to switch to light)
|
||
|
|
if (icon.classList.contains('fa-moon')) icon.classList.replace('fa-moon', 'fa-sun');
|
||
|
|
else icon.classList = 'fas fa-sun';
|
||
|
|
} else {
|
||
|
|
// In light mode we want Moon icon (to switch to dark)
|
||
|
|
if (icon.classList.contains('fa-sun')) icon.classList.replace('fa-sun', 'fa-moon');
|
||
|
|
else icon.classList = 'fas fa-moon';
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
function toggleTheme(callback = null) {
|
||
|
|
currentTheme = currentTheme === 'light' ? 'dark' : 'light';
|
||
|
|
localStorage.setItem('theme', currentTheme);
|
||
|
|
initTheme();
|
||
|
|
if (callback) callback();
|
||
|
|
}
|
||
|
|
|
||
|
|
// --- Formatting Functions ---
|
||
|
|
function formatBytes(bytes, decimals = 2) {
|
||
|
|
if (bytes === 0) return '0 B';
|
||
|
|
const k = 1024;
|
||
|
|
const dm = decimals < 0 ? 0 : decimals;
|
||
|
|
const sizes = ['B', 'KB', 'MB', 'GB', 'TB'];
|
||
|
|
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
||
|
|
return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i];
|
||
|
|
}
|
||
|
|
|
||
|
|
function formatRate(rate) {
|
||
|
|
return parseFloat(rate).toFixed(3) + ' Mbps';
|
||
|
|
}
|
||
|
|
|
||
|
|
function parseServerDate(dateStr) {
|
||
|
|
if (!dateStr) return null;
|
||
|
|
let isoStr = dateStr.replace(' ', 'T');
|
||
|
|
if (!isoStr.endsWith('Z') && !isoStr.includes('+')) {
|
||
|
|
isoStr += 'Z';
|
||
|
|
}
|
||
|
|
return new Date(isoStr);
|
||
|
|
}
|
||
|
|
|
||
|
|
function formatCertDate(dateString) {
|
||
|
|
if (!dateString || dateString === 'N/A') return 'N/A';
|
||
|
|
|
||
|
|
try {
|
||
|
|
// Handle OpenSSL date format: "Jun 9 08:37:28 2024 GMT"
|
||
|
|
if (dateString.includes('GMT')) {
|
||
|
|
const months = {
|
||
|
|
'Jan': '01', 'Feb': '02', 'Mar': '03', 'Apr': '04',
|
||
|
|
'May': '05', 'Jun': '06', 'Jul': '07', 'Aug': '08',
|
||
|
|
'Sep': '09', 'Oct': '10', 'Nov': '11', 'Dec': '12'
|
||
|
|
};
|
||
|
|
|
||
|
|
const parts = dateString.split(' ');
|
||
|
|
const month = months[parts[0]];
|
||
|
|
const day = parts[1].padStart(2, '0');
|
||
|
|
const year = parts[3];
|
||
|
|
const time = parts[2];
|
||
|
|
|
||
|
|
return `${day}-${month}-${year} ${time}`;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Try to parse as ISO date or other format
|
||
|
|
const date = new Date(dateString);
|
||
|
|
if (!isNaN(date.getTime())) {
|
||
|
|
return date.toLocaleDateString('en-GB', {
|
||
|
|
day: '2-digit',
|
||
|
|
month: 'short',
|
||
|
|
year: 'numeric',
|
||
|
|
hour: '2-digit',
|
||
|
|
minute: '2-digit',
|
||
|
|
hour12: false
|
||
|
|
}).replace(',', '');
|
||
|
|
}
|
||
|
|
|
||
|
|
return dateString;
|
||
|
|
} catch (error) {
|
||
|
|
console.log('Date formatting error:', error, 'for date:', dateString);
|
||
|
|
return dateString;
|
||
|
|
}
|
||
|
|
}
|