Wire optimistic locking, visibility audit log, full ticket export
Optimistic locking: - TicketView now includes updated_at in window.ticketData - ticket.js saveTicket() sends expected_updated_at on every save so the server can detect concurrent edits - On conflict response, shows a clear toast: "ticket was modified by someone else while you were editing — reload to see latest version" - On success, syncs window.ticketData.updated_at from server response so subsequent saves use the correct lock key - update_ticket.php now returns updated_at in success response Visibility audit log: - updateVisibility() result is now checked; on success, logs a delta entry to the audit trail with from/to visibility and groups so the timeline shows who changed visibility and when Full ticket export: - export_tickets.php now accepts format=full with a single ticket_id - Produces a JSON file containing ticket fields, flat comment list (with author, timestamps, text), and the full audit timeline - Access-controlled: respects canUserAccessTicket() before exporting - EXPORT button added to ticket toolbar linking directly to the endpoint Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+18
-12
@@ -71,20 +71,22 @@ $visUserModel = new UserModel($conn);
|
||||
$allAvailableGroups = $visUserModel->getAllGroups();
|
||||
|
||||
// JSON-encode ticket fields for the inline script
|
||||
$json_ticket_id = json_encode($ticket['ticket_id'], JSON_HEX_TAG);
|
||||
$json_title = json_encode($ticket['title'], JSON_HEX_TAG);
|
||||
$json_status = json_encode($ticket['status'], JSON_HEX_TAG);
|
||||
$json_priority = json_encode($ticket['priority'], JSON_HEX_TAG);
|
||||
$json_category = json_encode($ticket['category'], JSON_HEX_TAG);
|
||||
$json_type = json_encode($ticket['type'], JSON_HEX_TAG);
|
||||
$json_ticket_id = json_encode($ticket['ticket_id'], JSON_HEX_TAG);
|
||||
$json_title = json_encode($ticket['title'], JSON_HEX_TAG);
|
||||
$json_status = json_encode($ticket['status'], JSON_HEX_TAG);
|
||||
$json_priority = json_encode($ticket['priority'], JSON_HEX_TAG);
|
||||
$json_category = json_encode($ticket['category'], JSON_HEX_TAG);
|
||||
$json_type = json_encode($ticket['type'], JSON_HEX_TAG);
|
||||
$json_updated_at = json_encode($ticket['updated_at'], JSON_HEX_TAG);
|
||||
$pageInlineScript = <<<JS
|
||||
window.ticketData = {
|
||||
ticket_id: {$json_ticket_id},
|
||||
title: {$json_title},
|
||||
status: {$json_status},
|
||||
priority: {$json_priority},
|
||||
category: {$json_category},
|
||||
type: {$json_type},
|
||||
ticket_id: {$json_ticket_id},
|
||||
title: {$json_title},
|
||||
status: {$json_status},
|
||||
priority: {$json_priority},
|
||||
category: {$json_category},
|
||||
type: {$json_type},
|
||||
updated_at: {$json_updated_at},
|
||||
};
|
||||
window.ticketData.id = window.ticketData.ticket_id;
|
||||
if (window.lt) lt.keys.initDefaults();
|
||||
@@ -122,6 +124,10 @@ include __DIR__ . '/layout_header.php';
|
||||
</select>
|
||||
<button type="button" id="editButton" class="lt-btn lt-btn-primary lt-btn-sm">EDIT</button>
|
||||
<button type="button" id="cloneButton" class="lt-btn lt-btn-sm">CLONE</button>
|
||||
<a id="exportFullBtn"
|
||||
href="/api/export_tickets.php?format=full&ticket_id=<?= (int)$ticket['ticket_id'] ?>"
|
||||
class="lt-btn lt-btn-ghost lt-btn-sm"
|
||||
title="Export this ticket with all comments and history as JSON">EXPORT</a>
|
||||
<button type="button" class="lt-btn lt-btn-ghost lt-btn-sm" data-modal-open="settingsModal">CFG</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user