v1.4.0
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:
50
src/resources/views/components/panel-switcher.blade.php
Normal file
50
src/resources/views/components/panel-switcher.blade.php
Normal file
@@ -0,0 +1,50 @@
|
||||
@props(['area' => null])
|
||||
|
||||
@php
|
||||
// $area is passed explicitly by each page (e.g. <x-topbar area="operator" />)
|
||||
// rather than inferred from request()->routeIs() here: this component is
|
||||
// rendered as part of each top-level Livewire page's own template, so it
|
||||
// re-renders on every wire:click/wire:model round-trip on that page (tab
|
||||
// switches, pagination, search, ...) — and during that AJAX request,
|
||||
// request()->route() is Livewire's own update route, not client./operator./
|
||||
// admin.*, which silently broke the highlight on every in-page interaction
|
||||
// when this used to key off the ambient request instead of an explicit prop.
|
||||
$user = auth()->user();
|
||||
$areas = [];
|
||||
|
||||
if ($user) {
|
||||
if ($user->isClient()) {
|
||||
$areas[] = ['label' => 'Klient', 'url' => route('client.dashboard'), 'active' => $area === 'client'];
|
||||
}
|
||||
if ($user->isOperator()) {
|
||||
$areas[] = ['label' => 'Operator', 'url' => route('operator.queue'), 'active' => $area === 'operator'];
|
||||
}
|
||||
if ($user->isAdmin()) {
|
||||
$areas[] = ['label' => 'Administrator', 'url' => route('admin.panel'), 'active' => $area === 'admin'];
|
||||
}
|
||||
}
|
||||
|
||||
$activeIndex = collect($areas)->search(fn ($area) => $area['active']);
|
||||
@endphp
|
||||
|
||||
@if (count($areas))
|
||||
<div
|
||||
class="panel-switch"
|
||||
style="position:absolute;left:50%;top:50%;transform:translate(-50%, -50%)"
|
||||
>
|
||||
@if ($activeIndex !== false)
|
||||
<span
|
||||
class="panel-switch-indicator"
|
||||
style="width:calc(100% / {{ count($areas) }});transform:translateX({{ $activeIndex * 100 }}%)"
|
||||
></span>
|
||||
@endif
|
||||
|
||||
@foreach ($areas as $item)
|
||||
<a
|
||||
href="{{ $item['url'] }}"
|
||||
wire:navigate
|
||||
class="panel-switch-option {{ $item['active'] ? 'panel-switch-option-active' : '' }}"
|
||||
>{{ $item['label'] }}</a>
|
||||
@endforeach
|
||||
</div>
|
||||
@endif
|
||||
@@ -1,18 +1,5 @@
|
||||
@php
|
||||
$user = auth()->user();
|
||||
$areas = [];
|
||||
|
||||
if ($user) {
|
||||
if ($user->isClient()) {
|
||||
$areas[] = ['label' => 'Panel Klienta', 'url' => route('client.dashboard'), 'active' => request()->routeIs('client.*')];
|
||||
}
|
||||
if ($user->isOperator()) {
|
||||
$areas[] = ['label' => 'Panel Operatora', 'url' => route('operator.queue'), 'active' => request()->routeIs('operator.*')];
|
||||
}
|
||||
if ($user->isAdmin()) {
|
||||
$areas[] = ['label' => 'Panel Administratora', 'url' => route('admin.panel'), 'active' => request()->routeIs('admin.*')];
|
||||
}
|
||||
}
|
||||
@endphp
|
||||
|
||||
@if ($user)
|
||||
@@ -26,23 +13,27 @@
|
||||
x-show="open"
|
||||
x-cloak
|
||||
class="nav-dropdown"
|
||||
style="position:absolute;top:100%;right:0;margin-top:6px;background:var(--color-surface);border:1px solid var(--color-divider);border-radius:8px;box-shadow:var(--shadow-md);min-width:200px;overflow:hidden;z-index:30"
|
||||
style="position:absolute;top:100%;right:0;margin-top:6px;background:var(--color-surface);border:1px solid var(--color-divider);border-radius:8px;box-shadow:var(--shadow-md);min-width:220px;overflow:hidden;z-index:30"
|
||||
>
|
||||
@foreach ($areas as $area)
|
||||
<a
|
||||
href="{{ $area['url'] }}"
|
||||
wire:navigate
|
||||
@click="open = false"
|
||||
class="theme-toggle-option"
|
||||
style="text-decoration:none;color:{{ $area['active'] ? 'var(--color-accent)' : 'var(--color-text)' }};font-size:12.5px"
|
||||
>{{ $area['label'] }}</a>
|
||||
@endforeach
|
||||
<div style="display:flex;flex-direction:column;gap:6px;padding:12px">
|
||||
<span style="font-weight:600;font-size:13px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap">{{ $user->name }}</span>
|
||||
<span style="font-size:11.5px;color:color-mix(in srgb, var(--color-text) 60%, transparent);overflow:hidden;text-overflow:ellipsis;white-space:nowrap">{{ $user->email }}</span>
|
||||
<div style="display:flex;flex-wrap:wrap;gap:4px;margin-top:2px">
|
||||
@if ($user->isClient())
|
||||
<span class="tag tag-neutral">Klient</span>
|
||||
@endif
|
||||
@if ($user->isOperator())
|
||||
<span class="tag tag-accent-2">Operator</span>
|
||||
@endif
|
||||
@if ($user->isAdmin())
|
||||
<span class="tag tag-accent">Administrator</span>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@if (count($areas))
|
||||
<div style="border-top:1px solid var(--color-divider)"></div>
|
||||
@endif
|
||||
<div style="border-top:1px solid var(--color-divider)"></div>
|
||||
|
||||
@if ($user && ($user->isOperator() || $user->isAdmin()))
|
||||
@if ($user->isOperator() || $user->isAdmin())
|
||||
<a
|
||||
href="{{ route('settings.notifications') }}"
|
||||
wire:navigate
|
||||
|
||||
@@ -1,18 +1,9 @@
|
||||
@php
|
||||
$panelLabel = match (true) {
|
||||
request()->routeIs('client.*') => 'Panel Klienta',
|
||||
request()->routeIs('operator.*') => 'Panel Operatora',
|
||||
request()->routeIs('admin.*') => 'Panel Administratora',
|
||||
default => null,
|
||||
};
|
||||
@endphp
|
||||
@props(['area' => null])
|
||||
|
||||
<div class="nav" style="position:relative;padding:16px 28px;border-bottom:1px solid var(--color-divider)">
|
||||
<span class="nav-brand">{{ \App\Support\Settings::get('company_name') }}</span>
|
||||
|
||||
@if ($panelLabel)
|
||||
<span class="nav-panel-label" style="position:absolute;left:50%;top:50%;transform:translate(-50%, -50%);font-weight:500;font-size:13.5px;white-space:nowrap">{{ $panelLabel }}</span>
|
||||
@endif
|
||||
<x-panel-switcher :area="$area" />
|
||||
|
||||
<x-theme-toggle />
|
||||
|
||||
@@ -20,6 +11,7 @@
|
||||
|
||||
@auth
|
||||
<livewire:notification-bell />
|
||||
<livewire:global-search />
|
||||
@endauth
|
||||
|
||||
<x-profile-menu />
|
||||
|
||||
Reference in New Issue
Block a user