Working on import

This commit is contained in:
Evan Summers 2025-08-07 18:27:07 +02:00
parent 61c4aab3e4
commit dbdf20b373
7 changed files with 56 additions and 15 deletions

View File

@ -13,6 +13,7 @@ class Settings::ImportsController < Settings::BaseController
domain_blocking: 'blocked_domains_failures.csv',
bookmarks: 'bookmarks_failures.csv',
lists: 'lists_failures.csv',
filters: 'filters_failures.csv',
}.freeze
TYPE_TO_HEADERS_MAP = {
@ -22,6 +23,7 @@ class Settings::ImportsController < Settings::BaseController
domain_blocking: false,
bookmarks: false,
lists: false,
filters: false,
}.freeze
RECENT_IMPORTS_LIMIT = 10

View File

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

View File

@ -19,6 +19,7 @@ class Form::Import
domain_blocking: ['#domain'],
bookmarks: ['#uri'],
lists: ['List name', 'Account address'],
filters: ['Title', 'Context', 'Keywords', 'Action', 'Expire after'],
}.freeze
KNOWN_FIRST_HEADERS = EXPECTED_HEADERS_BY_TYPE.values.map(&:first).uniq.freeze
@ -55,6 +56,8 @@ class Form::Import
:bookmarks
elsif file_name_matches?('lists')
:lists
elsif file_name_matches?('filters') || csv_headers_match?('Keywords')
:filters
end
end
@ -102,6 +105,8 @@ class Form::Import
['#uri']
when :lists
['List name', 'Account address']
when :filters
['Title', 'Context', 'Keywords', 'Action', 'Expire after']
end
end
@ -109,19 +114,30 @@ class Form::Import
return @csv_data if defined?(@csv_data)
csv_converter = lambda do |field, field_info|
case field_info.header
when 'Show boosts', 'Notify on new posts', 'Hide notifications'
ActiveModel::Type::Boolean.new.cast(field&.downcase)
when 'Languages'
field&.split(',')&.map(&:strip)&.presence
when 'Account address'
field.strip.gsub(/\A@/, '')
when '#domain'
field&.strip&.downcase
when '#uri', 'List name'
field.strip
if :type == :filters
case field_info.header
when 'Context', 'Keywords'
field&.split(',')&.map(&:strip)&.presence
when 'Expire after'
field.blank? ? nil : Time.zone.parse(field)
else
field
end
else
field
case field_info.header
when 'Show boosts', 'Notify on new posts', 'Hide notifications'
ActiveModel::Type::Boolean.new.cast(field&.downcase)
when 'Languages'
field&.split(',')&.map(&:strip)&.presence
when 'Account address'
field.strip.gsub(/\A@/, '')
when '#domain'
field&.strip&.downcase
when '#uri', 'List name'
field.strip
else
field
end
end
end

View File

@ -18,6 +18,10 @@ class BulkImportService < BaseService
import_bookmarks!
when :lists
import_lists!
when :filters
import_filters!
else
raise NotImplementedError, "Unknown import type: #{@import.type}"
end
@import.update!(state: :finished, finished_at: Time.now.utc) if @import.processed_items == @import.total_items
@ -182,4 +186,14 @@ class BulkImportService < BaseService
[row.id]
end
end
def import_filters!
rows = @import.rows.to_a
@account.custom_filters.destroy_all if @import.overwrite?
Import::RowWorker.push_bulk(rows) do |row|
[row.id]
end
end
end

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(filters muting blocking domain_blocking) },
group_label_method: ->(group) { I18n.t("imports.type_groups.#{group.first}") },
group_method: :last,
hint: t('imports.preface'),

View File

@ -1517,6 +1517,9 @@ en:
muting_html:
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>.
filters_html:
one: You are about to <strong>replace your filters</strong> with up to <strong>%{count} filter</strong> from <strong>%{filename}</strong>.
other: You are about to <strong>replace your filters</strong> with up to <strong>%{count} filters</strong> from <strong>%{filename}</strong>.
preambles:
blocking_html:
one: You are about to <strong>block</strong> up to <strong>%{count} account</strong> from <strong>%{filename}</strong>.
@ -1536,6 +1539,9 @@ en:
muting_html:
one: You are about to <strong>mute</strong> up to <strong>%{count} account</strong> from <strong>%{filename}</strong>.
other: You are about to <strong>mute</strong> up to <strong>%{count} accounts</strong> from <strong>%{filename}</strong>.
filters_html:
one: You are about to <strong>add</strong> up to <strong>%{count} filter</strong> from <strong>%{filename}</strong>.
other: You are about to <strong>add</strong> up to <strong>%{count} filters</strong> from <strong>%{filename}</strong>.
preface: You can import data that you have exported from another server, such as a list of the people you are following or blocking.
recent_imports: Recent imports
states:
@ -1564,6 +1570,7 @@ en:
following: Following list
lists: Lists
muting: Muting list
filters: Filters
upload: Upload
invites:
delete: Deactivate

View File

@ -112,8 +112,9 @@ RSpec.describe Export do
it 'returns a csv of custom filters' do
expect(export)
.to contain_exactly(
include(/statuses/),
include(/statuses/)
contain_exactly('Title', 'Context', 'Keywords', 'Action', 'Expire after'),
include('discourse', 'home,notifications', 'discourse', 'warn', be_blank),
include(be_present)
)
end
end