Accessibility pass: ARIA roles, label associations, CSS class migrations
- Add role=dialog/aria-modal/aria-labelledby to all 12 modal overlays (JS + PHP)
- Add aria-label="Close" to all 14 modal close buttons
- Add full ARIA combobox pattern to @mention autocomplete (listbox, option, aria-selected, aria-expanded)
- Add for= attributes to admin filter form labels (AuditLog, UserActivity, ApiKeys)
- Remove dead closeOnAdvancedSearchBackdropClick() from advanced-search.js
CSS/JS style cleanup:
- Move .ascii-banner static styles from JS inline to CSS class; add .ascii-banner--glow
- Add .ascii-banner-cursor, .loading-overlay--hiding, .has-overlay, tr[data-clickable]
- Add .animate-fadein/.animate-fadeout/.comment--deleting to ticket.css
- Add .lt-toast--hiding to base.css; remove opacity/transition inline JS
- Remove redundant cursor:pointer JS (already in th{} CSS rule)
- Remove trailing space in lt-select class attributes
Bug fixes:
- base.js: boot overlay opacity inline style was overriding .fade-out class opacity via
specificity (1000 vs 20), preventing the fade-out animation — removed
- ascii-banner.js: cursor used blink-caret (border-color only) instead of blink-cursor
(opacity-based), so the █ cursor never actually blinked — fixed
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -13,9 +13,10 @@ $nonce = SecurityHeadersMiddleware::getNonce();
|
||||
<title>Workflow Designer - Admin</title>
|
||||
<link rel="icon" type="image/png" href="<?php echo $GLOBALS['config']['ASSETS_URL']; ?>/images/favicon.png">
|
||||
<link rel="stylesheet" href="/assets/css/base.css">
|
||||
<link rel="stylesheet" href="<?php echo $GLOBALS['config']['ASSETS_URL']; ?>/css/dashboard.css">
|
||||
<link rel="stylesheet" href="<?php echo $GLOBALS['config']['ASSETS_URL']; ?>/css/ticket.css">
|
||||
<link rel="stylesheet" href="<?php echo $GLOBALS['config']['ASSETS_URL']; ?>/css/dashboard.css?v=20260320">
|
||||
<link rel="stylesheet" href="<?php echo $GLOBALS['config']['ASSETS_URL']; ?>/css/ticket.css?v=20260320">
|
||||
<script nonce="<?php echo $nonce; ?>" src="/assets/js/base.js"></script>
|
||||
<script nonce="<?php echo $nonce; ?>" src="<?php echo $GLOBALS['config']['ASSETS_URL']; ?>/js/utils.js?v=20260320"></script>
|
||||
<script nonce="<?php echo $nonce; ?>">
|
||||
window.CSRF_TOKEN = '<?php echo CsrfMiddleware::getToken(); ?>';
|
||||
</script>
|
||||
@@ -24,7 +25,7 @@ $nonce = SecurityHeadersMiddleware::getNonce();
|
||||
<div class="user-header">
|
||||
<div class="user-header-left">
|
||||
<a href="/" class="back-link">[ ← DASHBOARD ]</a>
|
||||
<span style="margin-left: 1rem; color: var(--terminal-amber);">Admin: Workflow Designer</span>
|
||||
<span class="admin-page-title">Admin: Workflow Designer</span>
|
||||
</div>
|
||||
<div class="user-header-right">
|
||||
<?php if (isset($GLOBALS['currentUser'])): ?>
|
||||
@@ -34,36 +35,36 @@ $nonce = SecurityHeadersMiddleware::getNonce();
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="ascii-frame-outer" style="max-width: 1200px; margin: 2rem auto;">
|
||||
<div class="ascii-frame-outer admin-container">
|
||||
<span class="bottom-left-corner">╚</span>
|
||||
<span class="bottom-right-corner">╝</span>
|
||||
|
||||
<div class="ascii-section-header">Status Workflow Designer</div>
|
||||
<div class="ascii-content">
|
||||
<div class="ascii-frame-inner">
|
||||
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 1rem;">
|
||||
<h2 style="margin: 0;">Status Transitions</h2>
|
||||
<div class="admin-header-row">
|
||||
<h2>Status Transitions</h2>
|
||||
<button data-action="show-create-modal" class="btn">+ NEW TRANSITION</button>
|
||||
</div>
|
||||
|
||||
<p style="color: var(--terminal-green-dim); margin-bottom: 1rem;">
|
||||
<p class="text-muted-green mb-1">
|
||||
Define which status transitions are allowed. This controls what options appear in the status dropdown.
|
||||
</p>
|
||||
|
||||
<!-- Visual Workflow Diagram -->
|
||||
<div style="margin-bottom: 2rem; padding: 1rem; border: 1px solid var(--terminal-green); background: var(--bg-secondary);">
|
||||
<h4 style="color: var(--terminal-amber); margin-bottom: 1rem;">Workflow Diagram</h4>
|
||||
<div style="display: flex; justify-content: center; gap: 2rem; flex-wrap: wrap;">
|
||||
<div class="workflow-diagram">
|
||||
<h4 class="admin-section-title">Workflow Diagram</h4>
|
||||
<div class="workflow-diagram-nodes">
|
||||
<?php
|
||||
$statuses = ['Open', 'Pending', 'In Progress', 'Closed'];
|
||||
foreach ($statuses as $status):
|
||||
$statusClass = 'status-' . str_replace(' ', '-', strtolower($status));
|
||||
?>
|
||||
<div style="text-align: center;">
|
||||
<div class="<?php echo $statusClass; ?>" style="padding: 0.5rem 1rem; display: inline-block;">
|
||||
<div class="workflow-diagram-node">
|
||||
<div class="<?php echo $statusClass; ?>">
|
||||
<?php echo $status; ?>
|
||||
</div>
|
||||
<div style="font-size: 0.8rem; color: var(--terminal-green-dim); margin-top: 0.5rem;">
|
||||
<div class="text-muted-green workflow-diagram-node-label">
|
||||
<?php
|
||||
$toCount = 0;
|
||||
if (isset($workflows)) {
|
||||
@@ -80,7 +81,8 @@ $nonce = SecurityHeadersMiddleware::getNonce();
|
||||
</div>
|
||||
|
||||
<!-- Transitions Table -->
|
||||
<table style="width: 100%;">
|
||||
<div class="table-wrapper">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>From Status</th>
|
||||
@@ -95,9 +97,7 @@ $nonce = SecurityHeadersMiddleware::getNonce();
|
||||
<tbody>
|
||||
<?php if (empty($workflows)): ?>
|
||||
<tr>
|
||||
<td colspan="7" style="text-align: center; padding: 2rem; color: var(--terminal-green-dim);">
|
||||
No transitions defined. Add transitions to enable status changes.
|
||||
</td>
|
||||
<td colspan="7" class="empty-state">No transitions defined. Add transitions to enable status changes.</td>
|
||||
</tr>
|
||||
<?php else: ?>
|
||||
<?php foreach ($workflows as $wf): ?>
|
||||
@@ -107,16 +107,16 @@ $nonce = SecurityHeadersMiddleware::getNonce();
|
||||
<?php echo htmlspecialchars($wf['from_status']); ?>
|
||||
</span>
|
||||
</td>
|
||||
<td style="text-align: center; color: var(--terminal-amber);">→</td>
|
||||
<td class="text-amber text-center">→</td>
|
||||
<td>
|
||||
<span class="status-<?php echo str_replace(' ', '-', strtolower($wf['to_status'])); ?>">
|
||||
<?php echo htmlspecialchars($wf['to_status']); ?>
|
||||
</span>
|
||||
</td>
|
||||
<td style="text-align: center;"><?php echo $wf['requires_comment'] ? '✓' : '−'; ?></td>
|
||||
<td style="text-align: center;"><?php echo $wf['requires_admin'] ? '✓' : '−'; ?></td>
|
||||
<td style="text-align: center;">
|
||||
<span style="color: <?php echo $wf['is_active'] ? 'var(--status-open)' : 'var(--status-closed)'; ?>;">
|
||||
<td class="text-center"><?php echo $wf['requires_comment'] ? '✓' : '−'; ?></td>
|
||||
<td class="text-center"><?php echo $wf['requires_admin'] ? '✓' : '−'; ?></td>
|
||||
<td class="text-center">
|
||||
<span class="<?php echo $wf['is_active'] ? 'text-open' : 'text-closed'; ?>">
|
||||
<?php echo $wf['is_active'] ? '✓' : '✗'; ?>
|
||||
</span>
|
||||
</td>
|
||||
@@ -129,16 +129,17 @@ $nonce = SecurityHeadersMiddleware::getNonce();
|
||||
<?php endif; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Create/Edit Modal -->
|
||||
<div class="lt-modal-overlay" id="workflowModal" aria-hidden="true">
|
||||
<div class="lt-modal" style="max-width: 450px;">
|
||||
<div class="lt-modal-overlay" id="workflowModal" aria-hidden="true" role="dialog" aria-modal="true" aria-labelledby="modalTitle">
|
||||
<div class="lt-modal lt-modal-sm">
|
||||
<div class="lt-modal-header">
|
||||
<span class="lt-modal-title" id="modalTitle">Create Transition</span>
|
||||
<button class="lt-modal-close" data-modal-close>✕</button>
|
||||
<button class="lt-modal-close" data-modal-close aria-label="Close">✕</button>
|
||||
</div>
|
||||
<form id="workflowForm">
|
||||
<input type="hidden" id="transition_id" name="transition_id">
|
||||
@@ -179,7 +180,6 @@ $nonce = SecurityHeadersMiddleware::getNonce();
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script nonce="<?php echo $nonce; ?>" src="<?php echo $GLOBALS['config']['ASSETS_URL']; ?>/js/toast.js"></script>
|
||||
<script nonce="<?php echo $nonce; ?>">
|
||||
const workflows = <?php echo json_encode($workflows ?? []); ?>;
|
||||
|
||||
@@ -232,25 +232,15 @@ $nonce = SecurityHeadersMiddleware::getNonce();
|
||||
is_active: document.getElementById('is_active').checked ? 1 : 0
|
||||
};
|
||||
|
||||
const method = data.transition_id ? 'PUT' : 'POST';
|
||||
const url = '/api/manage_workflows.php' + (data.transition_id ? '?id=' + data.transition_id : '');
|
||||
|
||||
fetch(url, {
|
||||
method: method,
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'X-CSRF-Token': window.CSRF_TOKEN
|
||||
},
|
||||
body: JSON.stringify(data)
|
||||
})
|
||||
.then(r => r.json())
|
||||
.then(result => {
|
||||
const apiCall = data.transition_id ? lt.api.put(url, data) : lt.api.post(url, data);
|
||||
apiCall.then(result => {
|
||||
if (result.success) {
|
||||
window.location.reload();
|
||||
} else {
|
||||
lt.toast.error(result.error || 'Failed to save');
|
||||
}
|
||||
});
|
||||
}).catch(err => lt.toast.error('Failed to save'));
|
||||
}
|
||||
|
||||
function editTransition(id) {
|
||||
@@ -268,14 +258,12 @@ $nonce = SecurityHeadersMiddleware::getNonce();
|
||||
}
|
||||
|
||||
function deleteTransition(id) {
|
||||
if (!confirm('Delete this status transition?')) return;
|
||||
fetch('/api/manage_workflows.php?id=' + id, {
|
||||
method: 'DELETE',
|
||||
headers: { 'X-CSRF-Token': window.CSRF_TOKEN }
|
||||
})
|
||||
.then(r => r.json())
|
||||
.then(data => {
|
||||
if (data.success) window.location.reload();
|
||||
showConfirmModal('Delete Transition', 'Delete this status transition?', 'error', function() {
|
||||
lt.api.delete('/api/manage_workflows.php?id=' + id)
|
||||
.then(data => {
|
||||
if (data.success) window.location.reload();
|
||||
else lt.toast.error(data.error || 'Failed to delete');
|
||||
}).catch(err => lt.toast.error('Failed to delete'));
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user