User export improvements 2 (#10560)
* FEATURE: Use predictable filenames inside the user archive export * FEATURE: Include badges in user archive export * FEATURE: Add user_visits table to the user archive export
This commit is contained in:
parent
43ffd4d28f
commit
5ec5fbd7ba
|
@ -13,13 +13,17 @@ module Jobs
|
|||
COMPONENTS ||= %w(
|
||||
user_archive
|
||||
user_archive_profile
|
||||
badges
|
||||
category_preferences
|
||||
visits
|
||||
)
|
||||
|
||||
HEADER_ATTRS_FOR ||= HashWithIndifferentAccess.new(
|
||||
user_archive: ['topic_title', 'categories', 'is_pm', 'post', 'like_count', 'reply_count', 'url', 'created_at'],
|
||||
user_archive_profile: ['location', 'website', 'bio', 'views'],
|
||||
badges: ['badge_id', 'badge_name', 'granted_at', 'post_id', 'seq', 'granted_manually', 'notification_id', 'featured_rank'],
|
||||
category_preferences: ['category_id', 'category_names', 'notification_level', 'dismiss_new_timestamp'],
|
||||
visits: ['visited_at', 'posts_read', 'mobile', 'time_read'],
|
||||
)
|
||||
|
||||
def execute(args)
|
||||
|
@ -36,13 +40,13 @@ module Jobs
|
|||
if respond_to? filename_method
|
||||
h[:filename] = public_send(filename_method)
|
||||
else
|
||||
h[:filename] = "#{name}-#{@current_user.username}-#{@timestamp}"
|
||||
h[:filename] = name
|
||||
end
|
||||
components.push(h)
|
||||
end
|
||||
|
||||
export_title = 'user_archive'.titleize
|
||||
filename = components.first[:filename]
|
||||
filename = "user_archive-#{@current_user.username}-#{@timestamp}"
|
||||
user_export = UserExport.create(file_name: filename, user_id: @current_user.id)
|
||||
|
||||
filename = "#{filename}-#{user_export.id}"
|
||||
|
@ -126,6 +130,29 @@ module Jobs
|
|||
end
|
||||
end
|
||||
|
||||
def badges_export
|
||||
return enum_for(:badges_export) unless block_given?
|
||||
|
||||
UserBadge
|
||||
.where(user_id: @current_user.id)
|
||||
.joins(:badge)
|
||||
.select(:badge_id, :granted_at, :post_id, :seq, :granted_by_id, :notification_id, :featured_rank)
|
||||
.order(:granted_at)
|
||||
.each do |ub|
|
||||
yield [
|
||||
ub.badge_id,
|
||||
ub.badge.display_name,
|
||||
ub.granted_at,
|
||||
ub.post_id,
|
||||
ub.seq,
|
||||
# Hide the admin's identity, simply indicate human or system
|
||||
User.human_user_id?(ub.granted_by_id),
|
||||
ub.notification_id,
|
||||
ub.featured_rank,
|
||||
]
|
||||
end
|
||||
end
|
||||
|
||||
def category_preferences_export
|
||||
return enum_for(:category_preferences_export) unless block_given?
|
||||
|
||||
|
@ -142,6 +169,22 @@ module Jobs
|
|||
end
|
||||
end
|
||||
|
||||
def visits_export
|
||||
return enum_for(:visits_export) unless block_given?
|
||||
|
||||
UserVisit
|
||||
.where(user_id: @current_user.id)
|
||||
.order(visited_at: :asc)
|
||||
.each do |uv|
|
||||
yield [
|
||||
uv.visited_at,
|
||||
uv.posts_read,
|
||||
uv.mobile,
|
||||
uv.time_read,
|
||||
]
|
||||
end
|
||||
end
|
||||
|
||||
def get_header(entity)
|
||||
if entity == 'user_list'
|
||||
header_array = HEADER_ATTRS_FOR['user_list'] + HEADER_ATTRS_FOR['user_stats'] + HEADER_ATTRS_FOR['user_profile']
|
||||
|
|
|
@ -73,8 +73,8 @@ describe Jobs::ExportUserArchive do
|
|||
end
|
||||
|
||||
expect(files.size).to eq(Jobs::ExportUserArchive::COMPONENTS.length)
|
||||
expect(files.find { |f| f.match 'user_archive-john_doe-' }).to_not be_nil
|
||||
expect(files.find { |f| f.match 'user_archive_profile-john_doe-' }).to_not be_nil
|
||||
expect(files.find { |f| f == 'user_archive.csv' }).to_not be_nil
|
||||
expect(files.find { |f| f == 'category_preferences.csv' }).to_not be_nil
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -149,6 +149,37 @@ describe Jobs::ExportUserArchive do
|
|||
end
|
||||
end
|
||||
|
||||
context 'badges' do
|
||||
let(:component) { 'badges' }
|
||||
|
||||
let(:admin) { Fabricate(:admin) }
|
||||
let(:badge1) { Fabricate(:badge) }
|
||||
let(:badge2) { Fabricate(:badge, multiple_grant: true) }
|
||||
let(:badge3) { Fabricate(:badge, multiple_grant: true) }
|
||||
let(:day_ago) { 1.day.ago }
|
||||
|
||||
it 'properly includes badge records' do
|
||||
grant_start = Time.now.utc
|
||||
BadgeGranter.grant(badge1, user)
|
||||
BadgeGranter.grant(badge2, user)
|
||||
BadgeGranter.grant(badge2, user, granted_by: admin)
|
||||
BadgeGranter.grant(badge3, user, post_id: Fabricate(:post).id)
|
||||
BadgeGranter.grant(badge3, user, post_id: Fabricate(:post).id)
|
||||
BadgeGranter.grant(badge3, user, post_id: Fabricate(:post).id)
|
||||
|
||||
data, csv_out = make_component_csv
|
||||
expect(data.length).to eq(6)
|
||||
|
||||
expect(data[0]['badge_id']).to eq(badge1.id.to_s)
|
||||
expect(data[0]['badge_name']).to eq(badge1.display_name)
|
||||
expect(data[0]['featured_rank']).to_not eq('')
|
||||
expect(DateTime.parse(data[0]['granted_at'])).to be >= DateTime.parse(grant_start.to_s)
|
||||
expect(data[2]['granted_manually']).to eq('true')
|
||||
expect(Post.find(data[3]['post_id'])).to_not be_nil
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
context 'category_preferences' do
|
||||
let(:component) { 'category_preferences' }
|
||||
|
||||
|
@ -201,4 +232,30 @@ describe Jobs::ExportUserArchive do
|
|||
end
|
||||
end
|
||||
|
||||
context 'visits' do
|
||||
let(:component) { 'visits' }
|
||||
let(:user2) { Fabricate(:user) }
|
||||
|
||||
it 'correctly exports the UserVisit table' do
|
||||
freeze_time '2017-03-01 12:00'
|
||||
|
||||
UserVisit.create(user_id: user.id, visited_at: 1.minute.ago, posts_read: 1, mobile: false, time_read: 10)
|
||||
UserVisit.create(user_id: user.id, visited_at: 2.days.ago, posts_read: 2, mobile: false, time_read: 20)
|
||||
UserVisit.create(user_id: user.id, visited_at: 1.week.ago, posts_read: 3, mobile: true, time_read: 30)
|
||||
UserVisit.create(user_id: user.id, visited_at: 1.year.ago, posts_read: 4, mobile: false, time_read: 40)
|
||||
UserVisit.create(user_id: user2.id, visited_at: 1.minute.ago, posts_read: 1, mobile: false, time_read: 50)
|
||||
|
||||
data, csv_out = make_component_csv
|
||||
|
||||
# user2's data is not mixed in
|
||||
expect(data.length).to eq(4)
|
||||
expect(data.find { |r| r['time_read'] == 50 }).to be_nil
|
||||
|
||||
expect(data[0]['visited_at']).to eq('2016-03-01')
|
||||
expect(data[0]['posts_read']).to eq('4')
|
||||
expect(data[0]['time_read']).to eq('40')
|
||||
expect(data[1]['mobile']).to eq('true')
|
||||
expect(data[3]['visited_at']).to eq('2017-03-01')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue