V2.1.1 #58

Merged
jamie merged 2 commits from v2.1.1 into main 2026-07-21 11:13:04 +01:00
4 changed files with 21 additions and 9 deletions
Showing only changes of commit 1b3404155c - Show all commits
+7 -7
View File
@@ -2925,14 +2925,14 @@ def api_dashboard():
})
cursor.execute('''
SELECT HOUR(timestamp) AS hour, COUNT(*) AS count
FROM AuditLog
WHERE timestamp >= DATE_SUB(NOW(), INTERVAL 24 HOUR)
GROUP BY HOUR(timestamp)
ORDER BY hour
SELECT timestamp FROM AuditLog
WHERE timestamp >= DATE_SUB(UTC_TIMESTAMP(), INTERVAL 24 HOUR)
''')
activity_by_hour = {row['hour']: row['count'] for row in cursor.fetchall()}
activity = [{'hour': h, 'count': activity_by_hour.get(h, 0)} for h in range(24)]
activity = [
row['timestamp'].strftime('%Y-%m-%d %H:%M:%S')
if hasattr(row['timestamp'], 'strftime') else str(row['timestamp'])
for row in cursor.fetchall()
]
return jsonify({
'stats': {
+1 -1
View File
@@ -213,7 +213,7 @@ export const api = {
available: number;
status: "active" | "alerting";
}[];
activity: { hour: number; count: number }[];
activity: string[];
}>(await fetchApi("/api/v2/dashboard"));
},
async search(q: string) {
+11
View File
@@ -21,3 +21,14 @@ export function formatLocalTime(ts?: string | null, fallback = "—"): string {
if (!d) return ts?.trim() || fallback;
return d.toLocaleString();
}
/** Bucket audit timestamps from the last 24h by local hour of day (023). */
export function bucketActivityByLocalHour(timestamps: string[]): { hour: number; count: number }[] {
const counts = new Array<number>(24).fill(0);
for (const ts of timestamps) {
const d = parseApiTimestamp(ts);
if (!d) continue;
counts[d.getHours()]++;
}
return counts.map((count, hour) => ({ hour, count }));
}
+2 -1
View File
@@ -3,6 +3,7 @@ import { ref, onMounted, computed } from "vue";
import { RouterLink } from "vue-router";
import { Network, Wifi, Layers, Server } from "lucide-vue-next";
import { api } from "@/api";
import { bucketActivityByLocalHour } from "@/utils/datetime";
interface DashboardStats {
total_ips: number;
@@ -46,7 +47,7 @@ onMounted(async () => {
const d = await api.dashboard();
stats.value = d.stats;
subnetOverview.value = d.subnet_overview;
activity.value = d.activity;
activity.value = bucketActivityByLocalHour(d.activity);
} catch (e) {
error.value = e instanceof Error ? e.message : "Failed to load dashboard";
} finally {