feat: Add 9 new features for enhanced UX and security

Quick Wins:
- Feature 1: Ticket linking in comments (#123456789 auto-links)
- Feature 6: Checkbox click area fix (click anywhere in cell)
- Feature 7: User groups display in settings modal

UI Enhancements:
- Feature 4: Collapsible sidebar with localStorage persistence
- Feature 5: Inline ticket preview popup on hover (300ms delay)
- Feature 2: Mobile responsive improvements (44px touch targets, iOS zoom fix)

Major Features:
- Feature 3: Kanban card view with status columns (toggle with localStorage)
- Feature 9: API key generation admin panel (/admin/api-keys)
- Feature 8: Ticket visibility levels (public/internal/confidential)

New files:
- views/admin/ApiKeysView.php
- api/generate_api_key.php
- api/revoke_api_key.php
- migrations/008_ticket_visibility.sql

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-23 10:01:50 -05:00
parent c32e9c871b
commit e86a5de3fd
19 changed files with 1933 additions and 39 deletions

View File

@@ -166,7 +166,51 @@
<!-- DIVIDER -->
<div class="ascii-divider"></div>
<!-- SECTION 5: Detailed Description -->
<!-- SECTION 5: Visibility Settings -->
<div class="ascii-section-header">Visibility Settings</div>
<div class="ascii-content">
<div class="ascii-frame-inner">
<div class="detail-group">
<label for="visibility">Ticket Visibility</label>
<select id="visibility" name="visibility" class="editable" onchange="toggleVisibilityGroups()">
<option value="public" selected>Public - All authenticated users</option>
<option value="internal">Internal - Specific groups only</option>
<option value="confidential">Confidential - Creator, assignee, admins only</option>
</select>
<p style="color: var(--terminal-green); font-size: 0.85rem; margin-top: 0.5rem; font-family: var(--font-mono);">
Controls who can view this ticket
</p>
</div>
<div id="visibilityGroupsContainer" class="detail-group" style="display: none; margin-top: 1rem;">
<label>Allowed Groups</label>
<div class="visibility-groups-list" style="display: flex; flex-wrap: wrap; gap: 0.75rem; margin-top: 0.5rem;">
<?php
// Get all available groups
require_once __DIR__ . '/../models/UserModel.php';
$userModel = new UserModel($conn);
$allGroups = $userModel->getAllGroups();
foreach ($allGroups as $group):
?>
<label style="display: flex; align-items: center; gap: 0.5rem; cursor: pointer;">
<input type="checkbox" name="visibility_groups[]" value="<?php echo htmlspecialchars($group); ?>" class="visibility-group-checkbox">
<span class="group-badge"><?php echo htmlspecialchars($group); ?></span>
</label>
<?php endforeach; ?>
<?php if (empty($allGroups)): ?>
<span style="color: var(--text-muted);">No groups available</span>
<?php endif; ?>
</div>
<p style="color: var(--terminal-amber); font-size: 0.85rem; margin-top: 0.5rem; font-family: var(--font-mono);">
Select which groups can view this ticket
</p>
</div>
</div>
</div>
<!-- DIVIDER -->
<div class="ascii-divider"></div>
<!-- SECTION 6: Detailed Description -->
<div class="ascii-section-header">Detailed Description</div>
<div class="ascii-content">
<div class="ascii-frame-inner">
@@ -251,6 +295,18 @@
div.textContent = text;
return div.innerHTML;
}
function toggleVisibilityGroups() {
const visibility = document.getElementById('visibility').value;
const groupsContainer = document.getElementById('visibilityGroupsContainer');
if (visibility === 'internal') {
groupsContainer.style.display = 'block';
} else {
groupsContainer.style.display = 'none';
// Uncheck all group checkboxes when hiding
document.querySelectorAll('.visibility-group-checkbox').forEach(cb => cb.checked = false);
}
}
</script>
</body>
</html>