0
0
Fork 0
mirror of https://github.com/discourse/discourse.git synced 2026-08-08 14:34:02 +08:00
discourse/app/serializers/site_category_serializer.rb
Kris ad87713821
FEATURE: add API for custom composer actions, new "event" composer action (#40203)
This creates a new API method, `addComposerAction`, which is used to add
a new "Create Event" action that's available in event category types
(enabled by the upcoming change `events category type setup`).

When creating a new topic in an events category, the composer will use
the "Create Event" action by default which automatically enters the
BBCode to create a new event.

Frontend core changes: 
* `composer-actions.js` - exports `registerComposerAction` and
`_clearRegisteredActions`, merges the actions into the dropdown, and the
selection routes to `opts.action()`
* `models/composer.js` - `titlePlaceholder` checks
`customizationFor("titlePlaceholder")` to apply a custom title
placeholder based on category
* `services/composer.js` - `saveIcon` checks
`customizationFor("saveIcon")` which is also based on category

Backend core changes: 
* `category_types` is moved from `CategorySerializer` to
`SiteCategorySerializer` because the composer gets category info from
`Site.categories`
* `Categories::Configure` and `Categories::Unconfigure` run
`Site.clear_cache` so category type changes happen immediately, they
were being cached for 30 minutes otherwise

Calendar and events plugin: 
* Initializer adds the event action type
* Inserts BBCode placeholder for events when selecting the event action
or switching to the events category in the composer (default action
type)
* Observes the content of the topic so we can switch action type when an
event is added or removed

The one piece I've saved for a later change is changing the action icon
in the composer... it's a bit wonky to do this in select-kit right now
(requires an observer as far as I can tell because it's not tracked) and
there's a PR that's switching the menu to DMenu
(https://github.com/discourse/discourse/pull/38068), which makes it
significantly easier

<img width="1000" alt="image"
src="https://github.com/user-attachments/assets/273d1ab9-e319-4a8f-91d5-d1c0227f3e6a"
/>
2026-05-28 09:56:34 -04:00

84 lines
2 KiB
Ruby
Vendored

# frozen_string_literal: true
class SiteCategorySerializer < BasicCategorySerializer
attributes :allowed_tags,
:allowed_tag_groups,
:allow_global_tags,
:read_only_banner,
:form_template_ids,
:category_types
has_many :category_required_tag_groups, key: :required_tag_groups, embed: :objects
def form_template_ids
object.form_template_ids.sort
end
def category_types
return {} if !SiteSetting.enable_simplified_category_creation
object.category_types
end
def include_allowed_tags?
SiteSetting.tagging_enabled
end
def allowed_tags
object.tags.pluck(:id, :name, :slug).map { |id, name, slug| { id: id, name: name, slug: slug } }
end
def include_allowed_tag_groups?
SiteSetting.tagging_enabled
end
def allowed_tag_groups
object.tag_groups.pluck(:name)
end
def include_allow_global_tags?
SiteSetting.tagging_enabled
end
def include_required_tag_groups?
SiteSetting.tagging_enabled
end
def name
return I18n.t("uncategorized_category_name") if object.uncategorized?
translated_name =
if ContentLocalization.show_translated_category?(object, scope)
object.get_localization&.name
else
object.name
end
translated_name || object.name
end
def description
localized_description || object.description
end
def description_text
return super if object.uncategorized?
return ERB::Util.html_escape(localized_description).html_safe if localized_description
object.description_text
end
def description_excerpt
return super if object.uncategorized?
return PrettyText.excerpt(localized_description, 300) if localized_description
object.description_excerpt
end
private
def localized_description
return @localized_description if defined?(@localized_description)
@localized_description =
if ContentLocalization.show_translated_category?(object, scope)
object.get_localization&.description.presence
end
end
end