WIP: export/import for account notes

pull/32430/head
Emelia Smith 2024-10-11 22:02:11 +02:00
parent e15befebbd
commit 3ee385ed2e
No known key found for this signature in database
11 changed files with 95 additions and 3 deletions

View File

@ -0,0 +1,19 @@
# frozen_string_literal: true
module Settings
module Exports
class AccountNotesController < BaseController
include Settings::ExportControllerConcern
def index
send_export_file
end
private
def export_data
@export.to_account_notes_csv
end
end
end
end

View File

@ -31,6 +31,7 @@ class BulkImport < ApplicationRecord
domain_blocking: 3,
bookmarks: 4,
lists: 5,
account_notes: 6,
}
enum :state, {

View File

@ -55,6 +55,14 @@ class Export
end
end
def to_account_notes_csv
CSV.generate(headers: ['Account address', 'Account note'], write_headers: true, encoding: Encoding::UTF_8) do |csv|
account.account_notes.includes(:target_account).reorder(id: :desc).each do |account_note|
csv << [acct(account_note.target_account), account_note.comment]
end
end
end
private
def to_csv(accounts)

View File

@ -19,6 +19,7 @@ class Form::Import
domain_blocking: ['#domain'],
bookmarks: ['#uri'],
lists: ['List name', 'Account address'],
account_notes: ['Account address', 'Account note'],
}.freeze
KNOWN_FIRST_HEADERS = EXPECTED_HEADERS_BY_TYPE.values.map(&:first).uniq.freeze
@ -32,6 +33,7 @@ class Form::Import
'#domain' => 'domain',
'#uri' => 'uri',
'List name' => 'list_name',
'Account note' => 'comment',
}.freeze
class EmptyFileError < StandardError; end
@ -55,6 +57,8 @@ class Form::Import
:bookmarks
elsif file_name_matches?('lists')
:lists
elsif csv_headers_match?('Account note') || file_name_matches?('account_notes')
:account_notes
end
end
@ -102,6 +106,8 @@ class Form::Import
['#uri']
when :lists
['List name', 'Account address']
when :account_notes
['Account address', 'Account note']
end
end
@ -118,7 +124,7 @@ class Form::Import
field.strip.gsub(/\A@/, '')
when '#domain'
field&.strip&.downcase
when '#uri', 'List name'
when '#uri', 'List name', 'Account note'
field.strip
else
field

View File

@ -14,6 +14,11 @@ class ExportSummary
prefix: true
)
delegate(
:account_notes,
to: :account
)
def initialize(account)
@account = account
@counts = populate_counts
@ -47,6 +52,10 @@ class ExportSummary
counts[:muting].value
end
def total_account_notes
counts[:account_notes].value
end
def total_statuses
account.statuses_count
end
@ -64,6 +73,7 @@ class ExportSummary
domain_blocks: account_domain_blocks.async_count,
owned_lists: account_owned_lists.async_count,
muting: account_muting.async_count,
account_notes: account_notes.async_count,
storage: account_media_attachments.async_sum(:file_file_size),
}
end

View File

@ -7,7 +7,7 @@ class BulkImportRowService
@type = row.bulk_import.type.to_sym
case @type
when :following, :blocking, :muting, :lists
when :following, :blocking, :muting, :lists, :account_notes
target_acct = @data['acct']
target_domain = domain(target_acct)
@target_account = stoplight_wrapper(target_domain).run { ResolveAccountService.new.call(target_acct, { check_delivery_availability: true }) }
@ -39,6 +39,10 @@ class BulkImportRowService
FollowService.new.call(@account, @target_account) unless @account.id == @target_account.id
list.accounts << @target_account
when :account_notes
@note = AccountNote.find_or_initialize_by(account: @account, target_account: @target_account)
@note.comment = @data['comment']
@note.save! if @note.changed?
end
true

View File

@ -18,6 +18,8 @@ class BulkImportService < BaseService
import_bookmarks!
when :lists
import_lists!
when :account_notes
import_account_notes!
end
@import.update!(state: :finished, finished_at: Time.now.utc) if @import.processed_items == @import.total_items
@ -182,4 +184,32 @@ class BulkImportService < BaseService
[row.id]
end
end
def import_account_notes!
rows_by_acct = extract_rows_by_acct
if @import.overwrite?
@account.account_notes.reorder(nil).find_each do |account_note|
row = rows_by_acct.delete(account_note.target_account.acct)
if row.nil?
account_note.destroy!
else
row.destroy
@import.processed_items += 1
@import.imported_items += 1
@note = AccountNote.find_or_initialize_by(account: @account, target_account: row.data['acct'])
@note.comment = row.data['comment']
@note.save! if @note.changed?
end
end
# Save pending infos due to `overwrite?` handling
@import.save!
end
Import::RowWorker.push_bulk(rows) do |row|
[row.id]
end
end
end

View File

@ -12,6 +12,10 @@
%th= t('accounts.posts_tab_heading')
%td= number_with_delimiter @export_summary.total_statuses
%td
%tr
%th= t('exports.account_notes')
%td= number_with_delimiter @export_summary.total_account_notes
%td= table_link_to 'download', t('exports.csv'), settings_exports_account_notes_path(format: :csv)
%tr
%th= t('admin.accounts.follows')
%td= number_with_delimiter @export_summary.total_follows

View File

@ -5,7 +5,7 @@
.field-group
= f.input :type,
as: :grouped_select,
collection: { constructive: %i(following bookmarks lists), destructive: %i(muting blocking domain_blocking) },
collection: { constructive: %i(following bookmarks lists), destructive: %i(muting blocking domain_blocking), other: %i(account_notes) },
group_label_method: ->(group) { I18n.t("imports.type_groups.#{group.first}") },
group_method: :last,
hint: t('imports.preface'),

View File

@ -1367,6 +1367,9 @@ en:
overwrite: Overwrite
overwrite_long: Replace current records with the new ones
overwrite_preambles:
account_notes_html:
one: You are about to import <strong>%{count} account note</strong> from <strong>%{filename}</strong>. Any existing account note on this account will be overwritten.
other: You are about to import <strong>%{count} account notes</strong> from <strong>%{filename}</strong>. Any existing account notes on these accounts will be overwritten.
blocking_html:
one: You are about to <strong>replace your block list</strong> with up to <strong>%{count} account</strong> from <strong>%{filename}</strong>.
other: You are about to <strong>replace your block list</strong> with up to <strong>%{count} accounts</strong> from <strong>%{filename}</strong>.
@ -1386,6 +1389,9 @@ en:
one: You are about to <strong>replace your list of muted account</strong> with up to <strong>%{count} account</strong> from <strong>%{filename}</strong>.
other: You are about to <strong>replace your list of muted accounts</strong> with up to <strong>%{count} accounts</strong> from <strong>%{filename}</strong>.
preambles:
account_notes_html:
one: You are about to import <strong>%{count} account note</strong> from <strong>%{filename}</strong>.
other: You are about to import <strong>%{count} account notes</strong> from <strong>%{filename}</strong>.
blocking_html:
one: You are about to <strong>block</strong> up to <strong>%{count} account</strong> from <strong>%{filename}</strong>.
other: You are about to <strong>block</strong> up to <strong>%{count} accounts</strong> from <strong>%{filename}</strong>.
@ -1415,6 +1421,7 @@ en:
success: Your data was successfully uploaded and will be processed in due time
time_started: Started at
titles:
account_notes: Importing account notes
blocking: Importing blocked accounts
bookmarks: Importing bookmarks
domain_blocking: Importing blocked domains
@ -1425,6 +1432,7 @@ en:
type_groups:
constructive: Follows & Bookmarks
destructive: Blocks & mutes
other: Other
types:
blocking: Blocking list
bookmarks: Bookmarks
@ -1432,6 +1440,7 @@ en:
following: Following list
lists: Lists
muting: Muting list
account_notes: Account notes
upload: Upload
invites:
delete: Deactivate

View File

@ -26,6 +26,7 @@ namespace :settings do
resources :follows, only: :index, controller: :following_accounts
resources :blocks, only: :index, controller: :blocked_accounts
resources :mutes, only: :index, controller: :muted_accounts
resources :account_notes, only: :index, controller: :account_notes
resources :lists, only: :index
resources :domain_blocks, only: :index, controller: :blocked_domains
resources :bookmarks, only: :index