Compare commits

..

4 Commits

Author SHA1 Message Date
ce95e555d5 CSS class migrations: admin views and boot overlay fade-out
- Replace style.display with .is-hidden classList in ApiKeysView, CustomFieldsView, RecurringTicketsView
- Convert boot overlay fade-out from style.opacity to .boot-overlay--fade-out CSS class
- Add .boot-overlay--fade-out rule to dashboard.css

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-20 21:20:55 -04:00
f45ec9b0f7 CSS class migrations in CreateTicketView: duplicate warning, visibility groups
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-20 21:18:16 -04:00
5a41ebf180 Convert ticket preview popup visibility to use .is-hidden CSS class
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-20 21:16:49 -04:00
e35401d54e CSS class migrations for ticket page: tabs, visibility, markdown preview, uploads
- Switch tab show/hide from style.display to .tab-content.active CSS class
- Convert visibilityGroupsField, markdownPreview, uploadProgress to use .is-hidden class
- Replace comment text div style.display with classList.add/remove('is-hidden')
- Add .is-hidden utility class to ticket.css

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-20 21:13:55 -04:00
10 changed files with 36 additions and 45 deletions

View File

@@ -2725,6 +2725,7 @@ input[type="checkbox"]:checked {
justify-content: center; justify-content: center;
transition: opacity 0.5s; transition: opacity 0.5s;
} }
.boot-overlay--fade-out { opacity: 0; }
#boot-text { #boot-text {
font-family: var(--font-mono); font-family: var(--font-mono);

View File

@@ -991,6 +991,7 @@ textarea.editable {
} }
.animate-fadein { animation: fadeIn 0.3s ease; } .animate-fadein { animation: fadeIn 0.3s ease; }
.is-hidden { display: none !important; }
.animate-fadeout { animation: fadeIn 0.2s ease reverse; } .animate-fadeout { animation: fadeIn 0.2s ease reverse; }
.comment--deleting { opacity: 0; transform: translateX(-20px); transition: opacity 0.3s, transform 0.3s; } .comment--deleting { opacity: 0; transform: translateX(-20px); transition: opacity 0.3s, transform 0.3s; }

View File

@@ -1451,8 +1451,7 @@ function initTicketPreview() {
// Create preview element // Create preview element
const preview = document.createElement('div'); const preview = document.createElement('div');
preview.id = 'ticketPreview'; preview.id = 'ticketPreview';
preview.className = 'ticket-preview-popup'; preview.className = 'ticket-preview-popup is-hidden';
preview.style.display = 'none';
document.body.appendChild(preview); document.body.appendChild(preview);
currentPreview = preview; currentPreview = preview;
@@ -1535,7 +1534,7 @@ function showTicketPreview(event) {
currentPreview.style.left = left + 'px'; currentPreview.style.left = left + 'px';
currentPreview.style.top = top + 'px'; currentPreview.style.top = top + 'px';
currentPreview.style.display = 'block'; currentPreview.classList.remove('is-hidden');
}, 300); }, 300);
} }
@@ -1545,7 +1544,7 @@ function hideTicketPreview() {
} }
previewTimeout = setTimeout(() => { previewTimeout = setTimeout(() => {
if (currentPreview) { if (currentPreview) {
currentPreview.style.display = 'none'; currentPreview.classList.add('is-hidden');
} }
}, 100); }, 100);
} }

View File

@@ -5,7 +5,7 @@ function toggleVisibilityGroupsEdit() {
const visibility = document.getElementById('visibilitySelect')?.value; const visibility = document.getElementById('visibilitySelect')?.value;
const groupsField = document.getElementById('visibilityGroupsField'); const groupsField = document.getElementById('visibilityGroupsField');
if (groupsField) { if (groupsField) {
groupsField.style.display = visibility === 'internal' ? 'block' : 'none'; groupsField.classList.toggle('is-hidden', visibility !== 'internal');
} }
} }
@@ -201,7 +201,7 @@ function togglePreview() {
if (!preview || !textarea || !toggleEl) return; if (!preview || !textarea || !toggleEl) return;
const isPreviewEnabled = toggleEl.checked; const isPreviewEnabled = toggleEl.checked;
preview.style.display = isPreviewEnabled ? 'block' : 'none'; preview.classList.toggle('is-hidden', !isPreviewEnabled);
if (isPreviewEnabled) { if (isPreviewEnabled) {
preview.innerHTML = parseMarkdown(textarea.value); preview.innerHTML = parseMarkdown(textarea.value);
@@ -222,9 +222,9 @@ function updatePreview() {
if (isMarkdownEnabled && commentText.trim()) { if (isMarkdownEnabled && commentText.trim()) {
previewDiv.innerHTML = parseMarkdown(commentText); previewDiv.innerHTML = parseMarkdown(commentText);
previewDiv.style.display = 'block'; previewDiv.classList.remove('is-hidden');
} else { } else {
previewDiv.style.display = 'none'; previewDiv.classList.add('is-hidden');
} }
} }
@@ -238,7 +238,7 @@ function toggleMarkdownMode() {
if (!isMasterEnabled) { if (!isMasterEnabled) {
previewToggle.checked = false; previewToggle.checked = false;
const preview = document.getElementById('markdownPreview'); const preview = document.getElementById('markdownPreview');
if (preview) preview.style.display = 'none'; if (preview) preview.classList.add('is-hidden');
} }
} }
@@ -450,17 +450,7 @@ function showTab(tabName) {
} }
// Hide all tabs // Hide all tabs
descriptionTab.style.display = 'none'; document.querySelectorAll('.tab-content').forEach(tab => tab.classList.remove('active'));
commentsTab.style.display = 'none';
if (attachmentsTab) {
attachmentsTab.style.display = 'none';
}
if (dependenciesTab) {
dependenciesTab.style.display = 'none';
}
if (activityTab) {
activityTab.style.display = 'none';
}
// Remove active class and aria-selected from all buttons // Remove active class and aria-selected from all buttons
document.querySelectorAll('.tab-btn').forEach(btn => { document.querySelectorAll('.tab-btn').forEach(btn => {
@@ -470,7 +460,7 @@ function showTab(tabName) {
// Show selected tab and activate its button // Show selected tab and activate its button
const tabEl = document.getElementById(`${tabName}-tab`); const tabEl = document.getElementById(`${tabName}-tab`);
if (tabEl) tabEl.style.display = 'block'; if (tabEl) tabEl.classList.add('active');
const activeBtn = document.querySelector(`.tab-btn[data-tab="${tabName}"]`); const activeBtn = document.querySelector(`.tab-btn[data-tab="${tabName}"]`);
if (activeBtn) { if (activeBtn) {
activeBtn.classList.add('active'); activeBtn.classList.add('active');
@@ -713,7 +703,7 @@ function handleFileUpload(files) {
let uploadedCount = 0; let uploadedCount = 0;
const totalFiles = files.length; const totalFiles = files.length;
progressDiv.style.display = 'block'; progressDiv.classList.remove('is-hidden');
statusText.textContent = `Uploading 0 of ${totalFiles} files...`; statusText.textContent = `Uploading 0 of ${totalFiles} files...`;
progressFill.style.width = '0%'; progressFill.style.width = '0%';
@@ -779,7 +769,7 @@ function resetUploadUI() {
const progressDiv = document.getElementById('uploadProgress'); const progressDiv = document.getElementById('uploadProgress');
const fileInput = document.getElementById('fileInput'); const fileInput = document.getElementById('fileInput');
progressDiv.style.display = 'none'; progressDiv.classList.add('is-hidden');
if (fileInput) { if (fileInput) {
fileInput.value = ''; fileInput.value = '';
} }
@@ -1181,7 +1171,7 @@ function editComment(commentId) {
`; `;
// Hide original text, show edit form // Hide original text, show edit form
textDiv.style.display = 'none'; textDiv.classList.add('is-hidden');
textDiv.after(editForm); textDiv.after(editForm);
commentDiv.classList.add('editing'); commentDiv.classList.add('editing');
@@ -1248,7 +1238,7 @@ function saveEditComment(commentId) {
// Remove edit form and show text // Remove edit form and show text
if (editForm) editForm.remove(); if (editForm) editForm.remove();
textDiv.style.display = ''; textDiv.classList.remove('is-hidden');
commentDiv.classList.remove('editing'); commentDiv.classList.remove('editing');
lt.toast.success('Comment updated successfully'); lt.toast.success('Comment updated successfully');
@@ -1270,7 +1260,7 @@ function cancelEditComment(commentId) {
const editForm = document.getElementById(`comment-edit-form-${commentId}`); const editForm = document.getElementById(`comment-edit-form-${commentId}`);
if (editForm) editForm.remove(); if (editForm) editForm.remove();
if (textDiv) textDiv.style.display = ''; if (textDiv) textDiv.classList.remove('is-hidden');
if (commentDiv) commentDiv.classList.remove('editing'); if (commentDiv) commentDiv.classList.remove('editing');
} }

View File

@@ -109,7 +109,7 @@ $nonce = SecurityHeadersMiddleware::getNonce();
<input type="text" id="title" name="title" class="editable" required placeholder="Enter a descriptive title for this ticket"> <input type="text" id="title" name="title" class="editable" required placeholder="Enter a descriptive title for this ticket">
</div> </div>
<!-- Duplicate Warning Area --> <!-- Duplicate Warning Area -->
<div id="duplicateWarning" class="inline-warning" role="alert" aria-live="polite" aria-atomic="true" style="display: none;"> <div id="duplicateWarning" class="inline-warning is-hidden" role="alert" aria-live="polite" aria-atomic="true">
<div class="text-amber fw-bold duplicate-heading"> <div class="text-amber fw-bold duplicate-heading">
Possible Duplicates Found Possible Duplicates Found
</div> </div>
@@ -210,7 +210,7 @@ $nonce = SecurityHeadersMiddleware::getNonce();
Controls who can view this ticket Controls who can view this ticket
</p> </p>
</div> </div>
<div id="visibilityGroupsContainer" class="detail-group" style="display: none;"> <div id="visibilityGroupsContainer" class="detail-group is-hidden">
<label>Allowed Groups</label> <label>Allowed Groups</label>
<div class="visibility-groups-list"> <div class="visibility-groups-list">
<?php <?php
@@ -277,7 +277,7 @@ $nonce = SecurityHeadersMiddleware::getNonce();
const title = this.value.trim(); const title = this.value.trim();
if (title.length < 5) { if (title.length < 5) {
document.getElementById('duplicateWarning').style.display = 'none'; document.getElementById('duplicateWarning').classList.add('is-hidden');
return; return;
} }
@@ -308,9 +308,9 @@ $nonce = SecurityHeadersMiddleware::getNonce();
html += '<p class="duplicate-hint">Consider checking these tickets before creating a new one.</p>'; html += '<p class="duplicate-hint">Consider checking these tickets before creating a new one.</p>';
listDiv.innerHTML = html; listDiv.innerHTML = html;
warningDiv.style.display = 'block'; warningDiv.classList.remove('is-hidden');
} else { } else {
warningDiv.style.display = 'none'; warningDiv.classList.add('is-hidden');
} }
}) })
.catch(error => { .catch(error => {
@@ -322,9 +322,9 @@ $nonce = SecurityHeadersMiddleware::getNonce();
const visibility = document.getElementById('visibility').value; const visibility = document.getElementById('visibility').value;
const groupsContainer = document.getElementById('visibilityGroupsContainer'); const groupsContainer = document.getElementById('visibilityGroupsContainer');
if (visibility === 'internal') { if (visibility === 'internal') {
groupsContainer.style.display = 'block'; groupsContainer.classList.remove('is-hidden');
} else { } else {
groupsContainer.style.display = 'none'; groupsContainer.classList.add('is-hidden');
document.querySelectorAll('.visibility-group-checkbox').forEach(cb => cb.checked = false); document.querySelectorAll('.visibility-group-checkbox').forEach(cb => cb.checked = false);
} }
} }

View File

@@ -63,7 +63,7 @@ $nonce = SecurityHeadersMiddleware::getNonce();
i++; i++;
} else { } else {
setTimeout(() => { setTimeout(() => {
bootOverlay.style.opacity = '0'; bootOverlay.classList.add('boot-overlay--fade-out');
setTimeout(() => bootOverlay.remove(), 500); setTimeout(() => bootOverlay.remove(), 500);
}, 500); }, 500);
clearInterval(interval); clearInterval(interval);

View File

@@ -222,7 +222,7 @@ $nonce = SecurityHeadersMiddleware::getNonce();
<option value="confidential" <?php echo $currentVisibility == 'confidential' ? 'selected' : ''; ?>>Confidential</option> <option value="confidential" <?php echo $currentVisibility == 'confidential' ? 'selected' : ''; ?>>Confidential</option>
</select> </select>
</div> </div>
<div class="metadata-field" id="visibilityGroupsField" <?php echo $currentVisibility !== 'internal' ? 'style="display: none;"' : ''; ?>> <div class="metadata-field<?php echo $currentVisibility !== 'internal' ? ' is-hidden' : ''; ?>" id="visibilityGroupsField">
<label class="metadata-label metadata-label-cyan">Allowed Groups:</label> <label class="metadata-label metadata-label-cyan">Allowed Groups:</label>
<div class="visibility-groups-edit"> <div class="visibility-groups-edit">
<?php foreach ($allAvailableGroups as $group): <?php foreach ($allAvailableGroups as $group):
@@ -326,7 +326,7 @@ $nonce = SecurityHeadersMiddleware::getNonce();
</div> </div>
<button id="addCommentBtn" class="btn">ADD COMMENT</button> <button id="addCommentBtn" class="btn">ADD COMMENT</button>
</div> </div>
<div id="markdownPreview" class="markdown-preview" style="display: none;"></div> <div id="markdownPreview" class="markdown-preview is-hidden"></div>
</div> </div>
</div> </div>
@@ -430,7 +430,7 @@ $nonce = SecurityHeadersMiddleware::getNonce();
<button type="button" id="browseFilesBtn" class="btn upload-browse-btn">BROWSE FILES</button> <button type="button" id="browseFilesBtn" class="btn upload-browse-btn">BROWSE FILES</button>
</div> </div>
</div> </div>
<div id="uploadProgress" class="upload-progress" style="display: none;"> <div id="uploadProgress" class="upload-progress is-hidden">
<div class="progress-bar"> <div class="progress-bar">
<div class="progress-fill" id="progressFill"></div> <div class="progress-fill" id="progressFill"></div>
</div> </div>

View File

@@ -66,7 +66,7 @@ $nonce = SecurityHeadersMiddleware::getNonce();
</div> </div>
<!-- New Key Display (hidden by default) --> <!-- New Key Display (hidden by default) -->
<div id="newKeyDisplay" class="ascii-frame-inner key-generated-alert" style="display: none;"> <div id="newKeyDisplay" class="ascii-frame-inner key-generated-alert is-hidden">
<h3 class="admin-section-title">New API Key Generated</h3> <h3 class="admin-section-title">New API Key Generated</h3>
<p class="text-danger text-sm mb-1"> <p class="text-danger text-sm mb-1">
Copy this key now. You won't be able to see it again! Copy this key now. You won't be able to see it again!
@@ -195,7 +195,7 @@ $nonce = SecurityHeadersMiddleware::getNonce();
if (data.success) { if (data.success) {
// Show the new key // Show the new key
document.getElementById('newKeyValue').value = data.api_key; document.getElementById('newKeyValue').value = data.api_key;
document.getElementById('newKeyDisplay').style.display = 'block'; document.getElementById('newKeyDisplay').classList.remove('is-hidden');
document.getElementById('keyName').value = ''; document.getElementById('keyName').value = '';
lt.toast.success('API key generated successfully'); lt.toast.success('API key generated successfully');

View File

@@ -123,7 +123,7 @@ $nonce = SecurityHeadersMiddleware::getNonce();
<option value="number">Number</option> <option value="number">Number</option>
</select> </select>
</div> </div>
<div class="setting-row" id="options_row" style="display: none;"> <div class="setting-row is-hidden" id="options_row">
<label for="field_options">Options (one per line)</label> <label for="field_options">Options (one per line)</label>
<textarea id="field_options" name="field_options" rows="4" placeholder="Option 1&#10;Option 2&#10;Option 3"></textarea> <textarea id="field_options" name="field_options" rows="4" placeholder="Option 1&#10;Option 2&#10;Option 3"></textarea>
</div> </div>
@@ -208,7 +208,7 @@ $nonce = SecurityHeadersMiddleware::getNonce();
function toggleOptionsField() { function toggleOptionsField() {
const type = document.getElementById('field_type').value; const type = document.getElementById('field_type').value;
document.getElementById('options_row').style.display = type === 'select' ? 'block' : 'none'; document.getElementById('options_row').classList.toggle('is-hidden', type !== 'select');
} }
function saveField(e) { function saveField(e) {

View File

@@ -135,7 +135,7 @@ $nonce = SecurityHeadersMiddleware::getNonce();
<option value="monthly">Monthly</option> <option value="monthly">Monthly</option>
</select> </select>
</div> </div>
<div class="setting-row" id="schedule_day_row" style="display: none;"> <div class="setting-row is-hidden" id="schedule_day_row">
<label for="schedule_day">Schedule Day</label> <label for="schedule_day">Schedule Day</label>
<select id="schedule_day" name="schedule_day"></select> <select id="schedule_day" name="schedule_day"></select>
</div> </div>
@@ -251,15 +251,15 @@ $nonce = SecurityHeadersMiddleware::getNonce();
daySelect.innerHTML = ''; daySelect.innerHTML = '';
if (type === 'daily') { if (type === 'daily') {
dayRow.style.display = 'none'; dayRow.classList.add('is-hidden');
} else if (type === 'weekly') { } else if (type === 'weekly') {
dayRow.style.display = 'flex'; dayRow.classList.remove('is-hidden');
const days = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday']; const days = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'];
days.forEach((day, i) => { days.forEach((day, i) => {
daySelect.innerHTML += `<option value="${i + 1}">${day}</option>`; daySelect.innerHTML += `<option value="${i + 1}">${day}</option>`;
}); });
} else if (type === 'monthly') { } else if (type === 'monthly') {
dayRow.style.display = 'flex'; dayRow.classList.remove('is-hidden');
for (let i = 1; i <= 28; i++) { for (let i = 1; i <= 28; i++) {
daySelect.innerHTML += `<option value="${i}">Day ${i}</option>`; daySelect.innerHTML += `<option value="${i}">Day ${i}</option>`;
} }