Add nested group filter
continuous-integration/drone/push Build is failing Details

This commit is contained in:
philipp lang 2023-04-25 00:28:44 +02:00
parent 58756b6094
commit 884ad31086
6 changed files with 81 additions and 8 deletions

View File

@ -0,0 +1,40 @@
<?php
namespace App\Member\Data;
use App\Group;
use Illuminate\Support\Collection;
use Spatie\LaravelData\Data;
use Spatie\LaravelData\DataCollection;
class NestedGroup extends Data
{
public function __construct(
public int $id,
public string $name,
) {
}
/**
* @return Collection<int, array{name: string, id: int}>
*/
public static function forSelect(?int $parentId = null, int $level = 0): Collection
{
$groups = collect([]);
foreach (Group::where('parent_id', $parentId)->orderBy('name')->get()->toBase() as $group) {
$groups->push(['name' => str_repeat('- ', $level).$group->name, 'id' => $group->id]);
$groups = $groups->merge(static::forSelect($group->id, $level + 1));
}
return $groups;
}
/**
* @return DataCollection<int, static>
*/
public static function cacheForSelect(): DataCollection
{
return static::collection(static::forSelect());
}
}

View File

@ -22,6 +22,7 @@ class FilterScope extends Filter
public ?int $activityId = null,
public ?int $subactivityId = null,
public string $search = '',
public ?int $groupId = null,
) {
}
@ -47,6 +48,11 @@ class FilterScope extends Filter
if ($this->billKind) {
$query->where('bill_kind', BillKind::fromValue($this->billKind));
}
if ($this->groupId) {
$query->where('group_id', $this->groupId);
}
if ($this->subactivityId || $this->activityId) {
$query->whereHas('memberships', function ($q) {
$q->active();

View File

@ -3,8 +3,8 @@
namespace App\Member;
use App\Course\Resources\CourseMemberResource;
use App\Group;
use App\Lib\HasMeta;
use App\Member\Data\NestedGroup;
use App\Member\Resources\NationalityResource;
use App\Member\Resources\RegionResource;
use App\Membership\MembershipResource;
@ -104,7 +104,7 @@ class MemberResource extends JsonResource
public static function meta(): array
{
return [
'groups' => Group::select('name', 'id')->get(),
'groups' => NestedGroup::cacheForSelect(),
'filter' => FilterScope::fromRequest(request()->input('filter', '')),
];
}

View File

@ -3,6 +3,7 @@
<div class="px-6 py-2 flex border-b border-gray-600 items-center space-x-3">
<f-text :value="getFilter('search')" @input="setFilter('search', $event)" id="search" name="search" label="Suchen …" size="sm"></f-text>
<f-switch v-show="hasModule('bill')" id="ausstand" @input="setFilter('ausstand', $event)" :items="getFilter('ausstand')" label="Nur Ausstände" size="sm"></f-switch>
<f-select id="group_id" @input="setFilter('group_id', $event)" :options="data.meta.groups" :value="getFilter('group_id')" label="Gruppierung" size="sm" name="group_id"></f-select>
<f-select
v-show="hasModule('bill')"
name="billKinds"

View File

@ -184,6 +184,23 @@ class IndexTest extends TestCase
$this->assertInertiaHas('E-Mail', $emailResponse, 'data.meta.filter.bill_kind');
}
public function testItCanFilterForGroups(): void
{
$this->withoutExceptionHandling()->login()->loginNami();
$group1 = Group::factory()->create();
$group2 = Group::factory()->create();
Member::factory()->defaults()->for($group1)->create();
Member::factory()->defaults()->for($group1)->create();
Member::factory()->defaults()->for($group1)->create();
$oneResponse = $this->callFilter('member.index', ['group_id' => $group1->id]);
$twoResponse = $this->callFilter('member.index', ['group_id' => $group2->id]);
$this->assertCount(3, $this->inertia($oneResponse, 'data.data'));
$this->assertCount(0, $this->inertia($twoResponse, 'data.data'));
$this->assertInertiaHas($group1->id, $oneResponse, 'data.meta.filter.group_id');
}
public function testItFiltersForAusstand(): void
{
$this->withoutExceptionHandling()->login()->loginNami();
@ -213,11 +230,17 @@ class IndexTest extends TestCase
public function testItLoadsGroups(): void
{
$this->withoutExceptionHandling()->login()->loginNami();
Group::factory()->name('UUI')->create();
$parent1 = Group::factory()->name('par1')->create();
$child1 = Group::factory()->name('ch1')->for($parent1, 'parent')->create();
$child2 = Group::factory()->name('ch2')->for($parent1, 'parent')->create();
$parent2 = Group::factory()->name('par2')->create();
$this->withoutExceptionHandling()->login()->loginNami(12345, 'password', $parent1);
$response = $this->get('/member');
$this->assertInertiaHas('UUI', $response, 'data.meta.groups.1.name');
$this->assertInertiaHas('par1', $response, 'data.meta.groups.0.name');
$this->assertInertiaHas('- ch1', $response, 'data.meta.groups.1.name');
$this->assertInertiaHas('- ch2', $response, 'data.meta.groups.2.name');
$this->assertInertiaHas('par2', $response, 'data.meta.groups.3.name');
}
}

View File

@ -29,11 +29,14 @@ abstract class TestCase extends BaseTestCase
Auth::fake();
}
public function loginNami(int $mglnr = 12345, string $password = 'password', int $groupId = 55): self
public function loginNami(int $mglnr = 12345, string $password = 'password', int|Group $groupId = 55): self
{
Auth::success($mglnr, $password);
$this->withNamiSettings($mglnr, $password, $groupId);
Group::factory()->create(['nami_id' => $groupId]);
$group = is_int($groupId)
? Group::factory()->create(['nami_id' => $groupId])
: $groupId;
$this->withNamiSettings($mglnr, $password, $group->id);
return $this;
}