Zwei Attrappen: ein Banner ohne Hintergrund und Rechte, die ihren Schluessel statt ihrer Beschreibung zeigten
parent
462c84ee23
commit
d8aee6ec2f
|
|
@ -162,6 +162,13 @@ class Roles extends Component
|
|||
->groupBy(fn (string $name) => str_contains($name, '.') ? strtok($name, '.') : 'sonstiges')
|
||||
->sortKeys(),
|
||||
'permissions' => $this->allPermissions(),
|
||||
// Der ganze `can`-Block als Array, nicht Eintrag für Eintrag über
|
||||
// `__()`. Ein Berechtigungsname trägt selbst einen Punkt
|
||||
// (`billing.manage`), und `__()` liest Punkte als Verschachtelung —
|
||||
// der Aufruf suchte `roles → can → billing → manage`, während in
|
||||
// der Sprachdatei ein FLACHER Schlüssel `'billing.manage'` steht.
|
||||
// Die Seite zeigte deshalb den Schlüssel statt der Beschreibung.
|
||||
'permissionLabels' => (array) trans('roles.can'),
|
||||
// Wie viele Menschen an dieser Rolle hängen — damit niemand blind
|
||||
// etwas wegnimmt, das gerade sechs Leute benutzen.
|
||||
'protectedRole' => 'Owner',
|
||||
|
|
|
|||
|
|
@ -33,8 +33,13 @@
|
|||
das gerade Geld kostet? Der Ton kommt vom dringendsten Zustand, der
|
||||
wirklich vorkommt — nicht von einer festen Farbe. --}}
|
||||
@php([$worstIcon, $worstText] = $tone[$worst])
|
||||
{{-- `bg-danger-bg` und `border-danger-border`, nicht `bg-danger/5`:
|
||||
dieses Haus hat für gedämpfte Töne eigene Tokens
|
||||
(resources/css/portal-tokens.css). Die Deckkraft-Schreibweise ergab
|
||||
hier gar keinen sichtbaren Hintergrund — der Kasten stand
|
||||
durchsichtig da, nur mit Rahmen. --}}
|
||||
<div class="flex items-center gap-3 rounded-lg border p-5 shadow-xs animate-rise
|
||||
{{ $worst === App\Support\OpenWork::SOLD ? 'border-danger/30 bg-danger/5' : 'border-line bg-surface' }}">
|
||||
{{ $worst === App\Support\OpenWork::SOLD ? 'border-danger-border bg-danger-bg' : 'border-line bg-surface' }}">
|
||||
<x-ui.icon :name="$worstIcon" class="{{ $worstText }}" />
|
||||
<p class="text-lg font-semibold {{ $worstText }}">
|
||||
{{ trans_choice('open_work.summary', $total, ['n' => $total]) }}
|
||||
|
|
|
|||
|
|
@ -85,7 +85,16 @@
|
|||
@disabled($isProtected)
|
||||
class="mt-0.5 size-4 shrink-0 rounded border-line-strong accent-[var(--accent-active)] disabled:opacity-50">
|
||||
<span class="min-w-0">
|
||||
<span class="block">{{ __('roles.can.'.$permission) }}</span>
|
||||
{{-- Aus dem Array gelesen statt über `__('roles.can.'.$permission)`.
|
||||
Ein Berechtigungsname trägt selbst einen Punkt
|
||||
(`billing.manage`), und `__()` liest Punkte als
|
||||
Verschachtelung — es suchte also `roles → can →
|
||||
billing → manage`, während in der Sprachdatei ein
|
||||
FLACHER Schlüssel `'billing.manage'` steht. Gefunden
|
||||
wurde nie etwas, also stand auf der Seite der
|
||||
Schlüssel selbst: „roles.can.billing.manage".
|
||||
Die Übersetzungen waren die ganze Zeit da. --}}
|
||||
<span class="block">{{ $permissionLabels[$permission] ?? $permission }}</span>
|
||||
<span class="block font-mono text-[11px] text-faint">{{ $permission }}</span>
|
||||
</span>
|
||||
</label>
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
use App\Livewire\Admin\Roles;
|
||||
use App\Models\Operator;
|
||||
use Livewire\Livewire;
|
||||
use Spatie\Permission\Models\Permission;
|
||||
use Spatie\Permission\Models\Role;
|
||||
|
||||
/**
|
||||
|
|
@ -146,3 +147,44 @@ it('groups the capabilities instead of listing twenty-one in a row', function ()
|
|||
->and($groups)->toHaveKey('provisioning')
|
||||
->and(count($groups))->toBeLessThan(21);
|
||||
});
|
||||
|
||||
/**
|
||||
* Die Rollenseite zeigte statt der Beschreibungen ihre eigenen Schlüssel:
|
||||
* „roles.can.billing.manage" stand da, wo „Rechnungen, Gutschriften,
|
||||
* Zahlungsprobleme" hingehört.
|
||||
*
|
||||
* Die Übersetzungen waren die ganze Zeit vorhanden. Der Aufruf lautete
|
||||
* `__('roles.can.'.$permission)`, und ein Berechtigungsname trägt selbst einen
|
||||
* Punkt — `__()` liest Punkte als Verschachtelung und suchte deshalb
|
||||
* `roles → can → billing → manage`, während in der Sprachdatei ein FLACHER
|
||||
* Schlüssel `'billing.manage'` steht. Gefunden wurde nie etwas.
|
||||
*/
|
||||
it('zeigt zu jeder Berechtigung ihre Beschreibung, nicht ihren Schluessel', function () {
|
||||
foreach (['de', 'en'] as $locale) {
|
||||
app()->setLocale($locale);
|
||||
|
||||
$labels = (array) trans('roles.can');
|
||||
|
||||
// Aus der Datenbank, nicht aus einer Liste im Test: so kann eine neu
|
||||
// angelegte Berechtigung nicht ohne Beschreibung durchrutschen.
|
||||
$permissions = Permission::query()
|
||||
->where('guard_name', 'operator')->pluck('name');
|
||||
|
||||
foreach ($permissions as $permission) {
|
||||
expect($labels[$permission] ?? null)
|
||||
->not->toBeNull("„{$permission}“ hat in lang/{$locale}/roles.php keine Beschreibung.")
|
||||
// Und die Beschreibung ist keine Wiederholung des Schlüssels.
|
||||
->not->toBe($permission);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
it('rendert die Beschreibungen wirklich auf der Seite', function () {
|
||||
// Gegen das ausgelieferte HTML, nicht gegen die Sprachdatei: der Fehler lag
|
||||
// nicht in den Texten, sondern darin, wie die Seite sie holte.
|
||||
$html = $this->actingAs(admin(), 'operator')->get(route('admin.roles'))->assertOk()->getContent();
|
||||
|
||||
expect($html)->toContain(e(trans('roles.can')['billing.manage']))
|
||||
// Und kein roher Schlüssel mehr.
|
||||
->and($html)->not->toContain('roles.can.billing.manage');
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in New Issue