feat: enhance task tracking with comment metadata, tag support, improved audit logging, and flatpickr integration.

This commit is contained in:
root
2026-03-29 23:34:27 +07:00
parent 97649d9a98
commit 68a764c0df
3 changed files with 205 additions and 86 deletions

View File

@@ -1,5 +1,6 @@
<?php
session_start();
date_default_timezone_set('Etc/GMT-7');
require_once 'db.php';
$action = (string)($_GET['action'] ?? 'dashboard');
@@ -13,7 +14,7 @@ if ($action === 'api') {
try { $pdo->exec("ALTER TABLE tasks ADD COLUMN assignor_type TEXT DEFAULT 'user'"); } catch(Exception $e) {}
try { $pdo->exec("ALTER TABLE tasks ADD COLUMN assignor_group_id INTEGER"); } catch(Exception $e) {}
try { $pdo->exec("ALTER TABLE tasks ADD COLUMN status_updated_at DATETIME"); } catch(Exception $e) {}
try { $pdo->exec("ALTER TABLE tasks ADD COLUMN due_date DATE"); } catch(Exception $e) {}
try { $pdo->exec("ALTER TABLE tasks ADD COLUMN due_date DATETIME"); } catch(Exception $e) {}
try { $pdo->exec("ALTER TABLE tasks ADD COLUMN custom_assignee_name TEXT"); } catch(Exception $e) {}
try { $pdo->exec("ALTER TABLE tasks ADD COLUMN completed_by INTEGER DEFAULT NULL"); } catch(Exception $e) {}
try { $pdo->exec("ALTER TABLE tasks ADD COLUMN archived_by INTEGER DEFAULT NULL"); } catch(Exception $e) {}
@@ -99,7 +100,16 @@ if ($action === 'api') {
g.name as assignor_group_name,
au.username as assignee_user_name,
ag.name as assignee_group_name,
(SELECT COUNT(*) FROM task_attachments ta WHERE ta.task_id = t.id) AS attachments_count
(SELECT COUNT(*) FROM task_attachments ta WHERE ta.task_id = t.id) AS attachments_count,
(SELECT COUNT(*) FROM task_comments tc WHERE tc.task_id = t.id) AS comments_count,
(SELECT comment FROM task_comments tc WHERE tc.task_id = t.id ORDER BY tc.created_at DESC LIMIT 1) AS last_comment,
(SELECT created_at FROM task_comments tc WHERE tc.task_id = t.id ORDER BY tc.created_at DESC LIMIT 1) AS last_comment_date,
(SELECT cu.username FROM task_comments tc JOIN users cu ON tc.created_by = cu.id WHERE tc.task_id = t.id ORDER BY tc.created_at DESC LIMIT 1) AS last_commenter,
t.status_updated_at,
t.completed_by,
t.archived_by,
t.tags,
t.title
FROM tasks t
LEFT JOIN users u ON t.assignor_id = u.id
LEFT JOIN groups g ON t.assignor_group_id = g.id
@@ -142,15 +152,35 @@ if ($action === 'api') {
$desc = (string)($row['description'] ?? '');
$desc = trim($desc) !== '' ? $desc : (string)($row['title'] ?? '');
$tags = !empty($row['tags']) ? array_filter(array_map('trim', explode(',', $row['tags']))) : [];
// Logic for last_modified_by
// If it's archived, 'Archived by' user; if completed, 'Completed by' user; otherwise latest commenter or creator.
$last_mod_by = 'System';
if ($row['status'] === 'archived' && $row['archived_by']) {
$last_mod_by = query("SELECT username FROM users WHERE id=?", [$row['archived_by']])->fetchColumn() ?: 'System';
} elseif ($row['status'] === 'completed' && $row['completed_by']) {
$last_mod_by = query("SELECT username FROM users WHERE id=?", [$row['completed_by']])->fetchColumn() ?: 'System';
} else {
$last_mod_by = $row['last_commenter'] ?: $row['assignor_user_name'];
}
$payload = [
'task_id' => (string)$row['id'],
'task_created_date' => $format_dt($row['created_at'] ?? null),
'task_name' => (string)$row['title'],
'task_created_date' => $format_dt($row['created_at'] ? $row['created_at'] . ' UTC' : null),
'from' => $from,
'to' => $to,
'task_description' => $desc,
'due_date' => $format_dt($row['due_date'] ?? null),
'current_status' => $format_status($row['status'] ?? null),
'attachments_count' => (int)($row['attachments_count'] ?? 0),
'tags_count' => count($tags),
'comments_count' => (int)($row['comments_count'] ?? 0),
'last_modified_by' => $last_mod_by,
'last_modified_date' => $format_dt(($row['status_updated_at'] ?: $row['created_at']) . ' UTC'),
'last_comment' => $row['last_comment'] ?: null,
'last_comment_date' => $format_dt($row['last_comment_date'] ? $row['last_comment_date'] . ' UTC' : null),
];
echo json_encode($payload);
@@ -171,15 +201,33 @@ if ($action === 'api') {
$desc = (string)($row['description'] ?? '');
$desc = trim($desc) !== '' ? $desc : (string)($row['title'] ?? '');
$tags = !empty($row['tags']) ? array_filter(array_map('trim', explode(',', $row['tags']))) : [];
$last_mod_by = 'System';
if ($row['status'] === 'archived' && $row['archived_by']) {
$last_mod_by = query("SELECT username FROM users WHERE id=?", [$row['archived_by']])->fetchColumn() ?: 'System';
} elseif ($row['status'] === 'completed' && $row['completed_by']) {
$last_mod_by = query("SELECT username FROM users WHERE id=?", [$row['completed_by']])->fetchColumn() ?: 'System';
} else {
$last_mod_by = $row['last_commenter'] ?: $row['assignor_user_name'];
}
$result[] = [
'task_id' => (string)$row['id'],
'task_created_date' => $format_dt($row['created_at'] ?? null),
'task_name' => (string)$row['title'],
'task_created_date' => $format_dt($row['created_at'] ? $row['created_at'] . ' UTC' : null),
'from' => $from,
'to' => $to,
'task_description' => $desc,
'due_date' => $format_dt($row['due_date'] ?? null),
'current_status' => $format_status($row['status'] ?? null),
'attachments_count' => (int)($row['attachments_count'] ?? 0),
'tags_count' => count($tags),
'comments_count' => (int)($row['comments_count'] ?? 0),
'last_modified_by' => $last_mod_by,
'last_modified_date' => $format_dt(($row['status_updated_at'] ?: $row['created_at']) . ' UTC'),
'last_comment' => $row['last_comment'] ?: null,
'last_comment_date' => $format_dt($row['last_comment_date'] ? $row['last_comment_date'] . ' UTC' : null),
];
}