minor UI fix, minot data processing improvements
This commit is contained in:
@@ -193,7 +193,7 @@ class OpenVPNAPI:
|
|||||||
|
|
||||||
# 1. Установка временных рамок
|
# 1. Установка временных рамок
|
||||||
if not end_date:
|
if not end_date:
|
||||||
end_date = datetime.now()
|
end_date = datetime.utcnow()
|
||||||
|
|
||||||
if not start_date:
|
if not start_date:
|
||||||
start_date = end_date - timedelta(hours=24) # Дефолт - сутки
|
start_date = end_date - timedelta(hours=24) # Дефолт - сутки
|
||||||
@@ -341,17 +341,24 @@ class OpenVPNAPI:
|
|||||||
for _ in range(points_count):
|
for _ in range(points_count):
|
||||||
current += timedelta(seconds=interval)
|
current += timedelta(seconds=interval)
|
||||||
ts_str = current.strftime('%Y-%m-%d %H:%M:%S')
|
ts_str = current.strftime('%Y-%m-%d %H:%M:%S')
|
||||||
|
ts_iso = ts_str.replace(' ', 'T') + 'Z'
|
||||||
|
|
||||||
if ts_str in db_data_map:
|
if ts_str in db_data_map:
|
||||||
final_data.append(db_data_map[ts_str])
|
item = db_data_map[ts_str].copy()
|
||||||
|
item['timestamp'] = ts_iso
|
||||||
|
final_data.append(item)
|
||||||
else:
|
else:
|
||||||
final_data.append({
|
final_data.append({
|
||||||
'timestamp': ts_str,
|
'timestamp': ts_iso,
|
||||||
'bytes_received': 0,
|
'bytes_received': 0,
|
||||||
'bytes_sent': 0,
|
'bytes_sent': 0,
|
||||||
'bytes_received_rate_mbps': 0,
|
'bytes_received_rate_mbps': 0,
|
||||||
'bytes_sent_rate_mbps': 0
|
'bytes_sent_rate_mbps': 0
|
||||||
})
|
})
|
||||||
|
else:
|
||||||
|
for item in final_data:
|
||||||
|
if 'timestamp' in item and isinstance(item['timestamp'], str):
|
||||||
|
item['timestamp'] = item['timestamp'].replace(' ', 'T') + 'Z'
|
||||||
|
|
||||||
return {
|
return {
|
||||||
'data': final_data,
|
'data': final_data,
|
||||||
@@ -475,7 +482,7 @@ class OpenVPNAPI:
|
|||||||
# Post-processing: Zero Fill
|
# Post-processing: Zero Fill
|
||||||
analytics['global_history_24h'] = []
|
analytics['global_history_24h'] = []
|
||||||
|
|
||||||
now = datetime.utcnow()
|
now = datetime.now(timezone.utc)
|
||||||
# Round down to nearest interval
|
# Round down to nearest interval
|
||||||
ts_now = now.timestamp()
|
ts_now = now.timestamp()
|
||||||
ts_aligned = ts_now - (ts_now % interval_seconds)
|
ts_aligned = ts_now - (ts_now % interval_seconds)
|
||||||
@@ -490,12 +497,15 @@ class OpenVPNAPI:
|
|||||||
for _ in range(96):
|
for _ in range(96):
|
||||||
current += timedelta(seconds=interval_seconds)
|
current += timedelta(seconds=interval_seconds)
|
||||||
ts_str = current.strftime('%Y-%m-%d %H:%M:%S')
|
ts_str = current.strftime('%Y-%m-%d %H:%M:%S')
|
||||||
|
ts_iso = ts_str.replace(' ', 'T') + 'Z'
|
||||||
|
|
||||||
if ts_str in db_data:
|
if ts_str in db_data:
|
||||||
analytics['global_history_24h'].append(db_data[ts_str])
|
item = db_data[ts_str].copy()
|
||||||
|
item['timestamp'] = ts_iso
|
||||||
|
analytics['global_history_24h'].append(item)
|
||||||
else:
|
else:
|
||||||
analytics['global_history_24h'].append({
|
analytics['global_history_24h'].append({
|
||||||
'timestamp': ts_str,
|
'timestamp': ts_iso,
|
||||||
'total_rx': 0,
|
'total_rx': 0,
|
||||||
'total_tx': 0,
|
'total_tx': 0,
|
||||||
'total_rx_rate': 0,
|
'total_rx_rate': 0,
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ class TimeSeriesAggregator:
|
|||||||
conn = self.db_provider()
|
conn = self.db_provider()
|
||||||
cursor = conn.cursor()
|
cursor = conn.cursor()
|
||||||
|
|
||||||
now = datetime.now()
|
now = datetime.utcnow()
|
||||||
|
|
||||||
# --- РАСЧЕТ ВРЕМЕННЫХ КВАНТОВ ---
|
# --- РАСЧЕТ ВРЕМЕННЫХ КВАНТОВ ---
|
||||||
# 1. Сутки (00:00:00)
|
# 1. Сутки (00:00:00)
|
||||||
|
|||||||
@@ -147,20 +147,24 @@ const renderChart = () => {
|
|||||||
{
|
{
|
||||||
label: !isSpeedMode.value ? 'Received (MB)' : 'RX Mbps',
|
label: !isSpeedMode.value ? 'Received (MB)' : 'RX Mbps',
|
||||||
data: dataRx,
|
data: dataRx,
|
||||||
borderColor: '#27ae60',
|
borderColor: '#3fb950',
|
||||||
backgroundColor: 'rgba(39, 174, 96, 0.1)',
|
backgroundColor: 'rgba(63, 185, 80, 0.15)',
|
||||||
borderWidth: 2,
|
borderWidth: 2,
|
||||||
fill: true,
|
fill: true,
|
||||||
tension: 0.3
|
tension: 0.3,
|
||||||
|
pointRadius: 3,
|
||||||
|
pointHoverRadius: 4
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: !isSpeedMode.value ? 'Sent (MB)' : 'TX Mbps',
|
label: !isSpeedMode.value ? 'Sent (MB)' : 'TX Mbps',
|
||||||
data: dataTx,
|
data: dataTx,
|
||||||
borderColor: '#2980b9',
|
borderColor: '#58a6ff',
|
||||||
backgroundColor: 'rgba(41, 128, 185, 0.1)',
|
backgroundColor: 'rgba(88, 166, 255, 0.15)',
|
||||||
borderWidth: 2,
|
borderWidth: 2,
|
||||||
fill: true,
|
fill: true,
|
||||||
tension: 0.3
|
tension: 0.3,
|
||||||
|
pointRadius: 3,
|
||||||
|
pointHoverRadius: 4
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -14,11 +14,25 @@ export function useFormatters() {
|
|||||||
|
|
||||||
function parseServerDate(dateStr) {
|
function parseServerDate(dateStr) {
|
||||||
if (!dateStr) return null;
|
if (!dateStr) return null;
|
||||||
let isoStr = dateStr.replace(' ', 'T');
|
// Handle ISO strings with Z
|
||||||
if (!isoStr.endsWith('Z') && !isoStr.includes('+')) {
|
if (dateStr.endsWith('Z')) return new Date(dateStr);
|
||||||
isoStr += 'Z';
|
|
||||||
|
// Assume format YYYY-MM-DD HH:MM:SS (standard backend output)
|
||||||
|
const [datePart, timePart] = dateStr.split(' ');
|
||||||
|
if (!datePart || !timePart) {
|
||||||
|
// Fallback for other formats
|
||||||
|
let isoStr = dateStr.replace(' ', 'T');
|
||||||
|
if (!isoStr.endsWith('Z') && !isoStr.includes('+')) {
|
||||||
|
isoStr += 'Z';
|
||||||
|
}
|
||||||
|
return new Date(isoStr);
|
||||||
}
|
}
|
||||||
return new Date(isoStr);
|
|
||||||
|
const [y, m, d] = datePart.split('-').map(Number);
|
||||||
|
const [h, min, s] = timePart.split(':').map(Number);
|
||||||
|
|
||||||
|
// Construct Date in UTC
|
||||||
|
return new Date(Date.UTC(y, m - 1, d, h, min, s !== undefined ? s : 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -304,7 +304,7 @@ const renderMainChart = () => {
|
|||||||
borderWidth: 2,
|
borderWidth: 2,
|
||||||
fill: true,
|
fill: true,
|
||||||
tension: 0.3,
|
tension: 0.3,
|
||||||
pointRadius: 0,
|
pointRadius: 3,
|
||||||
pointHoverRadius: 4
|
pointHoverRadius: 4
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -315,7 +315,7 @@ const renderMainChart = () => {
|
|||||||
borderWidth: 2,
|
borderWidth: 2,
|
||||||
fill: true,
|
fill: true,
|
||||||
tension: 0.3,
|
tension: 0.3,
|
||||||
pointRadius: 0,
|
pointRadius: 3,
|
||||||
pointHoverRadius: 4
|
pointHoverRadius: 4
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
Reference in New Issue
Block a user