diff --git a/app/controllers/admin/reviews_controller.rb b/app/controllers/admin/reviews_controller.rb index 5fe1f68f..7cc7955f 100644 --- a/app/controllers/admin/reviews_controller.rb +++ b/app/controllers/admin/reviews_controller.rb @@ -8,6 +8,7 @@ def initialize @reviews = T.let(nil, T.nilable(Review::RelationType)) @review = T.let(nil, T.nilable(Review)) @author = T.let(nil, T.nilable(User)) + @section = T.let(nil, T.nilable(Section)) end class IndexParams < T::Struct @@ -33,6 +34,7 @@ def show typed_params = TypedParams[ShowParams].new.extract!(params) @review = Review.find(typed_params.id) @author = @review.user + @section = T.must(@review.section) end class UpdateParams < T::Struct @@ -60,4 +62,31 @@ def update redirect_to(admin_review_path(@review)) end + + class UpdateAllParams < T::Struct + const :status, Review::Status + end + + # PATCH/PUT /admin/reviews/all + sig { void } + def update_all_pending + typed_params = TypedParams[UpdateAllParams].new.extract!(params) + status = typed_params.status + + pending_reviews = T.let(T.unsafe(Review.all.where(status: :pending)).to_a, T::Array[Review]) + pending_reviews.map do |review| + case status + when Review::Status::Approved + review.approve! + when Review::Status::Rejected + review.reject! + when Review::Status::Pending + review.set_pending! + else + T.absurd(status) + end + end + + redirect_to(admin_reviews_path) + end end diff --git a/app/views/admin/reviews/index.html.erb b/app/views/admin/reviews/index.html.erb index bef6e915..75060d52 100644 --- a/app/views/admin/reviews/index.html.erb +++ b/app/views/admin/reviews/index.html.erb @@ -2,6 +2,10 @@ <%= render "shared/page_header", title: "Admin: Reviews", breadcrumbs: [{ name: "Home", link: "/" }, { name: "Admin: Reviews", link: admin_reviews_path }] %> +
+ <%= button_to "Approve all", [:admin, :reviews, :all], method: :patch, params: { status: "approved" }, class: "inline-flex items-center rounded-md border border-transparent bg-red-600 px-6 py-3 text-base font-medium text-white shadow-sm hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-red-500 focus:ring-offset-2" %> +
+
<%= render "shared/list", collection: @reviews do |review| %> <%= render "shared/list_item", diff --git a/config/routes.rb b/config/routes.rb index 8f033d46..8413c053 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -28,6 +28,8 @@ end namespace :admin do + put "/reviews/all", to: "reviews#update_all_pending" + patch "/reviews/all", to: "reviews#update_all_pending" resources :reviews end diff --git a/test/integration/admin/reviews_controller_test.rb b/test/integration/admin/reviews_controller_test.rb index c50943fc..dacc2f13 100644 --- a/test/integration/admin/reviews_controller_test.rb +++ b/test/integration/admin/reviews_controller_test.rb @@ -112,4 +112,23 @@ class Admin::ReviewsControllerTest < ActionDispatch::IntegrationTest assert_equal 0, reviewer.notification_token_count end end + + describe "PATCH/PUT /admin/review/all" do + it "approves all pending reviews" do + create_current_term + reviewer = create(:user, notification_token_count: 0) + reviews = create_list(:review, 10, user: reviewer) + T.unsafe(NotifyUserAboutApprovedReviewJob).expects(:perform_later).once + T.unsafe(NotifyUserAboutRejectedReviewJob).expects(:perform_later).never + + sign_in create(:user, admin: true) + patch "/admin/reviews/all", params: { status: "approved" } + + reviewer.reload + + assert_response :found + assert_redirected_to(admin_reviews_path) + assert_equal 10, reviewer.notification_token_count + end + end end