From 884ad31086402cd4cf5794ae52b973da9b0e5828 Mon Sep 17 00:00:00 2001 From: philipp lang Date: Tue, 25 Apr 2023 00:28:44 +0200 Subject: [PATCH] Add nested group filter --- app/Member/Data/NestedGroup.php | 40 ++++++++++++++++++++++++++++ app/Member/FilterScope.php | 6 +++++ app/Member/MemberResource.php | 4 +-- resources/js/views/member/VIndex.vue | 1 + tests/Feature/Member/IndexTest.php | 29 +++++++++++++++++--- tests/TestCase.php | 9 ++++--- 6 files changed, 81 insertions(+), 8 deletions(-) create mode 100644 app/Member/Data/NestedGroup.php diff --git a/app/Member/Data/NestedGroup.php b/app/Member/Data/NestedGroup.php new file mode 100644 index 00000000..68007842 --- /dev/null +++ b/app/Member/Data/NestedGroup.php @@ -0,0 +1,40 @@ + + */ + 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 + */ + public static function cacheForSelect(): DataCollection + { + return static::collection(static::forSelect()); + } +} diff --git a/app/Member/FilterScope.php b/app/Member/FilterScope.php index 6ca8ea5f..546b5394 100644 --- a/app/Member/FilterScope.php +++ b/app/Member/FilterScope.php @@ -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(); diff --git a/app/Member/MemberResource.php b/app/Member/MemberResource.php index f80c00cf..fda33d14 100644 --- a/app/Member/MemberResource.php +++ b/app/Member/MemberResource.php @@ -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', '')), ]; } diff --git a/resources/js/views/member/VIndex.vue b/resources/js/views/member/VIndex.vue index c234689f..bbc321a2 100644 --- a/resources/js/views/member/VIndex.vue +++ b/resources/js/views/member/VIndex.vue @@ -3,6 +3,7 @@
+ 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'); } } diff --git a/tests/TestCase.php b/tests/TestCase.php index 784e1be6..95d5bbcd 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -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; }