add distinct devices

This commit is contained in:
lelo 2025-04-01 21:57:43 +02:00
parent 4f88727321
commit 7daf2eea6e
2 changed files with 73 additions and 33 deletions

View File

@ -155,20 +155,49 @@ def dashboard():
cursor = log_db.execute(query, params_for_filter) cursor = log_db.execute(query, params_for_filter)
rows = cursor.fetchall() rows = cursor.fetchall()
# 2. Daily access trend (line chart) # 2. Distinct device trend
# We'll group by day using substr(timestamp, 1, 10) -> YYYY-MM-DD # We'll group by hour if "today", by day if "7days"/"30days", by month if "365days"
query = f''' if timeframe == 'today':
SELECT substr(timestamp, 1, 10) AS date, COUNT(*) AS count # Group by hour: substr(timestamp, 12, 2) -> HH
FROM file_access_log query = f'''
WHERE timestamp >= ? {filetype_filter_sql} SELECT substr(timestamp, 12, 2) AS bucket, COUNT(DISTINCT device_id) AS count
GROUP BY date FROM file_access_log
ORDER BY date WHERE timestamp >= ? {filetype_filter_sql}
''' GROUP BY bucket
ORDER BY bucket
'''
elif timeframe in ('7days', '30days'):
# Group by day: substr(timestamp, 1, 10) -> YYYY-MM-DD
query = f'''
SELECT substr(timestamp, 1, 10) AS bucket, COUNT(DISTINCT device_id) AS count
FROM file_access_log
WHERE timestamp >= ? {filetype_filter_sql}
GROUP BY bucket
ORDER BY bucket
'''
elif timeframe == '365days':
# Group by month: substr(timestamp, 1, 7) -> YYYY-MM
query = f'''
SELECT substr(timestamp, 1, 7) AS bucket, COUNT(DISTINCT device_id) AS count
FROM file_access_log
WHERE timestamp >= ? {filetype_filter_sql}
GROUP BY bucket
ORDER BY bucket
'''
else:
# Default: group by day
query = f'''
SELECT substr(timestamp, 1, 10) AS bucket, COUNT(DISTINCT device_id) AS count
FROM file_access_log
WHERE timestamp >= ? {filetype_filter_sql}
GROUP BY bucket
ORDER BY bucket
'''
with log_db: with log_db:
cursor = log_db.execute(query, params_for_filter) cursor = log_db.execute(query, params_for_filter)
daily_rows = cursor.fetchall() distinct_device_data_rows = cursor.fetchall()
daily_access_data = [ distinct_device_data = [
dict(date=r[0], count=r[1]) for r in daily_rows dict(bucket=r[0], count=r[1]) for r in distinct_device_data_rows
] ]
# 3. Timeframe-based aggregation # 3. Timeframe-based aggregation
@ -322,7 +351,7 @@ def dashboard():
"dashboard.html", "dashboard.html",
timeframe=timeframe, timeframe=timeframe,
rows=rows, rows=rows,
daily_access_data=daily_access_data, distinct_device_data=distinct_device_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,

View File

@ -70,8 +70,8 @@
<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">Downloads</h5> <h5 class="card-title">eindeutige Nutzer nach Zeit</h5>
<canvas id="accessTrendChart"></canvas> <canvas id="distinctDeviceChart"></canvas>
</div> </div>
</div> </div>
</div> </div>
@ -80,7 +80,7 @@
<div class="card"> <div class="card">
<div class="card-body"> <div class="card-body">
<h5 class="card-title">Downloads nach Zeit</h5> <h5 class="card-title">Downloads nach Zeit</h5>
<canvas id="timeframeChart"></canvas> <canvas id="downloadTimeframeChart"></canvas>
</div> </div>
</div> </div>
</div> </div>
@ -170,7 +170,7 @@
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script> <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script> <script>
// Data passed from the backend as JSON // Data passed from the backend as JSON
const dailyAccessData = {{ daily_access_data|tojson }}; const distinctDeviceData = {{ distinct_device_data|tojson }};
// Replace topFilesData usage with timeframeData for this chart // Replace topFilesData usage with timeframeData for this chart
const timeframeData = {{ timeframe_data|tojson }}; const timeframeData = {{ timeframe_data|tojson }};
const userAgentData = {{ user_agent_data|tojson }}; const userAgentData = {{ user_agent_data|tojson }};
@ -206,31 +206,36 @@
} }
}); });
// Access Trend Chart - Line Chart // Distinct Device Chart
const ctxTrend = document.getElementById('accessTrendChart').getContext('2d'); const ctxDistinctDevice = document.getElementById('distinctDeviceChart').getContext('2d');
new Chart(ctxTrend, { new Chart(ctxDistinctDevice, {
type: 'line', type: 'bar',
data: { data: {
labels: dailyAccessData.map(item => item.date), labels: shiftedLabels,
datasets: [{ datasets: [{
label: 'Download Count', label: 'Device Count',
data: dailyAccessData.map(item => item.count), data: distinctDeviceData.map(item => item.count),
borderWidth: 2, borderWidth: 2
fill: true
}] }]
}, },
options: { options: {
responsive: true, responsive: true,
plugins: { legend: { position: 'top' } }, plugins: { legend: { display: false } },
scales: { scales: {
x: { title: { display: true, text: 'Datum' } }, x: { title: { display: true, text: 'Time Range' } },
y: { title: { display: true, text: 'Download Count' } } y: {
title: { display: true, text: 'Device Count' },
beginAtZero: true,
ticks: {
stepSize: 1
}
}
} }
} }
}); });
// Timeframe Breakdown Chart - Bar Chart (for "today" timeframe) // Timeframe Breakdown Chart - Bar Chart (for "today" timeframe)
const ctxTimeframe = document.getElementById('timeframeChart').getContext('2d'); const ctxTimeframe = document.getElementById('downloadTimeframeChart').getContext('2d');
new Chart(ctxTimeframe, { new Chart(ctxTimeframe, {
type: 'bar', type: 'bar',
data: { data: {
@ -238,15 +243,21 @@
datasets: [{ datasets: [{
label: 'Download Count', label: 'Download Count',
data: timeframeData.map(item => item.count), data: timeframeData.map(item => item.count),
borderWidth: 1 borderWidth: 2
}] }]
}, },
options: { options: {
responsive: true, responsive: true,
plugins: { legend: { display: false } }, plugins: { legend: { display: false } },
scales: { scales: {
x: { title: { display: true, text: 'Local Time Range' } }, x: { title: { display: true, text: 'Time Range' } },
y: { title: { display: true, text: 'Download Count' } } y: {
title: { display: true, text: 'Download Count' },
beginAtZero: true,
ticks: {
stepSize: 1
}
}
} }
} }
}); });