Skip to content
4 changes: 2 additions & 2 deletions resources/lang/vendor/filament-shield/en/filament-shield.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

'column.name' => 'Name',
'column.guard_name' => 'Guard Name',
'column.team' => 'Team',
'column.team' => 'Site',
'column.roles' => 'Roles',
'column.permissions' => 'Permissions',
'column.updated_at' => 'Updated At',
Expand All @@ -24,7 +24,7 @@
'field.guard_name' => 'Guard Name',
'field.permissions' => 'Permissions',
'field.team' => 'Site',
'field.team.placeholder' => 'Select a site ...',
'field.team.placeholder' => 'Global (all sites)',
'field.select_all.name' => 'Select All',
'field.select_all.message' => 'Enables/Disables all Permissions for this role',

Expand Down
15 changes: 15 additions & 0 deletions src/EclipseServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
use Eclipse\Core\Providers\HorizonServiceProvider;
use Eclipse\Core\Providers\TelescopeServiceProvider;
use Eclipse\Core\Services\Registry;
use Filament\Forms\Components\Field;
use Filament\Infolists\Components\Entry;
use Filament\Resources\Resource;
use Filament\Tables\Columns\Column;
use Illuminate\Auth\Events\Login;
Expand Down Expand Up @@ -121,9 +123,22 @@ public function boot(): void
// Register policies for classes that can't be guessed automatically
Gate::policy(Role::class, RolePolicy::class);

// Set common settings for Filament form
Field::configureUsing(function (Field $field) {
$field
->translateLabel();
});

// Set common settings for Filament infolist
Entry::configureUsing(function (Entry $entry) {
$entry
->translateLabel();
});

// Set common settings for Filament table columns
Column::configureUsing(function (Column $column) {
$column
->translateLabel()
->toggleable()
->sortable();
});
Expand Down
235 changes: 235 additions & 0 deletions src/Filament/Resources/RoleResource.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,235 @@
<?php

namespace Eclipse\Core\Filament\Resources;

use BezhanSalleh\FilamentShield\Contracts\HasShieldPermissions;
use BezhanSalleh\FilamentShield\Forms\ShieldSelectAllToggle;
use BezhanSalleh\FilamentShield\Support\Utils;
use BezhanSalleh\FilamentShield\Traits\HasShieldFormComponents;
use Eclipse\Core\Filament\Resources\RoleResource\Pages;
use Filament\Facades\Filament;
use Filament\Forms;
use Filament\Forms\Form;
use Filament\Pages\SubNavigationPosition;
use Filament\Resources\Resource;
use Filament\Tables;
use Filament\Tables\Table;
use Illuminate\Contracts\Support\Arrayable;
use Illuminate\Support\HtmlString;
use Illuminate\Support\Str;
use Illuminate\Validation\Rules\Unique;

class RoleResource extends Resource implements HasShieldPermissions
{
use HasShieldFormComponents;

protected static ?string $recordTitleAttribute = 'name';

public static function getPermissionPrefixes(): array
{
return [
'view',
'view_any',
'create',
'update',
'delete',
'delete_any',
];
}

public static function form(Form $form): Form
{
return $form
->schema([
Forms\Components\Grid::make()
->schema([
Forms\Components\Section::make()
->schema([
Forms\Components\TextInput::make('name')
->label(__('filament-shield::filament-shield.field.name'))
->unique(
ignoreRecord: true, /** @phpstan-ignore-next-line */
modifyRuleUsing: fn (Unique $rule) => ! Utils::isTenancyEnabled() ? $rule : $rule->where(Utils::getTenantModelForeignKey(), Filament::getTenant()?->id)
)
->required()
->maxLength(255),

Forms\Components\TextInput::make('guard_name')
->label(__('filament-shield::filament-shield.field.guard_name'))
->default(Utils::getFilamentAuthGuard())
->nullable()
->maxLength(255),

Forms\Components\TextInput::make(config('permission.column_names.team_foreign_key'))
->label(__('filament-shield::filament-shield.field.team'))
->placeholder(__('filament-shield::filament-shield.field.team.placeholder'))
->visible(function ($state, $context): bool {
if (empty($state) && $context === 'view') {
return true;
}

return false;
}),

Forms\Components\Select::make(config('permission.column_names.team_foreign_key'))
->label(__('filament-shield::filament-shield.field.team'))
->placeholder(__('filament-shield::filament-shield.field.team.placeholder'))
/** @phpstan-ignore-next-line */
->default([Filament::getTenant()?->id])
->visible(function ($state, $context): bool {
if (empty($state) && $context === 'view') {
return false;
}

return true;
})
->options(fn (): Arrayable => Utils::getTenantModel() ? Utils::getTenantModel()::pluck('name', 'id') : collect())
->dehydrated(fn (): bool => ! (static::shield()->isCentralApp() && Utils::isTenancyEnabled())),
ShieldSelectAllToggle::make('select_all')
->onIcon('heroicon-s-shield-check')
->offIcon('heroicon-s-shield-exclamation')
->label(__('filament-shield::filament-shield.field.select_all.name'))
->helperText(fn (): HtmlString => new HtmlString(__('filament-shield::filament-shield.field.select_all.message')))
->dehydrated(fn (bool $state): bool => $state),

])
->columns([
'sm' => 2,
'lg' => 3,
]),
]),
static::getShieldFormComponents(),
]);
}

public static function table(Table $table): Table
{
return $table
->columns([
Tables\Columns\TextColumn::make('name')
->weight('font-medium')
->label(__('filament-shield::filament-shield.column.name'))
->formatStateUsing(fn ($state): string => Str::headline($state))
->searchable(),
Tables\Columns\TextColumn::make('guard_name')
->badge()
->color('warning')
->label(__('filament-shield::filament-shield.column.guard_name')),
Tables\Columns\TextColumn::make('site.name')
->default('Global')
->badge()
->color(fn (mixed $state): string => str($state)->contains('Global') ? 'gray' : 'primary')
->label(__('filament-shield::filament-shield.column.team'))
->searchable(),
Tables\Columns\TextColumn::make('permissions_count')
->badge()
->label(__('filament-shield::filament-shield.column.permissions'))
->counts('permissions')
->colors(['success']),
Tables\Columns\TextColumn::make('updated_at')
->label(__('filament-shield::filament-shield.column.updated_at'))
->dateTime(),
])
->filters([
//
])
->actions([
Tables\Actions\EditAction::make(),
Tables\Actions\DeleteAction::make(),
])
->bulkActions([
Tables\Actions\DeleteBulkAction::make(),
]);
}

public static function getRelations(): array
{
return [
//
];
}

public static function getPages(): array
{
return [
'index' => Pages\ListRoles::route('/'),
'create' => Pages\CreateRole::route('/create'),
'view' => Pages\ViewRole::route('/{record}'),
'edit' => Pages\EditRole::route('/{record}/edit'),
];
}

public static function getCluster(): ?string
{
return Utils::getResourceCluster() ?? static::$cluster;
}

public static function getModel(): string
{
return Utils::getRoleModel();
}

public static function getModelLabel(): string
{
return __('filament-shield::filament-shield.resource.label.role');
}

public static function getPluralModelLabel(): string
{
return __('filament-shield::filament-shield.resource.label.roles');
}

public static function shouldRegisterNavigation(): bool
{
return Utils::isResourceNavigationRegistered();
}

public static function getNavigationGroup(): ?string
{
return Utils::isResourceNavigationGroupEnabled()
? __('filament-shield::filament-shield.nav.group')
: '';
}

public static function getNavigationLabel(): string
{
return __('filament-shield::filament-shield.nav.role.label');
}

public static function getNavigationIcon(): string
{
return __('filament-shield::filament-shield.nav.role.icon');
}

public static function getNavigationSort(): ?int
{
return Utils::getResourceNavigationSort();
}

public static function getSubNavigationPosition(): SubNavigationPosition
{
return Utils::getSubNavigationPosition() ?? static::$subNavigationPosition;
}

public static function getSlug(): string
{
return Utils::getResourceSlug();
}

public static function getNavigationBadge(): ?string
{
return Utils::isResourceNavigationBadgeEnabled()
? strval(static::getEloquentQuery()->count())
: null;
}

public static function isScopedToTenant(): bool
{
return Utils::isScopedToTenant();
}

public static function canGloballySearch(): bool
{
return Utils::isResourceGloballySearchable() && count(static::getGloballySearchableAttributes()) && static::canViewAny();
}
}
47 changes: 47 additions & 0 deletions src/Filament/Resources/RoleResource/Pages/CreateRole.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<?php

namespace Eclipse\Core\Filament\Resources\RoleResource\Pages;

use BezhanSalleh\FilamentShield\Support\Utils;
use Eclipse\Core\Filament\Resources\RoleResource;
use Filament\Resources\Pages\CreateRecord;
use Illuminate\Support\Arr;
use Illuminate\Support\Collection;

class CreateRole extends CreateRecord
{
protected static string $resource = RoleResource::class;

public Collection $permissions;

protected function mutateFormDataBeforeCreate(array $data): array
{
$this->permissions = collect($data)
->filter(function ($permission, $key) {
return ! in_array($key, ['name', 'guard_name', 'select_all', Utils::getTenantModelForeignKey()]);
})
->values()
->flatten()
->unique();

if (Arr::has($data, Utils::getTenantModelForeignKey())) {
return Arr::only($data, ['name', 'guard_name', Utils::getTenantModelForeignKey()]);
}

return Arr::only($data, ['name', 'guard_name']);
}

protected function afterCreate(): void
{
$permissionModels = collect();
$this->permissions->each(function ($permission) use ($permissionModels) {
$permissionModels->push(Utils::getPermissionModel()::firstOrCreate([
/** @phpstan-ignore-next-line */
'name' => $permission,
'guard_name' => $this->data['guard_name'],
]));
});

$this->record->syncPermissions($permissionModels);
}
}
54 changes: 54 additions & 0 deletions src/Filament/Resources/RoleResource/Pages/EditRole.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<?php

namespace Eclipse\Core\Filament\Resources\RoleResource\Pages;

use BezhanSalleh\FilamentShield\Support\Utils;
use Eclipse\Core\Filament\Resources\RoleResource;
use Filament\Actions;
use Filament\Resources\Pages\EditRecord;
use Illuminate\Support\Arr;
use Illuminate\Support\Collection;

class EditRole extends EditRecord
{
protected static string $resource = RoleResource::class;

public Collection $permissions;

protected function getActions(): array
{
return [
Actions\ViewAction::make(),
];
}

protected function mutateFormDataBeforeSave(array $data): array
{
$this->permissions = collect($data)
->filter(function ($permission, $key) {
return ! in_array($key, ['name', 'guard_name', 'select_all', Utils::getTenantModelForeignKey()]);
})
->values()
->flatten()
->unique();

if (Arr::has($data, Utils::getTenantModelForeignKey())) {
return Arr::only($data, ['name', 'guard_name', Utils::getTenantModelForeignKey()]);
}

return Arr::only($data, ['name', 'guard_name']);
}

protected function afterSave(): void
{
$permissionModels = collect();
$this->permissions->each(function ($permission) use ($permissionModels) {
$permissionModels->push(Utils::getPermissionModel()::firstOrCreate([
'name' => $permission,
'guard_name' => $this->data['guard_name'],
]));
});

$this->record->syncPermissions($permissionModels);
}
}
Loading
Loading