Implement comprehensive improvement plan (Phases 1-6)

Security (Phase 1-2):
- Add SecurityHeadersMiddleware with CSP, X-Frame-Options, etc.
- Add RateLimitMiddleware for API rate limiting
- Add security event logging to AuditLogModel
- Add ResponseHelper for standardized API responses
- Update config.php with security constants

Database (Phase 3):
- Add migration 014 for additional indexes
- Add migration 015 for ticket dependencies
- Add migration 016 for ticket attachments
- Add migration 017 for recurring tickets
- Add migration 018 for custom fields

Features (Phase 4-5):
- Add ticket dependencies with DependencyModel and API
- Add duplicate detection with check_duplicates API
- Add file attachments with AttachmentModel and upload/download APIs
- Add @mentions with autocomplete and highlighting
- Add quick actions on dashboard rows

Collaboration (Phase 5):
- Add mention extraction in CommentModel
- Add mention autocomplete dropdown in ticket.js
- Add mention highlighting CSS styles

Admin & Export (Phase 6):
- Add StatsModel for dashboard widgets
- Add dashboard stats cards (open, critical, unassigned, etc.)
- Add CSV/JSON export via export_tickets API
- Add rich text editor toolbar in markdown.js
- Add RecurringTicketModel with cron job
- Add CustomFieldModel for per-category fields
- Add admin views: RecurringTickets, CustomFields, Workflow,
  Templates, AuditLog, UserActivity
- Add admin APIs: manage_workflows, manage_templates,
  manage_recurring, custom_fields, get_users
- Add admin routes in index.php

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-20 09:55:01 -05:00
parent 8c7211d311
commit be505b7312
53 changed files with 6640 additions and 169 deletions

View File

@@ -1,16 +1,19 @@
<?php
require_once 'models/TicketModel.php';
require_once 'models/UserPreferencesModel.php';
require_once 'models/StatsModel.php';
class DashboardController {
private $ticketModel;
private $prefsModel;
private $statsModel;
private $conn;
public function __construct($conn) {
$this->conn = $conn;
$this->ticketModel = new TicketModel($conn);
$this->prefsModel = new UserPreferencesModel($conn);
$this->statsModel = new StatsModel($conn);
}
public function index() {
@@ -71,28 +74,37 @@ class DashboardController {
$tickets = $result['tickets'];
$totalTickets = $result['total'];
$totalPages = $result['pages'];
// Load dashboard statistics
$stats = $this->statsModel->getAllStats();
// Load the dashboard view
include 'views/DashboardView.php';
}
private function getCategories() {
$sql = "SELECT DISTINCT category FROM tickets WHERE category IS NOT NULL ORDER BY category";
$result = $this->conn->query($sql);
$stmt = $this->conn->prepare($sql);
$stmt->execute();
$result = $stmt->get_result();
$categories = [];
while($row = $result->fetch_assoc()) {
while ($row = $result->fetch_assoc()) {
$categories[] = $row['category'];
}
$stmt->close();
return $categories;
}
private function getTypes() {
$sql = "SELECT DISTINCT type FROM tickets WHERE type IS NOT NULL ORDER BY type";
$result = $this->conn->query($sql);
$stmt = $this->conn->prepare($sql);
$stmt->execute();
$result = $stmt->get_result();
$types = [];
while($row = $result->fetch_assoc()) {
while ($row = $result->fetch_assoc()) {
$types[] = $row['type'];
}
$stmt->close();
return $types;
}
}

View File

@@ -246,7 +246,6 @@ class TicketController {
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
$webhookResult = curl_exec($ch);