diff --git a/routes/__pycache__/main.cpython-313.pyc b/routes/__pycache__/main.cpython-313.pyc
index 00d9c04..3f073ba 100644
Binary files a/routes/__pycache__/main.cpython-313.pyc and b/routes/__pycache__/main.cpython-313.pyc differ
diff --git a/routes/main.py b/routes/main.py
index 43c1503..40eae0c 100644
--- a/routes/main.py
+++ b/routes/main.py
@@ -5,6 +5,18 @@ import os
from werkzeug.utils import secure_filename
from sqlalchemy import func, case, literal_column, text
from datetime import datetime, timedelta
+import logging
+import sys
+
+# Set up logging to show in console
+logging.basicConfig(
+ level=logging.DEBUG,
+ format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
+ handlers=[
+ logging.StreamHandler(sys.stdout)
+ ]
+)
+logger = logging.getLogger(__name__)
def init_routes(main_bp):
@main_bp.route('/')
@@ -16,6 +28,7 @@ def init_routes(main_bp):
@main_bp.route('/dashboard')
@login_required
def dashboard():
+ logger.info("Loading dashboard...")
# Get 3 most recent users
recent_contacts = User.query.order_by(User.created_at.desc()).limit(3).all()
# Count active and inactive users
@@ -24,10 +37,13 @@ def init_routes(main_bp):
# Room count and size logic
if current_user.is_admin:
+ logger.info("Loading admin dashboard...")
room_count = Room.query.count()
# Get total file and folder counts for admin
file_count = RoomFile.query.filter_by(type='file').count()
folder_count = RoomFile.query.filter_by(type='folder').count()
+ logger.info(f"Admin stats - Files: {file_count}, Folders: {folder_count}")
+
# Get total size of all files including trash
total_size = db.session.query(func.sum(RoomFile.size)).filter(RoomFile.type == 'file').scalar() or 0
# Get recent activity for all files
@@ -39,10 +55,21 @@ def init_routes(main_bp):
Room, RoomFile.room_id == Room.id
).join(
User, RoomFile.uploaded_by == User.id
+ ).filter(
+ RoomFile.deleted == False,
+ RoomFile.uploaded_at.isnot(None)
).order_by(
RoomFile.uploaded_at.desc()
).limit(10).all()
+ logger.info(f"Recent activity query results: {len(recent_activity)}")
+ if len(recent_activity) == 0:
+ # Debug query to see what files exist
+ all_files = RoomFile.query.filter_by(deleted=False).all()
+ logger.info(f"Total non-deleted files: {len(all_files)}")
+ for file in all_files[:5]: # Log first 5 files for debugging
+ logger.info(f"File: {file.name}, Uploaded: {file.uploaded_at}, Type: {file.type}")
+
# Format the activity data
formatted_activity = []
for file, room, user in recent_activity:
@@ -57,7 +84,8 @@ def init_routes(main_bp):
'can_download': True # Admin can download everything
}
formatted_activity.append(activity)
- recent_activity = formatted_activity
+ formatted_activities = formatted_activity
+ logger.info(f"Formatted activities: {len(formatted_activities)}")
# Get storage usage by file type including trash
storage_by_type = db.session.query(
case(
@@ -122,11 +150,24 @@ def init_routes(main_bp):
).join(
User, RoomFile.uploaded_by == User.id
).filter(
- RoomFile.room_id.in_(room_ids)
+ RoomFile.room_id.in_(room_ids),
+ RoomFile.deleted == False,
+ RoomFile.uploaded_at.isnot(None) # Ensure uploaded_at is not null
).order_by(
RoomFile.uploaded_at.desc()
).limit(10).all()
+ logger.info(f"Recent activity query results (non-admin): {len(recent_activity)}")
+ if len(recent_activity) == 0:
+ # Debug query to see what files exist
+ all_files = RoomFile.query.filter(
+ RoomFile.room_id.in_(room_ids),
+ RoomFile.deleted == False
+ ).all()
+ logger.info(f"Total non-deleted files in accessible rooms: {len(all_files)}")
+ for file in all_files[:5]: # Log first 5 files for debugging
+ logger.info(f"File: {file.name}, Uploaded: {file.uploaded_at}, Type: {file.type}")
+
# Format the activity data
formatted_activity = []
user_perms = {p.room_id: p for p in RoomMemberPermission.query.filter(
@@ -147,7 +188,7 @@ def init_routes(main_bp):
'can_download': perm.can_download if perm else False
}
formatted_activity.append(activity)
- recent_activity = formatted_activity
+ formatted_activities = formatted_activity
# Get storage usage by file type for accessible rooms including trash
storage_by_type = db.session.query(
case(
@@ -204,7 +245,6 @@ def init_routes(main_bp):
file_count=file_count,
folder_count=folder_count,
total_size=total_size,
- recent_activity=recent_activity,
storage_by_type=storage_by_type,
trash_count=trash_count,
starred_count=starred_count,
diff --git a/static/css/dashboard.css b/static/css/dashboard.css
new file mode 100644
index 0000000..8595c0d
--- /dev/null
+++ b/static/css/dashboard.css
@@ -0,0 +1,139 @@
+:root {
+ --primary-color: #16767b;
+ --secondary-color: #741b5f;
+ --primary-light: #1a8a90;
+ --secondary-light: #8a2170;
+ --warning-color: #ffd700;
+ --danger-color: #dc3545;
+}
+
+/* Masonry Layout */
+.masonry {
+ column-count: 1;
+ column-gap: 1.5rem;
+}
+
+@media (min-width: 768px) {
+ .masonry { column-count: 2; }
+}
+
+@media (min-width: 1200px) {
+ .masonry { column-count: 3; }
+}
+
+.masonry-card {
+ display: inline-block;
+ width: 100%;
+ margin-bottom: 1.5rem;
+}
+
+/* Card Styles */
+.card {
+ border: none;
+ border-radius: 10px;
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
+}
+
+.card-title {
+ color: var(--primary-color);
+}
+
+.card-title i {
+ color: var(--primary-color);
+}
+
+/* Button Styles */
+.btn-primary {
+ background-color: var(--primary-color);
+ border-color: var(--primary-color);
+}
+
+.btn-primary:hover {
+ background-color: var(--primary-light);
+ border-color: var(--primary-light);
+}
+
+/* Icon Colors */
+.icon-primary {
+ color: var(--primary-color);
+}
+
+.icon-danger {
+ color: var(--danger-color);
+}
+
+.icon-warning {
+ color: var(--warning-color);
+}
+
+/* Text Colors */
+.text-primary {
+ color: var(--primary-color) !important;
+}
+
+.text-danger {
+ color: var(--danger-color) !important;
+}
+
+/* Badge Styles */
+.badge-starred {
+ background-color: rgba(255, 215, 0, 0.15) !important;
+ color: var(--warning-color) !important;
+}
+
+.badge-trash {
+ background-color: rgba(220, 53, 69, 0.15) !important;
+ color: var(--danger-color) !important;
+}
+
+/* Contact Link Styles */
+.contact-link {
+ background-color: rgba(22, 118, 123, 0.08);
+ color: var(--primary-color);
+ transition: all 0.2s;
+}
+
+.contact-link:hover {
+ background-color: rgba(22, 118, 123, 0.12);
+ color: var(--primary-color);
+}
+
+/* Chart Container */
+.chart-container {
+ position: relative;
+ height: 200px;
+}
+
+/* Alert Styles */
+.alert-info {
+ background-color: rgba(22, 118, 123, 0.08);
+ border-color: rgba(22, 118, 123, 0.2);
+ color: var(--primary-color);
+}
+
+/* List Group Styles */
+.list-group-item {
+ border: none;
+ padding: 1rem 0;
+}
+
+.list-group-item:not(:last-child) {
+ border-bottom: 1px solid rgba(0, 0, 0, 0.05);
+}
+
+/* Download Button */
+.btn-download {
+ background-color: var(--primary-color);
+ border: none;
+ border-radius: 6px;
+ box-shadow: 0 1px 2px rgba(22, 118, 123, 0.08);
+ color: white;
+ transition: all 0.2s;
+}
+
+.btn-download:hover {
+ background-color: var(--primary-light);
+ color: white;
+ transform: translateY(-1px);
+ box-shadow: 0 2px 4px rgba(22, 118, 123, 0.12);
+}
\ No newline at end of file
diff --git a/templates/components/contact_status.html b/templates/components/contact_status.html
new file mode 100644
index 0000000..41287de
--- /dev/null
+++ b/templates/components/contact_status.html
@@ -0,0 +1,28 @@
+{% macro contact_status(active_count, inactive_count) %}
+
+
+
+
+
+
+
+
+
+
{{ active_count }}
+
Active
+
+
+
{{ inactive_count }}
+
Inactive
+
+
+
+
+
+{% endmacro %}
\ No newline at end of file
diff --git a/templates/components/contacts.html b/templates/components/contacts.html
new file mode 100644
index 0000000..6a8b038
--- /dev/null
+++ b/templates/components/contacts.html
@@ -0,0 +1,38 @@
+{% macro contacts(recent_contacts) %}
+
+
+
+
+ {% if recent_contacts %}
+
+ {% else %}
+
No contacts yet.
+ {% endif %}
+
+
+
+{% endmacro %}
\ No newline at end of file
diff --git a/templates/components/recent_activity.html b/templates/components/recent_activity.html
new file mode 100644
index 0000000..bbb32e3
--- /dev/null
+++ b/templates/components/recent_activity.html
@@ -0,0 +1,59 @@
+{% macro recent_activity(activities) %}
+
+
+
+
+
+ {% for activity in activities %}
+
+
+
+ {% if activity.type == 'folder' %}
+
+ {% else %}
+
+ {% endif %}
+
+
+
+
+
+
{{ activity.name }}
+ {% if activity.is_starred %}
+
+ Starred
+
+ {% endif %}
+ {% if activity.is_deleted %}
+
+ Trash
+
+ {% endif %}
+
+
+ {{ activity.room.name }} •
+ {{ activity.uploader.username }} {{ activity.uploader.last_name }} •
+ {% if activity.uploaded_at %}{{ activity.uploaded_at|timeago }}{% else %}Unknown{% endif %}
+
+
+ {% if activity.type == 'file' and activity.can_download %}
+
+
+
+ {% endif %}
+
+
+
+
+ {% endfor %}
+
+
+
+
+{% endmacro %}
\ No newline at end of file
diff --git a/templates/components/starred_files.html b/templates/components/starred_files.html
new file mode 100644
index 0000000..3b865bf
--- /dev/null
+++ b/templates/components/starred_files.html
@@ -0,0 +1,25 @@
+{% macro starred_files(starred_count, file_count) %}
+
+
+
+
+
Starred Files
+
View All
+
+
+
+
+
+
+
{{ starred_count }}
+
Starred
+
+
+
{{ file_count - starred_count }}
+
Unstarred
+
+
+
+
+
+{% endmacro %}
\ No newline at end of file
diff --git a/templates/components/storage_overview.html b/templates/components/storage_overview.html
new file mode 100644
index 0000000..f16dc3e
--- /dev/null
+++ b/templates/components/storage_overview.html
@@ -0,0 +1,44 @@
+{% from 'macros.html' import format_size %}
+
+{% macro storage_overview(room_count, file_count, folder_count, total_size) %}
+
+
+
+
+
Storage Overview
+
Browse
+
+
+
+
+
+ Rooms:
+
+
{{ room_count }}
+
+
+
+
+ Files:
+
+
{{ file_count }}
+
+
+
+
+ Folders:
+
+
{{ folder_count }}
+
+
+
+
+ Total Size:
+
+
{{ format_size(total_size) }}
+
+
+
+
+
+{% endmacro %}
\ No newline at end of file
diff --git a/templates/components/storage_usage.html b/templates/components/storage_usage.html
new file mode 100644
index 0000000..6641211
--- /dev/null
+++ b/templates/components/storage_usage.html
@@ -0,0 +1,32 @@
+{% from 'macros.html' import format_size %}
+
+{% macro storage_usage(storage_by_type) %}
+
+
+
+
+
Storage Usage
+
View Details
+
+ {% if storage_by_type %}
+
+
+
+
+ {% for type in storage_by_type %}
+
+
+
+ {{ type.extension|upper }}:
+
+
{{ format_size(type.total_size) }}
+
+ {% endfor %}
+
+ {% else %}
+
No storage data available
+ {% endif %}
+
+
+
+{% endmacro %}
\ No newline at end of file
diff --git a/templates/components/trash.html b/templates/components/trash.html
new file mode 100644
index 0000000..b8faafa
--- /dev/null
+++ b/templates/components/trash.html
@@ -0,0 +1,53 @@
+{% from 'macros.html' import format_size %}
+
+{% macro trash(trash_count, pending_deletion, oldest_trash_date, trash_size) %}
+
+
+
+
+
+
+
+
+ Files in trash:
+
+
{{ trash_count }}
+
+
+
+
+ Deleting in 7 days:
+
+
{{ pending_deletion }}
+
+
+
+
+ Oldest deletion:
+
+
{{ oldest_trash_date|default('N/A') }}
+
+
+
+
+ Storage used:
+
+
{{ format_size(trash_size) }}
+
+
+
+
+
+
Files will be permanently deleted after 30 days
+
You can restore files before they are permanently deleted
+
+
+
+
+
+
+
+{% endmacro %}
\ No newline at end of file
diff --git a/templates/components/trash_type.html b/templates/components/trash_type.html
new file mode 100644
index 0000000..4df623f
--- /dev/null
+++ b/templates/components/trash_type.html
@@ -0,0 +1,30 @@
+{% macro trash_type(trash_by_type) %}
+
+
+
+
+
Trash by Type
+
View All
+
+ {% if trash_by_type %}
+
+
+
+
+ {% for type in trash_by_type %}
+
+
+
+ {{ type.extension|upper }}:
+
+
{{ type.count }}
+
+ {% endfor %}
+
+ {% else %}
+
No files in trash
+ {% endif %}
+
+
+
+{% endmacro %}
\ No newline at end of file
diff --git a/templates/dashboard.html b/templates/dashboard.html
index 5cc2c29..f1b4e85 100644
--- a/templates/dashboard.html
+++ b/templates/dashboard.html
@@ -2,6 +2,10 @@
{% block title %}Dashboard - DocuPulse{% endblock %}
+{% block extra_css %}
+
+{% endblock %}
+
{% block content %}
Welcome back, {{ current_user.username }}!
@@ -13,17 +17,13 @@
-{% macro format_size(size) %}
- {% if size < 1024 %}
- {{ size }} B
- {% elif size < 1024 * 1024 %}
- {{ (size / 1024)|round(1) }} KB
- {% elif size < 1024 * 1024 * 1024 %}
- {{ (size / (1024 * 1024))|round(1) }} MB
- {% else %}
- {{ (size / (1024 * 1024 * 1024))|round(1) }} GB
- {% endif %}
-{% endmacro %}
+{% from 'components/storage_overview.html' import storage_overview %}
+{% from 'components/storage_usage.html' import storage_usage %}
+{% from 'components/contacts.html' import contacts %}
+{% from 'components/contact_status.html' import contact_status %}
+{% from 'components/starred_files.html' import starred_files %}
+{% from 'components/trash.html' import trash %}
+{% from 'components/trash_type.html' import trash_type %}
-
-
-
-
-
Storage Overview
-
Browse
-
-
-
-
-
- Rooms:
-
-
{{ room_count }}
-
-
-
-
- Files:
-
-
{{ file_count }}
-
-
-
-
- Folders:
-
-
{{ folder_count }}
-
-
-
-
- Total Size:
-
-
{{ format_size(total_size) }}
-
-
-
-
-
-
-
-
-
-
-
- {% for activity in recent_activity %}
-
-
-
- {% if activity.type == 'folder' %}
-
- {% else %}
-
- {% endif %}
-
-
-
-
-
-
{{ activity.name }}
- {% if activity.is_starred %}
-
- Starred
-
- {% endif %}
- {% if activity.is_deleted %}
-
- Trash
-
- {% endif %}
-
-
- {{ activity.room.name }} •
- {{ activity.uploader.username }} {{ activity.uploader.last_name }} •
- {% if activity.uploaded_at %}{{ activity.uploaded_at|timeago }}{% else %}Unknown{% endif %}
-
-
- {% if activity.type == 'file' and activity.can_download %}
-
-
-
- {% endif %}
-
-
-
-
- {% endfor %}
-
-
-
-
-
-
-
-
-
-
Storage Usage
-
View Details
-
- {% if storage_by_type %}
-
-
-
-
- {% for type in storage_by_type %}
-
-
-
- {{ type.extension|upper }}:
-
-
{{ format_size(type.total_size) }}
-
- {% endfor %}
-
- {% else %}
-
No storage data available
- {% endif %}
-
-
-
-
+ {{ storage_overview(room_count, file_count, folder_count, total_size) }}
+ {{ storage_usage(storage_by_type) }}
+
{% if current_user.is_admin %}
-
-
-
-
- {% if recent_contacts %}
-
- {% else %}
-
No contacts yet.
- {% endif %}
-
-
-
-
-
-
-
-
-
-
-
-
-
{{ active_count }}
-
Active
-
-
-
{{ inactive_count }}
-
Inactive
-
-
-
-
-
+ {{ contacts(recent_contacts) }}
+ {{ contact_status(active_count, inactive_count) }}
{% endif %}
-
-
-
-
-
-
Starred Files
-
View All
-
-
-
-
-
-
-
{{ starred_count }}
-
Starred
-
-
-
{{ file_count - starred_count }}
-
Unstarred
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Files in trash:
-
-
{{ trash_count }}
-
-
-
-
- Deleting in 7 days:
-
-
{{ pending_deletion }}
-
-
-
-
- Oldest deletion:
-
-
{{ oldest_trash_date|default('N/A') }}
-
-
-
-
- Storage used:
-
-
{{ format_size(trash_size) }}
-
-
-
-
-
-
Files will be permanently deleted after 30 days
-
You can restore files before they are permanently deleted
-
-
-
-
-
-
-
-
-
-
-
-
-
Trash by Type
-
View All
-
- {% if trash_by_type %}
-
-
-
-
- {% for type in trash_by_type %}
-
-
-
- {{ type.extension|upper }}:
-
-
{{ type.count }}
-
- {% endfor %}
-
- {% else %}
-
No files in trash
- {% endif %}
-
-
-
+
+ {{ starred_files(starred_count, file_count) }}
+ {{ trash(trash_count, pending_deletion, oldest_trash_date, trash_size) }}
+ {{ trash_type(trash_by_type) }}
{% endblock %}
diff --git a/templates/macros.html b/templates/macros.html
new file mode 100644
index 0000000..8014364
--- /dev/null
+++ b/templates/macros.html
@@ -0,0 +1,11 @@
+{% macro format_size(size) %}
+ {% if size < 1024 %}
+ {{ size }} B
+ {% elif size < 1024 * 1024 %}
+ {{ (size / 1024)|round(1) }} KB
+ {% elif size < 1024 * 1024 * 1024 %}
+ {{ (size / (1024 * 1024))|round(1) }} MB
+ {% else %}
+ {{ (size / (1024 * 1024 * 1024))|round(1) }} GB
+ {% endif %}
+{% endmacro %}
\ No newline at end of file