From 3e9c3d52885e8648e994599376291a306f63cfee Mon Sep 17 00:00:00 2001 From: Wotuu Date: Fri, 15 Nov 2024 14:43:56 +0100 Subject: [PATCH] #2611 Route publishing page now shows an option to enable/disable route publishing. When disabled, any scheduled route publishes will not trigger. --- .../Controllers/Ajax/AjaxTeamController.php | 13 ++++++++ .../Team/TeamRoutePublishingFormRequest.php | 30 +++++++++++++++++++ app/Models/Team.php | 22 +++++++------- app/Policies/TeamPolicy.php | 5 ++++ ...blishing_enabled_column_to_teams_table.php | 28 +++++++++++++++++ lang/en_US/js.php | 1 + lang/en_US/view_team.php | 5 +++- .../assets/js/custom/inline/team/edit.js | 16 +++++++++- resources/views/team/edit.blade.php | 3 ++ .../team/edittabs/routepublishing.blade.php | 11 +++++++ routes/web.php | 1 + 11 files changed, 123 insertions(+), 12 deletions(-) create mode 100644 app/Http/Requests/Team/TeamRoutePublishingFormRequest.php create mode 100644 database/migrations/2024_11_15_133655_add_route_publishing_enabled_column_to_teams_table.php diff --git a/app/Http/Controllers/Ajax/AjaxTeamController.php b/app/Http/Controllers/Ajax/AjaxTeamController.php index 55e159a96..1513e9242 100644 --- a/app/Http/Controllers/Ajax/AjaxTeamController.php +++ b/app/Http/Controllers/Ajax/AjaxTeamController.php @@ -4,6 +4,7 @@ use App\Http\Controllers\Controller; use App\Http\Requests\Team\TeamDefaultRoleFormRequest; +use App\Http\Requests\Team\TeamRoutePublishingFormRequest; use App\Models\DungeonRoute\DungeonRoute; use App\Models\Patreon\PatreonAdFreeGiveaway; use App\Models\Patreon\PatreonBenefit; @@ -41,6 +42,18 @@ public function changeDefaultRole(TeamDefaultRoleFormRequest $request, Team $tea return response()->noContent(); } + /** + * @throws AuthorizationException + */ + public function changeRoutePublishing(TeamRoutePublishingFormRequest $request, Team $team): Response + { + $this->authorize('change-route-publishing', $team); + + $team->update(['route_publishing_enabled' => $request->get('enabled')]); + + return response()->noContent(); + } + /** * @return array|Application|ResponseFactory|Response * diff --git a/app/Http/Requests/Team/TeamRoutePublishingFormRequest.php b/app/Http/Requests/Team/TeamRoutePublishingFormRequest.php new file mode 100644 index 000000000..b90857969 --- /dev/null +++ b/app/Http/Requests/Team/TeamRoutePublishingFormRequest.php @@ -0,0 +1,30 @@ + ['required', Rule::in(0, 1)], + ]; + } +} diff --git a/app/Models/Team.php b/app/Models/Team.php index d456cbacd..5a9f6a95e 100644 --- a/app/Models/Team.php +++ b/app/Models/Team.php @@ -22,22 +22,22 @@ * @property string $description * @property string $invite_code * @property string $default_role + * @property boolean $route_publishing_enabled * * @property Collection $teamUsers * @property Collection $members - * @property Collection $dungeonroutes + * @property Collection $dungeonRoutes * * @mixin Eloquent */ class Team extends Model { use HasIconFile; + use GeneratesPublicKey; protected $visible = ['name', 'description', 'public_key']; - protected $fillable = ['default_role']; - - use GeneratesPublicKey; + protected $fillable = ['default_role', 'route_publishing_enabled']; /** * https://stackoverflow.com/a/34485411/771270 @@ -57,7 +57,7 @@ public function members(): BelongsToMany return $this->belongsToMany(User::class, 'team_users'); } - public function dungeonroutes(): HasMany + public function dungeonRoutes(): HasMany { return $this->hasMany(DungeonRoute::class); } @@ -67,7 +67,7 @@ public function dungeonroutes(): HasMany */ public function getVisibleRouteCount(): int { - return $this->dungeonroutes()->whereIn('published_state_id', PublishedState::whereIn('name', [ + return $this->dungeonRoutes()->whereIn('published_state_id', PublishedState::whereIn('name', [ PublishedState::TEAM, PublishedState::WORLD, PublishedState::WORLD_WITH_LINK, ])->get()->pluck('id'))->count(); } @@ -76,6 +76,7 @@ public function getVisibleRouteCount(): int * Checks if a user can add/remove a route to this team or not. * * @param User $user + * @return bool */ public function canAddRemoveRoute(User $user): bool { @@ -259,6 +260,7 @@ public function isUserAdmin(User $user): bool public function isUserCollaborator(User $user): bool { $userRole = $this->getUserRole($user); + return $userRole !== null && $this->getUserRole($user) !== TeamUser::ROLE_MEMBER; } @@ -329,7 +331,7 @@ public function removeMember(User $member): bool $member->patreonAdFreeGiveaway->delete(); } - $this->dungeonroutes()->where('team_id', $this->id)->where('author_id', $member->id)->update(['team_id' => null]); + $this->dungeonRoutes()->where('team_id', $this->id)->where('author_id', $member->id)->update(['team_id' => null]); $result = TeamUser::where('team_id', $this->id)->where('user_id', $member->id)->delete(); } catch (Exception) { logger()->error('Unable to remove member from team', [ @@ -379,7 +381,7 @@ public function getNewAdminUponAdminAccountDeletion(User $user): ?User )); } - $roles = TeamUser::ALL_ROLES; + $roles = TeamUser::ALL_ROLES; /** @var TeamUser|null $newOwner */ $newOwner = $this->teamUsers->where('user_id', '!=', $user->id) ->sortByDesc(static fn($obj, $key) => $roles[$obj->role]) @@ -391,7 +393,7 @@ public function getNewAdminUponAdminAccountDeletion(User $user): ?User public function getAvailableTags(): Collection { return Tag::where('tag_category_id', TagCategory::ALL[TagCategory::DUNGEON_ROUTE_TEAM]) - ->whereIn('model_id', $this->dungeonroutes->pluck('id')) + ->whereIn('model_id', $this->dungeonRoutes->pluck('id')) ->get(); } @@ -416,7 +418,7 @@ protected static function boot(): void } // Delete all tags team tags belonging to our routes Tag::where('tag_category_id', TagCategory::ALL[TagCategory::DUNGEON_ROUTE_TEAM]) - ->whereIn('model_id', $team->dungeonroutes->pluck('id')->toArray()) + ->whereIn('model_id', $team->dungeonRoutes->pluck('id')->toArray()) ->delete(); // Remove all users associated with this team TeamUser::where('team_id', $team->id)->delete(); diff --git a/app/Policies/TeamPolicy.php b/app/Policies/TeamPolicy.php index 67f4e5f8a..fd7df4de7 100644 --- a/app/Policies/TeamPolicy.php +++ b/app/Policies/TeamPolicy.php @@ -43,6 +43,11 @@ public function changeDefaultRole(User $user, Team $team): bool return $team->getUserRole($user) === TeamUser::ROLE_ADMIN; } + public function changeRoutePublishing(User $user, Team $team): bool + { + return $team->getUserRole($user) === TeamUser::ROLE_ADMIN; + } + public function removeMember(User $user, Team $team, User $member): bool { return $team->canRemoveMember($user, $member); diff --git a/database/migrations/2024_11_15_133655_add_route_publishing_enabled_column_to_teams_table.php b/database/migrations/2024_11_15_133655_add_route_publishing_enabled_column_to_teams_table.php new file mode 100644 index 000000000..bce42d8c8 --- /dev/null +++ b/database/migrations/2024_11_15_133655_add_route_publishing_enabled_column_to_teams_table.php @@ -0,0 +1,28 @@ +boolean('route_publishing_enabled')->default(false)->after('default_role'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('teams', function (Blueprint $table) { + $table->dropColumn('route_publishing_enabled'); + }); + } +}; diff --git a/lang/en_US/js.php b/lang/en_US/js.php index 7453a7c70..b4f56ecb5 100644 --- a/lang/en_US/js.php +++ b/lang/en_US/js.php @@ -368,6 +368,7 @@ 'admin_label' => 'Own', 'change_role_success' => 'Permissions updated', 'change_default_role_success' => 'Default role updated', + 'change_route_publishing_success' => 'Route publishing settings updated', 'team_admin' => 'Administrate team', 'team_moderator' => 'Moderate team', 'team_collaborator' => 'Edit routes', diff --git a/lang/en_US/view_team.php b/lang/en_US/view_team.php index e63348352..be689af09 100644 --- a/lang/en_US/view_team.php +++ b/lang/en_US/view_team.php @@ -24,7 +24,10 @@ 'members' => 'Members', ], 'routepublishing' => [ - 'title' => 'Route publishing', + 'title' => 'Route publishing', + 'warning' => 'When route publishing is enabled, all team members with role Moderator or Admin can adjust the published state of all your routes attached to this team.', + 'description' => 'Route publishing allows you to publish routes with the world on a schedule. You can set a date/time per route when they will automatically be put in Published state and be visible to the world.', + 'enabled' => 'Enabled', ], 'routes' => [ 'title' => 'Route list', diff --git a/resources/assets/js/custom/inline/team/edit.js b/resources/assets/js/custom/inline/team/edit.js index 870e7c62b..684a628c5 100644 --- a/resources/assets/js/custom/inline/team/edit.js +++ b/resources/assets/js/custom/inline/team/edit.js @@ -90,6 +90,20 @@ class TeamEdit extends InlineCode { } }); }); + + $(this.options.routePublishingEnabledSelector).on('change', function(){ + $.ajax({ + type: 'PUT', + url: `/ajax/team/${self.options.teamPublicKey}/routepublishing`, + dataType: 'json', + data: { + enabled: parseInt($(this).val()) + }, + success: function () { + showSuccessNotification(lang.get('messages.change_route_publishing_success')); + } + }); + }); } /** @@ -250,7 +264,7 @@ class TeamEdit extends InlineCode { } } - let result = ''; + let result; if (roles.length === 0) { let icon = self._getIcon(data); diff --git a/resources/views/team/edit.blade.php b/resources/views/team/edit.blade.php index dd91ddef3..328bfb5f2 100644 --- a/resources/views/team/edit.blade.php +++ b/resources/views/team/edit.blade.php @@ -69,6 +69,9 @@ @include('common.general.inline', ['path' => 'team/edit', 'options' => [ 'dependenciesById' => [$routesTableInlineId], 'routesTableInlineId' => $routesTableInlineId, + + 'routePublishingEnabledSelector' => '#route_publishing_enabled_checkbox', + 'data' => $data, 'teamName' => $team->name, 'teamPublicKey' => $team->public_key, diff --git a/resources/views/team/edittabs/routepublishing.blade.php b/resources/views/team/edittabs/routepublishing.blade.php index 080b7773c..826903b75 100644 --- a/resources/views/team/edittabs/routepublishing.blade.php +++ b/resources/views/team/edittabs/routepublishing.blade.php @@ -11,9 +11,20 @@

{{ __('view_team.edittabs.routepublishing.title') }}

+ @component('common.general.alert', ['type' => 'warning', 'name' => 'team-route-publishing-warning']) + {{ __('view_team.edittabs.routepublishing.warning') }} + @endcomponent +
{{ __('view_team.edittabs.routepublishing.description') }}
+
+ {!! Form::label('route_publishing_enabled', __('view_team.edittabs.routepublishing.enabled')) !!} + {!! Form::checkbox('route_publishing_enabled', 1, $team->route_publishing_enabled ?? 0, [ + 'id' => 'route_publishing_enabled_checkbox', + 'class' => 'form-control left_checkbox' + ]) !!} +
@include('common.dungeonroute.table', [ 'inlineId' => $inlineId, diff --git a/routes/web.php b/routes/web.php index 320eef654..dbe4abbff 100644 --- a/routes/web.php +++ b/routes/web.php @@ -504,6 +504,7 @@ // Teams Route::prefix('team/{team}')->group(static function () { Route::put('/changedefaultrole', (new AjaxTeamController())->changeDefaultRole(...)); + Route::put('/routepublishing', (new AjaxTeamController())->changeRoutePublishing(...)); Route::put('/changerole', (new AjaxTeamController())->changeRole(...)); Route::post('/route/{dungeonroute}', (new AjaxTeamController())->addRoute(...)); Route::delete('/member/{user}', (new AjaxTeamController())->removeMember(...));