- 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>
Browsers ignore 'unsafe-inline' when a nonce is present. Reverting to
unsafe-inline only until all inline handlers are refactored.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Refactored TicketView.php to use event listeners instead of onclick
- Added unsafe-inline to CSP as fallback for legacy handlers in other views
- TODO: Complete refactoring of DashboardView and admin views
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Removed min-width: 180px from .setting-row label
- Changed min-width: 200px to min-width: 0 for form inputs
- Labels now size to content, inputs fill remaining space
- Updated cache version to 20260126c
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Added .setting-row-compact class for stacked label/input layout
- Updated TemplatesView.php grid to use compact rows (3 columns)
- Updated RecurringTicketsView.php grid to use compact rows (2 columns)
- Removed inline style="width: 100%" (handled by CSS now)
- Labels now stack above inputs in grid context for clarity
- Updated cache version to 20260126b
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Template fixes:
- Fixed column name mismatch: use 'default_priority' instead of 'priority'
- Updated manage_templates.php API INSERT and UPDATE queries
- Updated TemplatesView.php to use correct field name in PHP and JS
CSS improvements for .setting-row:
- Better flexbox layout with flex-wrap for responsiveness
- Proper styling for inputs, selects, and textareas in setting rows
- Labels now align to top (better for textareas)
- Added focus states with amber glow effect
- Improved checkbox styling within setting rows
- Better mobile responsive behavior (stacked layout)
- Updated cache version to 20260126a
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Standardized embed format across both ticket creation paths
- Added consistent priority colors (P1-P5) with distinct hex values
- Added priority labels (e.g., "P1 - Critical" instead of just "1")
- Added Source field showing hostname extracted from ticket title
- Added Status field to both webhook formats
- Added footer distinguishing "Automated Alert" vs "Manual Entry"
- Added timestamp to API endpoint webhooks
- Added error logging for failed webhook calls
- Added timeout (10s) to API endpoint curl calls
- Added null check for webhook URL in API endpoint
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>
Dashboard sidebar fixes:
- Added proper styling for sidebar interior on mobile
- Filter groups have touch-friendly labels (44px height)
- Larger checkboxes (22px)
- Full-width apply/clear buttons
- Border separators between filter groups
Ticket page fixes:
- Metadata fields stack vertically on mobile
- Assignment dropdown full-width
- All selects have 48px height and 16px font
- Better spacing throughout
- Sticky header
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Major mobile improvements:
- Sticky header with simplified controls
- Slide-out filter sidebar with overlay
- Bottom navigation bar (Home, Filter, New, Settings)
- Stacked toolbar layout
- Full-width modals sliding up from bottom
- Admin dropdown as bottom sheet
- Horizontal scrolling table with touch support
- 44px minimum touch targets throughout
- iOS zoom prevention on inputs
- Landscape mode optimizations
CSS changes:
- Rewrote all mobile styles with correct class names
- Added mobile bottom nav styles
- Fixed toolbar-left, toolbar-center, toolbar-right
- Fixed user-header-left, user-header-right
JS changes:
- initMobileSidebar now creates bottom nav
- Removed style.display = 'none' (CSS handles visibility)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Bug fixes:
- Fix ticket ID extraction using URLSearchParams instead of split()
- Add error handling for query result in get_users.php
- Make Discord webhook URLs dynamic (use HTTP_HOST)
Code cleanup:
- Remove debug console.log statements from dashboard.js and ticket.js
- Add getTicketIdFromUrl() helper function to both JS files
Documentation:
- Update Claude.md: fix web server (nginx not Apache), add new notes
- Update README.md: add keyboard shortcuts, update setup instructions
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Added routes for all API endpoints that were missing:
- ticket_dependencies, upload_attachment, delete_attachment
- get_users, assign_ticket, get_template
- bulk_operation, export_tickets
- generate_api_key, revoke_api_key
- manage_templates, manage_workflows, manage_recurring
- check_duplicates
This fixes the 500/404 errors on Dependencies tab and other API calls.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Change session.cookie_samesite from Strict to Lax for Authelia compatibility
- Redesign sidebar toggle with separate collapse/expand buttons
- Add script to create missing ticket_dependencies table
- Add .env.example template
- Add check for missing .env with helpful error message
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Fix collapsible sidebar toggle button positioning (moved outside sidebar)
- Toggle button now stays visible when sidebar is collapsed
- Update cache busting version
- Update Claude.md with new features documentation
- Update README.md with new features documentation
- Remove migrations folder (no longer needed)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add cache busting query params to JS/CSS files (v=20260123)
- Add visibility group selection UI for editing existing tickets
- Add toggleVisibilityGroupsEdit() and getSelectedVisibilityGroups() functions
- Fix visibility data being saved when editing tickets
- Pass $conn to views for UserModel access
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add timezone dropdown to settings modal with common timezones
- Save/load timezone preference per user
- Apply user's timezone preference after authentication
- Override system default with user preference if set
- Make dashboard logo clickable (returns to default filters)
- Show current timezone in settings
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add TIMEZONE config option (default: America/New_York)
- Set PHP default timezone from config
- Add timezone offset and abbreviation for JavaScript
- Update stat card filters to use server timezone
- Add timezone config to Dashboard and Ticket views
Timezone can be changed via TIMEZONE env variable.
All dates now consistent with server timezone (EST by default).
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 admin dropdown menu in dashboard header with links to all admin pages
- Fix template modal: larger size (800px), responsive grid, type/priority dropdowns
- Fix recurring tickets modal: add Type and Assign To fields, larger size
- Make dashboard stat cards clickable for quick filtering
- Fix user-activity query (remove is_active requirement)
- Add table existence check in ticket_dependencies API
- Fix table overflow on dashboard
- Update Claude.md and README.md with current project status
- Remove migrations directory (all migrations completed)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Completely rewrote README with all new features and admin routes
- Cleaned up remaining migration files
- Added detailed PHP error/exception handlers to dependencies API
to help debug the 500 error
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>
- Fix AuditLogModel instantiation with proper $conn parameter
- Fix log() call parameter order (details should be array, not ipAddress)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add session status check
- Remove broken AuditLogModel call without $conn in CSRF check
- Fix AuditLogModel instantiation with proper $conn parameter
- Fix log() call to pass array instead of JSON string for details
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add session status check before starting session
- Add error reporting settings for debugging
- Prevents potential session conflicts with RateLimitMiddleware
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The AuditLogModel was being instantiated without required $conn parameter
when logging CSRF failures, causing a 500 error.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add scripts/deploy.sh for safe deployment with uploads preservation
- Add scripts/cleanup_orphan_uploads.php to remove orphaned files
- Add .gitkeep to uploads folder
- Update .gitignore to exclude uploaded files but keep folder structure
The deploy script now:
- Backs up and restores .env file
- Backs up and restores uploads folder contents
- Runs database migrations automatically
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Remove is_active filter from get_users.php (column doesn't exist)
- Fix ticket ID validation regex in upload_attachment.php (9-digit format)
- Fix createSettingsModal reference to use openSettingsModal from settings.js
- Add error handling for dependencies tab to prevent infinite loading
- Add try-catch wrapper to ticket_dependencies.php API
- Make export dropdown visible only when tickets are selected
- Export only selected tickets instead of all filtered tickets
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Update generateTicketHash() to exclude hostname from hash for
cluster-wide Ceph issues, enabling proper deduplication across
all nodes in the cluster.
Cluster-wide issues detected by:
- [cluster-wide] tag in title
- HEALTH_ERR or HEALTH_WARN in title
- "cluster usage" in title
This prevents all nodes from creating duplicate tickets for the
same cluster-wide issue (e.g., Ceph HEALTH_WARN).
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Fixed markdown preview for comments by replacing marked.parse() calls
with parseMarkdown() function. The application uses a custom markdown
parser (markdown.js), not the marked.js library.
Changes:
- togglePreview(): Use parseMarkdown() instead of marked.parse()
- updatePreview(): Use parseMarkdown() instead of marked.parse()
Resolves issue where markdown preview didn't work for comments but
worked after posting.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Fixed scope issue where selectedOption variable was not accessible in
performStatusChange(). Updated function signature to accept selectedOption
as a parameter and updated both call sites to pass it.
Resolves error: "selectedOption is not defined" when changing ticket status.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Fixed syntax error from previous commit where updateTicketStatus()
function had incorrect closing. Changed `});` to `}` at line 434.
This was preventing showTab() and other functions from loading,
breaking the Description/Comments/Activity tab navigation.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Improved toast notification system with queue management:
**Features Added**:
1. **Toast Queuing**:
- Multiple toasts no longer replace each other
- Toasts are queued and displayed sequentially
- Smooth transitions between queued messages
- Prevents message loss during rapid operations
2. **Manual Dismissal**:
- Click [×] button to dismiss toast immediately
- Useful for long-duration error messages
- Clears auto-dismiss timeout on manual close
- Next queued toast appears immediately after dismiss
3. **Queue Management**:
- Internal toastQueue[] array tracks pending messages
- currentToast reference prevents overlapping displays
- dismissToast() handles both auto and manual dismissal
- Automatic dequeue when toast closes
**Implementation**:
- displayToast() separated from showToast() for queue handling
- timeoutId stored on toast element for cleanup
- Close button styled with terminal aesthetic ([×])
- 300ms fade-out animation preserved
**Benefits**:
✓ No lost messages during bulk operations
✓ Better UX - users can dismiss errors immediately
✓ Clean queue management prevents memory leaks
✓ Maintains terminal aesthetic with minimal close button
Example: Bulk assign 10 tickets with 2 failures now shows:
1. "Bulk assign: 8 succeeded, 2 failed" (toast 1)
2. Next operation's message queued (toast 2)
3. User can dismiss or wait for auto-dismiss
Co-Authored-By: Claude Sonnet 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>
Fixed sorting logic for the "Assigned To" column on dashboard:
Problem:
- "Unassigned" was sorted alphabetically with user names
- Appeared randomly in middle of list (after 'S', before 'V')
- Made it hard to find unassigned tickets when sorted
Solution:
- "Unassigned" tickets now always appear at end of list
- Regardless of sort direction (A→Z or Z→A)
- Assigned user names still sort normally among themselves
- Example A→Z: Alice, Bob, Charlie... Unassigned
- Example Z→A: Zack, Yolanda, Xavier... Unassigned
This keeps unassigned tickets grouped together and predictable.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>