FEATURE: New route for loading multiple user cards simultaneously (#9078)

Introduces `/user-cards.json`

Also allows the client-side user model to be passed an existing promise when loading, so that multiple models can share the same AJAX request
This commit is contained in:
David Taylor 2020-03-06 12:23:22 +00:00 committed by GitHub
parent 29ccdf5d35
commit ff62911a89
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 59 additions and 1 deletions

View File

@ -536,8 +536,12 @@ const User = RestModel.extend({
const user = this; const user = this;
return PreloadStore.getAndRemove(`user_${user.get("username")}`, () => { return PreloadStore.getAndRemove(`user_${user.get("username")}`, () => {
const useCardRoute = options && options.forCard; if (options && options.existingRequest) {
// Existing ajax request has been passed, use it
return options.existingRequest;
}
const useCardRoute = options && options.forCard;
if (options) delete options.forCard; if (options) delete options.forCard;
const path = useCardRoute const path = useCardRoute

View File

@ -99,6 +99,30 @@ class UsersController < ApplicationController
show(for_card: true) show(for_card: true)
end end
def cards
return redirect_to path('/login') if SiteSetting.hide_user_profiles_from_public && !current_user
user_ids = params.require(:user_ids).split(",").map(&:to_i)
raise Discourse::InvalidParameters.new(:user_ids) if user_ids.length > 50
users = User.where(id: user_ids).includes(:user_option,
:user_stat,
:default_featured_user_badges,
:user_profile,
:card_background_upload,
:primary_group,
:primary_email
)
users = users.filter { |u| guardian.can_see_profile?(u) }
preload_fields = User.whitelisted_user_custom_fields(guardian) + UserField.all.pluck(:id).map { |fid| "#{User::USER_FIELD_PREFIX}#{fid}" }
User.preload_custom_fields(users, preload_fields)
User.preload_recent_time_read(users)
render json: users, each_serializer: UserCardSerializer
end
def badges def badges
raise Discourse::NotFound unless SiteSetting.enable_badges? raise Discourse::NotFound unless SiteSetting.enable_badges?
show show

View File

@ -367,6 +367,8 @@ Discourse::Application.routes.draw do
get "user_preferences" => "users#user_preferences_redirect" get "user_preferences" => "users#user_preferences_redirect"
get ".well-known/change-password", to: redirect(relative_url_root + 'my/preferences/account', status: 302) get ".well-known/change-password", to: redirect(relative_url_root + 'my/preferences/account', status: 302)
get "user-cards" => "users#cards", format: :json
%w{users u}.each_with_index do |root_path, index| %w{users u}.each_with_index do |root_path, index|
get "#{root_path}" => "users#index", constraints: { format: 'html' } get "#{root_path}" => "users#index", constraints: { format: 'html' }

View File

@ -3052,6 +3052,34 @@ describe UsersController do
end end
end end
describe "#cards" do
fab!(:user) { Discourse.system_user }
fab!(:user2) { Fabricate(:user) }
it "returns success" do
get "/user-cards.json?user_ids=#{user.id},#{user2.id}"
expect(response.status).to eq(200)
parsed = JSON.parse(response.body)["users"]
expect(parsed.map { |u| u["username"] }).to contain_exactly(user.username, user2.username)
end
it "should redirect to login page for anonymous user when profiles are hidden" do
SiteSetting.hide_user_profiles_from_public = true
get "/user-cards.json?user_ids=#{user.id},#{user2.id}"
expect(response).to redirect_to '/login'
end
it "does not include hidden profiles" do
user2.user_option.update(hide_profile_and_presence: true)
get "/user-cards.json?user_ids=#{user.id},#{user2.id}"
expect(response.status).to eq(200)
parsed = JSON.parse(response.body)["users"]
expect(parsed.map { |u| u["username"] }).to contain_exactly(user.username)
end
end
describe '#badges' do describe '#badges' do
it "renders fine by default" do it "renders fine by default" do
get "/u/#{user.username}/badges" get "/u/#{user.username}/badges"