discourse/app/controllers/directory_items_controller.rb
Blake Erickson ee366f7ac7 FIX: Ensure load more directory items has a .json url
The `/directory_items` route needs to have a .json url, but the rails
url helper `_path` doesn't return the format of the route.

I tried passing in a format options to `directory_items_path`. Which
works in the rails console

```
[8] pry(main)> directory_items_path(params.merge(:format => :json))
=> "/directory_items.json?page=1"
```

but when I added that some logic to the controller it comes out as

```
/directory_items?format=json&page=1
```

(which is actually how I expect it to work based on how you pass in the
format param). Anyways, because I couldn't figure out how to pass a
format to the `_path` helper I just used URI.parse to append `.json`
manually.
2020-08-11 12:43:55 -06:00

94 lines
3.3 KiB
Ruby

# frozen_string_literal: true
class DirectoryItemsController < ApplicationController
PAGE_SIZE = 50
def index
raise Discourse::InvalidAccess.new(:enable_user_directory) unless SiteSetting.enable_user_directory?
period = params.require(:period)
period_type = DirectoryItem.period_types[period.to_sym]
raise Discourse::InvalidAccess.new(:period_type) unless period_type
result = DirectoryItem.where(period_type: period_type).includes(:user)
if params[:group]
group = Group.find_by(name: params[:group])
raise Discourse::InvalidParameters.new(:group) if group.blank?
guardian.ensure_can_see!(group)
guardian.ensure_can_see_group_members!(group)
result = result.includes(user: :groups).where(users: { groups: { id: group.id } })
else
result = result.includes(user: :primary_group)
end
if params[:exclude_usernames]
result = result.references(:user).where.not(users: { username: params[:exclude_usernames].split(",") })
end
order = params[:order] || DirectoryItem.headings.first
if DirectoryItem.headings.include?(order.to_sym)
dir = params[:asc] ? 'ASC' : 'DESC'
result = result.order("directory_items.#{order} #{dir}")
end
if period_type == DirectoryItem.period_types[:all]
result = result.includes(:user_stat)
end
page = params[:page].to_i
user_ids = nil
if params[:name].present?
user_ids = UserSearch.new(params[:name], include_staged_users: true).search.pluck(:id)
if user_ids.present?
# Add the current user if we have at least one other match
if current_user && result.dup.where(user_id: user_ids).exists?
user_ids << current_user.id
end
result = result.where(user_id: user_ids)
else
result = result.where('false')
end
end
if params[:username]
user_id = User.where(username_lower: params[:username].to_s.downcase).pluck_first(:id)
if user_id
result = result.where(user_id: user_id)
else
result = result.where('false')
end
end
result_count = result.count
result = result.limit(PAGE_SIZE).offset(PAGE_SIZE * page).to_a
more_params = params.slice(:period, :order, :asc).permit!
more_params[:page] = page + 1
load_more_uri = URI.parse(directory_items_path(more_params))
load_more_directory_items_json = "#{load_more_uri.path}.json?#{load_more_uri.query}"
# Put yourself at the top of the first page
if result.present? && current_user.present? && page == 0
position = result.index { |r| r.user_id == current_user.id }
# Don't show the record unless you're not in the top positions already
if (position || 10) >= 10
your_item = DirectoryItem.where(period_type: period_type, user_id: current_user.id).first
result.insert(0, your_item) if your_item
end
end
last_updated_at = DirectoryItem.last_updated_at(period_type)
render_json_dump(directory_items: serialize_data(result, DirectoryItemSerializer),
meta: {
last_updated_at: last_updated_at,
total_rows_directory_items: result_count,
load_more_directory_items: load_more_directory_items_json
}
)
end
end