- Fix fatal PHP error in UserModel::getAllGroups() - typo 'setCache'
should be 'setCached', was causing ticket page to fail to render
- Fix settings.js null reference errors when timezone element missing
on ticket page (only exists on dashboard)
- Fix ESC key detection for settings modal (checked 'block' but modal
uses 'flex' display)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Consolidate StatsModel queries from 12 to 3 using conditional aggregation
- Add input validation to DashboardController (sort columns, dates, priorities)
- Combine getCategories/getTypes into single query
- Add transaction support to BulkOperationsModel with atomic mode option
- Add depth limit (20) to dependency cycle detection to prevent DoS
- Add caching to UserModel.getAllGroups() with 5-minute TTL
- Improve ticket ID generation with 50 attempts, exponential backoff, and fallback
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Consolidate all 20 API files to use centralized Database helper
- Add optimistic locking to ticket updates to prevent concurrent conflicts
- Add caching to StatsModel (60s TTL) for dashboard performance
- Add health check endpoint (api/health.php) for monitoring
- Improve rate limit cleanup with cron script and efficient DirectoryIterator
- Enable rate limit response headers (X-RateLimit-*)
- Add audit logging for workflow transitions
- Log Discord webhook failures instead of silencing
- Fix visibility check on export_tickets.php
- Add database migration system with performance indexes
- Fix cron recurring tickets to use assignTicket method
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add CacheHelper for file-based caching with TTL support
- Add Database helper for centralized connection management
- Update WorkflowModel to cache status transitions (10 min TTL)
- Update UserPreferencesModel to cache user prefs (5 min TTL)
- Update manage_workflows.php to clear cache on changes
- Update get_users.php to use Database helper (example migration)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Check if updated_at column exists before using it in UPDATE query.
This allows comment editing to work before migration script is run.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add comment edit/delete functionality (owner or admin can modify)
- Add edit/delete buttons to comments in TicketView
- Create update_comment.php and delete_comment.php API endpoints
- Add updateComment() and deleteComment() methods to CommentModel
- Show "(edited)" indicator on modified comments
- Add migration script for updated_at column
- Auto-link URLs in plain text comments (non-markdown)
- Add markdown table support with proper HTML rendering
- Preserve code blocks during markdown parsing
- Fix mobile UI elements showing on desktop (add display:none defaults)
- Add mobile styles for CreateTicketView form elements
- Stack status-priority-row on mobile devices
- Update cache busters to v20260124e
- Update Claude.md and README.md documentation
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The WHERE conditions use 't.' prefix but the COUNT query was missing
the table alias, causing 500 errors when using priority_max, assigned_to,
or date filters.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add detailed error handling in DependencyModel (throw exceptions on failure)
- Add try-catch in ticket_dependencies.php to catch query errors
- Remove all old migrations (001-014) that have already been run
- Keep only new feature migrations (015-018) for reference
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Fixed server-side sorting for user-related columns on dashboard:
Problem:
- Clicking "Created By" or "Assigned To" headers didn't sort
- Columns were missing from $allowedColumns validation
- Fell back to ticket_id sort, appearing random to users
Solution:
1. Added 'created_by' and 'assigned_to' to $allowedColumns array
2. Smart sort expression mapping:
- created_by → sorts by display_name/username (not user ID)
- assigned_to → uses CASE to put unassigned at end, then sorts by name
- Other columns → use table prefix (t.column_name)
3. Database-level NULL handling for assigned_to:
- Uses CASE WHEN to sort unassigned tickets last
- Regardless of ASC/DESC direction
- Then alphabetically sorts assigned users
Result:
- A→Z: Alice, Bob, Charlie... Unassigned
- Z→A: Zack, Yolanda, Xavier... Unassigned
- Consistent grouping and predictable order
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Cache optimization with automatic expiration:
1. New Cache Structure:
- Changed from simple array to TTL-aware structure
- Each entry: ['data' => ..., 'expires' => timestamp]
- 5-minute (300s) TTL prevents indefinite stale data
2. Helper Methods:
- getCached($key): Returns data if not expired, null otherwise
- setCached($key, $data): Stores with expiration timestamp
- invalidateCache($userId, $username): Manual cache clearing
3. Updated All Cache Access Points:
- syncUserFromAuthelia() - User sync from Authelia
- getSystemUser() - System user for daemon operations
- getUserById() - User lookup by ID
- getUserByUsername() - User lookup by username
Benefits:
- Prevents memory leaks from unlimited cache growth
- Ensures user data refreshes periodically
- Maintains performance benefits of caching
- Automatic cleanup of expired entries
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Fixed all reported issues:
1. **Dark Mode Improvements:**
- Fixed bulk-actions-info white on white text (now yellow on dark background)
- Fixed timeline-content boxes with explicit dark mode colors
- All text now properly visible in dark mode
2. **Dashboard Enhancement:**
- Added "Assigned To" column showing ticket assignments
- Updated TicketModel query to include assigned user information
- Shows "Unassigned" when no user assigned
3. **Removed Ticket View Tracking:**
- Removed logTicketView call from TicketController
- Created migration 011 to delete all view records from audit_log
- Viewing tickets no longer clutters activity timeline
4. **Removed Duplicate Status Dropdown:**
- Removed status field from hamburger menu
- Status can now only be changed via the workflow-validated dropdown in ticket header
- Prevents confusion and ensures all status changes follow workflow rules
All changes improve usability and reduce clutter.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Add comprehensive bulk operations system for admins:
- Created BulkOperationsModel.php with operation tracking and processing
- Added bulk_operation.php API endpoint for bulk operations
- Created get_users.php API endpoint for user dropdown in bulk assign
- Updated DashboardView.php with checkboxes and bulk actions toolbar
- Added JavaScript functions for:
- Select all/clear selection
- Bulk close tickets
- Bulk assign tickets
- Bulk change priority
- Added comprehensive CSS for bulk actions toolbar and modals
- All bulk operations are admin-only (enforced server-side)
- Operations tracked in bulk_operations table with audit logging
- Supports bulk_close, bulk_assign, and bulk_priority operations
Admins can now select multiple tickets and perform batch operations, significantly improving workflow efficiency.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Add ticket template system for quick ticket creation:
- Created TemplateModel.php with full CRUD operations for templates
- Added get_template.php API endpoint to fetch template data
- Updated TicketController to load templates in create() method
- Modified CreateTicketView.php to include template selector dropdown
- Added loadTemplate() JavaScript function to populate form fields
- Templates include: title, description, category, type, and default priority
- Database already seeded with default templates (Hardware Failure, Software Installation, Network Issue, Maintenance Request)
Users can now select from predefined templates when creating tickets, speeding up common ticket creation workflows.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Add comprehensive workflow management system for ticket status transitions:
- Created WorkflowModel.php for managing status transition rules
- Updated TicketController.php to load allowed transitions for each ticket
- Modified TicketView.php to display dynamic status dropdown with only allowed transitions
- Enhanced api/update_ticket.php with server-side workflow validation
- Added updateTicketStatus() JavaScript function for client-side status changes
- Included CSS styling for status select dropdown with color-coded states
- Transitions can require comments or admin privileges
- Status changes are validated against status_transitions table
This feature enforces proper ticket workflows and prevents invalid status changes.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Add assigned_to column support in TicketModel with assignTicket() and unassignTicket() methods
- Create assign_ticket.php API endpoint for assignment operations
- Update TicketController to load user list from UserModel
- Add assignment dropdown UI in TicketView
- Add JavaScript handler for assignment changes
- Integrate with audit log for assignment tracking
Users can now assign tickets to team members via dropdown selector.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>