[deploy] Bulk Fetch Follow Button Data for Users (#7676)
This commit is contained in:
parent
4eb2f05387
commit
ea1d38d3b8
12 changed files with 156 additions and 7 deletions
|
|
@ -16,6 +16,7 @@ function callInitalizers(){
|
|||
initializeAllTagEditButtons();
|
||||
}
|
||||
initializeAllFollowButts();
|
||||
initializeUserFollowButts();
|
||||
initializeReadingListIcons();
|
||||
initializeSponsorshipVisibility();
|
||||
if ( document.getElementById("sidebar-additional") ) {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
'use strict';
|
||||
/* global initializeUserFollowButts */
|
||||
|
||||
function initializeAdditionalContentBoxes() {
|
||||
var el = document.getElementById('additional-content-area');
|
||||
|
|
@ -32,6 +32,7 @@ function initializeAdditionalContentBoxes() {
|
|||
el.innerHTML = html;
|
||||
initializeReadingListIcons();
|
||||
initializeAllFollowButts();
|
||||
initializeUserFollowButts();
|
||||
initializeSponsorshipVisibility();
|
||||
});
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -1,10 +1,59 @@
|
|||
function initializeAllFollowButts() {
|
||||
var followButts = document.getElementsByClassName('follow-action-button');
|
||||
for (var i = 0; i < followButts.length; i++) {
|
||||
initializeFollowButt(followButts[i]);
|
||||
if (!followButts[i].className.includes("follow-user")) {
|
||||
initializeFollowButt(followButts[i]);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
function fetchUserFollowStatuses(idButtonHash) {
|
||||
const url = new URL("/follows/bulk_show", document.location);
|
||||
const searchParams = new URLSearchParams();
|
||||
Object.keys(idButtonHash).forEach((id) => {
|
||||
searchParams.append("ids[]", id);
|
||||
});
|
||||
searchParams.append("followable_type", "User");
|
||||
url.search = searchParams;
|
||||
|
||||
fetch(url, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
Accept: 'application/json',
|
||||
'X-CSRF-Token': window.csrfToken,
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
credentials: 'same-origin',
|
||||
}).then((response) => response.json())
|
||||
.then((idStatuses) => {
|
||||
Object.keys(idStatuses).forEach(function(id) {
|
||||
addButtClickHandle(idStatuses[id], idButtonHash[id]);
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
function initializeUserFollowButtons(buttons) {
|
||||
if (buttons.length > 0) {
|
||||
var userIds = {};
|
||||
for (var i = 0; i < buttons.length; i++) {
|
||||
var userStatus = document.body.getAttribute('data-user-status');
|
||||
if (userStatus === 'logged-out') {
|
||||
addModalEventListener(buttons[i]);
|
||||
} else {
|
||||
var userId = JSON.parse(buttons[i].dataset.info).id
|
||||
userIds[userId] = buttons[i];
|
||||
}
|
||||
}
|
||||
|
||||
if (Object.keys(userIds).length > 0) { fetchUserFollowStatuses(userIds); }
|
||||
}
|
||||
}
|
||||
|
||||
function initializeUserFollowButts() {
|
||||
var buttons = document.getElementsByClassName('follow-action-button follow-user');
|
||||
initializeUserFollowButtons(buttons);
|
||||
}
|
||||
|
||||
//private
|
||||
|
||||
function initializeFollowButt(butt) {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
'use strict';
|
||||
/* global initializeUserFollowButts */
|
||||
|
||||
function initializeLocalStorageRender() {
|
||||
try {
|
||||
|
|
@ -8,6 +8,7 @@ function initializeLocalStorageRender() {
|
|||
initializeBaseUserData();
|
||||
initializeReadingListIcons();
|
||||
initializeAllFollowButts();
|
||||
initializeUserFollowButts();
|
||||
initializeSponsorshipVisibility();
|
||||
}
|
||||
} catch (err) {
|
||||
|
|
|
|||
|
|
@ -84,7 +84,7 @@ function buildArticleHTML(article) {
|
|||
<span class="bm-success">SAVED</span>\
|
||||
</button>'
|
||||
} else if (article.class_name === "User") {
|
||||
saveButton = '<button type="button" style="width: 122px" class="article-engagement-count engage-button follow-action-button"\
|
||||
saveButton = '<button type="button" style="width: 122px" class="article-engagement-count engage-button follow-action-button follow-user"\
|
||||
data-info=\'{"id":'+article.id+',"className":"User"}\' data-follow-action-button>\
|
||||
\
|
||||
</button>'
|
||||
|
|
|
|||
|
|
@ -25,6 +25,29 @@ class FollowsController < ApplicationController
|
|||
end
|
||||
end
|
||||
|
||||
def bulk_show
|
||||
skip_authorization
|
||||
render(plain: "not-logged-in") && return unless current_user
|
||||
|
||||
response = params.require(:ids).map(&:to_i).each_with_object({}) do |id, hsh|
|
||||
hsh[id] = if current_user.id == id
|
||||
"self"
|
||||
else
|
||||
following_them_check = FollowChecker.new(current_user, params[:followable_type], id).cached_follow_check
|
||||
following_you_check = FollowChecker.new(User.find_by(id: id), params[:followable_type], current_user.id).cached_follow_check
|
||||
if following_them_check && following_you_check
|
||||
"mutual"
|
||||
elsif following_you_check
|
||||
"follow-back"
|
||||
else
|
||||
following_them_check.to_s
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
render json: response
|
||||
end
|
||||
|
||||
def create
|
||||
authorize Follow
|
||||
|
||||
|
|
|
|||
|
|
@ -25,7 +25,8 @@ module Search
|
|||
"comments_count" => source["comments_count"],
|
||||
"badge_achievements_count" => source["badge_achievements_count"],
|
||||
"last_comment_at" => source["last_comment_at"],
|
||||
"roles" => source["roles"]
|
||||
"roles" => source["roles"],
|
||||
"user_id" => source["id"]
|
||||
}
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -116,6 +116,7 @@
|
|||
document.getElementById("substories").innerHTML = resultDivs.join("");
|
||||
initializeReadingListIcons();
|
||||
initializeAllFollowButts();
|
||||
initializeUserFollowButts();
|
||||
document.getElementById("substories").classList.add("search-results-loaded");
|
||||
if (content.result.length == 0) {
|
||||
document.getElementById("substories").innerHTML = '<div class="query-results-nothing">No results match that query</div>'
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import querystring;
|
||||
sub vcl_recv {
|
||||
# return this URL with only the parameters that match this regular expression
|
||||
if (req.url !~ "/internal/" && req.url !~ "/search/") {
|
||||
if (req.url !~ "/internal/" && req.url !~ "/search/" && req.url !~ "/bulk_show") {
|
||||
set req.url = querystring.regfilter_except(req.url, "^(a_id|args|article_id|article_ids|articles|asc|callback_url|category|chat_channel_id|client_id|code|collection_id|commentable_id|commentable_type|confirmation_token|created_at|end|filter|followable_id|followable_type|fork_id|i|key|message_offset|name|oauth_token|oauth_verifier|offset|org_id|organization_id|p|page|per_page|prefill|preview|purchaser|reactable_ids|redirect_uri|reported_url|reporter_username|response_type|scope|search|signature|sort|start|state|status|tag|tag_list|top|type_of|url|username|ut|verb)$");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -176,7 +176,11 @@ Rails.application.routes.draw do
|
|||
resources :feedback_messages, only: %i[index create]
|
||||
resources :organizations, only: %i[update create]
|
||||
resources :followed_articles, only: [:index]
|
||||
resources :follows, only: %i[show create update]
|
||||
resources :follows, only: %i[show create update] do
|
||||
collection do
|
||||
get "/bulk_show", to: "follows#bulk_show"
|
||||
end
|
||||
end
|
||||
resources :image_uploads, only: [:create]
|
||||
resources :blocks
|
||||
resources :notifications, only: [:index]
|
||||
|
|
|
|||
42
spec/requests/follows_bulk_show_spec.rb
Normal file
42
spec/requests/follows_bulk_show_spec.rb
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
require "rails_helper"
|
||||
|
||||
RSpec.describe "Follows #bulk_show", type: :request do
|
||||
let(:current_user) { create(:user) }
|
||||
let(:followed_user) { create(:user) }
|
||||
let(:not_followed_user) { create(:user) }
|
||||
let(:follow_back_user) { create(:user) }
|
||||
let(:mutal_follow_user) { create(:user) }
|
||||
|
||||
context "when ids are present" do
|
||||
before do
|
||||
sign_in current_user
|
||||
current_user.follow(followed_user)
|
||||
current_user.follow(mutal_follow_user)
|
||||
follow_back_user.follow(current_user)
|
||||
mutal_follow_user.follow(current_user)
|
||||
end
|
||||
|
||||
it "returns correct following values" do
|
||||
ids = [followed_user.id, not_followed_user.id, current_user.id, follow_back_user.id, mutal_follow_user.id]
|
||||
get bulk_show_follows_path, params: { ids: ids }
|
||||
|
||||
expect(response.parsed_body[current_user.id.to_s]).to eq("self")
|
||||
expect(response.parsed_body[followed_user.id.to_s]).to eq("true")
|
||||
expect(response.parsed_body[not_followed_user.id.to_s]).to eq("false")
|
||||
expect(response.parsed_body[follow_back_user.id.to_s]).to eq("follow-back")
|
||||
expect(response.parsed_body[mutal_follow_user.id.to_s]).to eq("mutual")
|
||||
end
|
||||
end
|
||||
|
||||
it "without ids raises a missing param error" do
|
||||
sign_in current_user
|
||||
expect { get bulk_show_follows_path, params: {} }.to raise_error(ActionController::ParameterMissing)
|
||||
end
|
||||
|
||||
it "rejects unless logged-in" do
|
||||
sign_out(current_user)
|
||||
get bulk_show_follows_path
|
||||
|
||||
expect(response.body).to eq("not-logged-in")
|
||||
end
|
||||
end
|
||||
26
spec/system/search/user_searches_users_spec.rb
Normal file
26
spec/system/search/user_searches_users_spec.rb
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
require "rails_helper"
|
||||
|
||||
RSpec.describe "User searches users", type: :system do
|
||||
let(:current_user) { create(:user) }
|
||||
let(:followed_user) { create(:user) }
|
||||
let(:not_followed_user) { create(:user) }
|
||||
let(:follow_back_user) { create(:user) }
|
||||
|
||||
before do
|
||||
sign_in current_user
|
||||
current_user.follow(followed_user)
|
||||
follow_back_user.follow(current_user)
|
||||
[current_user, followed_user, not_followed_user, follow_back_user].each(&:index_to_elasticsearch_inline)
|
||||
Search::User.refresh_index
|
||||
end
|
||||
|
||||
it "shows the correct follow buttons", js: true, elasticsearch: "User" do
|
||||
stub_request(:post, "http://www.google-analytics.com/collect")
|
||||
visit "/search?q=&filters=class_name:User"
|
||||
|
||||
expect(JSON.parse(find_button("EDIT PROFILE")["data-info"])["id"]).to eq(current_user.id)
|
||||
expect(JSON.parse(find_button("FOLLOWING")["data-info"])["id"]).to eq(followed_user.id)
|
||||
expect(JSON.parse(find_button("+ FOLLOW")["data-info"])["id"]).to eq(not_followed_user.id)
|
||||
expect(JSON.parse(find_button("+ FOLLOW BACK")["data-info"])["id"]).to eq(follow_back_user.id)
|
||||
end
|
||||
end
|
||||
Loading…
Add table
Reference in a new issue