diff --git a/app/controllers/admin/collections_controller.rb b/app/controllers/admin/collections_controller.rb index 2698abbd45..405c779e3d 100644 --- a/app/controllers/admin/collections_controller.rb +++ b/app/controllers/admin/collections_controller.rb @@ -20,7 +20,7 @@ module Admin def batch authorize [:admin, :collection], :index? - @collection_batch_action = Admin::CollectionBatchAction.new(admin_collection_batch_action_params.merge(current_account: current_account, report_id: params[:report_id], type: 'report')) + @collection_batch_action = Admin::CollectionBatchAction.new(admin_collection_batch_action_params.merge(current_account: current_account, report_id: params[:report_id], type: action_from_button)) @collection_batch_action.save! rescue ActionController::ParameterMissing @@ -57,5 +57,13 @@ module Admin def set_collections @collections = @account.collections.includes(accepted_collection_items: :account).page(params[:page]).per(PER_PAGE) end + + def action_from_button + if params[:report] + 'report' + elsif params[:remove_from_report] + 'remove_from_report' + end + end end end diff --git a/app/controllers/admin/reports_controller.rb b/app/controllers/admin/reports_controller.rb index 44ee7206bf..f12e3da4e1 100644 --- a/app/controllers/admin/reports_controller.rb +++ b/app/controllers/admin/reports_controller.rb @@ -16,6 +16,8 @@ module Admin @report_notes = @report.notes.chronological.includes(:account) @action_logs = @report.history.includes(:target) @form = Admin::StatusBatchAction.new + @collection_form = Admin::CollectionBatchAction.new + @collections = @report.collections @statuses = @report.statuses.with_includes end diff --git a/app/javascript/entrypoints/admin.tsx b/app/javascript/entrypoints/admin.tsx index 91c3bd640a..49ab58cc5b 100644 --- a/app/javascript/entrypoints/admin.tsx +++ b/app/javascript/entrypoints/admin.tsx @@ -69,8 +69,9 @@ on('change', '#batch_checkbox_all', ({ target }) => { '.batch-table__select-all', ); - document - .querySelectorAll(batchCheckboxClassName) + target + .closest('.batch-table') + ?.querySelectorAll(batchCheckboxClassName) .forEach((content) => { content.checked = target.checked; }); @@ -112,17 +113,20 @@ on('click', '.batch-table__select-all button', () => { } }); -on('change', batchCheckboxClassName, () => { - const checkAllElement = document.querySelector( +on('change', batchCheckboxClassName, (event) => { + const targetTable = (event.target as HTMLElement).closest('.batch-table'); + if (!targetTable) return; + + const checkAllElement = targetTable.querySelector( 'input#batch_checkbox_all', ); - const selectAllMatchingElement = document.querySelector( + const selectAllMatchingElement = targetTable.querySelector( '.batch-table__select-all', ); if (checkAllElement) { const allCheckboxes = Array.from( - document.querySelectorAll(batchCheckboxClassName), + targetTable.querySelectorAll(batchCheckboxClassName), ); checkAllElement.checked = allCheckboxes.every((content) => content.checked); checkAllElement.indeterminate = diff --git a/app/models/admin/collection_batch_action.rb b/app/models/admin/collection_batch_action.rb index d08f17d747..750582191c 100644 --- a/app/models/admin/collection_batch_action.rb +++ b/app/models/admin/collection_batch_action.rb @@ -13,7 +13,12 @@ class Admin::CollectionBatchAction < Admin::BaseAction def process_action! return unless collection_ids - add_to_report! + case type + when 'report' + add_to_report! + when 'remove_from_report' + handle_remove_from_report! + end end def add_to_report! @@ -24,6 +29,13 @@ class Admin::CollectionBatchAction < Admin::BaseAction @report_id = @report.id end + def handle_remove_from_report! + return unless with_report? + + @report.collections = (@report.collections - selected_collections) + @report.save! + end + def selected_collections @report.target_account.collections.where(id: collection_ids) end diff --git a/app/views/admin/reports/show.html.haml b/app/views/admin/reports/show.html.haml index 0aa2f69ba5..bae69cca04 100644 --- a/app/views/admin/reports/show.html.haml +++ b/app/views/admin/reports/show.html.haml @@ -63,23 +63,26 @@ = render partial: 'admin/shared/status_batch_row', collection: @statuses, as: :status, locals: { f: f } - if Mastodon::Feature.collections_enabled? - %details{ open: @report.collections.any? } + %details{ open: @collections.any? } %summary - = t 'admin.reports.collections', count: @report.collections.size + = t 'admin.reports.collections', count: @collections.size - = form_with model: @form, url: batch_admin_account_collections_path(@report.target_account_id, report_id: @report.id) do |f| + = form_with model: @collection_form, url: batch_admin_account_collections_path(@report.target_account_id, report_id: @report.id) do |f| .batch-table .batch-table__toolbar %label.batch-table__toolbar__select.batch-checkbox-all + = check_box_tag :batch_checkbox_all, nil, false .batch-table__toolbar__actions = link_to safe_join([material_symbol('add'), t('admin.reports.add_to_report')]), admin_account_collections_path(@report.target_account_id, report_id: @report.id), class: 'table-action-link' + - if !@collections.empty? && @report.unresolved? + = f.button safe_join([material_symbol('close'), t('admin.collections.batch.remove_from_report')]), name: :remove_from_report, class: 'table-action-link', type: :submit .batch-table__body - - if @report.collections.empty? + - if @collections.empty? = nothing_here 'nothing-here--under-tabs' - else - = render partial: 'admin/shared/collection_batch_row', collection: @report.collections, as: :collection, locals: { f: f } + = render partial: 'admin/shared/collection_batch_row', collection: @collections, as: :collection, locals: { f: f } - if @report.unresolved? %hr.spacer/ diff --git a/config/locales/en.yml b/config/locales/en.yml index 4a95e738b4..41c80e39d0 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -349,6 +349,7 @@ en: back_to_report: Back to report page batch: add_to_report: 'Add to report #%{id}' + remove_from_report: Remove from report report: Report collection_title: Collection by %{name} contents: Contents diff --git a/spec/models/admin/collection_batch_action_spec.rb b/spec/models/admin/collection_batch_action_spec.rb index 0ed57817e0..e4ebb2439e 100644 --- a/spec/models/admin/collection_batch_action_spec.rb +++ b/spec/models/admin/collection_batch_action_spec.rb @@ -46,5 +46,15 @@ RSpec.describe Admin::CollectionBatchAction do expect(Report.last.collections).to include(collection) end end + + context 'when type is remove_from_report' do + let(:report_id) { report.id } + let(:type) { 'remove_from_report' } + + it 'does not remove report but removes collection' do + expect { subject.save! }.to change { report.reload.collections }.to([]) + .and not_change(Report, :count) + end + end end end diff --git a/spec/requests/admin/collections_spec.rb b/spec/requests/admin/collections_spec.rb index 6cb3a1ec2d..c6f1833a2b 100644 --- a/spec/requests/admin/collections_spec.rb +++ b/spec/requests/admin/collections_spec.rb @@ -6,7 +6,8 @@ RSpec.describe 'Admin Collections' do let(:account) { Fabricate(:account) } let(:other_account) { Fabricate(:account) } let(:collection) { Fabricate(:collection, account: account) } - let!(:second_collection) { Fabricate(:collection, account: account) } + let(:unreported_collection) { Fabricate(:collection, account: account) } + let(:second_collection) { Fabricate(:collection, account: account) } let(:report) { Fabricate(:report, account: other_account, target_account: account) } before do @@ -32,20 +33,49 @@ RSpec.describe 'Admin Collections' do end describe 'POST /admin/accounts/:account_id/collections/batch' do - subject { post batch_admin_account_collections_path(account_id: account.id, report_id: report_id, admin_collection_batch_action: { collection_ids: [collection.id, second_collection.id] }) } + subject { post batch_admin_account_collections_path(:account_id => account.id, :report_id => report_id, action_from_button => '', :admin_collection_batch_action => { collection_ids: [collection.id, second_collection.id] }) } context 'with a valid report' do let(:report_id) { report.id } + let(:action_from_button) { 'report' } it 'redirects to the report page' do report.collections << collection subject expect(response).to redirect_to(admin_report_path(report.id)) + expect(response.body).to be_empty + expect(response).to have_http_status(302) end end context 'with an invalid report' do let(:report_id) { nil } + let(:action_from_button) { 'report' } + + it 'redirects to the account collections page' do + subject + expect(response).to redirect_to(admin_account_collections_path(account.id)) + expect(response).to have_http_status(302) + end + end + + context 'with valid remove_from_report' do + let(:report_id) { report.id } + let(:action_from_button) { 'remove_from_report' } + + before do + report.collections << [second_collection, unreported_collection] + end + + it 'redirects to the account collections page' do + subject + expect(response).to redirect_to(admin_report_path(report.id)) + end + end + + context 'with invalid remove_from_report' do + let(:report_id) { nil } + let(:action_from_button) { 'remove_from_report' } it 'redirects to the account collections page' do subject