Compare commits

..

7 Commits

14 changed files with 105 additions and 21 deletions

View File

@ -353,6 +353,8 @@ def dashboard():
start_dt = now - timedelta(hours=24) start_dt = now - timedelta(hours=24)
elif session['timeframe'] == '7days': elif session['timeframe'] == '7days':
start_dt = now - timedelta(days=7) start_dt = now - timedelta(days=7)
elif session['timeframe'] == '14days':
start_dt = now - timedelta(days=14)
elif session['timeframe'] == '30days': elif session['timeframe'] == '30days':
start_dt = now - timedelta(days=30) start_dt = now - timedelta(days=30)
elif session['timeframe'] == '365days': elif session['timeframe'] == '365days':
@ -381,7 +383,7 @@ def dashboard():
# removed and moved to file_access() function # removed and moved to file_access() function
# 2. Distinct device trend # 2. Distinct device trend
# We'll group by hour if "today", by day if "7days"/"30days", by month if "365days" # We'll group by hour if "today", by day if 7days/14days/30days, by month if 365days
if session['timeframe'] == 'last24hours': if session['timeframe'] == 'last24hours':
# Group by hour: substr(timestamp, 12, 2) -> HH # Group by hour: substr(timestamp, 12, 2) -> HH
query = f''' query = f'''
@ -391,7 +393,7 @@ def dashboard():
GROUP BY bucket GROUP BY bucket
ORDER BY bucket ORDER BY bucket
''' '''
elif session['timeframe'] in ('7days', '30days'): elif session['timeframe'] in ('7days', '14days', '30days'):
# Group by day: substr(timestamp, 1, 10) -> YYYY-MM-DD # Group by day: substr(timestamp, 1, 10) -> YYYY-MM-DD
query = f''' query = f'''
SELECT substr(timestamp, 1, 10) AS bucket, COUNT(DISTINCT device_id) AS count SELECT substr(timestamp, 1, 10) AS bucket, COUNT(DISTINCT device_id) AS count
@ -426,7 +428,7 @@ def dashboard():
] ]
# 3. Download trend # 3. Download trend
# We'll group by hour if "today", by day if "7days"/"30days", by month if "365days". # We'll group by hour if "today", by day if 7days/14days/30days, by month if 365days.
if session['timeframe'] == 'last24hours': if session['timeframe'] == 'last24hours':
# Hour: substr(timestamp, 12, 2) -> HH # Hour: substr(timestamp, 12, 2) -> HH
query = f''' query = f'''
@ -436,7 +438,7 @@ def dashboard():
GROUP BY bucket GROUP BY bucket
ORDER BY bucket ORDER BY bucket
''' '''
elif session['timeframe'] in ('7days', '30days'): elif session['timeframe'] in ('7days', '14days', '30days'):
# Day: substr(timestamp, 1, 10) -> YYYY-MM-DD # Day: substr(timestamp, 1, 10) -> YYYY-MM-DD
query = f''' query = f'''
SELECT substr(timestamp, 1, 10) AS bucket, COUNT(*) AS count SELECT substr(timestamp, 1, 10) AS bucket, COUNT(*) AS count

View File

@ -152,7 +152,7 @@ def require_secret(f):
header_text_color = app_config.get('header_text_color', '#fff') header_text_color = app_config.get('header_text_color', '#fff')
background_color = app_config.get('background_color', '#fff') background_color = app_config.get('background_color', '#fff')
main_text_color = app_config.get('main_text_color', '#000') main_text_color = app_config.get('main_text_color', '#000')
return render_template('index.html', return render_template('permission.html',
title_short=title_short, title_short=title_short,
title_long=title_long, title_long=title_long,
header_color=header_color, header_color=header_color,
@ -160,7 +160,7 @@ def require_secret(f):
main_text_color=main_text_color, main_text_color=main_text_color,
background_color=background_color, background_color=background_color,
admin_enabled=is_admin() admin_enabled=is_admin()
) ), 403 # Forbidden
return decorated_function return decorated_function
def require_admin(f): def require_admin(f):

View File

@ -107,7 +107,7 @@ def generate_top_list(category):
now = datetime.now() now = datetime.now()
# We'll compare the timestamp # We'll compare the timestamp
start_dt = now - timedelta(days=30) start_dt = now - timedelta(days=14)
start_str = start_dt.isoformat() start_str = start_dt.isoformat()
# Filter for mimes that start with the given type # Filter for mimes that start with the given type

View File

@ -347,3 +347,24 @@ footer {
@keyframes spin { @keyframes spin {
to { transform: rotate(360deg); } to { transform: rotate(360deg); }
} }
.card-body.collapsable {
display: none;
transition: max-height 0.3s ease;
overflow: hidden;
}
.card-body.collapsable.show {
display: block;
max-height: 1000px;
}
.toggle-icon {
font-size: 1.5rem;
user-select: none;
}
.toggle-icon:hover {
color: #007bff;
}

34
static/general.js Normal file
View File

@ -0,0 +1,34 @@
document.addEventListener('DOMContentLoaded', function() {
// (No per-icon setup needed here—just ensure your CSS is in place.)
});
// 1) Delegate clicks on any .toggle-icon, now or in the future:
document.addEventListener('click', function(e) {
// Find the closest .toggle-icon ancestor of the click target, if any
if (!e.target.classList.contains('toggle-icon')) return;
var icon = e.target;
// Prevent clicks on the icon from bubbling further if you want
e.stopPropagation();
// Locate its .card-body.collapsable in the same card
var card = icon.closest('.card');
if (!card) return;
var body = card.querySelector('.card-body.collapsable');
if (!body) return;
// Toggle the 'show' class and swap +/ text
if (body.classList.contains('show')) {
// Collapse: remove show, update icon, remove from set
body.classList.remove('show');
icon.textContent = '+';
icon.setAttribute('aria-expanded', 'false');
openCards.add(key);
} else {
// Expand: add show, update icon, add to set
body.classList.add('show');
icon.textContent = '';
icon.setAttribute('aria-expanded', 'true');
openCards.add(key);
}
});

View File

@ -57,7 +57,7 @@
</div> </div>
{% block scripts %}{% endblock %} {% block scripts %}{% endblock %}
<script src="{{ url_for('static', filename='general.js') }}"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
</body> </body>
</html> </html>

View File

@ -26,7 +26,7 @@
{% block content %} {% block content %}
<div class="container-fluid"> <div class="container-fluid">
<h2>Übersicht deiner gültigen Links</h2> <h2>Verbindungen der letzten 10 Minuten</h2>
<span class="ms-3"> <span class="ms-3">
Anzahl Verbindungen: <strong id="totalConnections">0</strong> Anzahl Verbindungen: <strong id="totalConnections">0</strong>
</span> </span>

View File

@ -20,6 +20,8 @@
Last 24 Hours Last 24 Hours
{% elif session['timeframe'] == '7days' %} {% elif session['timeframe'] == '7days' %}
Last 7 Days Last 7 Days
{% elif session['timeframe'] == '14days' %}
Last 14 Days
{% elif session['timeframe'] == '30days' %} {% elif session['timeframe'] == '30days' %}
Last 30 Days Last 30 Days
{% elif session['timeframe'] == '365days' %} {% elif session['timeframe'] == '365days' %}
@ -41,6 +43,12 @@
Last 7 Days Last 7 Days
</a> </a>
</li> </li>
<li>
<a class="dropdown-item {% if session['timeframe'] == '14days' %}active{% endif %}"
href="{{ url_for('dashboard', timeframe='14days') }}">
Last 14 Days
</a>
</li>
<li> <li>
<a class="dropdown-item {% if session['timeframe'] == '30days' %}active{% endif %}" <a class="dropdown-item {% if session['timeframe'] == '30days' %}active{% endif %}"
href="{{ url_for('dashboard', timeframe='30days') }}"> href="{{ url_for('dashboard', timeframe='30days') }}">

View File

@ -9,7 +9,7 @@
<!-- Main Container --> <!-- Main Container -->
<div class="container"> <div class="container">
<h2>Auswertung-Dateizugriffe</h2> <h2>Top 20 Dateizugriffe</h2>
<!-- Dropdown Controls --> <!-- Dropdown Controls -->
<div class="mb-4 d-flex flex-wrap gap-2"> <div class="mb-4 d-flex flex-wrap gap-2">
@ -21,6 +21,8 @@
Last 24 Hours Last 24 Hours
{% elif session['timeframe'] == '7days' %} {% elif session['timeframe'] == '7days' %}
Last 7 Days Last 7 Days
{% elif session['timeframe'] == '14days' %}
Last 14 Days
{% elif session['timeframe'] == '30days' %} {% elif session['timeframe'] == '30days' %}
Last 30 Days Last 30 Days
{% elif session['timeframe'] == '365days' %} {% elif session['timeframe'] == '365days' %}
@ -42,6 +44,12 @@
Last 7 Days Last 7 Days
</a> </a>
</li> </li>
<li>
<a class="dropdown-item {% if session['timeframe'] == '14days' %}active{% endif %}"
href="{{ url_for('file_access', timeframe='14days') }}">
Last 14 Days
</a>
</li>
<li> <li>
<a class="dropdown-item {% if session['timeframe'] == '30days' %}active{% endif %}" <a class="dropdown-item {% if session['timeframe'] == '30days' %}active{% endif %}"
href="{{ url_for('file_access', timeframe='30days') }}"> href="{{ url_for('file_access', timeframe='30days') }}">
@ -62,10 +70,11 @@
<!-- Detailed Table of Top File Accesses --> <!-- Detailed Table of Top File Accesses -->
{% for top20_item in top20 %} {% for top20_item in top20 %}
<div class="card mb-4"> <div class="card mb-4">
<div class="card-header"> <div class="card-header d-flex justify-content-between align-items-center">
Top 20 Dateizugriffe ({{ top20_item['category'] }}) <span>{{ top20_item['category'] }}</span>
<span class="toggle-icon" aria-label="collapse" role="button" tabindex="0">+</span>
</div> </div>
<div class="card-body"> <div class="card-body collapsable">
<div class="table-responsive"> <div class="table-responsive">
<table class="table table-striped"> <table class="table table-striped">
<thead> <thead>
@ -94,6 +103,4 @@
</div> </div>
{% endblock %} {% endblock %}
{% block scripts %}
{% endblock %}

View File

@ -92,7 +92,8 @@
// header // header
const h5 = document.createElement('h5'); const h5 = document.createElement('h5');
h5.innerHTML = `Link${expired ? ' <span class="text-danger fw-bold"> ! abgelaufen !</span>' : ''}`; folderNames = rec.folders.map(f => f.foldername).join(', ');
h5.innerHTML = `Ordner: ${folderNames}${expired ? ' <span class="text-danger fw-bold"> ! abgelaufen !</span>' : ''}`;
body.appendChild(h5); body.appendChild(h5);
// secret input // secret input

View File

@ -46,6 +46,8 @@
type="button" id="timeframeDropdown" data-bs-toggle="dropdown" aria-expanded="false"> type="button" id="timeframeDropdown" data-bs-toggle="dropdown" aria-expanded="false">
{% if session['songs_dashboard_timeframe'] == '7' %} {% if session['songs_dashboard_timeframe'] == '7' %}
Last 7 Days Last 7 Days
{% elif session['songs_dashboard_timeframe'] == '14' %}
Last 14 Days
{% elif session['songs_dashboard_timeframe'] == '30' %} {% elif session['songs_dashboard_timeframe'] == '30' %}
Last 30 Days Last 30 Days
{% elif session['songs_dashboard_timeframe'] == '90' %} {% elif session['songs_dashboard_timeframe'] == '90' %}
@ -65,6 +67,12 @@
Last 7 Days Last 7 Days
</a> </a>
</li> </li>
<li>
<a class="dropdown-item {% if session['songs_dashboard_timeframe'] == '14' %}active{% endif %}"
href="{{ url_for('songs_dashboard', timeframe='14') }}">
Last 14 Days
</a>
</li>
<li> <li>
<a class="dropdown-item {% if session['songs_dashboard_timeframe'] == '30' %}active{% endif %}" <a class="dropdown-item {% if session['songs_dashboard_timeframe'] == '30' %}active{% endif %}"
href="{{ url_for('songs_dashboard', timeframe='30') }}"> href="{{ url_for('songs_dashboard', timeframe='30') }}">

View File

@ -1,6 +1,7 @@
import os import os
import sys import sys
import time import time
import torch
import whisper import whisper
import concurrent.futures import concurrent.futures
import json import json
@ -18,7 +19,6 @@ with open("transcription_config.yml", "r", encoding="utf-8") as file:
settings = yaml.safe_load(file) settings = yaml.safe_load(file)
folder_list = settings.get("folder_list") folder_list = settings.get("folder_list")
model_name = settings.get("model_name") model_name = settings.get("model_name")
device = settings.get("device")
def load_audio_librosa(path: str, sr: int = 16_000) -> np.ndarray: def load_audio_librosa(path: str, sr: int = 16_000) -> np.ndarray:
audio, orig_sr = librosa.load(path, sr=sr) # load + resample to 16 kHz audio, orig_sr = librosa.load(path, sr=sr) # load + resample to 16 kHz
@ -222,7 +222,10 @@ def process_folder(root_folder):
else: else:
print(f"Checked {checked_files} files. Start to transcribe {len(valid_files)} files.") print(f"Checked {checked_files} files. Start to transcribe {len(valid_files)} files.")
print("Loading Whisper model...") # Choose “cuda” if available, otherwise “cpu”
device = "cuda" if torch.cuda.is_available() else "cpu"
print(f"Loading Whisper model on {device}")
model = whisper.load_model(model_name, device=device) model = whisper.load_model(model_name, device=device)
# Use a thread pool to pre-load files concurrently. # Use a thread pool to pre-load files concurrently.