Skip to content

Commit

Permalink
[ADVAPP-978]: Enhance the user list experience by introducing filters…
Browse files Browse the repository at this point in the history
… for users who have no assigned permissions (#1134)

* Add roles filter in users list

* Change no_roles to none

* update test case

* Change id to getKey and update search query

* add group to roles filter

* cs fixer
  • Loading branch information
amit-canyon authored Nov 27, 2024
1 parent 7bcbabf commit 758d10c
Show file tree
Hide file tree
Showing 2 changed files with 115 additions and 38 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@

use function Pest\Laravel\actingAs;
use function Pest\Livewire\livewire;

use AdvisingApp\Authorization\Models\Role;

use function PHPUnit\Framework\assertTrue;
use function PHPUnit\Framework\assertFalse;

Expand Down Expand Up @@ -307,3 +310,64 @@
$userInTeamA->merge($userInTeamB)
);
});

it('filters users based on roles', function () {
asSuperAdmin();

$roleA = Role::factory()->create(['name' => 'Role A']);
$roleB = Role::factory()->create(['name' => 'Role B']);
$roleC = Role::factory()->create(['name' => 'Role C']);

$usersInRoleA = User::factory()
->count(3)
->create()
->each(function ($user) use ($roleA) {
$user->assignRole($roleA);
});

$usersInRoleB = User::factory()
->count(3)
->create()
->each(function ($user) use ($roleB) {
$user->assignRole($roleB);
});

$usersInRoleC = User::factory()
->count(3)
->create()
->each(function ($user) use ($roleC) {
$user->assignRole($roleC);
});

$noRolesUsers = User::factory()->count(2)->create();

livewire(ListUsers::class)
->filterTable('roles', [$roleA->getKey()])
->assertCanSeeTableRecords(
$usersInRoleA
)
->assertCanNotSeeTableRecords(
$noRolesUsers->merge($usersInRoleB)->merge($usersInRoleC)
)
->filterTable('roles', [$roleB->getKey()])
->assertCanSeeTableRecords(
$usersInRoleB
)
->assertCanNotSeeTableRecords(
$noRolesUsers->merge($usersInRoleA)->merge($usersInRoleC)
)
->filterTable('roles', [$roleB->getKey(), $roleC->getKey()])
->assertCanSeeTableRecords(
$usersInRoleB->merge($usersInRoleC)
)
->assertCanNotSeeTableRecords(
$noRolesUsers->merge($usersInRoleA)
)
->filterTable('roles', ['none'])
->assertCanSeeTableRecords(
$noRolesUsers
)
->assertCanNotSeeTableRecords(
$usersInRoleA->merge($usersInRoleB)->merge($usersInRoleC)
);
});
89 changes: 51 additions & 38 deletions app/Filament/Resources/UserResource/Pages/ListUsers.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@
use Filament\Resources\Pages\ListRecords;
use Filament\Tables\Filters\SelectFilter;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Query\Expression;
use AdvisingApp\Authorization\Models\Role;
use Filament\Tables\Actions\RestoreAction;
use Filament\Tables\Filters\TrashedFilter;
use Illuminate\Contracts\Support\Htmlable;
Expand Down Expand Up @@ -155,30 +157,62 @@ public function table(Table $table): Table
->visible((fn () => auth()->user()->can('user.*.restore'))),
SelectFilter::make('teams')
->label('Team')
->options($this->getTeamsOption())
->getSearchResultsUsing(fn (string $search) => Team::query()->where('name', 'like', '%' . $search . '%')->take(50)->pluck('name', 'id')->toArray())
->query(fn (Builder $query, array $data) => $this->teamFilter($query, $data))
->options(
fn (): array => [
'' => [
'unassigned' => 'Unassigned',
],
'Teams' => Team::query()->take(50)->orderBy('name')->pluck('name', 'id')->toArray(),
]
)
->getSearchResultsUsing(fn (string $search): array => ['Teams' => Team::query()->where(new Expression('lower(name)'), 'like', '%' . strtolower($search) . '%')->take(50)->pluck('name', 'id')->toArray()])
->query(function (Builder $query, array $data) {
if (empty($data['values'])) {
return;
}

$query->when(in_array('unassigned', $data['values']), function ($query) {
$query->whereDoesntHave('teams');
})
->{in_array('unassigned', $data['values']) ? 'orWhereHas' : 'whereHas'}('teams', function ($query) use ($data) {
$query->whereIn('team_id', array_filter($data['values'], fn ($value) => $value !== 'unassigned'));
});
})
->multiple()
->searchable()
->preload(),
SelectFilter::make('roles')
->label('Roles')
->options(
fn (): array => [
'' => [
'none' => 'None',
],
'Roles' => Role::query()->take(50)->orderBy('name')->pluck('name', 'id')->toArray(),
]
)
->getSearchResultsUsing(fn (string $search): array => ['Roles' => Role::query()->where(new Expression('lower(name)'), 'like', '%' . strtolower($search) . '%')->take(50)->orderBy('name')->pluck('name', 'id')->toArray()])
->query(
function (Builder $query, array $data) {
if (empty($data['values'])) {
return;
}

$query->when(in_array('none', $data['values']), function ($query) {
$query->whereDoesntHave('roles');
})
->{in_array('none', $data['values']) ? 'orWhereHas' : 'whereHas'}('roles', function ($query) use ($data) {
$query->whereIn('id', array_filter($data['values'], fn ($value) => $value !== 'none'));
});
}
)
->multiple()
->searchable()
->preload(),
])
->defaultSort('name', 'asc');
}

public function getTeamsOption(): array
{
$teams = Team::query()->take(50)->pluck('name', 'id')->toArray();

return [
'' => [
'unassigned' => 'Unassigned',
],
'Teams' => [
...$teams,
],
];
}

protected function getHeaderActions(): array
{
return [
Expand All @@ -188,25 +222,4 @@ protected function getHeaderActions(): array
CreateAction::make(),
];
}

protected function teamFilter(Builder $query, array $data): void
{
if (empty($data['values'])) {
return;
}

$query->where(function ($query) use ($data) {
$filteredValues = $data['values'];
$query->when(in_array('unassigned', $filteredValues), function ($query) {
$query->whereDoesntHave('teams');
})
->orWhereHas('teams', function ($query) use ($filteredValues) {
if (in_array('unassigned', $filteredValues)) {
unset($filteredValues[array_search('unassigned', $filteredValues)]);
}

$query->whereIn('team_id', $filteredValues);
});
});
}
}

0 comments on commit 758d10c

Please sign in to comment.