113 lines
No EOL
4.2 KiB
Python
113 lines
No EOL
4.2 KiB
Python
from flask import Blueprint, render_template
|
|
from flask_login import login_required, current_user
|
|
from datetime import datetime, timedelta
|
|
from app.models import File, Share, Download
|
|
import os
|
|
|
|
dashboard_bp = Blueprint('dashboard', __name__)
|
|
|
|
@dashboard_bp.route('/')
|
|
@login_required
|
|
def index():
|
|
# Get some stats for the dashboard
|
|
total_files = File.query.filter_by(user_id=current_user.id, is_folder=False).count()
|
|
total_folders = File.query.filter_by(user_id=current_user.id, is_folder=True).count()
|
|
|
|
# Recent files for quick access
|
|
recent_files = File.query.filter_by(user_id=current_user.id, is_folder=False)\
|
|
.order_by(File.updated_at.desc())\
|
|
.limit(8).all()
|
|
|
|
# Root folders for quick navigation
|
|
root_folders = File.query.filter_by(user_id=current_user.id, is_folder=True, parent_id=None)\
|
|
.order_by(File.name)\
|
|
.limit(8).all()
|
|
|
|
# Count active shares (if Share model exists)
|
|
active_shares = 0
|
|
recent_activities = 0
|
|
|
|
# Check if Share and Download models exist/are imported
|
|
try:
|
|
# Count active shares
|
|
active_shares = Share.query.filter_by(user_id=current_user.id).filter(
|
|
(Share.expires_at > datetime.now()) | (Share.expires_at.is_(None))
|
|
).count()
|
|
|
|
# Recent activities count (downloads, shares, etc.)
|
|
recent_activities = Download.query.join(Share)\
|
|
.filter(Share.user_id == current_user.id)\
|
|
.filter(Download.timestamp > (datetime.now() - timedelta(days=7)))\
|
|
.count()
|
|
except:
|
|
# Models not ready yet, using default values
|
|
pass
|
|
|
|
return render_template('dashboard.html',
|
|
title='Dashboard',
|
|
total_files=total_files,
|
|
total_folders=total_folders,
|
|
recent_files=recent_files,
|
|
root_folders=root_folders,
|
|
active_shares=active_shares,
|
|
recent_activities=recent_activities,
|
|
now=datetime.now(),
|
|
file_icon=get_file_icon,
|
|
format_size=format_file_size)
|
|
|
|
def get_file_icon(mime_type, filename):
|
|
"""Return Font Awesome icon class based on file type"""
|
|
if mime_type:
|
|
if mime_type.startswith('image/'):
|
|
return 'fa-file-image'
|
|
elif mime_type.startswith('video/'):
|
|
return 'fa-file-video'
|
|
elif mime_type.startswith('audio/'):
|
|
return 'fa-file-audio'
|
|
elif mime_type.startswith('text/'):
|
|
return 'fa-file-alt'
|
|
elif mime_type.startswith('application/pdf'):
|
|
return 'fa-file-pdf'
|
|
elif 'spreadsheet' in mime_type or 'excel' in mime_type:
|
|
return 'fa-file-excel'
|
|
elif 'presentation' in mime_type or 'powerpoint' in mime_type:
|
|
return 'fa-file-powerpoint'
|
|
elif 'document' in mime_type or 'word' in mime_type:
|
|
return 'fa-file-word'
|
|
|
|
# Check by extension
|
|
ext = os.path.splitext(filename)[1].lower()[1:]
|
|
if ext in ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'svg', 'webp']:
|
|
return 'fa-file-image'
|
|
elif ext in ['mp4', 'avi', 'mov', 'wmv', 'flv', 'mkv']:
|
|
return 'fa-file-video'
|
|
elif ext in ['mp3', 'wav', 'ogg', 'flac', 'm4a']:
|
|
return 'fa-file-audio'
|
|
elif ext in ['doc', 'docx', 'odt']:
|
|
return 'fa-file-word'
|
|
elif ext in ['xls', 'xlsx', 'ods', 'csv']:
|
|
return 'fa-file-excel'
|
|
elif ext in ['ppt', 'pptx', 'odp']:
|
|
return 'fa-file-powerpoint'
|
|
elif ext == 'pdf':
|
|
return 'fa-file-pdf'
|
|
elif ext in ['zip', 'rar', '7z', 'tar', 'gz']:
|
|
return 'fa-file-archive'
|
|
elif ext in ['txt', 'rtf', 'md']:
|
|
return 'fa-file-alt'
|
|
elif ext in ['html', 'css', 'js', 'py', 'java', 'php', 'c', 'cpp', 'json', 'xml']:
|
|
return 'fa-file-code'
|
|
|
|
return 'fa-file'
|
|
|
|
def format_file_size(size):
|
|
"""Format file size in bytes to human-readable format"""
|
|
if not size:
|
|
return "0 B"
|
|
|
|
size_names = ("B", "KB", "MB", "GB", "TB")
|
|
i = 0
|
|
while size >= 1024 and i < len(size_names) - 1:
|
|
size /= 1024
|
|
i += 1
|
|
return f"{size:.1f} {size_names[i]}" |