mirror of
https://github.com/lingble/chatwoot.git
synced 2025-11-02 20:18:08 +00:00
chore: Limit the number of articles retrieved by widget (#11095)
The UI displays only six articles, and this update introduces a per_page parameter to control the number of articles returned per API call. The value is capped between 1 and 100, with a default fallback if a lower number is set. This change is necessary due to high website traffic, where excessive payloads are returned without adding value. **Changes:** - Add index to status, account_id, portal_id, views. - Add per_page param in the API. - Update the code in the frontend to fetch only 6
This commit is contained in:
@@ -6,17 +6,25 @@ class Public::Api::V1::Portals::ArticlesController < Public::Api::V1::Portals::B
|
|||||||
layout 'portal'
|
layout 'portal'
|
||||||
|
|
||||||
def index
|
def index
|
||||||
@articles = @portal.articles.published
|
@articles = @portal.articles.published.includes(:category, :author)
|
||||||
@articles_count = @articles.count
|
@articles_count = @articles.count
|
||||||
search_articles
|
search_articles
|
||||||
order_by_sort_param
|
order_by_sort_param
|
||||||
@articles = @articles.page(list_params[:page]) if list_params[:page].present?
|
limit_results
|
||||||
end
|
end
|
||||||
|
|
||||||
def show; end
|
def show; end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
def limit_results
|
||||||
|
return if list_params[:per_page].blank?
|
||||||
|
|
||||||
|
per_page = [list_params[:per_page].to_i, 100].min
|
||||||
|
per_page = 25 if per_page < 1
|
||||||
|
@articles = @articles.page(list_params[:page]).per(per_page)
|
||||||
|
end
|
||||||
|
|
||||||
def search_articles
|
def search_articles
|
||||||
@articles = @articles.search(list_params) if list_params.present?
|
@articles = @articles.search(list_params) if list_params.present?
|
||||||
end
|
end
|
||||||
@@ -45,7 +53,7 @@ class Public::Api::V1::Portals::ArticlesController < Public::Api::V1::Portals::B
|
|||||||
end
|
end
|
||||||
|
|
||||||
def list_params
|
def list_params
|
||||||
params.permit(:query, :locale, :sort, :status, :page)
|
params.permit(:query, :locale, :sort, :status, :page, :per_page)
|
||||||
end
|
end
|
||||||
|
|
||||||
def permitted_params
|
def permitted_params
|
||||||
|
|||||||
@@ -103,6 +103,7 @@ const getMostReadArticles = (slug, locale) => ({
|
|||||||
page: 1,
|
page: 1,
|
||||||
sort: 'views',
|
sort: 'views',
|
||||||
status: 1,
|
status: 1,
|
||||||
|
per_page: 6,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -23,9 +23,13 @@
|
|||||||
#
|
#
|
||||||
# Indexes
|
# Indexes
|
||||||
#
|
#
|
||||||
|
# index_articles_on_account_id (account_id)
|
||||||
# index_articles_on_associated_article_id (associated_article_id)
|
# index_articles_on_associated_article_id (associated_article_id)
|
||||||
# index_articles_on_author_id (author_id)
|
# index_articles_on_author_id (author_id)
|
||||||
|
# index_articles_on_portal_id (portal_id)
|
||||||
# index_articles_on_slug (slug) UNIQUE
|
# index_articles_on_slug (slug) UNIQUE
|
||||||
|
# index_articles_on_status (status)
|
||||||
|
# index_articles_on_views (views)
|
||||||
#
|
#
|
||||||
class Article < ApplicationRecord
|
class Article < ApplicationRecord
|
||||||
include PgSearch::Model
|
include PgSearch::Model
|
||||||
|
|||||||
@@ -4,5 +4,5 @@ json.payload do
|
|||||||
end
|
end
|
||||||
|
|
||||||
json.meta do
|
json.meta do
|
||||||
json.articles_count @articles.published.size
|
json.articles_count @articles_count
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0" />
|
||||||
|
<body>
|
||||||
|
</body>
|
||||||
|
|
||||||
<%
|
<%
|
||||||
user_id = 1
|
user_id = 1
|
||||||
|
|||||||
8
db/migrate/20250315202035_add_index_to_articles.rb
Normal file
8
db/migrate/20250315202035_add_index_to_articles.rb
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
class AddIndexToArticles < ActiveRecord::Migration[7.0]
|
||||||
|
def change
|
||||||
|
add_index :articles, :status unless index_exists?(:articles, :status)
|
||||||
|
add_index :articles, :views unless index_exists?(:articles, :views)
|
||||||
|
add_index :articles, :portal_id unless index_exists?(:articles, :portal_id)
|
||||||
|
add_index :articles, :account_id unless index_exists?(:articles, :account_id)
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -10,7 +10,7 @@
|
|||||||
#
|
#
|
||||||
# It's strongly recommended that you check this file into your version control system.
|
# It's strongly recommended that you check this file into your version control system.
|
||||||
|
|
||||||
ActiveRecord::Schema[7.0].define(version: 2025_02_28_185548) do
|
ActiveRecord::Schema[7.0].define(version: 2025_03_15_202035) do
|
||||||
# These extensions should be enabled to support this database
|
# These extensions should be enabled to support this database
|
||||||
enable_extension "pg_stat_statements"
|
enable_extension "pg_stat_statements"
|
||||||
enable_extension "pg_trgm"
|
enable_extension "pg_trgm"
|
||||||
@@ -159,9 +159,13 @@ ActiveRecord::Schema[7.0].define(version: 2025_02_28_185548) do
|
|||||||
t.string "slug", null: false
|
t.string "slug", null: false
|
||||||
t.integer "position"
|
t.integer "position"
|
||||||
t.string "locale", default: "en", null: false
|
t.string "locale", default: "en", null: false
|
||||||
|
t.index ["account_id"], name: "index_articles_on_account_id"
|
||||||
t.index ["associated_article_id"], name: "index_articles_on_associated_article_id"
|
t.index ["associated_article_id"], name: "index_articles_on_associated_article_id"
|
||||||
t.index ["author_id"], name: "index_articles_on_author_id"
|
t.index ["author_id"], name: "index_articles_on_author_id"
|
||||||
|
t.index ["portal_id"], name: "index_articles_on_portal_id"
|
||||||
t.index ["slug"], name: "index_articles_on_slug", unique: true
|
t.index ["slug"], name: "index_articles_on_slug", unique: true
|
||||||
|
t.index ["status"], name: "index_articles_on_status"
|
||||||
|
t.index ["views"], name: "index_articles_on_views"
|
||||||
end
|
end
|
||||||
|
|
||||||
create_table "attachments", id: :serial, force: :cascade do |t|
|
create_table "attachments", id: :serial, force: :cascade do |t|
|
||||||
|
|||||||
@@ -58,6 +58,23 @@ RSpec.describe 'Public Articles API', type: :request do
|
|||||||
expect(response_data[1][:views]).to eq(1)
|
expect(response_data[1][:views]).to eq(1)
|
||||||
expect(response_data.last[:id]).to eq(article.id)
|
expect(response_data.last[:id]).to eq(article.id)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'limits results based on per_page parameter' do
|
||||||
|
get "/hc/#{portal.slug}/#{category.locale}/articles.json", params: { per_page: 2 }
|
||||||
|
|
||||||
|
expect(response).to have_http_status(:success)
|
||||||
|
response_data = JSON.parse(response.body, symbolize_names: true)[:payload]
|
||||||
|
expect(response_data.length).to eq(2)
|
||||||
|
expect(JSON.parse(response.body, symbolize_names: true)[:meta][:articles_count]).to eq(5)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'uses default items per page if per_page is less than 1' do
|
||||||
|
get "/hc/#{portal.slug}/#{category.locale}/articles.json", params: { per_page: 0 }
|
||||||
|
|
||||||
|
expect(response).to have_http_status(:success)
|
||||||
|
response_data = JSON.parse(response.body, symbolize_names: true)[:payload]
|
||||||
|
expect(response_data.length).to eq(3)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'GET /public/api/v1/portals/:slug/articles/:id' do
|
describe 'GET /public/api/v1/portals/:slug/articles/:id' do
|
||||||
|
|||||||
Reference in New Issue
Block a user