From c5d6f2ad21effab5cc813ac51a6cb77d44908988 Mon Sep 17 00:00:00 2001 From: Edward Hibbert Date: Mon, 12 Aug 2024 11:51:57 +0100 Subject: [PATCH] Allow network coordinators to remove host role on a group. --- lang/en/groups.php | 1 + lang/fr-BE/groups.php | 1 + lang/fr/groups.php | 1 + resources/js/components/GroupPage.vue | 6 ++++ resources/js/components/GroupVolunteer.vue | 13 +++++++++ resources/js/components/GroupVolunteers.vue | 2 +- resources/js/mixins/group.js | 3 ++ resources/js/store/volunteers.js | 10 +++++++ resources/views/group/view.blade.php | 2 ++ tests/Feature/Groups/GroupHostTest.php | 31 +++++++++++++++++++++ 10 files changed, 69 insertions(+), 1 deletion(-) diff --git a/lang/en/groups.php b/lang/en/groups.php index 8bb447603..3348c93bd 100644 --- a/lang/en/groups.php +++ b/lang/en/groups.php @@ -89,6 +89,7 @@ 'events' => 'event|events', 'no_volunteers' => 'There are no volunteers in this group', 'remove_volunteer' => 'Remove Volunteer', + 'remove_host_role' => 'Remove Host role', 'make_host' => 'Make Host', 'not_counting' => 'Not counting toward this group\'s environmental impact is|Not counting toward this group\'s environmental impact are', 'calendar_copy_title' => 'Access all group events in your personal calendar', diff --git a/lang/fr-BE/groups.php b/lang/fr-BE/groups.php index 732540ad4..37540c624 100644 --- a/lang/fr-BE/groups.php +++ b/lang/fr-BE/groups.php @@ -88,6 +88,7 @@ 'events' => 'évenement|évenements', 'group_facts' => 'Réalisations du Repair Café', 'make_host' => 'Nommer organisateur', + 'remove_host_role' => 'Retirer rôle d\'organisateur', 'not_counting' => 'L\'impact environnemental de ce Repair Café n\'est pas pris en compte', 'no_volunteers' => 'Il n\'y a pas de bénévoles dans ce repair café', 'read_less' => ' LIRE MOINS', diff --git a/lang/fr/groups.php b/lang/fr/groups.php index e2ab0af84..14d7f391b 100644 --- a/lang/fr/groups.php +++ b/lang/fr/groups.php @@ -88,6 +88,7 @@ 'events' => 'évenement|évenements', 'group_facts' => 'Réalisations du Repair Café', 'make_host' => 'Nommer organisateur', + 'remove_host_role' => 'Retirer rôle d\'organisateur', 'not_counting' => 'L\'impact environnemental de ce Repair Café n\'est pas pris en compte', 'no_volunteers' => 'Il n\'y a pas de bénévoles dans ce repair café', 'read_less' => ' LIRE MOINS', diff --git a/resources/js/components/GroupPage.vue b/resources/js/components/GroupPage.vue index 1202ac867..594651a39 100644 --- a/resources/js/components/GroupPage.vue +++ b/resources/js/components/GroupPage.vue @@ -92,6 +92,11 @@ export default { required: false, default: false }, + candemote: { + type: Boolean, + required: false, + default: false + }, canSeeDelete: { type: Boolean, required: false, @@ -164,6 +169,7 @@ export default { // computed properties once we have good access to the session on the client. this.initialGroup.idgroups = this.idgroups this.initialGroup.canedit = this.canedit + this.initialGroup.candemote = this.candemote this.initialGroup.ingroup = this.ingroup this.$store.dispatch('groups/set', this.initialGroup) diff --git a/resources/js/components/GroupVolunteer.vue b/resources/js/components/GroupVolunteer.vue index 2633366fd..2fb4cfa1d 100644 --- a/resources/js/components/GroupVolunteer.vue +++ b/resources/js/components/GroupVolunteer.vue @@ -38,6 +38,7 @@ + {{ __('groups.remove_host_role') }} {{ __('groups.make_host') }} {{ __('groups.remove_volunteer') }} @@ -67,6 +68,11 @@ export default { required: false, default: false }, + candemote: { + type: Boolean, + required: false, + default: false + }, }, data () { return { @@ -140,6 +146,13 @@ export default { this.error = e.message } }, + async removeHostRole() { + try { + await this.$store.dispatch('volunteers/removehost', this.volunteer.id) + } catch (e) { + this.error = e.message + } + }, confirm() { this.$refs.confirm.show() } diff --git a/resources/js/components/GroupVolunteers.vue b/resources/js/components/GroupVolunteers.vue index 2c5d5b31c..5bd9affc0 100644 --- a/resources/js/components/GroupVolunteers.vue +++ b/resources/js/components/GroupVolunteers.vue @@ -12,7 +12,7 @@
- +
diff --git a/resources/js/mixins/group.js b/resources/js/mixins/group.js index 70b913cae..661c5fd15 100644 --- a/resources/js/mixins/group.js +++ b/resources/js/mixins/group.js @@ -11,6 +11,9 @@ export default { canedit() { return this.group ? this.group.canedit : false }, + candemote() { + return this.group ? this.group.candemote : false + }, ingroup() { return this.group ? this.group.ingroup : false } diff --git a/resources/js/store/volunteers.js b/resources/js/store/volunteers.js index e11cb653b..049aad9db 100644 --- a/resources/js/store/volunteers.js +++ b/resources/js/store/volunteers.js @@ -34,6 +34,9 @@ export default { }, makeHost(state, id) { state.listGroup[id].host = true + }, + removeHost(state, id) { + state.listGroup[id].host = false } }, actions: { @@ -58,6 +61,13 @@ export default { host: true }) commit('makeHost', id) + }, + async removehost({commit, dispatch}, id) { + const vol = this.state.volunteers.listGroup[id] + const ret = await axios.patch('/api/v2/groups/' + vol.group + '/volunteers/' + vol.user, { + host: false + }) + commit('removeHost', id) } }, } \ No newline at end of file diff --git a/resources/views/group/view.blade.php b/resources/views/group/view.blade.php index 8e561640b..06ba74af7 100644 --- a/resources/views/group/view.blade.php +++ b/resources/views/group/view.blade.php @@ -43,6 +43,7 @@ } $can_edit_group = App\Helpers\Fixometer::hasRole($user, 'Administrator') || $isCoordinatorForGroup || $is_host_of_group; + $can_demote = App\Helpers\Fixometer::hasRole($user, 'Administrator') || $isCoordinatorForGroup; $can_see_delete = App\Helpers\Fixometer::hasRole($user, 'Administrator'); $can_perform_delete = $can_see_delete && $group->canDelete(); @@ -148,6 +149,7 @@ :top-devices="{{ json_encode($top, JSON_INVALID_UTF8_IGNORE) }}" :events="{{ json_encode($expanded_events, JSON_INVALID_UTF8_IGNORE) }}" :canedit="{{ $can_edit_group ? 'true' : 'false' }}" + :candemote="{{ $can_demote ? 'true' : 'false' }}" :can-see-delete="{{ $can_see_delete ? 'true' : 'false' }}" :can-perform-delete="{{ $can_perform_delete ? 'true' : 'false' }}" calendar-copy-url="{{ $showCalendar ? url("/calendar/group/{$group->idgroups}") : '' }}" diff --git a/tests/Feature/Groups/GroupHostTest.php b/tests/Feature/Groups/GroupHostTest.php index c288521f1..0b09d471b 100644 --- a/tests/Feature/Groups/GroupHostTest.php +++ b/tests/Feature/Groups/GroupHostTest.php @@ -114,4 +114,35 @@ public function testHostMakeHost() $this->expectException(AuthenticationException::class); $response = $this->delete("/api/v2/groups/{$this->idgroups}/volunteers/{$host->id}?api_token=" . $host->api_token); } + + public function providerTrueFalse() + { + return [ + [false], + [true], + ]; + } + + /** + * @dataProvider providerTrueFalse + */ + public function testNetworkCoordinatorDemoteHost($addToNetwork) { + $host = User::factory()->host()->create(); + $this->group->addVolunteer($host); + $this->group->makeMemberAHost($host); + + $coordinator = User::factory()->networkCoordinator()->create(); + + if ($addToNetwork) { + $this->network->addCoordinator($coordinator); + } else { + $this->expectException(AuthenticationException::class); + } + + $response = $this->patch("/api/v2/groups/{$this->idgroups}/volunteers/{$host->id}?api_token=".$coordinator->api_token, [ + 'host' => true, + ]); + + $response->assertSuccessful(); + } }