2019-05-02 18:17:27 -04:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
2013-02-05 14:16:51 -05:00
|
|
|
class TopicViewSerializer < ApplicationSerializer
|
2013-06-20 17:20:08 -04:00
|
|
|
include PostStreamSerializerMixin
|
2017-09-26 02:42:27 -04:00
|
|
|
include SuggestedTopicsMixin
|
2018-02-22 09:57:02 -05:00
|
|
|
include TopicTagsMixin
|
2017-04-11 15:11:23 -04:00
|
|
|
include ApplicationHelper
|
2013-02-05 14:16:51 -05:00
|
|
|
|
2015-01-28 11:01:01 -05:00
|
|
|
def self.attributes_from_topic(*list)
|
|
|
|
[list].flatten.each do |attribute|
|
|
|
|
attributes(attribute)
|
|
|
|
class_eval %{def #{attribute}
|
|
|
|
object.topic.#{attribute}
|
|
|
|
end}
|
|
|
|
end
|
2013-02-05 14:16:51 -05:00
|
|
|
end
|
|
|
|
|
2019-01-03 12:03:01 -05:00
|
|
|
attributes_from_topic(
|
|
|
|
:id,
|
|
|
|
:title,
|
|
|
|
:fancy_title,
|
|
|
|
:posts_count,
|
|
|
|
:created_at,
|
|
|
|
:views,
|
|
|
|
:reply_count,
|
|
|
|
:like_count,
|
|
|
|
:last_posted_at,
|
|
|
|
:visible,
|
|
|
|
:closed,
|
|
|
|
:archived,
|
|
|
|
:has_summary,
|
|
|
|
:archetype,
|
|
|
|
:slug,
|
|
|
|
:category_id,
|
|
|
|
:word_count,
|
|
|
|
:deleted_at,
|
|
|
|
:user_id,
|
|
|
|
:featured_link,
|
|
|
|
:featured_link_root_domain,
|
|
|
|
:pinned_globally,
|
|
|
|
:pinned_at,
|
2019-10-22 00:02:49 -04:00
|
|
|
:pinned_until,
|
2020-10-16 15:24:38 -04:00
|
|
|
:image_url,
|
2022-02-08 22:55:32 -05:00
|
|
|
:slow_mode_seconds,
|
|
|
|
:external_id,
|
2019-01-03 12:03:01 -05:00
|
|
|
)
|
|
|
|
|
|
|
|
attributes(
|
|
|
|
:draft,
|
|
|
|
:draft_key,
|
|
|
|
:draft_sequence,
|
|
|
|
:posted,
|
|
|
|
:unpinned,
|
|
|
|
:pinned,
|
|
|
|
:current_post_number,
|
|
|
|
:highest_post_number,
|
|
|
|
:last_read_post_number,
|
|
|
|
:last_read_post_id,
|
|
|
|
:deleted_by,
|
|
|
|
:has_deleted,
|
|
|
|
:actions_summary,
|
|
|
|
:expandable_first_post,
|
|
|
|
:is_warning,
|
|
|
|
:chunk_size,
|
|
|
|
:bookmarked,
|
2021-09-20 18:45:47 -04:00
|
|
|
:bookmarks,
|
2019-01-03 12:03:01 -05:00
|
|
|
:message_archived,
|
|
|
|
:topic_timer,
|
|
|
|
:unicode_title,
|
|
|
|
:message_bus_last_id,
|
|
|
|
:participant_count,
|
|
|
|
:destination_category_id,
|
|
|
|
:pm_with_non_human_user,
|
2019-08-27 08:09:00 -04:00
|
|
|
:queued_posts_count,
|
2020-03-24 05:12:52 -04:00
|
|
|
:show_read_indicator,
|
2020-04-08 12:52:36 -04:00
|
|
|
:requested_group_name,
|
2020-10-16 15:24:38 -04:00
|
|
|
:thumbnails,
|
2020-12-14 14:08:20 -05:00
|
|
|
:user_last_posted_at,
|
2021-05-21 10:13:14 -04:00
|
|
|
:is_shared_draft,
|
|
|
|
:slow_mode_enabled_until,
|
2023-07-12 10:21:51 -04:00
|
|
|
:summarizable,
|
2019-01-03 12:03:01 -05:00
|
|
|
)
|
2013-02-05 14:16:51 -05:00
|
|
|
|
2019-04-12 09:55:27 -04:00
|
|
|
has_one :details, serializer: TopicViewDetailsSerializer, root: false, embed: :objects
|
|
|
|
has_many :pending_posts, serializer: TopicPendingPostSerializer, root: false, embed: :objects
|
2024-01-10 13:30:59 -05:00
|
|
|
has_many :categories, serializer: TopicCategorySerializer, embed: :objects
|
2013-02-05 14:16:51 -05:00
|
|
|
|
2020-04-08 12:52:36 -04:00
|
|
|
has_one :published_page, embed: :objects
|
|
|
|
|
2019-04-12 09:55:27 -04:00
|
|
|
def details
|
|
|
|
object
|
2013-02-05 14:16:51 -05:00
|
|
|
end
|
|
|
|
|
2017-05-16 15:04:09 -04:00
|
|
|
def message_bus_last_id
|
|
|
|
object.message_bus_last_id
|
|
|
|
end
|
|
|
|
|
2014-12-12 11:47:20 -05:00
|
|
|
def chunk_size
|
|
|
|
object.chunk_size
|
|
|
|
end
|
2014-09-08 11:11:56 -04:00
|
|
|
|
|
|
|
def is_warning
|
2019-04-12 09:55:27 -04:00
|
|
|
object.personal_message && object.topic.subtype == TopicSubtype.moderator_warning
|
2014-09-08 11:11:56 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
def include_is_warning?
|
|
|
|
is_warning
|
|
|
|
end
|
2015-05-14 03:21:02 -04:00
|
|
|
|
2022-02-08 22:55:32 -05:00
|
|
|
def include_external_id?
|
|
|
|
external_id
|
|
|
|
end
|
|
|
|
|
2013-06-20 17:20:08 -04:00
|
|
|
def draft
|
|
|
|
object.draft
|
2013-02-05 14:16:51 -05:00
|
|
|
end
|
|
|
|
|
2013-06-20 17:20:08 -04:00
|
|
|
def draft_key
|
|
|
|
object.draft_key
|
2013-02-07 10:45:24 -05:00
|
|
|
end
|
2013-05-16 02:55:07 -04:00
|
|
|
|
2013-06-20 17:20:08 -04:00
|
|
|
def draft_sequence
|
|
|
|
object.draft_sequence
|
2013-02-05 14:16:51 -05:00
|
|
|
end
|
|
|
|
|
2015-12-29 21:26:21 -05:00
|
|
|
def include_message_archived?
|
2019-04-12 09:55:27 -04:00
|
|
|
object.personal_message
|
2015-12-29 21:26:21 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
def message_archived
|
|
|
|
object.topic.message_archived?(scope.user)
|
|
|
|
end
|
|
|
|
|
2013-07-12 16:38:21 -04:00
|
|
|
def deleted_by
|
|
|
|
BasicUserSerializer.new(object.topic.deleted_by, root: false).as_json
|
|
|
|
end
|
|
|
|
|
2013-02-05 14:16:51 -05:00
|
|
|
# Topic user stuff
|
|
|
|
def has_topic_user?
|
|
|
|
object.topic_user.present?
|
|
|
|
end
|
|
|
|
|
2018-03-23 21:44:39 -04:00
|
|
|
def current_post_number
|
2018-11-20 19:58:47 -05:00
|
|
|
object.current_post_number
|
2018-03-23 21:44:39 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
def include_current_post_number?
|
2018-11-20 19:58:47 -05:00
|
|
|
object.current_post_number.present?
|
2018-03-23 21:44:39 -04:00
|
|
|
end
|
|
|
|
|
2013-06-20 17:20:08 -04:00
|
|
|
def highest_post_number
|
|
|
|
object.highest_post_number
|
|
|
|
end
|
|
|
|
|
2016-05-24 16:21:23 -04:00
|
|
|
def last_read_post_id
|
2018-06-26 23:11:22 -04:00
|
|
|
return nil unless last_read_post_number
|
2018-06-27 00:33:57 -04:00
|
|
|
object.filtered_post_id(last_read_post_number)
|
2016-05-24 16:21:23 -04:00
|
|
|
end
|
|
|
|
alias_method :include_last_read_post_id?, :has_topic_user?
|
|
|
|
|
2013-02-05 14:16:51 -05:00
|
|
|
def last_read_post_number
|
2016-05-24 16:21:23 -04:00
|
|
|
@last_read_post_number ||= object.topic_user.last_read_post_number
|
2013-02-05 14:16:51 -05:00
|
|
|
end
|
|
|
|
alias_method :include_last_read_post_number?, :has_topic_user?
|
|
|
|
|
|
|
|
def posted
|
|
|
|
object.topic_user.posted?
|
|
|
|
end
|
|
|
|
alias_method :include_posted?, :has_topic_user?
|
|
|
|
|
2013-03-06 15:17:07 -05:00
|
|
|
def pinned
|
2014-04-09 20:56:56 -04:00
|
|
|
PinnedCheck.pinned?(object.topic, object.topic_user)
|
|
|
|
end
|
|
|
|
|
|
|
|
def unpinned
|
|
|
|
PinnedCheck.unpinned?(object.topic, object.topic_user)
|
2013-03-06 15:17:07 -05:00
|
|
|
end
|
|
|
|
|
2014-02-05 17:54:16 -05:00
|
|
|
def actions_summary
|
2019-04-12 09:55:27 -04:00
|
|
|
object.actions_summary
|
2014-02-05 17:54:16 -05:00
|
|
|
end
|
2013-02-05 14:16:51 -05:00
|
|
|
|
2014-07-15 17:02:43 -04:00
|
|
|
def has_deleted
|
|
|
|
object.has_deleted?
|
|
|
|
end
|
|
|
|
|
|
|
|
def include_has_deleted?
|
|
|
|
object.guardian.can_see_deleted_posts?
|
|
|
|
end
|
|
|
|
|
2014-04-01 15:29:15 -04:00
|
|
|
def expandable_first_post
|
|
|
|
true
|
|
|
|
end
|
|
|
|
|
|
|
|
def include_expandable_first_post?
|
|
|
|
object.topic.expandable_first_post?
|
|
|
|
end
|
|
|
|
|
2015-01-12 06:10:15 -05:00
|
|
|
def bookmarked
|
2020-04-21 23:44:19 -04:00
|
|
|
object.has_bookmarks?
|
2015-01-12 06:10:15 -05:00
|
|
|
end
|
|
|
|
|
2021-09-20 18:45:47 -04:00
|
|
|
def bookmarks
|
|
|
|
object.bookmarks
|
2020-04-15 19:20:44 -04:00
|
|
|
end
|
|
|
|
|
2017-05-11 18:23:18 -04:00
|
|
|
def topic_timer
|
2022-05-04 23:21:01 -04:00
|
|
|
topic_timer = object.topic.public_topic_timer
|
|
|
|
|
|
|
|
return nil if topic_timer.blank?
|
|
|
|
|
|
|
|
if topic_timer.publishing_to_category?
|
|
|
|
return nil if !scope.can_see_category?(Category.find_by(id: topic_timer.category_id))
|
|
|
|
end
|
|
|
|
|
2017-08-11 22:18:04 -04:00
|
|
|
TopicTimerSerializer.new(object.topic.public_topic_timer, root: false)
|
2017-03-21 23:12:02 -04:00
|
|
|
end
|
|
|
|
|
2016-12-05 07:31:43 -05:00
|
|
|
def include_featured_link?
|
|
|
|
SiteSetting.topic_featured_link_enabled
|
|
|
|
end
|
|
|
|
|
2017-11-29 08:52:41 -05:00
|
|
|
def include_featured_link_root_domain?
|
|
|
|
SiteSetting.topic_featured_link_enabled && object.topic.featured_link
|
|
|
|
end
|
|
|
|
|
2017-04-11 15:11:23 -04:00
|
|
|
def include_unicode_title?
|
2017-12-20 23:20:30 -05:00
|
|
|
object.topic.title.match?(/:[\w\-+]+:/)
|
2017-04-11 15:11:23 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
def unicode_title
|
2017-07-21 14:24:28 -04:00
|
|
|
Emoji.gsub_emoji_to_unicode(object.topic.title)
|
2017-04-11 15:11:23 -04:00
|
|
|
end
|
|
|
|
|
2017-04-26 23:53:53 -04:00
|
|
|
def include_pm_with_non_human_user?
|
2019-04-12 09:55:27 -04:00
|
|
|
object.personal_message
|
2017-04-26 23:53:53 -04:00
|
|
|
end
|
|
|
|
|
2018-05-20 22:28:12 -04:00
|
|
|
def pm_with_non_human_user
|
|
|
|
object.topic.pm_with_non_human_user?
|
|
|
|
end
|
|
|
|
|
2017-09-13 11:14:03 -04:00
|
|
|
def participant_count
|
2017-12-13 01:19:42 -05:00
|
|
|
object.participant_count
|
2017-09-13 11:14:03 -04:00
|
|
|
end
|
|
|
|
|
2018-03-13 15:59:12 -04:00
|
|
|
def destination_category_id
|
|
|
|
object.topic.shared_draft.category_id
|
|
|
|
end
|
|
|
|
|
|
|
|
def include_destination_category_id?
|
2021-05-06 15:09:31 -04:00
|
|
|
scope.can_see_shared_draft? && SiteSetting.shared_drafts_enabled? &&
|
|
|
|
object.topic.shared_draft.present?
|
2018-03-13 15:59:12 -04:00
|
|
|
end
|
|
|
|
|
2020-12-14 14:08:20 -05:00
|
|
|
def is_shared_draft
|
|
|
|
include_destination_category_id?
|
|
|
|
end
|
2021-01-14 12:20:34 -05:00
|
|
|
|
2020-12-14 14:08:20 -05:00
|
|
|
alias_method :include_is_shared_draft?, :include_destination_category_id?
|
|
|
|
|
2019-04-12 09:55:27 -04:00
|
|
|
def include_pending_posts?
|
2021-12-02 12:03:43 -05:00
|
|
|
scope.authenticated? && object.queued_posts_enabled?
|
2019-01-03 12:03:01 -05:00
|
|
|
end
|
|
|
|
|
2019-04-12 09:55:27 -04:00
|
|
|
def queued_posts_count
|
|
|
|
object.queued_posts_count
|
2019-01-03 12:03:01 -05:00
|
|
|
end
|
|
|
|
|
2019-04-12 09:55:27 -04:00
|
|
|
def include_queued_posts_count?
|
2021-12-02 12:03:43 -05:00
|
|
|
scope.is_staff? && object.queued_posts_enabled?
|
2017-04-26 23:53:53 -04:00
|
|
|
end
|
2019-08-27 08:09:00 -04:00
|
|
|
|
|
|
|
def show_read_indicator
|
|
|
|
object.show_read_indicator?
|
|
|
|
end
|
2020-03-24 05:12:52 -04:00
|
|
|
|
|
|
|
def requested_group_name
|
2021-08-31 00:05:32 -04:00
|
|
|
Group
|
|
|
|
.joins(:group_users)
|
|
|
|
.where(
|
|
|
|
id: object.topic.custom_fields["requested_group_id"].to_i,
|
|
|
|
group_users: {
|
|
|
|
user_id: scope.user.id,
|
|
|
|
owner: true,
|
|
|
|
},
|
|
|
|
)
|
2023-02-12 23:39:45 -05:00
|
|
|
.pick(:name)
|
2020-03-24 05:12:52 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
def include_requested_group_name?
|
2021-08-31 00:05:32 -04:00
|
|
|
object.personal_message && object.topic.custom_fields["requested_group_id"]
|
2020-03-24 05:12:52 -04:00
|
|
|
end
|
2020-04-08 12:52:36 -04:00
|
|
|
|
|
|
|
def include_published_page?
|
2020-11-05 19:33:19 -05:00
|
|
|
SiteSetting.enable_page_publishing? && scope.is_staff? && object.published_page.present? &&
|
2022-09-28 19:24:33 -04:00
|
|
|
!SiteSetting.secure_uploads
|
2020-04-08 12:52:36 -04:00
|
|
|
end
|
FEATURE: Include optimized thumbnails for topics (#9215)
This introduces new APIs for obtaining optimized thumbnails for topics. There are a few building blocks required for this:
- Introduces new `image_upload_id` columns on the `posts` and `topics` table. This replaces the old `image_url` column, which means that thumbnails are now restricted to uploads. Hotlinked thumbnails are no longer possible. In normal use (with pull_hotlinked_images enabled), this has no noticeable impact
- A migration attempts to match existing urls to upload records. If a match cannot be found then the posts will be queued for rebake
- Optimized thumbnails are generated during post_process_cooked. If thumbnails are missing when serializing a topic list, then a sidekiq job is queued
- Topic lists and topics now include a `thumbnails` key, which includes all the available images:
```
"thumbnails": [
{
"max_width": null,
"max_height": null,
"url": "//example.com/original-image.png",
"width": 1380,
"height": 1840
},
{
"max_width": 1024,
"max_height": 1024,
"url": "//example.com/optimized-image.png",
"width": 768,
"height": 1024
}
]
```
- Themes can request additional thumbnail sizes by using a modifier in their `about.json` file:
```
"modifiers": {
"topic_thumbnail_sizes": [
[200, 200],
[800, 800]
],
...
```
Remember that these are generated asynchronously, so your theme should include logic to fallback to other available thumbnails if your requested size has not yet been generated
- Two new raw plugin outlets are introduced, to improve the customisability of the topic list. `topic-list-before-columns` and `topic-list-before-link`
2020-05-05 04:07:50 -04:00
|
|
|
|
|
|
|
def thumbnails
|
|
|
|
extra_sizes = ThemeModifierHelper.new(request: scope.request).topic_thumbnail_sizes
|
|
|
|
object.topic.thumbnail_info(enqueue_if_missing: true, extra_sizes: extra_sizes)
|
|
|
|
end
|
2020-10-16 15:24:38 -04:00
|
|
|
|
|
|
|
def user_last_posted_at
|
|
|
|
object.topic_user.last_posted_at
|
|
|
|
end
|
|
|
|
|
|
|
|
def include_user_last_posted_at?
|
2020-10-23 10:31:59 -04:00
|
|
|
has_topic_user? && object.topic.slow_mode_seconds.to_i > 0
|
2020-10-16 15:24:38 -04:00
|
|
|
end
|
2021-05-21 10:13:14 -04:00
|
|
|
|
|
|
|
def slow_mode_enabled_until
|
|
|
|
object.topic.slow_mode_topic_timer&.execute_at
|
|
|
|
end
|
2023-07-12 10:21:51 -04:00
|
|
|
|
|
|
|
def summarizable
|
|
|
|
object.summarizable?
|
|
|
|
end
|
2024-01-10 13:30:59 -05:00
|
|
|
|
|
|
|
def include_categories?
|
2024-01-17 13:26:51 -05:00
|
|
|
scope.can_lazy_load_categories?
|
2024-01-10 13:30:59 -05:00
|
|
|
end
|
2013-02-05 14:16:51 -05:00
|
|
|
end
|