/
courses_presenter.rb
165 lines (132 loc) · 4.36 KB
/
courses_presenter.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
# frozen_string_literal: true
require_dependency "#{Rails.root}/lib/word_count"
require_dependency "#{Rails.root}/lib/analytics/histogram_plotter"
#= Presenter for courses / campaign view
class CoursesPresenter
attr_reader :current_user, :campaign_param
def initialize(current_user:, campaign_param: nil, courses_list: nil, page: nil, tag: nil)
@current_user = current_user
@campaign_param = campaign_param
@page = page
@tag = tag
@courses_list = courses_list || campaign_courses
end
def campaign_courses
return unless campaign
# Those with campaign editing rights can see the private courses
can_remove_course? ? campaign.courses : campaign.courses.nonprivate
end
def user_courses
return unless current_user
current_user.courses.current_and_future
end
def campaign
@campaign ||= Campaign.find_by(slug: campaign_param)
end
def campaign_articles
return tag_articles if @tag
articles = campaign.articles_courses.tracked
.includes(article: :wiki)
.includes(:course).where(courses: { private: false })
.paginate(page: @page, per_page: 100)
# Sorting can be particularly slow for large numbers of articles.
articles = articles.order('articles.deleted', character_sum: :desc) unless too_many_articles?
articles
end
# If there are too many articles, rendering a page of them can take a very long time.
ARTICLE_LIMIT = 50000
def too_many_articles?
@too_many ||= campaign.articles_courses.count > ARTICLE_LIMIT
end
def tag_articles
ArticlesCourses.tracked.includes(article: :wiki)
.includes(:course).where(courses: { private: false })
.where(course: @courses_list)
.paginate(page: @page, per_page: 100)
end
def can_remove_course?
@can_remove ||= current_user&.admin? || campaign_organizer?
end
alias can_delete_course? can_remove_course?
def campaign_organizer?
return false unless campaign
return @campaign_organizer if @campaign_organizer_set
@campaign_organizer_set = true
@campaign_organizer ||= campaign.organizers.include?(current_user)
end
def courses
@courses_list
end
def course_count
@course_count ||= courses.count
end
def active_courses
courses.current_and_future
end
def search_courses(q)
courses.joins(:instructors).includes(:instructors).where(
'lower(title) like ? OR lower(school) like ? ' \
'OR lower(term) like ? OR lower(username) like ?',
"%#{q}%", "%#{q}%", "%#{q}%", "%#{q}%"
).distinct
end
def courses_by_recent_edits
# Sort first by recent edit count, and then by course title
courses.order('recent_revision_count DESC, title').paginate(page: @page, per_page: 100)
end
def active_courses_by_recent_edits
active_courses.order('recent_revision_count DESC, title').limit(100)
end
COURSE_SUMS_SQL = 'SUM(character_sum), ' \
'SUM(article_count), ' \
'SUM(new_article_count), ' \
'SUM(view_sum), ' \
'SUM(user_count), ' \
'SUM(courses.references_count)'
def course_sums
@course_sums ||= courses.pick(Arel.sql(COURSE_SUMS_SQL))
end
def word_count
@word_count ||= WordCount.from_characters(course_sums[0] || 0)
end
def references_count
course_sums[5] || 0
end
def article_count
course_sums[1] || 0
end
def new_article_count
course_sums[2] || 0
end
def view_sum
course_sums[3] || 0
end
def user_count
course_sums[4] || 0
end
def course_string_prefix
campaign&.course_string_prefix || Features.default_course_string_prefix
end
def uploads_in_use_count
@uploads_in_use_count ||= courses.sum(:uploads_in_use_count)
end
def upload_usage_count
@upload_usage_count ||= courses.sum(:upload_usages_count)
end
def trained_count
courses.sum(:trained_count)
end
def trained_percent
return 100 if user_count.zero?
100 * trained_count.to_f / user_count
end
def wikidata_stats
stats ||= courses.joins(:course_stat).where.not(course_stats: nil).filter_map do |course|
course.course_stat.stats_hash['www.wikidata.org']
end
return { 'www.wikidata.org' => stats.inject { |a, b| a.merge(b) { |_, x, y| x + y } } }
end
def creation_date
I18n.l campaign.created_at.to_date
end
end