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
166
167
168
169
170
171
172
173
|
# frozen_string_literal: true
class Explore::ProjectsController < Explore::ApplicationController
include PageLimiter
include ParamsBackwardCompatibility
include RendersMemberAccess
include RendersProjectsList
include SortingHelper
include SortingPreference
MIN_SEARCH_LENGTH = 3
PAGE_LIMIT = 50
RSS_ENTRIES_LIMIT = 20
before_action :set_non_archived_param
before_action :set_sorting
# For background information on the limit, see:
# https://gitlab.com/gitlab-org/gitlab/-/issues/38357
# https://gitlab.com/gitlab-org/gitlab/-/issues/262682
before_action only: [:index, :trending, :starred] do
limit_pages(PAGE_LIMIT)
end
rescue_from PageOutOfBoundsError, with: :page_out_of_bounds
feature_category :groups_and_projects
# TODO: Set higher urgency after addressing https://gitlab.com/gitlab-org/gitlab/-/issues/357913
# and https://gitlab.com/gitlab-org/gitlab/-/issues/358945
urgency :low, [:index, :topics, :trending, :starred, :topic]
def index
show_alert_if_search_is_disabled
@projects = load_projects
respond_to do |format|
format.html
format.json do
render json: {
html: view_to_html_string("explore/projects/_projects", projects: @projects)
}
end
end
end
def trending
params[:trending] = true
@projects = load_projects
respond_to do |format|
format.html
format.json do
render json: {
html: view_to_html_string("explore/projects/_projects", projects: @projects)
}
end
end
end
# rubocop: disable CodeReuse/ActiveRecord
def starred
@projects = load_projects.reorder('star_count DESC')
respond_to do |format|
format.html
format.json do
render json: {
html: view_to_html_string("explore/projects/_projects", projects: @projects)
}
end
end
end
# rubocop: enable CodeReuse/ActiveRecord
def topics
load_project_counts
load_topics
end
def topic
load_topic
return render_404 unless @topic
params[:topic] = @topic.name
@projects = load_projects
respond_to do |format|
format.html
format.atom do
@projects = @projects.projects_order_id_desc.limit(RSS_ENTRIES_LIMIT)
render layout: 'xml'
end
end
end
private
def load_project_counts
@all_user_projects = ProjectsFinder.new(params: { non_public: true }, current_user: current_user).execute
@all_starred_projects = ProjectsFinder.new(params: { starred: true }, current_user: current_user).execute
end
def load_projects
load_project_counts
finder_params = {
minimum_search_length: MIN_SEARCH_LENGTH,
not_aimed_for_deletion: true
}
projects = ProjectsFinder.new(current_user: current_user, params: params.merge(finder_params)).execute
projects = preload_associations(projects)
projects = projects.page(params[:page]).without_count
prepare_projects_for_rendering(projects)
end
def load_topics
@topics = Projects::TopicsFinder.new(params: params.permit(:search)).execute.page(params[:page]).without_count
end
def load_topic
topic_name = Feature.enabled?(:explore_topics_cleaned_path) ? URI.decode_www_form_component(params[:topic_name]) : params[:topic_name]
@topic = Projects::Topic.find_by_name_case_insensitive(topic_name)
end
# rubocop: disable CodeReuse/ActiveRecord
def preload_associations(projects)
projects.includes(:route, :creator, :group, :project_feature, :topics, namespace: [:route, :owner])
end
# rubocop: enable CodeReuse/ActiveRecord
def set_sorting
params[:sort] = set_sort_order
@sort = params[:sort]
end
def default_sort_order
sort_value_latest_activity
end
def sorting_field
Project::SORTING_PREFERENCE_FIELD
end
def page_out_of_bounds(error)
load_project_counts
@max_page_number = error.message
respond_to do |format|
format.html do
render "page_out_of_bounds", status: :bad_request
end
format.json do
render json: {
html: view_to_html_string("explore/projects/page_out_of_bounds")
}, status: :bad_request
end
end
end
def show_alert_if_search_is_disabled
return if current_user || params[:name].blank? && params[:search].blank? || !html_request? || Feature.disabled?(:disable_anonymous_project_search, type: :ops)
flash.now[:notice] = _('You must sign in to search for specific projects.')
end
end
Explore::ProjectsController.prepend_mod_with('Explore::ProjectsController')
|