discourse/app/controllers/admin/config/customize_controller.rb
Osama Sayegh e564ab5f63
PERF: Improve performance of the new themes listing page (#32641)
The new themes listing page at `/admin/config/customize/themes`
currently has poor performance compared to the components page
(`/admin/config/customize/components`) due to various N+1 issues,
loading all themes and components from the server when only themes are
needed, and serializing data/attributes that aren't needed for rendering
the themes grid.

This commit improves the performance by eliminating all N+1 that are
currently present, excluding components from the page payload, and
reducing the amount of data transmitted for each theme when loading the
page.
2025-05-08 19:18:07 +03:00

50 lines
1.5 KiB
Ruby

# frozen_string_literal: true
class Admin::Config::CustomizeController < Admin::AdminController
PAGE_SIZE = 20
def themes
themes =
Theme
.include_basic_relations
.includes(:theme_fields, color_scheme: [:color_scheme_colors])
.where(component: false)
.order(:name)
render json: { themes: serialize_data(themes, ThemeIndexSerializer) }
end
def components
page = params[:page]&.to_i
components =
Theme.include_basic_relations.where(component: true).order(:name).limit(PAGE_SIZE + 1)
components = components.offset(page * PAGE_SIZE) if page && page > 0
name_search_term = params[:name].presence&.strip
if name_search_term
components = components.where("themes.name ILIKE ?", "%#{name_search_term}%")
end
status_filter = params[:status].presence
if status_filter
case status_filter
when "used"
components = components.joins(:parent_themes).distinct
when "unused"
components = components.left_joins(:parent_themes).where(parent_themes: { id: nil })
when "updates_available"
components = components.joins(:remote_theme).where(remote_theme: { commits_behind: 1.. })
else
raise Discourse::InvalidParameters if status_filter != "all"
end
end
components = components.to_a
has_more = components.size > PAGE_SIZE
components = components[...PAGE_SIZE]
render json: { has_more:, components: serialize_data(components, ComponentIndexSerializer) }
end
end