mirror of
https://github.com/discourse/discourse.git
synced 2024-11-24 11:52:56 +08:00
49f4c548ef
Users can now pin bookmarks from their bookmark list. This will anchor the bookmark to the top of the list, and show a pin icon next to it. This also applies in the nav bookmarks panel. If there are multiple pinned bookmarks they sort by last updated order.
158 lines
4.8 KiB
Ruby
158 lines
4.8 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
class Bookmark < ActiveRecord::Base
|
|
BOOKMARK_LIMIT = 2000
|
|
|
|
self.ignored_columns = [
|
|
"delete_when_reminder_sent" # TODO(2021-07-22): remove
|
|
]
|
|
|
|
belongs_to :user
|
|
belongs_to :post
|
|
belongs_to :topic
|
|
|
|
def self.reminder_types
|
|
@reminder_types ||= Enum.new(
|
|
later_today: 1,
|
|
next_business_day: 2,
|
|
tomorrow: 3,
|
|
next_week: 4,
|
|
next_month: 5,
|
|
custom: 6,
|
|
start_of_next_business_week: 7,
|
|
later_this_week: 8
|
|
)
|
|
end
|
|
|
|
def self.auto_delete_preferences
|
|
@auto_delete_preferences ||= Enum.new(
|
|
never: 0,
|
|
when_reminder_sent: 1,
|
|
on_owner_reply: 2
|
|
)
|
|
end
|
|
|
|
validates :reminder_at, presence: {
|
|
message: I18n.t("bookmarks.errors.time_must_be_provided"),
|
|
if: -> { reminder_type.present? }
|
|
}
|
|
|
|
validate :unique_per_post_for_user
|
|
validate :ensure_sane_reminder_at_time
|
|
validate :bookmark_limit_not_reached
|
|
validates :name, length: { maximum: 100 }
|
|
|
|
# we don't care whether the post or topic is deleted,
|
|
# they hold important information about the bookmark
|
|
def post
|
|
Post.unscoped { super }
|
|
end
|
|
|
|
def topic
|
|
Topic.unscoped { super }
|
|
end
|
|
|
|
def unique_per_post_for_user
|
|
existing_bookmark = Bookmark.find_by(user_id: user_id, post_id: post_id)
|
|
return if existing_bookmark.blank? || existing_bookmark.id == id
|
|
self.errors.add(:base, I18n.t("bookmarks.errors.already_bookmarked_post"))
|
|
end
|
|
|
|
def ensure_sane_reminder_at_time
|
|
return if reminder_at.blank?
|
|
if reminder_at < Time.zone.now
|
|
self.errors.add(:base, I18n.t("bookmarks.errors.cannot_set_past_reminder"))
|
|
end
|
|
if reminder_at > 10.years.from_now.utc
|
|
self.errors.add(:base, I18n.t("bookmarks.errors.cannot_set_reminder_in_distant_future"))
|
|
end
|
|
end
|
|
|
|
def bookmark_limit_not_reached
|
|
return if user.bookmarks.count < BOOKMARK_LIMIT
|
|
self.errors.add(:base, I18n.t("bookmarks.errors.too_many", user_bookmarks_url: "#{Discourse.base_url}/my/activity/bookmarks"))
|
|
end
|
|
|
|
def no_reminder?
|
|
self.reminder_at.blank? && self.reminder_type.blank?
|
|
end
|
|
|
|
def auto_delete_when_reminder_sent?
|
|
self.auto_delete_preference == Bookmark.auto_delete_preferences[:when_reminder_sent]
|
|
end
|
|
|
|
def auto_delete_on_owner_reply?
|
|
self.auto_delete_preference == Bookmark.auto_delete_preferences[:on_owner_reply]
|
|
end
|
|
|
|
def clear_reminder!
|
|
update!(
|
|
reminder_at: nil,
|
|
reminder_type: nil,
|
|
reminder_last_sent_at: Time.zone.now,
|
|
reminder_set_at: nil
|
|
)
|
|
end
|
|
|
|
scope :pending_reminders, ->(before_time = Time.now.utc) do
|
|
where("reminder_at IS NOT NULL AND reminder_at <= :before_time", before_time: before_time)
|
|
end
|
|
|
|
scope :pending_reminders_for_user, ->(user) do
|
|
pending_reminders.where(user: user)
|
|
end
|
|
|
|
def self.count_per_day(opts = nil)
|
|
opts ||= {}
|
|
result = where('bookmarks.created_at >= ?', opts[:start_date] || (opts[:since_days_ago] || 30).days.ago)
|
|
result = result.where('bookmarks.created_at <= ?', opts[:end_date]) if opts[:end_date]
|
|
result = result.joins(:topic).merge(Topic.in_category_and_subcategories(opts[:category_id])) if opts[:category_id]
|
|
result.group('date(bookmarks.created_at)')
|
|
.order('date(bookmarks.created_at)')
|
|
.count
|
|
end
|
|
|
|
##
|
|
# Deletes bookmarks that are attached to posts/topics that were deleted
|
|
# more than X days ago. We don't delete bookmarks instantly when a post/topic
|
|
# is deleted so that there is a grace period to un-delete.
|
|
def self.cleanup!
|
|
grace_time = 3.days.ago
|
|
DB.exec(<<~SQL, grace_time: grace_time)
|
|
DELETE FROM bookmarks b
|
|
USING topics t, posts p
|
|
WHERE (b.topic_id = t.id AND b.post_id = p.id)
|
|
AND (t.deleted_at < :grace_time OR p.deleted_at < :grace_time)
|
|
SQL
|
|
end
|
|
end
|
|
|
|
# == Schema Information
|
|
#
|
|
# Table name: bookmarks
|
|
#
|
|
# id :bigint not null, primary key
|
|
# user_id :bigint not null
|
|
# topic_id :bigint not null
|
|
# post_id :bigint not null
|
|
# name :string(100)
|
|
# reminder_type :integer
|
|
# reminder_at :datetime
|
|
# created_at :datetime not null
|
|
# updated_at :datetime not null
|
|
# reminder_last_sent_at :datetime
|
|
# reminder_set_at :datetime
|
|
# auto_delete_preference :integer default(0), not null
|
|
# pinned :boolean default(FALSE)
|
|
#
|
|
# Indexes
|
|
#
|
|
# index_bookmarks_on_post_id (post_id)
|
|
# index_bookmarks_on_reminder_at (reminder_at)
|
|
# index_bookmarks_on_reminder_set_at (reminder_set_at)
|
|
# index_bookmarks_on_reminder_type (reminder_type)
|
|
# index_bookmarks_on_topic_id (topic_id)
|
|
# index_bookmarks_on_user_id (user_id)
|
|
# index_bookmarks_on_user_id_and_post_id (user_id,post_id) UNIQUE
|
|
#
|