mirror of
https://github.com/DRYTRIX/TimeTracker.git
synced 2026-05-04 03:09:50 -05:00
69f2c80308
This commit addresses multiple issues with the Admin Settings page and improves PDF invoice logo embedding for better cross-platform reliability. ## Admin Settings UI - Missing Fields Fixed The Admin → Settings page was incomplete, showing only basic timer and regional settings. Added all missing sections: - User Management: Self-registration toggle with admin username note - Company Branding: Full company info fields (name, email, phone, website, address, tax ID, bank info) plus logo upload with preview - Invoice Defaults: Prefix, start number, payment terms, and notes - Backup Settings: Retention days and backup time configuration - Export Settings: CSV delimiter preference selector - Privacy & Analytics: Telemetry opt-in with detailed privacy information The backend was already handling these fields - this was purely a frontend template issue where form fields were missing. ## Analytics/Telemetry Preference Synchronization Fixed critical bug where analytics checkbox in Admin Settings only updated the database but not the InstallationConfig file that the telemetry system actually reads from. Changes now properly sync both systems: - On page load: Auto-sync database from InstallationConfig (source of truth) - On save: Update both database AND InstallationConfig simultaneously - Added logging for analytics preference changes - Updated UI references: Initial setup and Telemetry dashboard now point to Admin → Settings as the primary location - Added clear privacy information explaining what data is collected ## PDF Logo Embedding Enhancement Improved logo reliability in PDF invoices by switching from file:// URIs to base64 data URIs: - More reliable across platforms (Windows, Linux, macOS) - Works consistently in Docker containers - Self-contained (no filesystem path dependencies) - Automatic MIME type detection for all formats (PNG, JPG, GIF, SVG, WEBP) - Graceful fallback to file:// URI if base64 fails - Added comprehensive debug logging for troubleshooting ## Diagnostic Tools & Documentation - Created test_logo_pdf.py: Diagnostic script to identify logo issues - Created LOGO_PDF_TROUBLESHOOTING.md: Comprehensive troubleshooting guide - Enhanced error messages with debug output throughout logo processing - Added context passing fixes for PDF template rendering ## Files Changed ### Core Fixes - app/templates/admin/settings.html: Complete rewrite with all sections - app/routes/admin.py: InstallationConfig sync for analytics preference - app/static/uploads/logos/.gitkeep: Ensure logos directory tracked by git ### PDF Logo Enhancement - app/utils/pdf_generator.py: Base64 encoding + explicit context passing - app/utils/template_filters.py: get_logo_base64() helper with debug logging - app/templates/invoices/pdf_default.html: Base64 logo embedding ### Analytics Synchronization - app/templates/setup/initial_setup.html: Updated settings reference - app/templates/admin/telemetry.html: Cross-reference to Admin → Settings ### Documentation - docs/GETTING_STARTED.md: Updated to reflect actual UI behavior - test_logo_pdf.py: New diagnostic script - LOGO_PDF_TROUBLESHOOTING.md: New troubleshooting guide ## Testing Run diagnostic script to verify logo configuration:
158 lines
10 KiB
HTML
158 lines
10 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>Welcome - TimeTracker</title>
|
|
<link rel="stylesheet" href="{{ url_for('static', filename='dist/output.css') }}">
|
|
<link rel="stylesheet" href="{{ url_for('static', filename='toast-notifications.css') }}">
|
|
<script>
|
|
// On page load or when changing themes, best to add inline in `head` to avoid FOUC
|
|
if (localStorage.getItem('color-theme') === 'dark' || (!('color-theme' in localStorage) && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
|
|
document.documentElement.classList.add('dark');
|
|
} else {
|
|
document.documentElement.classList.remove('dark')
|
|
}
|
|
</script>
|
|
</head>
|
|
<body class="bg-background-light dark:bg-background-dark text-text-light dark:text-text-dark">
|
|
<div class="min-h-screen flex items-center justify-center px-4 py-8">
|
|
<div class="w-full max-w-5xl grid grid-cols-1 md:grid-cols-2 gap-0 bg-card-light dark:bg-card-dark border border-border-light dark:border-border-dark rounded-xl shadow-lg overflow-hidden">
|
|
<!-- Left side - Branding -->
|
|
<div class="hidden md:flex flex-col items-center justify-center p-10 bg-background-light dark:bg-background-dark border-r border-border-light dark:border-border-dark">
|
|
<div class="text-center">
|
|
<img src="{{ url_for('static', filename='images/drytrix-logo.svg') }}" alt="logo" class="w-24 h-24 mx-auto">
|
|
<h1 class="text-3xl font-bold mt-4 text-primary">TimeTracker</h1>
|
|
<p class="mt-2 text-text-muted-light dark:text-text-muted-dark">Track time. Stay organized.</p>
|
|
|
|
<!-- Privacy Principles -->
|
|
<div class="mt-8 space-y-3 text-left">
|
|
<p class="text-sm font-semibold text-text-light dark:text-text-dark mb-3">🔒 Privacy First</p>
|
|
<div class="flex items-start text-sm text-text-muted-light dark:text-text-muted-dark">
|
|
<svg class="h-5 w-5 text-green-500 mr-2 flex-shrink-0 mt-0.5" fill="currentColor" viewBox="0 0 20 20">
|
|
<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clip-rule="evenodd"/>
|
|
</svg>
|
|
<span>Self-hosted on your server</span>
|
|
</div>
|
|
<div class="flex items-start text-sm text-text-muted-light dark:text-text-muted-dark">
|
|
<svg class="h-5 w-5 text-green-500 mr-2 flex-shrink-0 mt-0.5" fill="currentColor" viewBox="0 0 20 20">
|
|
<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clip-rule="evenodd"/>
|
|
</svg>
|
|
<span>Anonymous telemetry (opt-in)</span>
|
|
</div>
|
|
<div class="flex items-start text-sm text-text-muted-light dark:text-text-muted-dark">
|
|
<svg class="h-5 w-5 text-green-500 mr-2 flex-shrink-0 mt-0.5" fill="currentColor" viewBox="0 0 20 20">
|
|
<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clip-rule="evenodd"/>
|
|
</svg>
|
|
<span>No PII collected ever</span>
|
|
</div>
|
|
<div class="flex items-start text-sm text-text-muted-light dark:text-text-muted-dark">
|
|
<svg class="h-5 w-5 text-green-500 mr-2 flex-shrink-0 mt-0.5" fill="currentColor" viewBox="0 0 20 20">
|
|
<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clip-rule="evenodd"/>
|
|
</svg>
|
|
<span>Open source & transparent</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Right side - Setup Form -->
|
|
<div class="p-8 overflow-y-auto max-h-[90vh]">
|
|
<h2 class="text-2xl font-bold tracking-tight">Welcome to TimeTracker</h2>
|
|
<p class="mt-2 text-sm text-text-muted-light dark:text-text-muted-dark">Let's get you set up in just a moment</p>
|
|
|
|
<form class="mt-6 space-y-6" method="POST" action="{{ url_for('setup.initial_setup') }}">
|
|
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
|
|
|
|
<!-- Welcome Message -->
|
|
<div class="bg-primary/10 border border-primary/20 rounded-lg p-4">
|
|
<h3 class="text-sm font-semibold text-primary mb-2">🎉 Thank you for choosing TimeTracker!</h3>
|
|
<p class="text-sm text-text-muted-light dark:text-text-muted-dark">
|
|
Your data stays on your server, and you have complete control.
|
|
</p>
|
|
</div>
|
|
|
|
<!-- Telemetry Opt-in Section -->
|
|
<div class="bg-background-light dark:bg-gray-700 border border-border-light dark:border-border-dark rounded-lg p-4">
|
|
<h3 class="text-base font-semibold mb-3">📊 Help Us Improve (Optional)</h3>
|
|
|
|
<div class="mb-3">
|
|
<label class="flex items-start cursor-pointer">
|
|
<input type="checkbox" name="telemetry_enabled" class="mt-1 h-4 w-4 text-primary border-border-light dark:border-border-dark rounded focus:ring-primary">
|
|
<span class="ml-3 text-sm">
|
|
<span class="font-medium">Enable anonymous telemetry</span>
|
|
<span class="block text-text-muted-light dark:text-text-muted-dark mt-1">
|
|
Help us understand usage patterns to improve TimeTracker
|
|
</span>
|
|
</span>
|
|
</label>
|
|
</div>
|
|
|
|
<!-- Collapsible details -->
|
|
<details class="text-sm mt-3">
|
|
<summary class="cursor-pointer font-medium text-primary hover:underline">
|
|
What data is collected?
|
|
</summary>
|
|
<div class="mt-3 space-y-3 pl-4 border-l-2 border-primary/30">
|
|
<div>
|
|
<p class="font-semibold text-green-600 dark:text-green-400">✓ What we collect:</p>
|
|
<ul class="list-disc list-inside space-y-1 ml-2 text-text-muted-light dark:text-text-muted-dark">
|
|
<li>Anonymous installation fingerprint (hashed)</li>
|
|
<li>Application version & platform info</li>
|
|
<li>Feature usage statistics</li>
|
|
<li>Internal numeric IDs only</li>
|
|
</ul>
|
|
</div>
|
|
|
|
<div>
|
|
<p class="font-semibold text-red-600 dark:text-red-400">✗ What we DON'T collect:</p>
|
|
<ul class="list-disc list-inside space-y-1 ml-2 text-text-muted-light dark:text-text-muted-dark">
|
|
<li>No usernames or emails</li>
|
|
<li>No project names or descriptions</li>
|
|
<li>No time entry data or notes</li>
|
|
<li>No client or business data</li>
|
|
<li>No IP addresses or PII</li>
|
|
</ul>
|
|
</div>
|
|
|
|
<div class="bg-primary/10 rounded p-3 text-xs">
|
|
<p class="text-text-light dark:text-text-dark">
|
|
<strong>Why?</strong> Anonymous usage data helps us prioritize features and fix issues.
|
|
You can change this anytime in <strong>Admin → Settings</strong> (Privacy & Analytics section).
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</details>
|
|
</div>
|
|
|
|
<!-- Submit Button -->
|
|
<button type="submit" class="btn btn-primary w-full">
|
|
<i class="fa-solid fa-check mr-2"></i>
|
|
Complete Setup & Continue
|
|
</button>
|
|
|
|
<div class="text-xs text-center text-text-muted-light dark:text-text-muted-dark">
|
|
<p>By continuing, you agree to use TimeTracker under the <a href="https://www.gnu.org/licenses/gpl-3.0.html" class="text-primary hover:underline" target="_blank">GPL-3.0 License</a></p>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Flash Messages (hidden; converted to toasts) -->
|
|
<div id="flash-messages-container" class="hidden">
|
|
{% with messages = get_flashed_messages(with_categories=true) %}
|
|
{% if messages %}
|
|
{% for category, message in messages %}
|
|
<div class="alert {% if category == 'success' %}alert-success{% elif category == 'error' %}alert-danger{% elif category == 'warning' %}alert-warning{% else %}alert-info{% endif %}" data-toast-message="{{ message }}" data-toast-type="{{ category }}"></div>
|
|
{% endfor %}
|
|
{% endif %}
|
|
{% endwith %}
|
|
</div>
|
|
|
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.2/js/all.min.js"></script>
|
|
<script src="{{ url_for('static', filename='toast-notifications.js') }}"></script>
|
|
</body>
|
|
</html>
|
|
|