Add command palette (Ctrl+K / Cmd+K) globally
Adds lt-cmd-overlay HTML to layout_header.php and initializes lt.cmdPalette with commands for: navigation (Dashboard, New Ticket), filters (My Tickets, Unassigned, P1 Critical), admin pages (if admin), and recent tickets (last 5 viewed, stored in localStorage). TicketView.php records each viewed ticket ID to localStorage under lt_recent_tickets so the command palette can surface them as Recent. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -206,4 +206,60 @@ $_lt_assetVer = $GLOBALS['config']['ASSET_VERSION'] ?? '20260329';
|
||||
|
||||
</header><!-- /.lt-header -->
|
||||
|
||||
<!-- ── COMMAND PALETTE OVERLAY (Ctrl+K / ⌘K) ──────────────────── -->
|
||||
<div id="lt-cmd-overlay" class="lt-cmd-overlay" role="dialog" aria-modal="true" aria-label="Command palette" aria-hidden="true">
|
||||
<div id="lt-cmd-palette" class="lt-cmd-palette" role="combobox" aria-expanded="true" aria-haspopup="listbox">
|
||||
<div class="lt-cmd-input-wrap">
|
||||
<span aria-hidden="true" style="opacity:0.45;margin-right:0.4rem;font-size:0.9em">⌕</span>
|
||||
<input class="lt-cmd-input" type="text" placeholder="Type a command or search…"
|
||||
autocomplete="off" spellcheck="false" aria-label="Command search" aria-autocomplete="list"
|
||||
aria-controls="lt-cmd-results-list">
|
||||
<kbd style="font-size:0.6rem;opacity:0.4;white-space:nowrap">ESC</kbd>
|
||||
</div>
|
||||
<div class="lt-cmd-results" id="lt-cmd-results-list" role="listbox"></div>
|
||||
</div>
|
||||
</div>
|
||||
<script nonce="<?= htmlspecialchars($nonce, ENT_QUOTES, 'UTF-8') ?>">
|
||||
(function() {
|
||||
var isAdmin = <?= json_encode($_lt_isAdmin) ?>;
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
var commands = [
|
||||
{ id: 'nav-dashboard', label: 'Dashboard', icon: '⌂', group: 'Navigate', action: function(){ location.href = '/'; } },
|
||||
{ id: 'nav-new-ticket', label: 'New Ticket', icon: '+', group: 'Navigate', kbd: 'N', action: function(){ location.href = '/create'; } },
|
||||
{ id: 'filter-mine', label: 'My Open Tickets', icon: '◈', group: 'Filter', action: function(){ location.href = '/?assigned_to=me&status=Open,In+Progress,Pending'; } },
|
||||
{ id: 'filter-unassigned', label: 'Unassigned Tickets', icon: '◌', group: 'Filter', action: function(){ location.href = '/?assigned_to=none'; } },
|
||||
{ id: 'filter-critical', label: 'P1 Critical Tickets', icon: '!', group: 'Filter', action: function(){ location.href = '/?priority=1'; } },
|
||||
];
|
||||
if (isAdmin) {
|
||||
[
|
||||
{ id: 'admin-templates', label: 'Admin: Templates', icon: '▤', href: '/admin/templates' },
|
||||
{ id: 'admin-workflow', label: 'Admin: Workflow', icon: '⇌', href: '/admin/workflow' },
|
||||
{ id: 'admin-audit', label: 'Admin: Audit Log', icon: '📋', href: '/admin/audit-log' },
|
||||
{ id: 'admin-api-keys', label: 'Admin: API Keys', icon: '🔑', href: '/admin/api-keys' },
|
||||
{ id: 'admin-users', label: 'Admin: User Activity', icon: '👤', href: '/admin/user-activity' },
|
||||
{ id: 'admin-recurring', label: 'Admin: Recurring', icon: '↻', href: '/admin/recurring-tickets' },
|
||||
{ id: 'admin-fields', label: 'Admin: Custom Fields', icon: '⊞', href: '/admin/custom-fields' },
|
||||
].forEach(function(c) {
|
||||
commands.push({ id: c.id, label: c.label, icon: c.icon, group: 'Admin', action: function(href){ return function(){ location.href = href; }; }(c.href) });
|
||||
});
|
||||
}
|
||||
// Inject recent ticket IDs from localStorage
|
||||
try {
|
||||
var recent = JSON.parse(localStorage.getItem('lt_recent_tickets') || '[]');
|
||||
recent.slice(0, 5).forEach(function(id) {
|
||||
commands.push({ id: 'recent-' + id, label: 'Ticket #' + id, icon: '◷', group: 'Recent', tags: ['ticket'], action: function(tid){ return function(){ location.href = '/ticket/' + tid; }; }(id) });
|
||||
});
|
||||
} catch(_) {}
|
||||
if (window.lt && lt.cmdPalette) lt.cmdPalette.init(commands);
|
||||
});
|
||||
// Keyboard shortcut: Ctrl+K / Cmd+K
|
||||
document.addEventListener('keydown', function(e) {
|
||||
if ((e.ctrlKey || e.metaKey) && e.key === 'k') {
|
||||
e.preventDefault();
|
||||
if (window.lt && lt.cmdPalette) lt.cmdPalette.open();
|
||||
}
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
|
||||
<main class="lt-main lt-container" id="main-content" style="padding-top: calc(var(--header-height, 56px) + var(--space-lg, 1.5rem))">
|
||||
|
||||
Reference in New Issue
Block a user