2019-05-03 06:17:27 +08:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
2013-02-06 03:16:51 +08:00
|
|
|
class CurrentUserSerializer < BasicUserSerializer
|
2022-06-14 15:39:56 +08:00
|
|
|
include UserTagNotificationsMixin
|
2022-12-23 11:45:29 +08:00
|
|
|
include UserSidebarMixin
|
2013-02-06 03:16:51 +08:00
|
|
|
|
2013-02-26 00:42:20 +08:00
|
|
|
attributes :name,
|
|
|
|
:unread_notifications,
|
|
|
|
:unread_private_messages,
|
2020-04-01 07:09:20 +08:00
|
|
|
:unread_high_priority_notifications,
|
2022-08-03 13:57:59 +08:00
|
|
|
:all_unread_notifications_count,
|
2016-11-08 16:12:40 +08:00
|
|
|
:read_first_notification?,
|
2013-02-26 00:42:20 +08:00
|
|
|
:admin?,
|
|
|
|
:notification_channel_position,
|
2013-02-15 01:10:53 +08:00
|
|
|
:moderator?,
|
2013-05-02 15:22:27 +08:00
|
|
|
:staff?,
|
2022-06-30 08:18:12 +08:00
|
|
|
:whisperer?,
|
2015-01-22 04:58:04 +08:00
|
|
|
:title,
|
2020-05-15 06:42:00 +08:00
|
|
|
:any_posts,
|
2013-06-12 00:30:38 +08:00
|
|
|
:trust_level,
|
2017-08-29 00:07:30 +08:00
|
|
|
:can_send_private_email_messages,
|
2021-04-01 08:22:40 +08:00
|
|
|
:can_send_private_messages,
|
2013-11-07 01:56:26 +08:00
|
|
|
:can_edit,
|
2014-01-22 01:42:20 +08:00
|
|
|
:can_invite_to_forum,
|
2014-02-14 00:42:35 +08:00
|
|
|
:no_password,
|
2014-03-08 01:58:53 +08:00
|
|
|
:can_delete_account,
|
2014-06-18 09:21:40 +08:00
|
|
|
:custom_fields,
|
2014-06-19 02:04:10 +08:00
|
|
|
:muted_category_ids,
|
2022-02-17 07:42:02 +08:00
|
|
|
:indirectly_muted_category_ids,
|
2021-05-06 07:14:07 +08:00
|
|
|
:regular_category_ids,
|
|
|
|
:tracked_category_ids,
|
|
|
|
:watched_first_post_category_ids,
|
|
|
|
:watched_category_ids,
|
|
|
|
:watched_tags,
|
|
|
|
:watching_first_post_tags,
|
|
|
|
:tracked_tags,
|
|
|
|
:muted_tags,
|
|
|
|
:regular_tags,
|
2015-04-07 16:02:10 +08:00
|
|
|
:dismissed_banner_key,
|
2015-04-11 04:29:13 +08:00
|
|
|
:is_anonymous,
|
2019-01-04 01:03:01 +08:00
|
|
|
:reviewable_count,
|
2022-08-03 13:57:59 +08:00
|
|
|
:unseen_reviewable_count,
|
2022-12-01 07:05:32 +08:00
|
|
|
:new_personal_messages_notifications_count,
|
2021-08-27 00:16:00 +08:00
|
|
|
:read_faq?,
|
2016-09-18 12:30:15 +08:00
|
|
|
:previous_visit_at,
|
2017-08-12 10:05:16 +08:00
|
|
|
:seen_notification_id,
|
|
|
|
:primary_group_id,
|
2021-07-08 15:46:21 +08:00
|
|
|
:flair_group_id,
|
2018-02-09 01:56:10 +08:00
|
|
|
:can_create_topic,
|
2020-08-19 22:41:40 +08:00
|
|
|
:can_create_group,
|
2018-06-14 02:57:32 +08:00
|
|
|
:link_posting_access,
|
2018-07-27 14:41:07 +08:00
|
|
|
:external_id,
|
2022-09-27 15:10:20 +08:00
|
|
|
:associated_account_ids,
|
2018-10-11 01:00:08 +08:00
|
|
|
:top_category_ids,
|
2019-03-20 12:40:25 +08:00
|
|
|
:groups,
|
2019-04-05 22:13:36 +08:00
|
|
|
:second_factor_enabled,
|
2019-04-12 07:02:18 +08:00
|
|
|
:ignored_users,
|
2020-08-14 21:40:56 +08:00
|
|
|
:featured_topic,
|
2020-12-18 23:03:51 +08:00
|
|
|
:do_not_disturb_until,
|
2021-03-19 21:19:15 +08:00
|
|
|
:has_topic_draft,
|
2021-05-06 07:14:07 +08:00
|
|
|
:can_review,
|
2021-07-27 19:05:33 +08:00
|
|
|
:draft_count,
|
2022-04-28 15:27:06 +08:00
|
|
|
:pending_posts_count,
|
2022-06-30 14:54:20 +08:00
|
|
|
:status,
|
2022-08-31 09:16:28 +08:00
|
|
|
:grouped_unread_notifications,
|
2022-12-23 11:45:29 +08:00
|
|
|
:display_sidebar_tags,
|
|
|
|
:sidebar_tags,
|
|
|
|
:sidebar_category_ids,
|
2023-02-03 11:44:40 +08:00
|
|
|
:sidebar_sections,
|
2023-06-07 12:09:30 +08:00
|
|
|
:new_new_view_enabled?,
|
DEV: Upgrade search-menu to glimmer (#20482)
# Top level view
This PR is the first version of converting the search menu and its logic from (deprecated) widgets to glimmer components. The changes are hidden behind a group based feature flag. This will give us the ability to test the new implementation in a production setting before fully committing to the new search menu.
# What has changed
The majority of the logic from the widget implementation has been updated to fit within the context of a glimmer component, but it has not fundamentally changed. Instead of having a single widget - [search-menu.js](https://github.com/discourse/discourse/blob/main/app/assets/javascripts/discourse/app/widgets/search-menu.js) - that built the bulk of the search menu logic, we split the logic into (20+) bite size components. This greatly increases the readability and makes extending a component in the search menu much more straightforward.
That being said, certain pieces needed to be rewritten from scratch as they did not translate from widget -> glimmer, or there was a general code upgraded needed. There are a few of these changes worth noting:
### Search Service
**Search Term** -> In the widget implementation we had a overly complex way of managing the current search term. We tracked the search term across multiple different states (`term`, `opts.term`, `searchData.term`) causing headaches. This PR introduces a single source of truth:
```js
this.search.activeGlobalSearchTerm
```
This tracked value is available anywhere the `search` service is injected. In the case the search term should be needs to be updated you can call
```js
this.search.activeGlobalSearchTerm = "foo"
```
**event listeners** -> In the widget implementation we defined event listeners **only** on the search input to handle things such as
- keyboard navigation / shortcuts
- closing the search menu
- performing a search with "enter"
Having this in one place caused a lot of bloat in our logic as we had to handle multiple different cases in one location. Do _x_ if it is this element, but do _y_ if it is another. This PR updates the event listeners to be attached to individual components, allowing for a more fine tuned set of actions per element. To not duplicate logic across multiple components, we have condensed shared logic to actions on the search service to be reused. For example - `this.search.handleArrowUpOrDown` - to handle keyboard navigation.
### Search Context
We have unique logic based on the current search context (topic / tag / category / user / etc). This context is set within a models route file. We have updated the search service with a tracked value `searchContext` that can be utilized and updated from any component where the search service is injected.
```js
# before
this.searchService.set("searchContext", user.searchContext);
# after
this.searchService.searchContext = user.searchContext;
```
# Views
<img width="434" alt="Screenshot 2023-06-15 at 11 01 01 AM" src="https://github.com/discourse/discourse/assets/50783505/ef57e8e6-4e7b-4ba0-a770-8f2ed6310569">
<img width="418" alt="Screenshot 2023-06-15 at 11 04 11 AM" src="https://github.com/discourse/discourse/assets/50783505/2c1e0b38-d12c-4339-a1d5-04f0c1932b08">
<img width="413" alt="Screenshot 2023-06-15 at 11 04 34 AM" src="https://github.com/discourse/discourse/assets/50783505/b871d164-88cb-405e-9b78-d326a6f63686">
<img width="419" alt="Screenshot 2023-06-15 at 11 07 51 AM" src="https://github.com/discourse/discourse/assets/50783505/c7309a19-f541-47f4-94ef-10fa65658d8c">
<img width="424" alt="Screenshot 2023-06-15 at 11 04 48 AM" src="https://github.com/discourse/discourse/assets/50783505/f3dba06e-b029-431c-b3d0-36727b9e6dce">
<img width="415" alt="Screenshot 2023-06-15 at 11 08 57 AM" src="https://github.com/discourse/discourse/assets/50783505/ad4e7250-040c-4d06-bf06-99652f4c7b7c">
2023-06-16 22:24:07 +08:00
|
|
|
:experimental_search_menu_groups_enabled?
|
2021-08-27 00:16:00 +08:00
|
|
|
|
|
|
|
delegate :user_stat, to: :object, private: true
|
|
|
|
delegate :any_posts, :draft_count, :pending_posts_count, :read_faq?, to: :user_stat
|
2018-02-09 01:56:10 +08:00
|
|
|
|
2022-12-06 00:25:30 +08:00
|
|
|
has_one :user_option, embed: :object, serializer: CurrentUserOptionSerializer
|
|
|
|
|
2023-02-22 05:55:44 +08:00
|
|
|
def sidebar_sections
|
|
|
|
SidebarSection
|
2023-04-06 06:55:47 +08:00
|
|
|
.public_sections
|
|
|
|
.or(SidebarSection.where(user_id: object.id))
|
2023-05-25 09:10:32 +08:00
|
|
|
.includes(:sidebar_urls)
|
2023-05-04 10:14:09 +08:00
|
|
|
.order("(section_type IS NOT NULL) DESC, (public IS TRUE) DESC")
|
2023-02-22 05:55:44 +08:00
|
|
|
.map { |section| SidebarSectionSerializer.new(section, root: false) }
|
|
|
|
end
|
|
|
|
|
2018-12-18 15:41:42 +08:00
|
|
|
def groups
|
2021-05-12 18:06:39 +08:00
|
|
|
owned_group_ids = GroupUser.where(user_id: id, owner: true).pluck(:group_id).to_set
|
2022-09-21 12:32:47 +08:00
|
|
|
|
2021-09-07 12:30:40 +08:00
|
|
|
object
|
|
|
|
.visible_groups
|
|
|
|
.pluck(:id, :name, :has_messages)
|
|
|
|
.map do |id, name, has_messages|
|
|
|
|
group = { id: id, name: name, has_messages: has_messages }
|
2021-05-12 18:06:39 +08:00
|
|
|
group[:owner] = true if owned_group_ids.include?(id)
|
|
|
|
group
|
|
|
|
end
|
2018-12-18 15:41:42 +08:00
|
|
|
end
|
2018-12-10 23:23:29 +08:00
|
|
|
|
2018-06-14 02:57:32 +08:00
|
|
|
def link_posting_access
|
|
|
|
scope.link_posting_access
|
2018-02-09 01:56:10 +08:00
|
|
|
end
|
2017-12-21 08:23:45 +08:00
|
|
|
|
|
|
|
def can_create_topic
|
|
|
|
scope.can_create_topic?(nil)
|
|
|
|
end
|
2013-02-06 03:16:51 +08:00
|
|
|
|
2020-08-19 22:41:40 +08:00
|
|
|
def can_create_group
|
|
|
|
scope.can_create_group?
|
|
|
|
end
|
|
|
|
|
|
|
|
def include_can_create_group?
|
|
|
|
scope.can_create_group?
|
|
|
|
end
|
|
|
|
|
2017-08-29 00:07:30 +08:00
|
|
|
def can_send_private_email_messages
|
2018-08-27 09:38:11 +08:00
|
|
|
scope.can_send_private_messages_to_email?
|
2017-08-29 00:07:30 +08:00
|
|
|
end
|
|
|
|
|
2021-04-01 08:22:40 +08:00
|
|
|
def can_send_private_messages
|
2022-11-07 07:11:18 +08:00
|
|
|
scope.can_send_private_messages?
|
2021-04-01 08:22:40 +08:00
|
|
|
end
|
|
|
|
|
2013-06-12 00:30:38 +08:00
|
|
|
def can_edit
|
|
|
|
true
|
|
|
|
end
|
|
|
|
|
2013-11-07 01:56:26 +08:00
|
|
|
def can_invite_to_forum
|
2020-05-07 04:57:26 +08:00
|
|
|
scope.can_invite_to_forum?
|
2013-11-07 01:56:26 +08:00
|
|
|
end
|
|
|
|
|
|
|
|
def include_can_invite_to_forum?
|
|
|
|
scope.can_invite_to_forum?
|
|
|
|
end
|
|
|
|
|
2014-01-22 01:42:20 +08:00
|
|
|
def no_password
|
|
|
|
true
|
|
|
|
end
|
|
|
|
|
|
|
|
def include_no_password?
|
|
|
|
!object.has_password?
|
|
|
|
end
|
|
|
|
|
2014-02-14 00:42:35 +08:00
|
|
|
def include_can_delete_account?
|
2014-02-14 04:51:19 +08:00
|
|
|
scope.can_delete_user?(object)
|
2014-02-14 00:42:35 +08:00
|
|
|
end
|
|
|
|
|
|
|
|
def can_delete_account
|
2014-02-14 04:51:19 +08:00
|
|
|
true
|
2014-02-14 00:42:35 +08:00
|
|
|
end
|
|
|
|
|
2014-06-06 04:16:30 +08:00
|
|
|
def custom_fields
|
2014-06-11 09:57:22 +08:00
|
|
|
fields = nil
|
|
|
|
if SiteSetting.public_user_custom_fields.present?
|
|
|
|
fields = SiteSetting.public_user_custom_fields.split("|")
|
|
|
|
end
|
|
|
|
DiscoursePluginRegistry.serialized_current_user_fields.each do |f|
|
|
|
|
fields ||= []
|
|
|
|
fields << f
|
|
|
|
end
|
|
|
|
|
|
|
|
if fields.present?
|
2017-11-15 08:55:37 +08:00
|
|
|
User.custom_fields_for_ids([object.id], fields)[object.id] || {}
|
2014-06-11 09:57:22 +08:00
|
|
|
else
|
|
|
|
{}
|
|
|
|
end
|
2014-06-06 04:16:30 +08:00
|
|
|
end
|
|
|
|
|
2014-06-18 09:21:40 +08:00
|
|
|
def muted_category_ids
|
2021-05-06 07:14:07 +08:00
|
|
|
categories_with_notification_level(:muted)
|
2018-07-27 14:41:07 +08:00
|
|
|
end
|
|
|
|
|
2022-02-17 07:42:02 +08:00
|
|
|
def indirectly_muted_category_ids
|
|
|
|
CategoryUser.indirectly_muted_category_ids(object)
|
|
|
|
end
|
|
|
|
|
2021-05-06 07:14:07 +08:00
|
|
|
def regular_category_ids
|
|
|
|
categories_with_notification_level(:regular)
|
|
|
|
end
|
|
|
|
|
|
|
|
def tracked_category_ids
|
|
|
|
categories_with_notification_level(:tracking)
|
|
|
|
end
|
|
|
|
|
|
|
|
def watched_category_ids
|
|
|
|
categories_with_notification_level(:watching)
|
|
|
|
end
|
|
|
|
|
|
|
|
def watched_first_post_category_ids
|
|
|
|
categories_with_notification_level(:watching_first_post)
|
|
|
|
end
|
|
|
|
|
2019-04-05 22:13:36 +08:00
|
|
|
def ignored_users
|
|
|
|
IgnoredUser.where(user: object.id).joins(:ignored_user).pluck(:username)
|
|
|
|
end
|
|
|
|
|
2018-07-27 14:41:07 +08:00
|
|
|
def top_category_ids
|
2018-07-30 18:36:36 +08:00
|
|
|
omitted_notification_levels = [
|
|
|
|
CategoryUser.notification_levels[:muted],
|
|
|
|
CategoryUser.notification_levels[:regular],
|
|
|
|
]
|
2018-07-27 14:41:07 +08:00
|
|
|
CategoryUser
|
|
|
|
.where(user_id: object.id)
|
2018-07-30 18:36:36 +08:00
|
|
|
.where.not(notification_level: omitted_notification_levels)
|
2018-07-27 14:41:07 +08:00
|
|
|
.order(
|
|
|
|
"
|
|
|
|
CASE
|
|
|
|
WHEN notification_level = 3 THEN 1
|
|
|
|
WHEN notification_level = 2 THEN 2
|
|
|
|
WHEN notification_level = 4 THEN 3
|
|
|
|
END",
|
|
|
|
)
|
2014-06-18 09:21:40 +08:00
|
|
|
.pluck(:category_id)
|
2018-07-31 11:42:30 +08:00
|
|
|
.slice(0, SiteSetting.header_dropdown_category_count)
|
2014-06-18 09:21:40 +08:00
|
|
|
end
|
|
|
|
|
2014-06-19 02:04:10 +08:00
|
|
|
def dismissed_banner_key
|
|
|
|
object.user_profile.dismissed_banner_key
|
|
|
|
end
|
|
|
|
|
2015-04-07 16:02:10 +08:00
|
|
|
def is_anonymous
|
2015-04-08 10:29:43 +08:00
|
|
|
object.anonymous?
|
2015-04-07 16:02:10 +08:00
|
|
|
end
|
|
|
|
|
2021-03-20 03:20:41 +08:00
|
|
|
def can_review
|
|
|
|
scope.can_see_review_queue?
|
|
|
|
end
|
|
|
|
|
2017-08-12 10:05:16 +08:00
|
|
|
def include_primary_group_id?
|
|
|
|
object.primary_group_id.present?
|
|
|
|
end
|
|
|
|
|
2018-03-08 11:54:31 +08:00
|
|
|
def external_id
|
|
|
|
object&.single_sign_on_record&.external_id
|
|
|
|
end
|
|
|
|
|
|
|
|
def include_external_id?
|
2021-02-08 18:04:33 +08:00
|
|
|
SiteSetting.enable_discourse_connect
|
2018-03-08 11:54:31 +08:00
|
|
|
end
|
2019-03-20 12:40:25 +08:00
|
|
|
|
2022-09-27 15:10:20 +08:00
|
|
|
def associated_account_ids
|
|
|
|
values = {}
|
|
|
|
|
|
|
|
object.user_associated_accounts.map do |user_associated_account|
|
|
|
|
values[user_associated_account.provider_name] = user_associated_account.provider_uid
|
|
|
|
end
|
|
|
|
|
|
|
|
values
|
|
|
|
end
|
|
|
|
|
|
|
|
def include_associated_account_ids?
|
|
|
|
SiteSetting.include_associated_account_ids
|
|
|
|
end
|
|
|
|
|
2019-03-20 12:40:25 +08:00
|
|
|
def second_factor_enabled
|
2022-12-08 06:41:22 +08:00
|
|
|
object.totp_enabled? || object.security_keys_enabled?
|
2019-03-20 12:40:25 +08:00
|
|
|
end
|
2019-12-10 03:15:47 +08:00
|
|
|
|
|
|
|
def featured_topic
|
|
|
|
object.user_profile.featured_topic
|
|
|
|
end
|
2021-03-19 21:19:15 +08:00
|
|
|
|
|
|
|
def has_topic_draft
|
|
|
|
true
|
|
|
|
end
|
|
|
|
|
|
|
|
def include_has_topic_draft?
|
|
|
|
Draft.has_topic_draft(object)
|
|
|
|
end
|
2022-04-28 15:27:06 +08:00
|
|
|
|
2022-05-27 17:15:14 +08:00
|
|
|
def include_status?
|
2022-07-05 23:12:22 +08:00
|
|
|
SiteSetting.enable_user_status && object.has_status?
|
2022-05-27 17:15:14 +08:00
|
|
|
end
|
|
|
|
|
|
|
|
def status
|
|
|
|
UserStatusSerializer.new(object.user_status, root: false)
|
|
|
|
end
|
2022-07-14 14:30:46 +08:00
|
|
|
|
2022-12-01 07:09:57 +08:00
|
|
|
def unseen_reviewable_count
|
|
|
|
Reviewable.unseen_reviewable_count(object)
|
|
|
|
end
|
2013-02-06 03:16:51 +08:00
|
|
|
end
|