add hourly bar diagram

This commit is contained in:
lelo 2025-03-30 19:21:52 +00:00
parent 2101669567
commit 2ee5cf3a26
2 changed files with 82 additions and 25 deletions

View File

@ -123,16 +123,44 @@ def dashboard():
''', (start.isoformat(),)) ''', (start.isoformat(),))
daily_access_data = [dict(date=row[0], count=row[1]) for row in cursor.fetchall()] daily_access_data = [dict(date=row[0], count=row[1]) for row in cursor.fetchall()]
# Top files for bar chart # Aggregate download counts by time bucket according to the timeframe.
cursor.execute(''' if timeframe == 'today':
SELECT rel_path, COUNT(*) as access_count # Group by hour (0-23)
FROM file_access_log cursor.execute('''
WHERE timestamp >= ? SELECT strftime('%H', timestamp) as bucket, COUNT(*) as count
GROUP BY rel_path FROM file_access_log
ORDER BY access_count DESC WHERE timestamp >= ?
LIMIT 10 GROUP BY bucket
''', (start.isoformat(),)) ORDER BY bucket
top_files_data = [dict(rel_path=row[0], access_count=row[1]) for row in cursor.fetchall()] ''', (start.isoformat(),))
elif timeframe in ('7days', '30days'):
# Group by day (YYYY-MM-DD)
cursor.execute('''
SELECT date(timestamp) as bucket, COUNT(*) as count
FROM file_access_log
WHERE timestamp >= ?
GROUP BY bucket
ORDER BY bucket
''', (start.isoformat(),))
elif timeframe == '365days':
# Group by month (YYYY-MM)
cursor.execute('''
SELECT strftime('%Y-%m', timestamp) as bucket, COUNT(*) as count
FROM file_access_log
WHERE timestamp >= ?
GROUP BY bucket
ORDER BY bucket
''', (start.isoformat(),))
else:
# Fallback: group by day
cursor.execute('''
SELECT date(timestamp) as bucket, COUNT(*) as count
FROM file_access_log
WHERE timestamp >= ?
GROUP BY bucket
ORDER BY bucket
''', (start.isoformat(),))
timeframe_data = [dict(bucket=row[0], count=row[1]) for row in cursor.fetchall()]
# User agent distribution (aggregate by device type) # User agent distribution (aggregate by device type)
cursor.execute(''' cursor.execute('''
@ -224,10 +252,10 @@ def dashboard():
timeframe=timeframe, timeframe=timeframe,
rows=rows, rows=rows,
daily_access_data=daily_access_data, daily_access_data=daily_access_data,
top_files_data=top_files_data,
user_agent_data=user_agent_data, user_agent_data=user_agent_data,
folder_data=folder_data, folder_data=folder_data,
location_data=location_data, location_data=location_data,
total_accesses=total_accesses, total_accesses=total_accesses,
unique_files=unique_files, unique_files=unique_files,
unique_user=unique_user) unique_user=unique_user,
timeframe_data=timeframe_data)

View File

@ -75,12 +75,12 @@
</div> </div>
</div> </div>
</div> </div>
<!-- Top Files Accessed Chart --> <!-- Timeframe Breakdown Chart (Bar Chart) -->
<div class="col-md-6 mb-4"> <div class="col-md-6 mb-4">
<div class="card"> <div class="card">
<div class="card-body"> <div class="card-body">
<h5 class="card-title">Häufig geladene Dateien</h5> <h5 class="card-title">Downloads nach Zeit</h5>
<canvas id="topFilesChart"></canvas> <canvas id="timeframeChart"></canvas>
</div> </div>
</div> </div>
</div> </div>
@ -171,11 +171,41 @@
<script> <script>
// Data passed from the backend as JSON // Data passed from the backend as JSON
const dailyAccessData = {{ daily_access_data|tojson }}; const dailyAccessData = {{ daily_access_data|tojson }};
const topFilesData = {{ top_files_data|tojson }}; // Replace topFilesData usage with timeframeData for this chart
// Note: user_agent_data now contains 'device' and 'count' const timeframeData = {{ timeframe_data|tojson }};
const userAgentData = {{ user_agent_data|tojson }}; const userAgentData = {{ user_agent_data|tojson }};
const folderData = {{ folder_data|tojson }}; const folderData = {{ folder_data|tojson }};
// shift the labels to local time zone
const timeframe = "{{ timeframe }}"; // e.g., 'today', '7days', '30days', or '365days'
const shiftedLabels = timeframeData.map(item => {
if (timeframe === 'today') {
// For "today", the bucket is an hour in UTC (e.g., "14")
const utcHour = parseInt(item.bucket, 10);
const now = new Date();
// Create Date objects for the start and end of the hour in UTC
const utcStart = new Date(Date.UTC(now.getFullYear(), now.getMonth(), now.getDate(), utcHour));
const utcEnd = new Date(Date.UTC(now.getFullYear(), now.getMonth(), now.getDate(), utcHour + 1));
// Convert to local time strings, e.g., "16:00"
const localStart = utcStart.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
const localEnd = utcEnd.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
return `${localStart} - ${localEnd}`;
} else if (timeframe === '7days' || timeframe === '30days') {
// For these timeframes, the bucket is a date in the format "YYYY-MM-DD"
const utcDate = new Date(item.bucket + 'T00:00:00Z');
return utcDate.toLocaleDateString(); // Adjust formatting as needed
} else if (timeframe === '365days') {
// For this timeframe, the bucket is a month in the format "YYYY-MM"
const [year, month] = item.bucket.split('-');
const dateObj = new Date(year, month - 1, 1);
// Format to something like "Mar 2025"
return dateObj.toLocaleString([], { month: 'short', year: 'numeric' });
} else {
// Fallback: use the bucket value as-is
return item.bucket;
}
});
// Access Trend Chart - Line Chart // Access Trend Chart - Line Chart
const ctxTrend = document.getElementById('accessTrendChart').getContext('2d'); const ctxTrend = document.getElementById('accessTrendChart').getContext('2d');
new Chart(ctxTrend, { new Chart(ctxTrend, {
@ -199,25 +229,24 @@
} }
}); });
// Top Files Chart - Horizontal Bar Chart // Timeframe Breakdown Chart - Bar Chart (for "today" timeframe)
const ctxTopFiles = document.getElementById('topFilesChart').getContext('2d'); const ctxTimeframe = document.getElementById('timeframeChart').getContext('2d');
new Chart(ctxTopFiles, { new Chart(ctxTimeframe, {
type: 'bar', type: 'bar',
data: { data: {
labels: topFilesData.map(item => item.full_path), labels: shiftedLabels,
datasets: [{ datasets: [{
label: 'Download Count', label: 'Download Count',
data: topFilesData.map(item => item.access_count), data: timeframeData.map(item => item.count),
borderWidth: 1 borderWidth: 1
}] }]
}, },
options: { options: {
indexAxis: 'y',
responsive: true, responsive: true,
plugins: { legend: { display: false } }, plugins: { legend: { display: false } },
scales: { scales: {
x: { title: { display: true, text: 'Download Count' } }, x: { title: { display: true, text: 'Local Time Range' } },
y: { title: { display: true, text: '' } } y: { title: { display: true, text: 'Download Count' } }
} }
} }
}); });