+
+
+
+
+
-
-
-
Work timer
-
- Start a user-specific timer. It remains active if the browser is closed.
+
+ Ticket timer
+
+
+
+ Record focused work against this ticket.
-
- @if ($hasRunningTimer)
-
- @else
-
- @endif
- @if ($message)
-
- {{ $message }}
+ @if ($hasRunningTimer)
+
+
+
+ Running
+
+
+
+ {{ gmdate('H:i:s', max(0, (int) $elapsedSeconds)) }}
+
+
+
+ Started {{ $startedAtDisplay }}
+
@endif
+
- @error('timer')
-
- {{ $message }}
-
- @enderror
-
-
-
- Timer note
-
-
-
+ @if ($message)
+
+ {{ $message }}
+ @endif
-
- @if ($hasRunningTimer)
-
-
- End timer
- Ending...
-
- @else
-
-
- Start timer
- Starting...
-
- @endif
+ @error('timer')
+
+ {{ $message }}
+ @enderror
+
+
+
+ Timer note
+
+
+
+
+
+
+
+ {{ $hasRunningTimer ? 'End the timer to add the elapsed time to the ticket.' : 'Start a timer when work begins. Only one active timer is allowed.' }}
+
+
+ @if ($hasRunningTimer)
+
+
+ End timer
+ Ending...
+
+ @else
+
+
+ Start timer
+ Starting...
+
+ @endif
+
+
diff --git a/Modules/Helpdesk/Resources/views/partials/ticket-controls.blade.php b/Modules/Helpdesk/Resources/views/partials/ticket-controls.blade.php
index 14d38b7e..b157108f 100644
--- a/Modules/Helpdesk/Resources/views/partials/ticket-controls.blade.php
+++ b/Modules/Helpdesk/Resources/views/partials/ticket-controls.blade.php
@@ -1,47 +1,3 @@
-@php
- use Illuminate\Support\Facades\Schema;
- use Modules\Helpdesk\Models\TicketTimeLog;
-
- $ticketTimeLogTable = (new TicketTimeLog())->getTable();
-
- $hasEndedAtColumn = Schema::hasColumn($ticketTimeLogTable, 'ended_at');
- $hasStoppedAtColumn = Schema::hasColumn($ticketTimeLogTable, 'stopped_at');
- $hasFinishedAtColumn = Schema::hasColumn($ticketTimeLogTable, 'finished_at');
- $hasUserIdColumn = Schema::hasColumn($ticketTimeLogTable, 'user_id');
-
- $runningTimerQuery = TicketTimeLog::query()
- ->where('ticket_id', $ticket->getKey())
- ->whereNotNull('started_at')
- ->orderByDesc('started_at');
-
- if ($hasUserIdColumn) {
- $runningTimerQuery->where('user_id', auth()->id());
- }
-
- if ($hasEndedAtColumn) {
- $runningTimerQuery->whereNull('ended_at');
- }
-
- if ($hasStoppedAtColumn) {
- $runningTimerQuery->whereNull('stopped_at');
- }
-
- if ($hasFinishedAtColumn) {
- $runningTimerQuery->whereNull('finished_at');
- }
-
- $runningTimer = ($hasEndedAtColumn || $hasStoppedAtColumn || $hasFinishedAtColumn)
- ? $runningTimerQuery->first()
- : null;
-
- $runningTimerStartedAt = $runningTimer?->started_at;
- $runningTimerElapsedSeconds = $runningTimerStartedAt
- ? max(0, now()->diffInSeconds($runningTimerStartedAt))
- : 0;
- $runningTimerElapsedDisplay = gmdate('H:i:s', $runningTimerElapsedSeconds);
- $hasRunningTimer = $runningTimerStartedAt !== null;
-@endphp
-
@can('update', $ticket)
Log time, assignment, status and priority
-
-
-
-
-
-
-
- Running
-
-
- {{ $runningTimerElapsedDisplay }}
-
-
@@ -93,41 +32,9 @@
@endif
- @if ($hasRunningTimer)
-
-
-
-
- Timer running
-
-
-
- Started {{ $runningTimerStartedAt->format('d M Y H:i:s') }}
-
-
-
-
-
- {{ $runningTimerElapsedDisplay }}
-
-
-
- Elapsed
-
-
-
-
- @endif
-
-
- @include('helpdesk::partials.ticket-time-timer', [
- 'ticket' => $ticket,
- ])
-
+ @include('helpdesk::partials.ticket-time-timer', [
+ 'ticket' => $ticket,
+ ])
-
-
@endcan
diff --git a/Modules/Helpdesk/Resources/views/partials/ticket-time-timer.blade.php b/Modules/Helpdesk/Resources/views/partials/ticket-time-timer.blade.php
index 6fa54a66..715c0947 100644
--- a/Modules/Helpdesk/Resources/views/partials/ticket-time-timer.blade.php
+++ b/Modules/Helpdesk/Resources/views/partials/ticket-time-timer.blade.php
@@ -1,3 +1,3 @@
@can('update', $ticket)
- @livewire('Modules\\Helpdesk\\Livewire\\TicketTimer', ['ticket' => $ticket], key('helpdesk-ticket-timer-'.$ticket->getKey()))
+ @livewire('helpdesk.ticket-timer', ['ticket' => $ticket], key('helpdesk-ticket-timer-'.$ticket->getKey()))
@endcan
diff --git a/Modules/Helpdesk/Tests/Feature/TicketTimerCleanUiFilesTest.php b/Modules/Helpdesk/Tests/Feature/TicketTimerCleanUiFilesTest.php
new file mode 100644
index 00000000..a7f2e501
--- /dev/null
+++ b/Modules/Helpdesk/Tests/Feature/TicketTimerCleanUiFilesTest.php
@@ -0,0 +1,35 @@
+assertStringContainsString("@include('helpdesk::partials.ticket-time-timer'", $controls);
+ $this->assertStringNotContainsString('data-helpdesk-running-summary-badge', $controls);
+ $this->assertStringNotContainsString('data-helpdesk-panel-elapsed', $controls);
+ $this->assertStringNotContainsString('MutationObserver', $controls);
+ $this->assertStringContainsString('data-helpdesk-live-elapsed', $timer);
+ $this->assertStringContainsString("Livewire::component('helpdesk.ticket-timer'", $provider);
+ }
+
+ /**
+ * The module must not contain accidental duplicate Blade folders or macOS artefacts.
+ */
+ public function test_helpdesk_module_does_not_contain_known_rubbish_files(): void
+ {
+ $this->assertDirectoryDoesNotExist(base_path('Modules/Helpdesk/resources/views/views'));
+ $this->assertFileDoesNotExist(base_path('Modules/Helpdesk/.DS_Store'));
+ $this->assertFileDoesNotExist(base_path('Modules/Helpdesk/resources/.DS_Store'));
+ }
+}
diff --git a/Modules/Helpdesk/Tests/Feature/TicketTimerLiveDisplayFilesTest.php b/Modules/Helpdesk/Tests/Feature/TicketTimerLiveDisplayFilesTest.php
index 14b656bf..21e5d17c 100644
--- a/Modules/Helpdesk/Tests/Feature/TicketTimerLiveDisplayFilesTest.php
+++ b/Modules/Helpdesk/Tests/Feature/TicketTimerLiveDisplayFilesTest.php
@@ -13,10 +13,10 @@ class TicketTimerLiveDisplayFilesTest extends TestCase
{
$view = (string) file_get_contents(base_path('Modules/Helpdesk/resources/views/livewire/ticket-timer.blade.php'));
- $this->assertStringContainsString('x-data', $view);
+ $this->assertStringContainsString('data-helpdesk-live-elapsed', $view);
$this->assertStringContainsString('Date.parse', $view);
$this->assertStringContainsString('setInterval', $view);
- $this->assertStringContainsString('started_at', $view);
+ $this->assertStringContainsString('data-helpdesk-started-at', $view);
$this->assertStringContainsString('data-dusk="ticket-running-time"', $view);
$this->assertStringNotContainsString('localStorage', $view);
$this->assertStringNotContainsString('sessionStorage', $view);
diff --git a/Modules/Helpdesk/Tests/Feature/TicketTimerSecondsFilesTest.php b/Modules/Helpdesk/Tests/Feature/TicketTimerSecondsFilesTest.php
index 856d382c..dc27665a 100644
--- a/Modules/Helpdesk/Tests/Feature/TicketTimerSecondsFilesTest.php
+++ b/Modules/Helpdesk/Tests/Feature/TicketTimerSecondsFilesTest.php
@@ -18,9 +18,9 @@ class TicketTimerSecondsFilesTest extends TestCase
$this->assertStringContainsString("'seconds'", $component);
$this->assertStringContainsString("'seconds'", $model);
$this->assertStringContainsString('diffInSeconds', $component);
- $this->assertStringContainsString('sum(\'seconds\')', $component);
- $this->assertStringContainsString('HH:MM:SS', 'HH:MM:SS');
- $this->assertStringContainsString('formatted()', $view);
+ $this->assertStringContainsString('sum('seconds')', $component);
+ $this->assertStringContainsString('formatElapsed', $view);
+ $this->assertStringContainsString('data-helpdesk-live-elapsed', $view);
$this->assertStringNotContainsString('localStorage', $component);
$this->assertStringNotContainsString('localStorage', $view);
}
@@ -33,7 +33,7 @@ class TicketTimerSecondsFilesTest extends TestCase
$partial = (string) file_get_contents(base_path('Modules/Helpdesk/resources/views/partials/ticket-time-log-history-query.blade.php'));
$this->assertStringContainsString('TicketTimeLog::query()', $partial);
- $this->assertStringContainsString('whereNotNull(\'ended_at\')', $partial);
+ $this->assertStringContainsString('whereNotNull('ended_at')', $partial);
$this->assertStringContainsString('seconds', $partial);
}
}
diff --git a/Modules/Helpdesk/Tests/Feature/TicketTimerStartDisplayFilesTest.php b/Modules/Helpdesk/Tests/Feature/TicketTimerStartDisplayFilesTest.php
index f48ee809..8a16bcfb 100644
--- a/Modules/Helpdesk/Tests/Feature/TicketTimerStartDisplayFilesTest.php
+++ b/Modules/Helpdesk/Tests/Feature/TicketTimerStartDisplayFilesTest.php
@@ -13,13 +13,14 @@ class TicketTimerStartDisplayFilesTest extends TestCase
{
$component = (string) file_get_contents(base_path('Modules/Helpdesk/Livewire/TicketTimer.php'));
$view = (string) file_get_contents(base_path('Modules/Helpdesk/resources/views/livewire/ticket-timer.blade.php'));
+ $partial = (string) file_get_contents(base_path('Modules/Helpdesk/resources/views/partials/ticket-time-timer.blade.php'));
$this->assertStringContainsString('$this->activeTimer = $timer->fresh();', $component);
$this->assertStringContainsString('$this->elapsedSeconds = 0;', $component);
$this->assertStringContainsString("dispatch('timer-started')", $component);
$this->assertStringContainsString('$hasRunningTimer = $activeTimer && $activeTimer->ended_at === null;', $view);
- $this->assertStringContainsString('data-helpdesk-running-timer', $view);
- $this->assertStringContainsString('x-on:timer-started.window', $view);
+ $this->assertStringContainsString('data-helpdesk-live-elapsed', $view);
+ $this->assertStringContainsString("@livewire('helpdesk.ticket-timer'", $partial);
$this->assertStringNotContainsString('wire:ignore', $view);
}
}
diff --git a/Modules/Helpdesk/changelog.yaml b/Modules/Helpdesk/changelog.yaml
index 721d4317..c93fe1f4 100644
--- a/Modules/Helpdesk/changelog.yaml
+++ b/Modules/Helpdesk/changelog.yaml
@@ -7,3 +7,29 @@
- Added persistent started_at, ended_at, and duration_seconds fields to existing helpdesk time logs where available.
- Added a reusable Blade include for placing the timer above the existing manual time log form.
- Added regression tests for module path, Livewire view root safety, and non-session timer state.
+- version: 1.9.30
+ date: 2026-06-23
+ type: bugfix
+ summary: Clean up Helpdesk timer UI state and remove duplicate timer display code.
+ changes:
+ - Replaced the oversized timer display with a compact professional ticket timer panel.
+ - Hid the elapsed timer before start and after end so it only displays while a timer is active.
+ - Added an inline loaded browser timer updater in the Livewire view instead of an unused standalone JavaScript file.
+ - Removed duplicate running timer summary and MutationObserver logic from ticket controls.
+ - Registered the timer Livewire component with the helpdesk.ticket-timer alias.
+ - Removed duplicate Resources/views/views timer files and macOS artefacts from the clean module.
+ - Added file-level regression coverage for the timer UI cleanup.
+- version: 1.9.31
+ date: 2026-06-23
+ type: bugfix
+ summary: Reduce Helpdesk start timer button size.
+ changes:
+ - Made the inactive-state Start timer button more compact while preserving accessible focus and loading states.
+ - Kept the timer display hidden before start and after end, with no new standalone JavaScript files.
+- version: 1.9.32
+ date: 2026-06-23
+ type: bugfix
+ summary: Widen Helpdesk start timer button so the label fits on one line.
+ changes:
+ - Updated the inactive Start timer action with a minimum width and no-wrap text so the label does not split.
+ - Preserved the clean inline timer display behaviour with no unused standalone JavaScript file.
diff --git a/Modules/Helpdesk/module.json b/Modules/Helpdesk/module.json
index 31300457..eac8e81b 100644
--- a/Modules/Helpdesk/module.json
+++ b/Modules/Helpdesk/module.json
@@ -22,5 +22,5 @@
"Modules\\Helpdesk\\Providers\\HelpdeskServiceProvider"
],
"files": [],
- "version": "1.9.29"
+ "version": "1.9.32"
}