From 9b39536eb2cb48a9715651f2244935ea32dc06b0 Mon Sep 17 00:00:00 2001 From: Rajendra Kadam <rkadam@gitlab.com> Date: Thu, 15 Feb 2024 16:01:11 +0000 Subject: [PATCH] Add sorting based on project star as default sort for CI components - Adding order_by_star_count - Using it by default --- app/models/ci/catalog/listing.rb | 3 ++- app/models/ci/catalog/resource.rb | 10 ++++++++++ spec/models/ci/catalog/listing_spec.rb | 25 +++++++++++++++++++++---- spec/models/ci/catalog/resource_spec.rb | 22 +++++++++++++++++++--- 4 files changed, 52 insertions(+), 8 deletions(-) diff --git a/app/models/ci/catalog/listing.rb b/app/models/ci/catalog/listing.rb index e534b7d1a5c58..1485b58b5c6c8 100644 --- a/app/models/ci/catalog/listing.rb +++ b/app/models/ci/catalog/listing.rb @@ -21,8 +21,9 @@ def resources(sort: nil, search: nil, scope: :all) when 'latest_released_at_desc' then relation.order_by_latest_released_at_desc when 'latest_released_at_asc' then relation.order_by_latest_released_at_asc when 'created_at_asc' then relation.order_by_created_at_asc + when 'created_at_desc' then relation.order_by_created_at_desc else - relation.order_by_created_at_desc + relation.order_by_star_count(:desc) end end diff --git a/app/models/ci/catalog/resource.rb b/app/models/ci/catalog/resource.rb index 73f4356bdbfa0..61d716e3b7f97 100644 --- a/app/models/ci/catalog/resource.rb +++ b/app/models/ci/catalog/resource.rb @@ -10,6 +10,7 @@ module Catalog class Resource < ::ApplicationRecord include PgFullTextSearchable include Gitlab::VisibilityLevel + include Sortable self.table_name = 'catalog_resources' @@ -35,6 +36,15 @@ class Resource < ::ApplicationRecord scope :order_by_name_asc, -> { reorder(arel_table[:name].asc.nulls_last) } scope :order_by_latest_released_at_desc, -> { reorder(arel_table[:latest_released_at].desc.nulls_last) } scope :order_by_latest_released_at_asc, -> { reorder(arel_table[:latest_released_at].asc.nulls_last) } + scope :order_by_star_count, ->(direction) do + build_keyset_order_on_joined_column( + scope: joins(:project), + attribute_name: 'project_star_count', + column: Project.arel_table[:star_count], + direction: direction, + nullable: :nulls_last + ) + end delegate :avatar_path, :star_count, :full_path, to: :project diff --git a/spec/models/ci/catalog/listing_spec.rb b/spec/models/ci/catalog/listing_spec.rb index 356a0dcee67b3..07ac6c0f6ad4c 100644 --- a/spec/models/ci/catalog/listing_spec.rb +++ b/spec/models/ci/catalog/listing_spec.rb @@ -6,12 +6,21 @@ let_it_be(:user) { create(:user) } let_it_be(:namespace) { create(:group) } let_it_be(:public_namespace_project) do - create(:project, :public, namespace: namespace, name: 'A public namespace project') + create(:project, :public, namespace: namespace, name: 'A public namespace project', star_count: 10) + end + + let_it_be(:public_project) do + create(:project, :public, name: 'B public test project', star_count: 20) + end + + let_it_be(:namespace_project_a) do + create(:project, namespace: namespace, name: 'Test namespace project', star_count: 30) + end + + let_it_be(:namespace_project_b) do + create(:project, namespace: namespace, name: 'X namespace Project', star_count: 40) end - let_it_be(:public_project) { create(:project, :public, name: 'B public test project') } - let_it_be(:namespace_project_a) { create(:project, namespace: namespace, name: 'Test namespace project') } - let_it_be(:namespace_project_b) { create(:project, namespace: namespace, name: 'X namespace Project') } let_it_be(:project_noaccess) { create(:project, namespace: namespace, name: 'Project with no access') } let_it_be(:internal_project) { create(:project, :internal, name: 'Internal project') } @@ -94,6 +103,14 @@ internal_resource.update!(created_at: tomorrow + 1) end + context 'when there is no sort parameter' do + let_it_be(:sort) { nil } + + it 'contains catalog resource sorted by star_count descending' do + is_expected.to eq([private_namespace_resource, public_resource_b, public_resource_a, internal_resource]) + end + end + context 'when the sort is created_at ascending' do let_it_be(:sort) { :created_at_asc } diff --git a/spec/models/ci/catalog/resource_spec.rb b/spec/models/ci/catalog/resource_spec.rb index 674d6476a610f..d20189050b969 100644 --- a/spec/models/ci/catalog/resource_spec.rb +++ b/spec/models/ci/catalog/resource_spec.rb @@ -5,9 +5,9 @@ RSpec.describe Ci::Catalog::Resource, feature_category: :pipeline_composition do let_it_be(:current_user) { create(:user) } - let_it_be(:project_a) { create(:project, name: 'A') } - let_it_be(:project_b) { create(:project, name: 'B') } - let_it_be(:project_c) { create(:project, name: 'C', description: 'B') } + let_it_be(:project_a) { create(:project, name: 'A', star_count: 20) } + let_it_be(:project_b) { create(:project, name: 'B', star_count: 10) } + let_it_be(:project_c) { create(:project, name: 'C', description: 'B', star_count: 30) } let_it_be_with_reload(:resource_a) do create(:ci_catalog_resource, project: project_a, latest_released_at: '2023-02-01T00:00:00Z') @@ -122,6 +122,22 @@ end end + describe 'order_by_star_count_desc' do + it 'returns catalog resources sorted by project star count in descending order' do + ordered_resources = described_class.order_by_star_count(:desc) + + expect(ordered_resources).to eq([resource_c, resource_a, resource_b]) + end + end + + describe 'order_by_star_count_asc' do + it 'returns catalog resources sorted by project star count in ascending order' do + ordered_resources = described_class.order_by_star_count(:asc) + + expect(ordered_resources).to eq([resource_b, resource_a, resource_c]) + end + end + describe 'authorized catalog resources' do let_it_be(:namespace) { create(:group) } let_it_be(:other_namespace) { create(:group) } -- GitLab