Fixed issue where invoices were always displaying EUR as the currency
regardless of what was configured in Settings. The Invoice model had a
hard-coded default of 'EUR' and the invoice creation route wasn't
explicitly setting the currency from Settings.
Changes:
- Updated invoice creation route to fetch and use currency from Settings
- Updated invoice duplication to preserve original invoice's currency
- Added currency code display to all monetary values in invoice templates
- Added currency code display to invoice list totals
- Created migration script to update existing invoices
- Added comprehensive unit tests and smoke tests
- Added detailed documentation for the fix
Backend changes:
- app/routes/invoices.py: Retrieve currency from Settings when creating
invoices, pass currency_code explicitly to Invoice constructor
- app/routes/invoices.py: Preserve currency_code when duplicating invoices
Frontend changes:
- app/templates/invoices/view.html: Display currency code next to all
monetary values (items, extra goods, subtotals, tax, totals)
- app/templates/invoices/list.html: Display currency code next to
invoice totals in list view
Testing:
- tests/test_invoice_currency_fix.py: 10 unit tests covering various
currency scenarios and edge cases
- tests/test_invoice_currency_smoke.py: 2 end-to-end smoke tests
Migration:
- migrations/fix_invoice_currency.py: Script to update existing invoices
to use the currency from Settings
This fix is fully backward compatible. Existing invoices will continue
to work with their current currency values. Run the migration script to
update existing invoices to match the Settings currency.
Resolves: #153 (invoices-display-currency-as-eur-and-not-usd)
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:
The Time Entry Templates page (/templates) was throwing a 500 error
when displaying templates with usage data. The templates referenced
a 'timeago' Jinja2 filter that was never registered.
Changes:
- Added timeago filter to app/utils/template_filters.py
- Converts datetime to human-readable relative time (e.g., "2 hours ago")
- Handles None, naive/aware datetimes, and future dates gracefully
- Provides appropriate granularity from seconds to years
- Uses proper singular/plural forms
- Added 11 comprehensive unit tests in tests/test_utils.py
- Tests for None values, all time ranges, edge cases
- Tests for naive datetimes and future dates
- Tests for singular/plural formatting
- Added smoke test in tests/test_time_entry_templates.py
- Specifically tests templates with usage_count and last_used_at
- Ensures the filter renders correctly in the template
The filter is used in:
- app/templates/time_entry_templates/list.html (line 96)
- app/templates/time_entry_templates/edit.html (line 140)
Fixes#151
Implement comprehensive support for exporting extra goods (products,
services, materials, licenses) in invoice PDF documents. Extra goods
now appear in the invoice items table alongside time-based billing
entries with rich formatting including name, description, SKU codes,
and category labels.
Changes:
- Enhanced InvoicePDFGenerator._generate_items_rows() to include extra
goods with detailed formatting (name, description, SKU, category)
- Updated pdf_default.html template to render extra goods loop in the
invoice items table with conditional display of optional fields
- Enhanced InvoicePDFGeneratorFallback._build_items_table() for
ReportLab compatibility with multi-line descriptions
- Added 6 comprehensive tests covering both WeasyPrint and ReportLab
generators (unit tests and smoke tests)
- Created complete feature documentation in
docs/INVOICE_EXTRA_GOODS_PDF_EXPORT.md
Technical Details:
- Extra goods display quantity, unit price, and total amount
- Automatic inclusion in invoice totals via existing calculate_totals()
- No database migrations required (extra_goods table already exists)
- Backward compatible - invoices without goods unchanged
- Supports both primary (WeasyPrint) and fallback (ReportLab) generators
Testing:
- 6 new tests added to tests/test_invoices.py
- 3 tests pass on Windows (ReportLab fallback)
- 3 tests require WeasyPrint system dependencies (Linux/Docker)
- All code changes validated with no linter errors
Files Modified:
- app/utils/pdf_generator.py
- app/templates/invoices/pdf_default.html
- app/utils/pdf_generator_fallback.py
- tests/test_invoices.py
Files Created:
- docs/INVOICE_EXTRA_GOODS_PDF_EXPORT.md
- INVOICE_GOODS_EXPORT_IMPLEMENTATION_SUMMARY.md
BREAKING CHANGE: Permission system now actively enforced across all routes
## Summary
Complete implementation of advanced role-based access control (RBAC) system
with full route protection, UI conditionals, and enhanced management interface.
## Route Protection
- Updated all admin routes to use @admin_or_permission_required decorator
- Replaced inline admin checks with granular permission checks in:
* Admin routes: user management, settings, backups, telemetry, OIDC
* Project routes: create, edit, delete, archive, bulk operations
* Client routes: create, edit, delete, archive, bulk operations
- Maintained backward compatibility with existing @admin_required decorator
## UI Permission Integration
- Added template helpers (has_permission, has_any_permission) to all templates
- Navigation conditionally shows admin/OIDC links based on permissions
- Action buttons (Edit, Delete, Archive) conditional on user permissions
- Project and client pages respect permission requirements
- Create buttons visible only with appropriate permissions
## Enhanced Roles & Permissions UI
- Added statistics dashboard showing:
* Total roles, system roles, custom roles, assigned users
- Implemented expandable permission details in roles list
* Click to view all permissions grouped by category
* Visual checkmarks for assigned permissions
- Enhanced user list with role visibility:
* Shows all assigned roles as color-coded badges
* Blue badges for system roles, gray for custom roles
* Yellow badges for legacy roles with migration prompt
* Merged legacy role column into unified "Roles & Permissions"
- User count per role now clickable and accurate
## Security Improvements
- Added CSRF tokens to all new permission system forms:
* Role creation/edit form
* Role deletion form
* User role assignment form
- All POST requests now protected against CSRF attacks
## Technical Details
- Fixed SQLAlchemy relationship query issues (AppenderQuery)
- Proper use of .count() for relationship aggregation
- Jinja2 namespace for accumulating counts in templates
- Responsive grid layouts for statistics and permission cards
## Documentation
- Created comprehensive implementation guides
- Added permission enforcement documentation
- Documented UI enhancements and features
- Included CSRF protection review
## Impact
- Permissions are now actively enforced, not just defined
- Admins can easily see who has what access
- Clear visual indicators of permission assignments
- Secure forms with CSRF protection
- Production-ready permission system
Implement a complete expense tracking feature that allows users to record,
manage, approve, and track business expenses with full integration into
existing project management and invoicing systems.
Features:
- Create and manage expenses with detailed information (amount, category,
vendor, receipts, tax tracking)
- Multi-currency support (EUR, USD, GBP, CHF)
- Approval workflow with admin oversight (pending → approved → rejected)
- Reimbursement tracking and status management
- Billable expense flagging for client invoicing
- Receipt file upload and attachment
- Project and client association with auto-client selection
- Tag-based organization and advanced filtering
- CSV export functionality
- Analytics dashboard with category breakdowns
- API endpoints for programmatic access
Database Changes:
- Add expenses table with comprehensive schema
- Create Alembic migration (029_add_expenses_table.py)
- Add composite indexes for query performance
- Implement proper foreign key constraints and cascading
Routes & Templates:
- Add expenses blueprint with 14 endpoints (CRUD, approval, export, API)
- Create 4 responsive templates (list, form, view, dashboard)
- Implement advanced filtering (status, category, project, client, date range)
- Add permission-based access control (user vs admin)
- Integrate receipt file upload handling
User Experience:
- Add "Expenses" to Insights navigation menu
- Auto-populate client when project is selected
- Provide visual feedback for auto-selections
- Display summary statistics and analytics
- Implement pagination and search functionality
Testing & Documentation:
- Add 40+ comprehensive tests covering models, methods, and workflows
- Create complete user documentation (docs/EXPENSE_TRACKING.md)
- Add API documentation and examples
- Include troubleshooting guide and best practices
Integration:
- Link expenses to projects for cost tracking
- Associate with clients for billing purposes
- Connect billable expenses to invoicing system
- Add PostHog event tracking for analytics
- Implement structured logging for audit trail
Security:
- Role-based access control (users see only their expenses)
- Admin-only approval and reimbursement actions
- CSRF protection and file upload validation
- Proper permission checks on all operations
This implementation follows existing codebase patterns and includes full
test coverage, documentation, and database migrations per project standards.
Implemented a comprehensive Weekly Time Goals system that allows users to set
and track weekly hour targets with real-time progress monitoring.
Features:
- WeeklyTimeGoal model with status tracking (active, completed, failed, cancelled)
- Full CRUD interface for managing weekly goals
- Real-time progress calculation based on logged time entries
- Dashboard widget showing current week's goal progress
- Daily breakdown view with detailed statistics
- Automatic status updates based on goal completion and week end
- API endpoints for goal data and progress tracking
Technical changes:
- Added app/models/weekly_time_goal.py with local timezone support
- Created migration 027_add_weekly_time_goals.py for database schema
- Added app/routes/weekly_goals.py blueprint with all CRUD routes
- Created templates: index.html, create.html, edit.html, view.html
- Integrated weekly goal widget into main dashboard
- Added "Weekly Goals" navigation item to sidebar
- Implemented comprehensive test suite in tests/test_weekly_goals.py
- Added feature documentation in docs/WEEKLY_TIME_GOALS.md
Bug fixes:
- Fixed timezone handling to use TZ environment variable instead of Config.TIMEZONE
- Corrected log_event() calls to use proper signature (event name as first positional argument)
- Manually created database table via SQL when Alembic migration didn't execute
Database schema:
- weekly_time_goals table with user_id, target_hours, week_start_date, week_end_date, status, notes
- Indexes on user_id, week_start_date, status, and composite (user_id, week_start_date)
- Foreign key constraint to users table with CASCADE delete
The feature supports flexible week start days per user, calculates remaining hours,
provides daily average targets, and automatically updates goal status based on progress.
Implement comprehensive time rounding preferences that allow each user to
configure how their time entries are rounded when stopping timers.
Features:
- Per-user rounding settings (independent from global config)
- Multiple rounding intervals: 1, 5, 10, 15, 30, 60 minutes
- Three rounding methods: nearest, up (ceiling), down (floor)
- Enable/disable toggle for flexible time tracking
- Real-time preview showing rounding examples
- Backward compatible with existing global rounding settings
Database Changes:
- Add migration 027 with three new user columns:
* time_rounding_enabled (Boolean, default: true)
* time_rounding_minutes (Integer, default: 1)
* time_rounding_method (String, default: 'nearest')
Implementation:
- Update User model with rounding preference fields
- Modify TimeEntry.calculate_duration() to use per-user rounding
- Create app/utils/time_rounding.py with core rounding logic
- Update user settings route and template with rounding UI
- Add comprehensive unit, model, and smoke tests (50+ test cases)
UI/UX:
- Add "Time Rounding Preferences" section to user settings page
- Interactive controls with live example visualization
- Descriptive help text and method explanations
- Fix navigation: Settings link now correctly points to user.settings
- Fix CSRF token in settings form
Documentation:
- Add comprehensive user guide (docs/TIME_ROUNDING_PREFERENCES.md)
- Include API documentation and usage examples
- Provide troubleshooting guide and best practices
- Add deployment instructions for migration
Testing:
- Unit tests for rounding logic (tests/test_time_rounding.py)
- Model integration tests (tests/test_time_rounding_models.py)
- End-to-end smoke tests (tests/test_time_rounding_smoke.py)
Fixes:
- Correct settings navigation link in user dropdown menu
- Fix CSRF token format in user settings template
This feature enables flexible billing practices, supports different client
requirements, and maintains exact time tracking when needed.
Add enhanced project archiving functionality for better organization of
completed projects with metadata tracking and validation.
Key Features:
- Archive metadata tracking (timestamp, user, reason)
- Archive form with quick-select reason templates
- Bulk archiving with optional shared reason
- Archive information display on project details
- Prevent time tracking on archived projects
- Activity logging for archive/unarchive actions
Database Changes:
- Add migration 026_add_project_archiving_metadata.py
- New fields: archived_at, archived_by (FK), archived_reason
- Index on archived_at for faster filtering
- Cascade on user deletion (SET NULL)
Model Enhancements (app/models/project.py):
- Enhanced archive() method with user_id and reason parameters
- Enhanced unarchive() method to clear all metadata
- New properties: is_archived, archived_by_user
- Updated to_dict() to include archive metadata
Route Updates (app/routes/projects.py):
- Convert archive route to GET/POST (form-based)
- Add archive reason handling
- Enhanced bulk operations with reason support
- Activity logging for all archive operations
UI Improvements:
- New archive form template (app/templates/projects/archive.html)
- Quick-select buttons for common archive reasons
- Archive metadata display on project view page
- Bulk archive modal with reason input
- Updated project list filtering
Validation (app/routes/timer.py):
- Prevent timer start on archived projects
- Block manual entry creation on archived projects
- Block bulk entry creation on archived projects
- Clear error messages for users
Testing:
- 90+ comprehensive test cases
- Unit tests (tests/test_project_archiving.py)
- Model tests (tests/test_project_archiving_models.py)
- Smoke tests for complete workflows
- Edge case coverage
Documentation:
- User guide (docs/PROJECT_ARCHIVING_GUIDE.md)
- Implementation summary (PROJECT_ARCHIVING_IMPLEMENTATION_SUMMARY.md)
- API reference and examples
- Best practices and troubleshooting
Migration Notes:
- Backward compatible with existing archived projects
- Existing archives will have NULL metadata (can be added later)
- No data migration required
- Run: migrations/manage_migrations.py upgrade head
Breaking Changes: None
- All changes are additive and backward compatible
Related: Feat-Project-Archiving branch
Implement comprehensive client notes system allowing users to add
internal notes about clients that are never visible to clients
themselves. Notes support importance flagging, full CRUD operations,
and proper access controls.
Key Changes:
- Add ClientNote model with user/client relationships
- Create Alembic migration (025) for client_notes table
- Implement full REST API with 9 endpoints
- Add client_notes blueprint with CRUD routes
- Create UI templates (edit page + notes section on client view)
- Add importance toggle with AJAX functionality
- Implement permission system (users edit own, admins edit all)
Features:
- Internal-only notes with rich text support
- Mark notes as important for quick identification
- Author tracking with timestamps
- Cascade delete when client is removed
- Mobile-responsive design
- i18n support for all user-facing text
Testing:
- 24 comprehensive model tests
- 23 route/integration tests
- Full coverage of CRUD operations and permissions
Documentation:
- Complete feature guide in docs/CLIENT_NOTES_FEATURE.md
- API documentation with examples
- Troubleshooting section
- Updated main docs index
Database:
- Migration revision 025 (depends on 024)
- Fixed PostgreSQL boolean default value issue
- 4 indexes for query performance
- CASCADE delete constraint on client_id
This feature addresses the need for teams to track important
information about clients internally without exposing sensitive
notes to client-facing interfaces or documents.
Features:
Add favorite projects feature allowing users to star/bookmark frequently used projects
New UserFavoriteProject association model with user-project relationships
Star icons in project list for one-click favorite toggling via AJAX
Filter to display only favorite projects
Per-user favorites with proper isolation and cascade delete behavior
Activity logging for favorite/unfavorite actions
Database:
Add user_favorite_projects table with migration (023_add_user_favorite_projects.py)
Foreign keys to users and projects with CASCADE delete
Unique constraint preventing duplicate favorites
Indexes on user_id and project_id for query optimization
Models:
User model: Add favorite_projects relationship with helper methods
add_favorite_project() - add project to favorites
remove_favorite_project() - remove from favorites
is_project_favorite() - check favorite status
get_favorite_projects() - retrieve favorites with status filter
Project model: Add is_favorited_by() method and include favorite status in to_dict()
Export UserFavoriteProject model in app/models/__init__.py
Routes:
Add /projects/<id>/favorite POST endpoint to favorite a project
Add /projects/<id>/unfavorite POST endpoint to unfavorite a project
Update /projects GET route to support favorites=true query parameter
Fix status filtering to work correctly with favorites JOIN query
Add /reports/export/form GET endpoint for enhanced CSV export form
Templates:
Update projects/list.html:
Add favorites filter dropdown to filter form (5-column grid)
Add star icon column with Font Awesome icons (filled/unfilled)
Add JavaScript toggleFavorite() function for AJAX favorite toggling
Improve hover states and transitions for better UX
Pass favorite_project_ids and favorites_only to template
Update reports/index.html:
Update CSV export link to point to new export form
Add icon and improve hover styling
Reports:
Enhance CSV export functionality with dedicated form page
Add filter options for users, projects, clients, and date ranges
Set default date range to last 30 days
Import Client model and or_ operator for advanced filtering
Testing:
Comprehensive test suite in tests/test_favorite_projects.py (550+ lines)
Model tests for UserFavoriteProject creation and validation
User/Project method tests for favorite operations
Route tests for favorite/unfavorite endpoints
Filtering tests for favorites-only view
Relationship tests for cascade delete behavior
Smoke tests for complete workflows
Coverage for edge cases and error handling
Documentation:
Add comprehensive feature documentation in docs/FAVORITE_PROJECTS_FEATURE.md
User guide with step-by-step instructions
Technical implementation details
API documentation for new endpoints
Migration guide and troubleshooting
Performance and security considerations
Template Cleanup:
Remove duplicate templates from root templates/ directory
Admin templates (dashboard, users, settings, OIDC debug, etc.)
Client CRUD templates
Error page templates
Invoice templates
Project templates
Report templates
Timer templates
All templates now properly located in app/templates/
Breaking Changes:
None - fully backward compatible
Migration Required:
Run alembic upgrade head to create user_favorite_projects table
Implement comprehensive time entry duplication feature that allows users
to quickly copy previous entries with pre-filled data, improving
productivity for repetitive time tracking tasks.
Features:
- Add duplicate route endpoint (/timer/duplicate/<id>)
- Add duplicate buttons to dashboard and edit entry pages
- Pre-fill project, task, notes, tags, and billable status
- Show information banner with original entry details
- Implement permission checks (users can duplicate own entries, admins can duplicate any)
- Track analytics events for duplication actions
Backend Changes:
- app/routes/timer.py: Add duplicate_timer() route with security checks
- Route handles pre-filling manual entry form with original entry data
- Analytics tracking for 'timer.duplicated' events
Frontend Changes:
- app/templates/main/dashboard.html: Add duplicate icon button to Recent Entries table
- templates/timer/edit_timer.html: Add duplicate button next to Back button
- app/templates/timer/manual_entry.html: Support pre-filled data and duplication context
- Add blue information banner showing original entry details when duplicating
Testing:
- Add comprehensive test suite with 21 tests (all passing)
- tests/test_time_entry_duplication.py: Unit, integration, security, smoke, and edge case tests
- Test coverage includes: route access, authentication, pre-fill functionality, permissions, UI visibility
Documentation:
- docs/features/TIME_ENTRY_DUPLICATION.md: Technical documentation
- docs/user-guides/DUPLICATING_TIME_ENTRIES.md: User guide with examples
- TIME_ENTRY_DUPLICATION_IMPLEMENTATION.md: Implementation details
- TIME_ENTRY_DUPLICATION_FEATURE_SUMMARY.md: Complete feature overview
Benefits:
- Saves ~60% time when logging similar work
- Reduces manual data entry for recurring tasks
- Maintains data consistency through field copying
- Intuitive workflow with clear visual feedback
Security:
- Users can only duplicate their own entries
- Admin users can duplicate any entry
- Proper authentication and permission checks
Breaking Changes: None
Replace the external placeholder avatar service (pravatar.cc) with real user
avatars in the kanban board cards. This ensures consistency with the rest of
the application and displays actual user profile pictures.
Changes:
- Use task.assigned_user.get_avatar_url() to fetch real user avatars
- Add graceful fallback to user initials when avatar is missing or fails to load
- Include error handling with onerror event for broken image links
- Apply consistent styling (rounded, bordered, object-cover) matching the
navigation bar and profile pages
- Maintain tooltip with user display name for accessibility
This aligns the kanban board with the avatar display pattern used throughout
the application and improves the user experience by showing real profile
pictures instead of generic placeholder images.
Improved the Release Build workflow to clearly show that PostHog and Sentry
credentials are being injected from the GitHub Secret Store, providing better
transparency and auditability.
Changes:
- Enhanced workflow step name to explicitly mention "GitHub Secrets"
- Added comprehensive logging with visual separators and clear sections
- Added before/after file content display showing placeholder replacement
- Added secret availability verification with format validation
- Added detailed error messages with step-by-step fix instructions
- Enhanced release summary to highlight successful credential injection
- Updated build configuration documentation with cross-references
Benefits:
- Developers can immediately see credentials come from GitHub Secret Store
- Security teams have clear audit trail of credential injection process
- Better troubleshooting with detailed error messages
- Secrets remain protected with proper redaction (first 8 + last 4 chars)
- Multiple validation steps ensure correct injection
The workflow now outputs 50+ lines of structured logging showing:
- Secret store location (Settings → Secrets and variables → Actions)
- Target file being modified (app/config/analytics_defaults.py)
- Verification that secrets are available
- Format validation (phc_* pattern for PostHog)
- Confirmation of successful placeholder replacement
- Summary with redacted credential previews
Workflow: .github/workflows/cd-release.yml
Documentation: docs/cicd/README_BUILD_CONFIGURATION.md
Fully backward compatible - no breaking changes.
- Changed tasks/view.html grid from 2 to 3 columns to position Details
section at top right instead of bottom
- Changed tasks/edit.html grid from 2 to 3 columns with form spanning
2 columns for better proportions
- Task form now takes 2/3 width and info sidebar takes 1/3 width
- Improves UX by making the Start Timer button and info blocks more
appropriately sized
- Restores the original Tailwind UI layout with better visual balance
Fixes layout regression introduced in v3.2.3 that made the edit page
Start Timer button uncomfortably wide and pushed task details to the
bottom on the view page.
Major improvements:
- Add bulk operations functionality across clients, projects, and tasks
- Implement deletion and status management enhancements
- Add project code field with database migration (022)
- Improve inactive status handling for projects
Backend changes:
- Update project model with new code field and status logic
- Enhance routes for clients, projects, and tasks with bulk actions
- Add migration for project_code field (022_add_project_code_field.py)
Frontend updates:
- Refactor bulk actions widget component
- Update clients list and detail views with bulk operations
- Enhance project list, view, and kanban templates
- Improve task list, edit, view, and kanban displays
- Update base template with UI improvements
- Refine saved filters and time entry templates lists
Testing:
- Add test_project_inactive_status.py for status handling
- Update test_tasks_templates.py with new functionality
Documentation:
- Add BULK_OPERATIONS_IMPROVEMENTS.md
- Add DELETION_AND_STATUS_IMPROVEMENTS.md
- Add docs/QUICK_WINS_IMPLEMENTATION.md
- Update ALL_BUGFIXES_SUMMARY.md and IMPLEMENTATION_COMPLETE.md
Implements persistent flag tracking to ensure default client and project
are only created on fresh installations and never recreated after user
deletion during updates or restarts.
- Added initial_data_seeded flag to InstallationConfig
- Updated all 3 database initialization scripts to check flag
- Added 3 unit tests (all passing)
- Created comprehensive documentation
Fixes issue where defaults were recreated after deletion during updates.
This commit introduces several high-impact features to improve user experience
and productivity:
New Features:
- Activity Logging: Comprehensive audit trail tracking user actions across the
system with Activity model, including IP address and user agent tracking
- Time Entry Templates: Reusable templates for frequently logged activities with
usage tracking and quick-start functionality
- Saved Filters: Save and reuse common search/filter combinations across
different views (projects, tasks, reports)
- User Preferences: Enhanced user settings including email notifications,
timezone, date/time formats, week start day, and theme preferences
- Excel Export: Generate formatted Excel exports for time entries and reports
with styling and proper formatting
- Email Notifications: Complete email system for task assignments, overdue
invoices, comments, and weekly summaries with HTML templates
- Scheduled Tasks: Background task scheduler for periodic operations
Models Added:
- Activity: Tracks all user actions with detailed context and metadata
- TimeEntryTemplate: Stores reusable time entry configurations
- SavedFilter: Manages user-saved filter configurations
Routes Added:
- user.py: User profile and settings management
- saved_filters.py: CRUD operations for saved filters
- time_entry_templates.py: Template management endpoints
UI Enhancements:
- Bulk actions widget component
- Keyboard shortcuts help modal with advanced shortcuts
- Save filter widget component
- Email notification templates
- User profile and settings pages
- Saved filters management interface
- Time entry templates interface
Database Changes:
- Migration 022: Creates activities and time_entry_templates tables
- Adds user preference columns (notifications, timezone, date/time formats)
- Proper indexes for query optimization
Backend Updates:
- Enhanced keyboard shortcuts system (commands.js, keyboard-shortcuts-advanced.js)
- Updated projects, reports, and tasks routes with activity logging
- Safe database commit utilities integration
- Event tracking for analytics
Dependencies:
- Added openpyxl for Excel generation
- Added Flask-Mail dependencies
- Updated requirements.txt
All new features include proper error handling, activity logging integration,
and maintain existing functionality while adding new capabilities.
Store user avatars in persistent /data volume instead of application
directory to ensure profile pictures survive container rebuilds and
version updates.
Changes:
- Update avatar upload folder from app/static/uploads/avatars to
/data/uploads/avatars using existing app_data volume mount
- Modify get_avatar_upload_folder() in auth routes to use persistent
location with UPLOAD_FOLDER config
- Update User.get_avatar_path() to reference new storage location
- Add migration script to safely move existing avatars to new location
- Preserve backward compatibility - no database changes required
Benefits:
- Profile pictures now persist between Docker image updates
- Consistent with company logo storage pattern (/data/uploads)
- Better user experience - avatars not lost during upgrades
- Production-ready data/code separation
- All persistent uploads consolidated in app_data volume
Migration:
For existing installations with user avatars, run:
docker-compose run --rm app python /app/docker/migrate-avatar-storage.py
New installations work automatically with no action required.
Documentation:
- docs/AVATAR_STORAGE_MIGRATION.md - Full migration guide
- docs/AVATAR_PERSISTENCE_SUMMARY.md - Quick reference
- docs/TEST_AVATAR_PERSISTENCE.md - Testing guide
- AVATAR_PERSISTENCE_CHANGELOG.md - Detailed changelog
Files modified:
- app/routes/auth.py
- app/models/user.py
Files added:
- docker/migrate-avatar-storage.py
- docs/AVATAR_STORAGE_MIGRATION.md
- docs/AVATAR_PERSISTENCE_SUMMARY.md
- docs/TEST_AVATAR_PERSISTENCE.md
- AVATAR_PERSISTENCE_CHANGELOG.md
Tested: ✓ No linter errors, backward compatible, volume mount verified
- Add client_max_body_size 10M to nginx config to fix 413 error
- Add JavaScript preview for profile picture selection
- Include client-side validation for file size and type
Major Changes:
- Implement bulk delete functionality for tasks with custom confirmation dialog
* Add /tasks/bulk-delete POST route with permission checks
* Add checkboxes and "Delete Selected" button to task list
* Skip tasks with time entries, provide detailed feedback
* Log all deletions for audit trail
Improve task workflows and overall UX, and align backend routes with the
new UI flows. Update docs and development setup accordingly.
- UI: refine task list/view/edit templates, project views, and Kanban
partial (`_kanban_tailwind.html`)
- CSS: polish `app/static/enhanced-ui.css` for spacing, layout, and
responsiveness
- Routes: update `app/routes/tasks.py` and `app/routes/clients.py` to
support new edit/delete/filter behaviors and validations
- Templates: align clients/projects pages for consistency and navigation
- Docs: refresh `docs/GETTING_STARTED.md` and
`docs/TASK_MANAGEMENT_README.md`
- Dev: adjust `docker-compose.yml` and `setup.py` to match the latest
runtime/build expectations
- Tests: add coverage for delete actions, task project editing, and task
filters UI (`tests/test_delete_actions.py`,
`tests/test_task_edit_project.py`,
`tests/test_tasks_filters_ui.py`); update existing tests
Why:
- Streamlines common task operations and improves discoverability
- Ensures backend and UI are consistent and well-tested
- Enhanced invoice creation form with auto-fill client data from project selection
- Redesigned invoice edit page with improved layout and quick actions sidebar
- Added new generate-from-time template for adding unbilled time entries and costs
- Improved form styling and added responsive design enhancements
- Added internationalization (i18n) support throughout invoice templates
- Added notes and terms fields to invoice forms
- Implemented item removal functionality in invoice editor
- Added comprehensive tests for new invoice features
- Updated .gitignore to exclude logs directory
- Bumped version from 3.0.0 to 3.2.0
The invoice UI now provides:
- Quick actions panel with export, duplicate, and payment recording links
- Invoice summary sidebar showing totals and status
- Tips and guidance sidebars for better UX
- Client data auto-population when selecting projects
- Improved visual hierarchy and mobile responsiveness
- Simplify docker-compose setup and align environment defaults
- Update README and Quick Start to reflect the new compose flow
- Refine app initialization and configuration for clearer env handling
- Minor consistency and cleanup in config modules
No breaking changes expected.
Implement comprehensive analytics and monitoring system with PostHog integration,
complete observability stack (Prometheus, Grafana, Loki, Promtail), and CI/CD
workflows for automated builds.
Features:
- Add PostHog telemetry integration with privacy-focused event tracking
- Implement installation flow for opt-in telemetry configuration
- Add telemetry management UI in admin panel with detailed transparency
- Track key user events across all major features (projects, tasks, timer, etc.)
Infrastructure:
- Set up Prometheus for metrics collection
- Configure Grafana for visualization dashboards
- Integrate Loki and Promtail for log aggregation
- Add separate analytics docker-compose configuration
CI/CD:
- Add GitHub Actions workflows for building and publishing Docker images
- Implement separate dev and production build pipelines
- Configure automated image publishing to registry
Documentation:
- Restructure documentation into organized docs/ directory
- Add comprehensive guides for telemetry, analytics, and local development
- Create transparency documentation for tracked events
- Add CI/CD and build configuration guides
Code improvements:
- Integrate telemetry hooks across all route handlers
- Add feature flags and configuration management
- Refactor test suite for analytics functionality
- Clean up root directory by moving docs and removing test artifacts
Breaking changes:
- Requires new environment variables for PostHog configuration
- Docker compose setup now supports analytics stack
Changes: 73 files changed, 955 insertions(+), 14126 deletions(-)
Fixed multiple issues with keyboard shortcuts and browser notifications:
Keyboard Shortcuts:
- Fixed Ctrl+/ not working to focus search input
- Resolved conflict between three event handlers (base.html, commands.js, keyboard-shortcuts-advanced.js)
- Changed inline handler from Ctrl+K to Ctrl+/ to avoid command palette conflict
- Updated search bar UI badge to display Ctrl+/ instead of Ctrl+K
- Removed conflicting ? key handler from commands.js (now uses Shift+? for shortcuts panel)
- Improved key detection to properly handle special characters like / and ?
- Added debug logging for troubleshooting keyboard events
Final keyboard mapping:
- Ctrl+K: Open Command Palette
- Ctrl+/: Focus Search Input
- Shift+?: Show All Keyboard Shortcuts
- Esc: Close Modals/Panels
Notification System:
- Fixed "right-hand side of 'in' should be an object" error in smart-notifications.js
- Changed notification permission request to follow browser security policies
- Permission now checked silently on load, only requested on user interaction
- Added "Enable Notifications" banner in notification center panel
- Fixed service worker sync check to properly verify registration object
Browser Compatibility:
- All fixes respect browser security policies for notification permissions
- Graceful degradation when service worker features unavailable
- Works correctly on Chrome, Firefox, Safari, and Edge
Files modified:
- app/static/enhanced-search.js
- app/static/keyboard-shortcuts-advanced.js
- app/static/smart-notifications.js
- app/templates/base.html
- app/static/commands.js
Closes issues with keyboard shortcuts not responding and browser console errors.
ixes #88
When OIDC_POST_LOGOUT_REDIRECT_URI was unset, the application was still
attempting RP-Initiated Logout by falling back to a generated redirect URL.
This caused issues with OIDC providers like Authelia that don't support
RP-Initiated Logout, resulting in failed redirects to unsupported endpoints.
Changes:
- Modified logout logic in app/routes/auth.py to only attempt provider
logout when OIDC_POST_LOGOUT_REDIRECT_URI is explicitly configured
- If unset, users are now logged out locally and redirected to the
TimeTracker login page (expected behavior)
- If set, RP-Initiated Logout proceeds as before (backward compatible)
Documentation:
- Updated docs/OIDC_SETUP.md with guidance on when to set the config
- Added clear comments in env.example explaining optional behavior
- Documented troubleshooting steps for providers without RP-Initiated
Logout support (e.g., Authelia)
Tests:
- Added comprehensive test suite (tests/test_oidc_logout.py) with 9 tests
covering different logout scenarios and edge cases
- All existing tests continue to pass (no regressions)
This change is fully backward compatible. Users with providers supporting
RP-Initiated Logout can continue using OIDC_POST_LOGOUT_REDIRECT_URI as
before. Users with providers like Authelia should leave it unset for
local-only logout.
Add WTF_CSRF_TRUSTED_ORIGINS to app/config.py (env-driven, comma-separated; default https://track.example.com) to allow CSRF validation when referrer/origin host matches a trusted origin behind a proxy.
Keep existing ProxyFix(x_proto=1, x_host=1, x_for=1, x_port=1) so Flask honors X-Forwarded-* headers.
Ensure forms/AJAX post to the same origin you’ve configured via WTF_CSRF_TRUSTED_ORIGINS.
The OIDC callback was failing because parse_id_token() was called without
the required 'nonce' parameter, causing authentication to fail with a
TypeError. This prevented the issuer (iss) claim from being extracted,
which is required for successful OIDC login.
Changes:
- Check if ID token claims are already available in the token response
under 'userinfo' key (parsed by Authlib during authorize_access_token)
- If not available, retrieve nonce from session and pass it to
parse_id_token() method
- This ensures the issuer and subject claims are properly extracted from
the ID token instead of only relying on the userinfo endpoint
The issuer claim is only present in the ID token, not the userinfo
endpoint, so proper ID token parsing is essential for authentication.
Fixes #<issue_number>
Add comprehensive HTTPS support with two deployment options:
- mkcert for local development with trusted certificates
- Automatic SSL with Let's Encrypt for production
HTTPS Implementation:
- Add docker-compose.https-mkcert.yml for local HTTPS development
- Add docker-compose.https-auto.yml for automatic SSL certificates
- Create Dockerfile.mkcert for certificate generation
- Add setup scripts (setup-https-mkcert.sh/bat)
- Add startup scripts (start-https.sh/bat)
- Add certificate generation script (generate-mkcert-certs.sh)
CSRF and IP Access Fixes:
- Fix CSRF token validation for IP-based access
- Add CSRF troubleshooting documentation
- Update configuration to handle various access patterns
Documentation:
- Add HTTPS_MKCERT_GUIDE.md with setup instructions
- Add README_HTTPS.md with general HTTPS documentation
- Add README_HTTPS_AUTO.md for automatic SSL setup
- Add AUTOMATIC_HTTPS_SUMMARY.md
- Add CSRF_IP_ACCESS_FIX.md and CSRF_IP_FIX_SUMMARY.md
- Add docs/CSRF_IP_ACCESS_GUIDE.md
- Update main README.md with HTTPS information
Configuration:
- Update .gitignore for SSL certificates and nginx configs
- Update env.example with new HTTPS-related variables
- Update docker-compose.yml with SSL configuration options
This enables secure HTTPS access in both development and production
environments while maintaining compatibility with existing deployments.
Implement comprehensive CSRF token management with cookie-based
double-submit pattern to improve security and SPA compatibility.
Changes:
- Add CSRF cookie configuration in app/config.py
* WTF_CSRF_SSL_STRICT for strict SSL validation in production
* CSRF_COOKIE_NAME (default: XSRF-TOKEN) for framework compatibility
* CSRF_COOKIE_SECURE inherits from SESSION_COOKIE_SECURE by default
* CSRF_COOKIE_HTTPONLY, CSRF_COOKIE_SAMESITE, and CSRF_COOKIE_DOMAIN settings
- Implement CSRF cookie handler in app/__init__.py
* Set CSRF token in cookie after each request
* Configure cookie with secure flags based on environment settings
* Support for double-submit pattern and SPA frameworks
- Add client-side CSRF token management in base.html
* JavaScript utilities for token retrieval and validation
* Cookie synchronization for frameworks that read XSRF-TOKEN
* Auto-refresh mechanism for stale tokens (>15 minutes)
* Pre-submit token validation and refresh
* User notification for missing cookies/tokens
- Clean up docker-compose.yml environment variables
* Remove redundant SECRET_KEY, WTF_CSRF_*, and cookie security settings
* These are now managed through .env files and config.py
This enhancement provides better CSRF protection while maintaining
compatibility with modern JavaScript frameworks and SPA architectures.
- Fix infinite recursion error in showToast function by removing duplicate local definition
- Implement dynamic calendar legend that updates with actual project names and colors
- Add comprehensive button state management to prevent stuck "Processing..." states
- Implement immediate loading state clearing for all calendar actions (create, update, delete, duplicate)
- Add resetAllButtonStates() function to handle button state cleanup
- Remove delays in loading state transitions for better responsiveness
- Add error handling and logging for calendar events loading
- Ensure loading states are cleared on both success and error scenarios
- Add global reset function for manual button state recovery
- Improve loadTasksForProject error handling and null checks
Fixes:
- Calendar legend showing static placeholders instead of dynamic project data
- Buttons stuck in "Processing..." state after successful actions
- Loading states persisting for 2-3 seconds after completion
- Recursion errors in toast notification system
- Inconsistent button state management across calendar operations