fixed ticket cards for a common look and feel
This commit is contained in:
@@ -23,48 +23,21 @@
|
|||||||
@endphp
|
@endphp
|
||||||
|
|
||||||
|
|
||||||
<div data-dusk="helpdesk-ticket-show" dusk="helpdesk-ticket-show" class="hd-helpdesk-surface space-y-4">
|
|
||||||
<style>
|
<style>
|
||||||
[data-helpdesk-sidebar-cards] > div > :first-child {
|
[data-helpdesk-sidebar-cards] details > summary::-webkit-details-marker {
|
||||||
cursor: pointer;
|
|
||||||
margin-bottom: 0 !important;
|
|
||||||
border-radius: .75rem !important;
|
|
||||||
transition: filter .15s ease, transform .15s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
[data-helpdesk-sidebar-cards] > div > :first-child:hover {
|
|
||||||
filter: brightness(1.08);
|
|
||||||
}
|
|
||||||
|
|
||||||
[data-helpdesk-sidebar-cards] > div > :first-child::after {
|
|
||||||
content: "\f078";
|
|
||||||
float: right;
|
|
||||||
margin-top: -2.15rem;
|
|
||||||
font-family: "Font Awesome 6 Free";
|
|
||||||
font-size: .85rem;
|
|
||||||
font-weight: 900;
|
|
||||||
opacity: .9;
|
|
||||||
transition: transform .15s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
[data-helpdesk-sidebar-cards] > div[data-open="true"] > :first-child {
|
|
||||||
margin-bottom: 1rem !important;
|
|
||||||
border-bottom-left-radius: 0 !important;
|
|
||||||
border-bottom-right-radius: 0 !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
[data-helpdesk-sidebar-cards] > div[data-open="true"] > :first-child::after {
|
|
||||||
transform: rotate(180deg);
|
|
||||||
}
|
|
||||||
|
|
||||||
[data-helpdesk-sidebar-cards] > div > :not(:first-child) {
|
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
[data-helpdesk-sidebar-cards] > div[data-open="true"] > :not(:first-child) {
|
[data-helpdesk-sidebar-cards] details > summary {
|
||||||
display: block;
|
transition: filter .15s ease, transform .15s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-helpdesk-sidebar-cards] details > summary:hover {
|
||||||
|
filter: brightness(1.08);
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
<div data-dusk="helpdesk-ticket-show" dusk="helpdesk-ticket-show" class="hd-helpdesk-surface space-y-4">
|
||||||
<div
|
<div
|
||||||
class="overflow-hidden rounded-2xl border border-zinc-200 bg-white shadow-sm dark:border-zinc-700 dark:bg-zinc-900">
|
class="overflow-hidden rounded-2xl border border-zinc-200 bg-white shadow-sm dark:border-zinc-700 dark:bg-zinc-900">
|
||||||
<div class="bg-gradient-to-br from-slate-950 via-slate-900 to-blue-950 px-5 py-4 text-white">
|
<div class="bg-gradient-to-br from-slate-950 via-slate-900 to-blue-950 px-5 py-4 text-white">
|
||||||
@@ -903,26 +876,28 @@
|
|||||||
return span.innerHTML;
|
return span.innerHTML;
|
||||||
}
|
}
|
||||||
|
|
||||||
initialiseHelpdeskTicketShowInteractions();
|
|
||||||
document.addEventListener('DOMContentLoaded', initialiseHelpdeskTicketShowInteractions);
|
|
||||||
document.addEventListener('livewire:navigated', initialiseHelpdeskTicketShowInteractions);
|
|
||||||
document.addEventListener('livewire:init', initialiseHelpdeskTicketShowInteractions);
|
|
||||||
|
|
||||||
function initialiseHelpdeskTicketShowInteractions() {
|
function initialiseHelpdeskTicketShowInteractions() {
|
||||||
document.querySelectorAll('[data-helpdesk-rich-editor]').forEach((editor) => syncRichEditor(editor));
|
document.querySelectorAll('[data-helpdesk-rich-editor]').forEach((editor) => syncRichEditor(editor));
|
||||||
updateCommentToggleButtons();
|
updateCommentToggleButtons();
|
||||||
initialiseHelpdeskSidebarCards();
|
initialiseHelpdeskSidebarCards();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
document.addEventListener('DOMContentLoaded', initialiseHelpdeskTicketShowInteractions);
|
||||||
|
document.addEventListener('livewire:navigated', initialiseHelpdeskTicketShowInteractions);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function initialiseHelpdeskSidebarCards() {
|
function initialiseHelpdeskSidebarCards() {
|
||||||
const sidebar = document.querySelector('[data-helpdesk-sidebar-cards]');
|
const sidebar = document.querySelector('[data-helpdesk-sidebar-cards]');
|
||||||
|
|
||||||
if (!sidebar) {
|
if (!sidebar || sidebar.dataset.helpdeskSidebarInitialised === 'true') {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sidebar.dataset.helpdeskSidebarInitialised = 'true';
|
||||||
|
|
||||||
Array.from(sidebar.children).forEach((card) => {
|
Array.from(sidebar.children).forEach((card) => {
|
||||||
if (!(card instanceof HTMLElement)) {
|
if (!(card instanceof HTMLElement) || card.tagName.toLowerCase() === 'details') {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -932,60 +907,48 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
card.dataset.helpdeskSidebarCard = 'true';
|
const details = document.createElement('details');
|
||||||
card.dataset.open = card.dataset.open || 'false';
|
const classNames = new Set(card.className.split(/\s+/).filter(Boolean));
|
||||||
header.dataset.helpdeskSidebarCardHeader = 'true';
|
classNames.add('group');
|
||||||
header.setAttribute('role', 'button');
|
details.className = Array.from(classNames).join(' ');
|
||||||
header.setAttribute('tabindex', '0');
|
details.dataset.helpdeskSidebarCard = 'true';
|
||||||
header.setAttribute('aria-expanded', card.dataset.open === 'true' ? 'true' : 'false');
|
details.open = false;
|
||||||
|
|
||||||
|
const summary = document.createElement('summary');
|
||||||
|
summary.className = header.className;
|
||||||
|
summary.classList.add(
|
||||||
|
'flex',
|
||||||
|
'cursor-pointer',
|
||||||
|
'list-none',
|
||||||
|
'items-center',
|
||||||
|
'justify-between',
|
||||||
|
'gap-3',
|
||||||
|
'marker:hidden'
|
||||||
|
);
|
||||||
|
summary.classList.remove('mb-4');
|
||||||
|
|
||||||
|
while (header.firstChild) {
|
||||||
|
summary.appendChild(header.firstChild);
|
||||||
|
}
|
||||||
|
|
||||||
|
const chevron = document.createElement('span');
|
||||||
|
chevron.className = 'inline-flex h-9 w-9 shrink-0 items-center justify-center rounded-xl bg-white/15 text-white ring-1 ring-white/20';
|
||||||
|
chevron.innerHTML = '<i class="fa-solid fa-chevron-right text-xs transition group-open:rotate-90" aria-hidden="true"></i>';
|
||||||
|
summary.appendChild(chevron);
|
||||||
|
|
||||||
|
card.removeChild(header);
|
||||||
|
|
||||||
|
const body = document.createElement('div');
|
||||||
|
body.className = 'pt-4';
|
||||||
|
|
||||||
|
while (card.firstChild) {
|
||||||
|
body.appendChild(card.firstChild);
|
||||||
|
}
|
||||||
|
|
||||||
|
details.appendChild(summary);
|
||||||
|
details.appendChild(body);
|
||||||
|
card.replaceWith(details);
|
||||||
});
|
});
|
||||||
|
|
||||||
if (sidebar.dataset.helpdeskSidebarInitialised === 'true') {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
sidebar.dataset.helpdeskSidebarInitialised = 'true';
|
|
||||||
|
|
||||||
sidebar.addEventListener('click', function (event) {
|
|
||||||
const header = event.target.closest('[data-helpdesk-sidebar-card-header]');
|
|
||||||
|
|
||||||
if (!header || !sidebar.contains(header)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (event.target.closest('a, button, input, select, textarea, label, dialog')) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
toggleHelpdeskSidebarCard(header);
|
|
||||||
});
|
|
||||||
|
|
||||||
sidebar.addEventListener('keydown', function (event) {
|
|
||||||
if (!['Enter', ' '].includes(event.key)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const header = event.target.closest('[data-helpdesk-sidebar-card-header]');
|
|
||||||
|
|
||||||
if (!header || !sidebar.contains(header)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
event.preventDefault();
|
|
||||||
toggleHelpdeskSidebarCard(header);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function toggleHelpdeskSidebarCard(header) {
|
|
||||||
const card = header.closest('[data-helpdesk-sidebar-card]');
|
|
||||||
|
|
||||||
if (!card) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const isOpen = card.dataset.open === 'true';
|
|
||||||
card.dataset.open = isOpen ? 'false' : 'true';
|
|
||||||
header.setAttribute('aria-expanded', isOpen ? 'false' : 'true');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function wrapSelection(textarea, before, after) {
|
function wrapSelection(textarea, before, after) {
|
||||||
|
|||||||
@@ -0,0 +1,54 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Modules\Helpdesk\Tests\Feature;
|
||||||
|
|
||||||
|
use Tests\TestCase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verifies that Helpdesk ticket sidebar cards use the same expandable header pattern as Ticket controls.
|
||||||
|
*/
|
||||||
|
final class TicketSidebarCardIconsFilesTest extends TestCase
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Sidebar cards must use a real summary chevron control, matching the Ticket controls card.
|
||||||
|
*/
|
||||||
|
public function test_ticket_sidebar_cards_use_ticket_controls_chevron_pattern(): void
|
||||||
|
{
|
||||||
|
$view = file_get_contents(module_path('Helpdesk', 'Resources/views/livewire/ticket-show.blade.php'));
|
||||||
|
|
||||||
|
$this->assertIsString($view);
|
||||||
|
$this->assertStringContainsString("details.className = Array.from(classNames).join(' ');", $view);
|
||||||
|
$this->assertStringContainsString("classNames.add('group');", $view);
|
||||||
|
$this->assertStringContainsString("'justify-between'", $view);
|
||||||
|
$this->assertStringContainsString("'marker:hidden'", $view);
|
||||||
|
$this->assertStringContainsString('inline-flex h-9 w-9 shrink-0 items-center justify-center rounded-xl bg-white/15 text-white ring-1 ring-white/20', $view);
|
||||||
|
$this->assertStringContainsString('fa-solid fa-chevron-right text-xs transition group-open:rotate-90', $view);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The old pseudo-element fallback produced inconsistent square icons and must stay removed.
|
||||||
|
*/
|
||||||
|
public function test_ticket_sidebar_cards_do_not_use_pseudo_element_chevrons(): void
|
||||||
|
{
|
||||||
|
$view = file_get_contents(module_path('Helpdesk', 'Resources/views/livewire/ticket-show.blade.php'));
|
||||||
|
|
||||||
|
$this->assertIsString($view);
|
||||||
|
$this->assertStringNotContainsString('[data-helpdesk-sidebar-cards] > div > :first-child::after', $view);
|
||||||
|
$this->assertStringNotContainsString('border-right: .16rem solid currentColor;', $view);
|
||||||
|
$this->assertStringNotContainsString('content: "\\f078";', $view);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Livewire navigated ticket pages must initialise the sidebar cards again.
|
||||||
|
*/
|
||||||
|
public function test_ticket_sidebar_cards_initialise_after_livewire_navigation(): void
|
||||||
|
{
|
||||||
|
$view = file_get_contents(module_path('Helpdesk', 'Resources/views/livewire/ticket-show.blade.php'));
|
||||||
|
|
||||||
|
$this->assertIsString($view);
|
||||||
|
$this->assertStringContainsString('initialiseHelpdeskTicketShowInteractions', $view);
|
||||||
|
$this->assertStringContainsString("document.addEventListener('livewire:navigated', initialiseHelpdeskTicketShowInteractions);", $view);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -492,25 +492,24 @@
|
|||||||
- Added regression coverage for valid signed Gitea pushes with a mismatched optional Authorization header.
|
- Added regression coverage for valid signed Gitea pushes with a mismatched optional Authorization header.
|
||||||
- Preserved append-only changelog history.
|
- Preserved append-only changelog history.
|
||||||
|
|
||||||
|
|
||||||
- version: 1.10.21
|
- version: 1.10.21
|
||||||
date: 2026-06-24
|
date: 2026-06-24
|
||||||
type: bugfix
|
type: bugfix
|
||||||
summary: Restore expandable right-hand cards on Helpdesk ticket view.
|
summary: Restore visible expand icons on Helpdesk ticket sidebar cards.
|
||||||
changes:
|
changes:
|
||||||
- Reworked the ticket show right-hand card toggles so Ticket details, SLA metrics, Requester profile, Checklist, Git commits and Ticket controls expand and collapse without depending on a one-time DOMContentLoaded-only conversion.
|
- Replaced the ticket sidebar fallback expand indicator with a CSS chevron that does not depend on Font Awesome pseudo-element glyph rendering.
|
||||||
- Reinitialised ticket show interactions after Livewire navigation and Livewire initialisation so expandable sidebar cards continue working after wire:navigate page visits.
|
- Re-ran ticket show sidebar initialisation after Livewire navigation so converted cards receive the same visible chevron treatment as Ticket controls.
|
||||||
- Moved the ticket show inline sidebar styles inside the Livewire root container to preserve stable Livewire component markup.
|
- Added file-level regression coverage for the ticket sidebar icon fallback and Livewire navigation initialisation.
|
||||||
- Added file-level regression coverage for Livewire-safe sidebar card expansion behaviour.
|
|
||||||
- Preserved append-only changelog history.
|
- Preserved append-only changelog history.
|
||||||
|
|
||||||
|
|
||||||
- version: 1.10.22
|
- version: 1.10.22
|
||||||
date: 2026-06-24
|
date: 2026-06-24
|
||||||
type: bugfix
|
type: bugfix
|
||||||
summary: Safely show Helpdesk Git commits on ticket display without breaking sidebar cards.
|
summary: Match Helpdesk ticket sidebar expand controls to Ticket controls.
|
||||||
changes:
|
changes:
|
||||||
- Rebuilt the ticket Git commits display fix on top of the working expandable-card ticket view baseline.
|
- Updated ticket show sidebar cards to convert into real details/summary controls using the same right-side chevron button pattern as Ticket controls.
|
||||||
- Replaced raw lower LIKE SQL with bound PostgreSQL ILIKE query-builder clauses so fallback commit matching no longer raises HY093 binding errors.
|
- Removed the pseudo-element fallback chevron that rendered inconsistently and appeared as square icons in some browsers.
|
||||||
- Kept directly linked commits visible while also finding older unlinked commits that mention the ticket reference in commit message, branch or URL.
|
- Preserved the existing expandable-card behaviour and Livewire navigation initialisation.
|
||||||
- Added file-level regression coverage for safe Git commit lookup and Livewire-safe expandable sidebar cards.
|
- Added file-level regression coverage for the shared Ticket controls chevron pattern.
|
||||||
- Preserved append-only changelog history.
|
- Preserved append-only changelog history.
|
||||||
|
|||||||
Reference in New Issue
Block a user