feat: allow sorting of articles (#6833)
* feat: sort by position * chore: whitespace change * feat: add border bottom color to list item * feat: allow dragging articles * feat: add migration to reorder all articles * feat: add onsort method * feat: finish UI sorting * feat: show 50 per page in articles list * feat: add article sorting methods * feat: patch up reorder action with the API * refactor: better naming * chore: add comments * feat: attach position to article before create * feat: move article to end if moved between categories * chore: add comments * chore: update version * fix: don't change position if previous category was nil * fix: condition to trigger update on category change * refactor: store new_position * refactor: use grid instead of table * feat: add snug spacing * feat: add grab-icon * feat: add grab icon to list * refactor: show draggable only for category page * feat: add update_positions as a class method --------- Co-authored-by: Nithin David Thomas <1277421+nithindavid@users.noreply.github.com>
This commit is contained in:
@@ -54,6 +54,10 @@ class Article < ApplicationRecord
|
||||
validates :title, presence: true
|
||||
validates :content, presence: true
|
||||
|
||||
# ensuring that the position is always set correctly
|
||||
before_create :add_position_to_article
|
||||
after_save :category_id_changed_action, if: :saved_change_to_category_id?
|
||||
|
||||
enum status: { draft: 0, published: 1, archived: 2 }
|
||||
|
||||
scope :search_by_category_slug, ->(category_slug) { where(categories: { slug: category_slug }) if category_slug.present? }
|
||||
@@ -61,6 +65,7 @@ class Article < ApplicationRecord
|
||||
scope :search_by_author, ->(author_id) { where(author_id: author_id) if author_id.present? }
|
||||
scope :search_by_status, ->(status) { where(status: status) if status.present? }
|
||||
scope :order_by_updated_at, -> { reorder(updated_at: :desc) }
|
||||
scope :order_by_position, -> { reorder(position: :asc) }
|
||||
|
||||
# TODO: if text search slows down https://www.postgresql.org/docs/current/textsearch-features.html#TEXTSEARCH-UPDATE-TRIGGERS
|
||||
pg_search_scope(
|
||||
@@ -113,8 +118,50 @@ class Article < ApplicationRecord
|
||||
# rubocop:enable Rails/SkipsModelValidations
|
||||
end
|
||||
|
||||
def self.update_positions(positions_hash)
|
||||
positions_hash.each do |article_id, new_position|
|
||||
# Find the article by its ID and update its position
|
||||
article = Article.find(article_id)
|
||||
article.update!(position: new_position)
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def category_id_changed_action
|
||||
# We need to update the position of the article in the new category
|
||||
return unless persisted?
|
||||
|
||||
# this means the article is just created
|
||||
# and the category_id is newly set
|
||||
# and the position is already present
|
||||
return if created_at_before_last_save.nil? && position.present? && category_id_before_last_save.nil?
|
||||
|
||||
update_article_position_in_category
|
||||
end
|
||||
|
||||
def add_position_to_article
|
||||
# on creation if a position is already present, ignore it
|
||||
return if position.present?
|
||||
|
||||
update_article_position_in_category
|
||||
end
|
||||
|
||||
def update_article_position_in_category
|
||||
max_position = Article.where(category_id: category_id, account_id: account_id).maximum(:position)
|
||||
|
||||
new_position = max_position.present? ? max_position + 10 : 10
|
||||
|
||||
# update column to avoid validations if the article is already persisted
|
||||
if persisted?
|
||||
# rubocop:disable Rails/SkipsModelValidations
|
||||
update_column(:position, new_position)
|
||||
# rubocop:enable Rails/SkipsModelValidations
|
||||
else
|
||||
self.position = new_position
|
||||
end
|
||||
end
|
||||
|
||||
def ensure_account_id
|
||||
self.account_id = portal&.account_id
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user