Co nowego:
- Wsparcie Active Directory dla LDAP (obok LLDAP/OpenLDAP), przełącznik typu
  katalogu w Admin > Integracje.
- Wyszukiwarka klientów dla operatora (Operator > Klienci).
- Stronicowanie kolejki operatora (50/stronę) i dashboardu klienta (20/stronę).
- Globalna wyszukiwarka zgłoszeń (Ctrl+K/Cmd+K) z operatorami w stylu Gmaila
  (od:, temat:, treść:, numer:), plus przycisk "Szukaj" w panelu bocznym.
- Ostatnio przeglądane zgłoszenia w panelu bocznym operatora.
- Przeprojektowany pasek nawigacji: suwak Klient/Operator/Administrator
  zamiast rozwijanego menu, bogatsze menu profilu (nazwa/e-mail/role),
  dynamiczne tytuły kart przeglądarki na każdej podstronie.
- Narzędzie do jednorazowego importu historii zgłoszeń z Heska 3.x
  (scripts/hesk-import/).
- Poprawka: paginacja pokazywała surowe klucze tłumaczeń zamiast tekstu
  (brakujący lang/pl/pagination.php).

Zaktualizowana dokumentacja: README, CLAUDE.md, install.md, ARCHITECTURE.md,
CHANGELOG.md, wiki/*.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-05 00:58:35 +02:00
parent 7a8cf2037c
commit 03c6ec7cae
57 changed files with 2029 additions and 162 deletions

View File

@@ -0,0 +1,80 @@
<?php
use App\Livewire\Client\Dashboard;
use App\Livewire\Client\TicketShow;
use App\Livewire\Operator\Queue;
use App\Models\User;
use Livewire\Livewire;
test('the operator queue paginates instead of rendering every matching ticket at once', function () {
seedStatusesAndPriorities();
$operator = operatorUser('queue-page@example.com');
foreach (range(1, 55) as $i) {
makeTicket(['number' => str_pad($i, 4, '0', STR_PAD_LEFT)]);
}
$component = Livewire::actingAs($operator)->test(Queue::class);
expect($component->instance()->filteredTickets)->toHaveCount(50)
->and($component->instance()->filteredTickets->total())->toBe(55);
$component->call('gotoPage', 2);
expect($component->instance()->filteredTickets)->toHaveCount(5);
});
test('changing the queue search resets the operator to page 1', function () {
seedStatusesAndPriorities();
$operator = operatorUser('queue-page-reset@example.com');
foreach (range(1, 55) as $i) {
makeTicket(['number' => str_pad($i, 4, '0', STR_PAD_LEFT), 'subject' => 'Zgłoszenie']);
}
makeTicket(['number' => '9999', 'subject' => 'Unikalny temat']);
$component = Livewire::actingAs($operator)->test(Queue::class)->call('gotoPage', 2);
expect($component->instance()->filteredTickets->currentPage())->toBe(2);
$component->set('search', 'Unikalny');
expect($component->instance()->filteredTickets->currentPage())->toBe(1)
->and($component->instance()->filteredTickets)->toHaveCount(1);
});
test('the client dashboard paginates current/archive tickets separately', function () {
seedStatusesAndPriorities();
$client = User::query()->create(['name' => 'Client', 'email' => 'dash-page@example.com', 'roles' => ['client']]);
foreach (range(1, 25) as $i) {
makeTicket(['number' => str_pad($i, 4, '0', STR_PAD_LEFT), 'customer_id' => $client->id, 'email' => $client->email, 'name' => $client->name, 'status_key' => 'new']);
}
foreach (range(1, 3) as $i) {
makeTicket(['number' => '90'.$i, 'customer_id' => $client->id, 'email' => $client->email, 'name' => $client->name, 'status_key' => 'closed']);
}
$component = Livewire::actingAs($client)->test(Dashboard::class);
expect($component->instance()->currentTickets)->toHaveCount(20)
->and($component->instance()->currentTickets->total())->toBe(25)
->and($component->instance()->archiveTickets)->toHaveCount(3);
});
test('"Inne Twoje zgłoszenia" shows only a handful until "Pokaż wszystkie" is clicked', function () {
seedStatusesAndPriorities();
$client = User::query()->create(['name' => 'Client', 'email' => 'other-tickets@example.com', 'roles' => ['client']]);
$viewed = makeTicket(['number' => '5000', 'customer_id' => $client->id, 'email' => $client->email, 'name' => $client->name]);
foreach (range(1, 8) as $i) {
makeTicket(['number' => '60'.$i, 'customer_id' => $client->id, 'email' => $client->email, 'name' => $client->name]);
}
$component = Livewire::actingAs($client)->test(TicketShow::class, ['ticket' => $viewed]);
expect($component->instance()->otherTickets)->toHaveCount(5)
->and($component->instance()->otherTicketsCount)->toBe(8);
$component->call('revealAllOtherTickets');
expect($component->instance()->otherTickets)->toHaveCount(8);
});