diff --git a/tickets.php b/tickets.php index b1d4f494..842a8f1c 100644 --- a/tickets.php +++ b/tickets.php @@ -36,6 +36,17 @@ if (isset($_GET['status']) && is_array($_GET['status']) && !empty($_GET['status' } } +if (isset($_GET['category'])) { + if ($_GET['category'] == 'empty') { + $category_snippet = "AND ticket_category = 0 "; + } elseif ($_GET['category'] == 'all') { + $category_snippet = ""; + } else { + $category_snippet = "AND ticket_category = " . $_GET['category']; + } +} + + // Ticket assignment status filter // Default - any $ticket_assigned_query = ''; @@ -48,7 +59,7 @@ if (isset($_GET['assigned']) & !empty($_GET['assigned'])) { $ticket_assigned_query = 'AND ticket_assigned_to = ' . intval($_GET['assigned']); $ticket_assigned_filter_id = intval($_GET['assigned']); } -} +} //Rebuild URL $url_query_strings_sort = http_build_query(array_merge($_GET, array('sort' => $sort, 'order' => $order, 'status' => $status, 'assigned' => $ticket_assigned_filter_id))); @@ -70,7 +81,9 @@ $sql = mysqli_query( LEFT JOIN locations ON ticket_location_id = location_id LEFT JOIN vendors ON ticket_vendor_id = vendor_id LEFT JOIN ticket_statuses ON ticket_status = ticket_status_id + LEFT JOIN categories ON ticket_category = category_id WHERE $ticket_status_snippet " . $ticket_assigned_query . " + $category_snippet AND DATE(ticket_created_at) BETWEEN '$dtf' AND '$dtt' AND (CONCAT(ticket_prefix,ticket_number) LIKE '%$q%' OR client_name LIKE '%$q%' OR ticket_subject LIKE '%$q%' OR ticket_status_name LIKE '%$q%' OR ticket_priority LIKE '%$q%' OR user_name LIKE '%$q%' OR contact_name LIKE '%$q%' OR asset_name LIKE '%$q%' OR vendor_name LIKE '%$q%' OR ticket_vendor_ticket_number LIKE '%q%') $ticket_permission_snippet @@ -99,6 +112,15 @@ $sql_total_tickets_assigned = mysqli_query($mysqli, "SELECT COUNT(ticket_id) AS $row = mysqli_fetch_array($sql_total_tickets_assigned); $user_active_assigned_tickets = intval($row['total_tickets_assigned']); +$sql_categories = mysqli_query( + $mysqli, + "SELECT * FROM categories + WHERE category_type = 'Ticket' + ORDER BY category_name" +); + + + ?> + + +id = $id; + $statuses[$id]->name = $name; + $statuses[$id]->tickets = []; + $statuses[$id]->order = $kanban_order; // Store the order +} + +// Fetch tickets and merge into statuses +$sql = mysqli_query( + $mysqli, + "SELECT SQL_CALC_FOUND_ROWS * FROM tickets + LEFT JOIN clients ON ticket_client_id = client_id + LEFT JOIN contacts ON ticket_contact_id = contact_id + LEFT JOIN users ON ticket_assigned_to = user_id + LEFT JOIN assets ON ticket_asset_id = asset_id + LEFT JOIN locations ON ticket_location_id = location_id + LEFT JOIN vendors ON ticket_vendor_id = vendor_id + LEFT JOIN ticket_statuses ON ticket_status = ticket_status_id + LEFT JOIN categories ON ticket_category = category_id + WHERE $ticket_status_snippet " . $ticket_assigned_query . " + $category_snippet + AND DATE(ticket_created_at) BETWEEN '$dtf' AND '$dtt' + AND (CONCAT(ticket_prefix,ticket_number) LIKE '%$q%' OR client_name LIKE '%$q%' OR ticket_subject LIKE '%$q%' OR ticket_status_name LIKE '%$q%' OR ticket_priority LIKE '%$q%' OR user_name LIKE '%$q%' OR contact_name LIKE '%$q%' OR asset_name LIKE '%$q%' OR vendor_name LIKE '%$q%' OR ticket_vendor_ticket_number LIKE '%q%') + $ticket_permission_snippet + ORDER BY $sort $order" +); + +while ($row = mysqli_fetch_array($sql)) { + $id = $row['ticket_status_id']; + $ticket_order = $row['ticket_kanban']; + $row['ticket_order'] = $ticket_order; // Store the ticket order + + if (isset($statuses[$id])) { + $statuses[$id]->tickets[] = $row; + } +} + +// Convert associative array to indexed array for sorting +$kanban_array = array_values($statuses); + +// Sort the array by the 'order' field, moving null values to the end +usort($kanban_array, function($a, $b) { + if ($a->order === null) return 1; + if ($b->order === null) return -1; + return $a->order - $b->order; +}); + +// Sort tickets within each column by 'ticket_kanban' +foreach ($kanban_array as $kanban_column) { + usort($kanban_column->tickets, function($a, $b) { + return $a['ticket_order'] - $b['ticket_order']; + }); +} + +// Re-index the sorted array back to associative array if needed +$ordered_kanban = []; +foreach ($kanban_array as $item) { + $ordered_kanban[$item->id] = $item; +} + +$kanban = $ordered_kanban; + + + + + + +?> + +
+ +
+
name); ?>
+
+ tickets as $item){ + if ($item['ticket_priority'] == "High") { + $ticket_priority_color = "danger"; + } elseif ($item['ticket_priority'] == "Medium") { + $ticket_priority_color = "warning"; + } else { + $ticket_priority_color = "info"; + } + ?> + +
+ + + + + + +
+ + + + +
+ + +
+ + +
+ +
+ + + +
+ + +
+
+ +
+ + + + + + + + + + + + + diff --git a/tickets_list.php b/tickets_list.php new file mode 100644 index 00000000..6ed456c7 --- /dev/null +++ b/tickets_list.php @@ -0,0 +1,290 @@ +
+
+
+ + +
+ + "> + + + + + + + = 2) { ?> + + + + + + + + + + + + Never

"; + } else { + $ticket_updated_at_display = "

Never

"; + } + } else { + $ticket_updated_at_display = "$ticket_updated_at_time_ago
$ticket_updated_at"; + } + + $project_id = intval($row['ticket_project_id']); + + $client_id = intval($row['ticket_client_id']); + $client_name = nullable_htmlentities($row['client_name']); + $contact_name = nullable_htmlentities($row['contact_name']); + $contact_email = nullable_htmlentities($row['contact_email']); + + if ($ticket_priority == "High") { + $ticket_priority_color = "danger"; + } elseif ($ticket_priority == "Medium") { + $ticket_priority_color = "warning"; + } else { + $ticket_priority_color = "info"; + } + + $ticket_assigned_to = intval($row['ticket_assigned_to']); + if (empty($ticket_assigned_to)) { + if (!empty($ticket_closed_at)) { + $ticket_assigned_to_display = "

Not Assigned

"; + } else { + $ticket_assigned_to_display = "

Not Assigned

"; + } + } else { + $ticket_assigned_to_display = nullable_htmlentities($row['user_name']); + } + + if (empty($contact_name)) { + $contact_display = "-"; + } else { + $contact_display = "$contact_name
$contact_email"; + } + + // Get who last updated the ticket - to be shown in the last Response column + + // Defaults to prevent undefined errors + $ticket_reply_created_at = ""; + $ticket_reply_created_at_time_ago = "Never"; + $ticket_reply_by_display = ""; + $ticket_reply_type = "Client"; // Default to client for un-replied tickets + + $sql_ticket_reply = mysqli_query($mysqli, + "SELECT ticket_reply_type, ticket_reply_created_at, contact_name, user_name FROM ticket_replies + LEFT JOIN users ON ticket_reply_by = user_id + LEFT JOIN contacts ON ticket_reply_by = contact_id + WHERE ticket_reply_ticket_id = $ticket_id + AND ticket_reply_archived_at IS NULL + ORDER BY ticket_reply_id DESC LIMIT 1" + ); + $row = mysqli_fetch_array($sql_ticket_reply); + + if ($row) { + $ticket_reply_type = nullable_htmlentities($row['ticket_reply_type']); + if ($ticket_reply_type == "Client") { + $ticket_reply_by_display = nullable_htmlentities($row['contact_name']); + } else { + $ticket_reply_by_display = nullable_htmlentities($row['user_name']); + } + $ticket_reply_created_at = nullable_htmlentities($row['ticket_reply_created_at']); + $ticket_reply_created_at_time_ago = timeAgo($ticket_reply_created_at); + } + + + // Get Tasks + $sql_tasks = mysqli_query( $mysqli, "SELECT * FROM tasks WHERE task_ticket_id = $ticket_id ORDER BY task_created_at ASC"); + $task_count = mysqli_num_rows($sql_tasks); + // Get Completed Task Count + $sql_tasks_completed = mysqli_query($mysqli, + "SELECT * FROM tasks + WHERE task_ticket_id = $ticket_id + AND task_completed_at IS NOT NULL" + ); + $completed_task_count = mysqli_num_rows($sql_tasks_completed); + + // Tasks Completed Percent + if($task_count) { + $tasks_completed_percent = round(($completed_task_count / $task_count) * 100); + } + + ?> + + "> + + + + + + + + + + + + + + + = 2) { ?> + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+
+ + Ticket + + + + Subject / Tasks + + + + Client / Contact + + + + Billable + + + + Priority + + + + Status + + + + Assigned + + + + Last Response + + + + Created + +
+ +
+ +
+ +
+ + + + + + + 0) { ?> +
+
+
+ + +
+

+
+ +
+ + +
+
+ + Yes"; + } else { + echo "No"; + } + ?> + + + + + $ticket_scheduled_for "; } ?> + + + +
+ +
+
+
+ +
+
+ + + + + + +
+ +
+
+