Fix Daily usage
This commit is contained in:
@@ -975,6 +975,12 @@ function fmtBytes(n) {
|
|||||||
const m=k/1024; if(m<1024) return m.toFixed(1)+" MiB";
|
const m=k/1024; if(m<1024) return m.toFixed(1)+" MiB";
|
||||||
return (m/1024).toFixed(1)+" GiB";
|
return (m/1024).toFixed(1)+" GiB";
|
||||||
}
|
}
|
||||||
|
function localDateKey(d = new Date()) {
|
||||||
|
const y = d.getFullYear();
|
||||||
|
const m = String(d.getMonth() + 1).padStart(2, "0");
|
||||||
|
const day = String(d.getDate()).padStart(2, "0");
|
||||||
|
return `${y}-${m}-${day}`;
|
||||||
|
}
|
||||||
function fmtDate(iso) {
|
function fmtDate(iso) {
|
||||||
if (!iso) return "—";
|
if (!iso) return "—";
|
||||||
const d = new Date(iso);
|
const d = new Date(iso);
|
||||||
@@ -1695,14 +1701,17 @@ async function loadVnstat() {
|
|||||||
renderVnstatRows(vnstatDailyBody, daily, "No daily usage recorded yet.");
|
renderVnstatRows(vnstatDailyBody, daily, "No daily usage recorded yet.");
|
||||||
renderVnstatRows(vnstatMonthlyBody, monthly, "No monthly usage recorded yet.");
|
renderVnstatRows(vnstatMonthlyBody, monthly, "No monthly usage recorded yet.");
|
||||||
|
|
||||||
const today = new Date().toISOString().slice(0,10);
|
// Use the server/database periods when available. Falling back to the
|
||||||
const month = today.slice(0,7);
|
// newest row avoids browser UTC/local-time mismatches that can make
|
||||||
const todayTotal = daily.filter(r => r.period === today).reduce((sum, r) => sum + (r.total_bytes||0), 0);
|
// "Today total" show 0 while the daily table has data.
|
||||||
const monthTotal = monthly.filter(r => r.period === month).reduce((sum, r) => sum + (r.total_bytes||0), 0);
|
const today = data.today_period || daily[0]?.period || localDateKey();
|
||||||
|
const month = data.month_period || today.slice(0,7);
|
||||||
|
const todayTotal = data.today_total_bytes ?? daily.filter(r => r.period === today).reduce((sum, r) => sum + (r.total_bytes||0), 0);
|
||||||
|
const monthTotal = data.month_total_bytes ?? monthly.filter(r => r.period === month).reduce((sum, r) => sum + (r.total_bytes||0), 0);
|
||||||
const ifaces = new Set([...daily, ...monthly].map(r => r.iface).filter(Boolean));
|
const ifaces = new Set([...daily, ...monthly].map(r => r.iface).filter(Boolean));
|
||||||
vnTodayTotal.textContent = fmtBytes(todayTotal);
|
vnTodayTotal.textContent = fmtBytes(todayTotal);
|
||||||
vnMonthTotal.textContent = fmtBytes(monthTotal);
|
vnMonthTotal.textContent = fmtBytes(monthTotal);
|
||||||
vnIfaceCount.textContent = String(ifaces.size || 0);
|
vnIfaceCount.textContent = String(data.interface_count ?? ifaces.size ?? 0);
|
||||||
vnstatStatus.textContent = "Updated: " + new Date().toLocaleTimeString() + " · history is kept until manually cleaned.";
|
vnstatStatus.textContent = "Updated: " + new Date().toLocaleTimeString() + " · history is kept until manually cleaned.";
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (e.message === "auth") doAuthError();
|
if (e.message === "auth") doAuthError();
|
||||||
|
|||||||
1553
admin_script.js
Normal file
1553
admin_script.js
Normal file
File diff suppressed because it is too large
Load Diff
@@ -80,9 +80,14 @@ type VnstatUsageRow struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type VnstatDTO struct {
|
type VnstatDTO struct {
|
||||||
Daily []VnstatUsageRow `json:"daily"`
|
Daily []VnstatUsageRow `json:"daily"`
|
||||||
Monthly []VnstatUsageRow `json:"monthly"`
|
Monthly []VnstatUsageRow `json:"monthly"`
|
||||||
UpdatedAt time.Time `json:"updated_at"`
|
UpdatedAt time.Time `json:"updated_at"`
|
||||||
|
TodayPeriod string `json:"today_period"`
|
||||||
|
MonthPeriod string `json:"month_period"`
|
||||||
|
TodayTotalBytes uint64 `json:"today_total_bytes"`
|
||||||
|
MonthTotalBytes uint64 `json:"month_total_bytes"`
|
||||||
|
InterfaceCount int `json:"interface_count"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Store) EnsureIfaceUsageTables(ctx context.Context) error {
|
func (s *Store) EnsureIfaceUsageTables(ctx context.Context) error {
|
||||||
@@ -167,7 +172,11 @@ func (s *Store) LoadIfaceUsage(ctx context.Context, days, months int) (VnstatDTO
|
|||||||
months = 12
|
months = 12
|
||||||
}
|
}
|
||||||
|
|
||||||
out := VnstatDTO{UpdatedAt: time.Now()}
|
now := time.Now()
|
||||||
|
todayPeriod := now.Format("2006-01-02")
|
||||||
|
monthPeriod := now.Format("2006-01")
|
||||||
|
out := VnstatDTO{UpdatedAt: now, TodayPeriod: todayPeriod, MonthPeriod: monthPeriod}
|
||||||
|
ifaceSet := make(map[string]struct{})
|
||||||
|
|
||||||
dailyRows, err := s.db.QueryContext(ctx, `
|
dailyRows, err := s.db.QueryContext(ctx, `
|
||||||
SELECT iface, usage_date::text, rx_bytes, tx_bytes
|
SELECT iface, usage_date::text, rx_bytes, tx_bytes
|
||||||
@@ -186,6 +195,10 @@ func (s *Store) LoadIfaceUsage(ctx context.Context, days, months int) (VnstatDTO
|
|||||||
}
|
}
|
||||||
r.TotalBytes = r.RxBytes + r.TxBytes
|
r.TotalBytes = r.RxBytes + r.TxBytes
|
||||||
out.Daily = append(out.Daily, r)
|
out.Daily = append(out.Daily, r)
|
||||||
|
ifaceSet[r.Iface] = struct{}{}
|
||||||
|
if r.Period == todayPeriod {
|
||||||
|
out.TodayTotalBytes += r.TotalBytes
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if err := dailyRows.Err(); err != nil {
|
if err := dailyRows.Err(); err != nil {
|
||||||
return out, err
|
return out, err
|
||||||
@@ -208,11 +221,17 @@ func (s *Store) LoadIfaceUsage(ctx context.Context, days, months int) (VnstatDTO
|
|||||||
}
|
}
|
||||||
r.TotalBytes = r.RxBytes + r.TxBytes
|
r.TotalBytes = r.RxBytes + r.TxBytes
|
||||||
out.Monthly = append(out.Monthly, r)
|
out.Monthly = append(out.Monthly, r)
|
||||||
|
ifaceSet[r.Iface] = struct{}{}
|
||||||
|
if r.Period == monthPeriod {
|
||||||
|
out.MonthTotalBytes += r.TotalBytes
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if err := monthlyRows.Err(); err != nil {
|
if err := monthlyRows.Err(); err != nil {
|
||||||
return out, err
|
return out, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
out.InterfaceCount = len(ifaceSet)
|
||||||
|
|
||||||
return out, nil
|
return out, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user