diff --git a/analytics.py b/analytics.py
index b16ebc6..cbccb40 100644
--- a/analytics.py
+++ b/analytics.py
@@ -353,6 +353,8 @@ def dashboard():
start_dt = now - timedelta(hours=24)
elif session['timeframe'] == '7days':
start_dt = now - timedelta(days=7)
+ elif session['timeframe'] == '14days':
+ start_dt = now - timedelta(days=14)
elif session['timeframe'] == '30days':
start_dt = now - timedelta(days=30)
elif session['timeframe'] == '365days':
@@ -381,7 +383,7 @@ def dashboard():
# removed and moved to file_access() function
# 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':
# Group by hour: substr(timestamp, 12, 2) -> HH
query = f'''
@@ -391,7 +393,7 @@ def dashboard():
GROUP 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
query = f'''
SELECT substr(timestamp, 1, 10) AS bucket, COUNT(DISTINCT device_id) AS count
@@ -426,7 +428,7 @@ def dashboard():
]
# 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':
# Hour: substr(timestamp, 12, 2) -> HH
query = f'''
@@ -436,7 +438,7 @@ def dashboard():
GROUP 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
query = f'''
SELECT substr(timestamp, 1, 10) AS bucket, COUNT(*) AS count
diff --git a/auth.py b/auth.py
index e604ed0..72c2cca 100644
--- a/auth.py
+++ b/auth.py
@@ -152,7 +152,7 @@ def require_secret(f):
header_text_color = app_config.get('header_text_color', '#fff')
background_color = app_config.get('background_color', '#fff')
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_long=title_long,
header_color=header_color,
@@ -160,7 +160,7 @@ def require_secret(f):
main_text_color=main_text_color,
background_color=background_color,
admin_enabled=is_admin()
- )
+ ), 403 # Forbidden
return decorated_function
def require_admin(f):
diff --git a/helperfunctions.py b/helperfunctions.py
index 92ba3c0..4c9f17e 100644
--- a/helperfunctions.py
+++ b/helperfunctions.py
@@ -107,7 +107,7 @@ def generate_top_list(category):
now = datetime.now()
# We'll compare the timestamp
- start_dt = now - timedelta(days=30)
+ start_dt = now - timedelta(days=14)
start_str = start_dt.isoformat()
# Filter for mimes that start with the given type
diff --git a/static/app.css b/static/app.css
index 9911970..cf0740a 100644
--- a/static/app.css
+++ b/static/app.css
@@ -346,4 +346,25 @@ footer {
@keyframes spin {
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;
}
\ No newline at end of file
diff --git a/static/app.js b/static/app.js
index cf4e913..af89095 100644
--- a/static/app.js
+++ b/static/app.js
@@ -498,4 +498,4 @@ function syncThemeColor() {
.forEach(svg => svg.setAttribute('fill', cssVar));
}
-document.addEventListener('DOMContentLoaded', syncThemeColor);
\ No newline at end of file
+document.addEventListener('DOMContentLoaded', syncThemeColor);
diff --git a/static/general.js b/static/general.js
new file mode 100644
index 0000000..56d59d4
--- /dev/null
+++ b/static/general.js
@@ -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);
+ }
+ });
diff --git a/templates/base.html b/templates/base.html
index c4f288d..3552ee0 100644
--- a/templates/base.html
+++ b/templates/base.html
@@ -57,7 +57,7 @@
{% block scripts %}{% endblock %}
-
+