feat: granular permissions, export backup, user/role management
Some checks failed
Tests / PHP 8.3 (push) Has been cancelled
Tests / PHP 8.4 (push) Has been cancelled
Tests / PHP 8.5 (push) Has been cancelled

- PermissionSeeder: 29 permissions with role mapping (admin/manager/staff)
- Policies updated to use hasPermissionTo() instead of hasRole()
- ExportBackup command: JSON per-table backup with chunk processing
- UserResource: CRUD users with role assignment (admin only)
- RoleResource: CRUD roles with permission assignment (admin only)
- UserPolicy + RolePolicy: admin-only access control
- ImportCskh: detailed skip logging with color in dry-run mode
- Widgets: permission-based visibility checks
- Tests: 8/8 pass (21 assertions)
This commit is contained in:
2026-05-02 04:47:10 +00:00
parent 7c5055075b
commit 3a8db5cae6
40 changed files with 1804 additions and 440 deletions

View File

@@ -16,16 +16,28 @@ class FeedbackTable
{
return $table
->columns([
TextColumn::make('id')
->label('#')
->sortable()
->weight('bold')
->color('primary'),
TextColumn::make('title')
->searchable()
->sortable(),
->sortable()
->weight('semibold')
->limit(40),
TextColumn::make('customer.name')
->searchable()
->sortable(),
TextColumn::make('customerProduct.product.name')
->label('Product')
->placeholder('General')
->sortable(),
->sortable()
->toggleable(),
TextColumn::make('contract.type')
->label('Contract')
->badge()
@@ -38,17 +50,17 @@ class FeedbackTable
})
->placeholder('-')
->toggleable(),
TextColumn::make('feedbackChannel.name')
->label('Channel')
->formatStateUsing(fn ($state, $record) => sprintf(
'<span style="display:inline-block;background:%s;color:#fff;padding:2px 10px;border-radius:9999px;font-size:0.75rem;">%s</span>',
$record->feedbackChannel?->color ?: '#6b7280',
e($state)
))
->html(),
->badge()
->color('gray'),
TextColumn::make('tags.name')
->badge()
->separator(','),
->separator(',')
->toggleable(),
TextColumn::make('status')
->badge()
->color(fn(string $state): string => match ($state) {
@@ -58,20 +70,28 @@ class FeedbackTable
'closed' => 'gray',
default => 'gray',
}),
TextColumn::make('currentDepartment.name')
->label('Department')
->badge()
->color('info')
->toggleable(),
TextColumn::make('assignedTo.name')
->label('Assigned To')
->toggleable(),
IconColumn::make('is_escalated')
->label('Escalated')
->boolean()
->toggleable(),
TextColumn::make('created_at')
->dateTime()
->label('Created')
->since()
->sortable()
->toggleable(),
->toggleable()
->color('secondary'),
])
->filters([
SelectFilter::make('status')