feat: Add build date functionality and enhance documentation pages

- Added a script to save the build date during Docker image build.
- Introduced a build_date property in the Settings class to retrieve the build date from the environment or file.
- Enhanced the homepage to display system statistics including processed files and active integrations.
- Updated the about page with a comprehensive list of features.
- Added new privacy, imprint, cookies, and terms pages with relevant content.
- Improved the license page with related information links.
- Refactored the base template for better mobile responsiveness and footer links.
This commit is contained in:
Christian Krakau-Louis
2025-04-07 00:05:49 +02:00
parent e669dc8553
commit b93c781339
12 changed files with 584 additions and 55 deletions
+24
View File
@@ -3,6 +3,7 @@
from pydantic_settings import BaseSettings
from typing import Optional, List, Dict, Any
import os
from datetime import datetime
class Settings(BaseSettings):
database_url: str
@@ -121,6 +122,29 @@ class Settings(BaseSettings):
# Feature flags
allow_file_delete: bool = True # Default to allowing file deletion from database
# Get build date from environment or file
@property
def build_date(self) -> str:
# First try to get build date from environment
env_build_date = os.environ.get("BUILD_DATE")
if env_build_date:
return env_build_date
# Then try to get build date from BUILD_DATE file
build_date_file = os.path.join(os.path.dirname(os.path.dirname(__file__)), "BUILD_DATE")
if os.path.exists(build_date_file):
with open(build_date_file, "r") as f:
return f.read().strip()
# If a timestamp file doesn't exist, try to get the app.py creation/modification time
app_file = os.path.join(os.path.dirname(__file__), "app.py")
if os.path.exists(app_file):
timestamp = os.path.getmtime(app_file)
return datetime.fromtimestamp(timestamp).strftime("%B %d, %Y")
# Default to current date if not found elsewhere
return datetime.now().strftime("%B %d, %Y")
# Get version from file or environment
@property
def version(self) -> str:
+49 -3
View File
@@ -4,21 +4,55 @@ General routes for the application homepage and basic pages.
from fastapi import Request, HTTPException
from fastapi.responses import FileResponse
from pathlib import Path
from datetime import date
from app.views.base import APIRouter, templates, require_login
from app.utils.config_validator import get_provider_status, validate_storage_configs
router = APIRouter()
@router.get("/", include_in_schema=False)
async def serve_index(request: Request):
"""Serve the index/home page."""
return templates.TemplateResponse("index.html", {"request": request})
# Get provider information from config validator
providers = get_provider_status()
# Count configured providers
configured_providers = sum(1 for provider in providers.values() if provider['configured'])
# Count different types of storage targets
storage_issues = validate_storage_configs()
configured_storage_targets = sum(1 for provider, issues in storage_issues.items()
if not issues and provider in ['dropbox', 'nextcloud', 'sftp',
's3', 'ftp', 'webdav',
'google_drive', 'onedrive'])
# Create stats object to pass to the template
stats = {
"processed_files": 0, # Placeholder - would need actual DB query
"active_integrations": configured_providers,
"storage_targets": configured_storage_targets
}
return templates.TemplateResponse("index.html", {"request": request, "stats": stats})
@router.get("/about", include_in_schema=False)
async def serve_about(request: Request):
"""Serve the about page."""
return templates.TemplateResponse("about.html", {"request": request})
@router.get("/privacy", include_in_schema=False)
async def serve_privacy(request: Request):
"""Serve the privacy policy page."""
# Pass the current date for the "Last Updated" field
current_date = date.today().strftime("%B %d, %Y")
return templates.TemplateResponse("privacy.html", {"request": request, "current_date": current_date})
@router.get("/imprint", include_in_schema=False)
async def serve_imprint(request: Request):
"""Serve the imprint/impressum page."""
return templates.TemplateResponse("imprint.html", {"request": request})
@router.get("/upload", include_in_schema=False)
@require_login
async def serve_upload(request: Request):
@@ -43,7 +77,7 @@ async def serve_license(request: Request):
Path("/app/LICENSE"), # Docker container path
Path.home() / "LICENSE", # Home directory (fallback)
]
license_text = None
# Try to read from any of the possible locations
@@ -66,7 +100,7 @@ This software is licensed under the Apache License 2.0.
The full license text could not be located on this system.
Please visit http://www.apache.org/licenses/LICENSE-2.0 for the complete license text.
"""
return templates.TemplateResponse(
"license.html",
{
@@ -74,3 +108,15 @@ Please visit http://www.apache.org/licenses/LICENSE-2.0 for the complete license
"license_text": license_text
}
)
@router.get("/cookies", include_in_schema=False)
async def serve_cookies(request: Request):
"""Serve the cookie policy page."""
current_date = date.today().strftime("%B %d, %Y")
return templates.TemplateResponse("cookies.html", {"request": request, "current_date": current_date})
@router.get("/terms", include_in_schema=False)
async def serve_terms(request: Request):
"""Serve the terms of service page."""
current_date = date.today().strftime("%B %d, %Y")
return templates.TemplateResponse("terms.html", {"request": request, "current_date": current_date})