This commit fixes a bug in the "Dark Mode" checkbox in the interface user
preferences where the checkbox state doesn't appear in the disabled
state if the user disables dark mode.
This happens because when rendering the checkbox, we check the relevant
user options field within the controller's `init` method, but at that
point in the controller's life cycle, the `user_option` object isn't
available. What we should do instead is move this check to the route's
`setupController` method where the `user_option` object is available and
we can set the correct state on the controller.
https://meta.discourse.org/t/-/349976 (private topic)
While working with some themes, I noticed that all of these buttons
don't have the `topic-footer-button` class, so it can't really be used
effectively. The admin menu, bookmark button, and reply button were all
missing it. This adds the class.

This PR adds two attributes (`op_can_like` & `op_liked`) to
`TopicListItemSerializer`.
We've also added `serialize_topic_op_likes_data` theme modifier so that
these two attributes are only added when a theme or component needs this
data.
Likely we want the group smtp email job to retry. Also added a check to
see if we already have an email log entry for the message to avoid
possible duplicates on retry.
Related previous commit: ed47b550266e1ab669c756b0ecb48d1685b08fee
This patch adds two things:
1. An outcome matcher (`on_lock_not_acquired`), allowing to react when
there was a problem with the lock.
2. Compatibility with the steps inspector, allowing to display properly
the steps of a service containing locks.
Currently, the markdown for uploads is counted towards post minimum length requirements. This change introduces a site setting `prevent_uploads_only_posts` which can be flipped to exclude upload segments from the calculation.
Until now, we were excluding uploads with a not null
access_control_post_id from cleanup, because we were still
considering them "secure" even though they might have been
`secure: false`.
It's not necessary to keep these around, these are no more
important than regular uploads if they are not referenced
by anything.
Previously, were always forcing the page to reload
for the wizard after pressing Next for the styling step,
with the logic that if style changes are being made,
the admin needs to see them straight away.
However this doesn't make sense if nothing changes on
that step. This commit makes the change to only refresh
the page if any of the settings on the step changed,
bringing it in line with other steps.
This setting was introduced a year ago for
51016e56dd99a9ad4bd82cdc6c0cf968754c70ed, which was
formerly a design experiment.
In practice on our hosting, noone has ever disabled this
setting, and it's for a useful feature. There is no
point keeping it.

Stopping propagation when a `DMenu`'s trigger is clicked could prevent
another floating UI element, e.g. the search menu in the header, from
closing when clicking outside of it. We call `stopPropagation` on the
event to allow more clicks within a `DMenu`'s trigger without it getting
closed, so we shouldn't stop the event propagation if the `DMenu` hasn't
been expanded yet.
This change includes the following updates:
- Rename view all to view all drafts
- Remove view all link from drop-down when all drafts are displayed in
the menu
- Different icon for draft topics and PMs (adds envelope for PMs)
- Disable drop-down when New Topic button is disabled (private
categories etc)
- Improve drafts drop-down loading (no longer disables the trigger btn
on click)
In the current admin index page, all plugins show up as tabs. This includes plugins with auto-generated config routes.
This changes the tabs to include only plugins with custom UIs.
Plugins like for example AI or Akismet create reviewable items. When the
plugin is disabled, then we cannot properly handle those items.
In that situation, we should display warnings about unhandled types.
Instruct admin to reenable plugins. In addition, we should allow the
admin to delete all pending reviews from disabled plugins.
This change updates the Automation plugin to make use of the `use_new_show_route` plugin flag, as well as generally updating the UI to match current admin UI guidelines. Notable changes include:
- Moving template/router/controller files to make use of the `admin.adminPlugins.show` route.
- Changing the URIs from `/admin/plugins/discourse-automation` to `/admin/plugins/automation`, to match the `PLUGIN_NAME`.
- Adding UI wrappers around the New/Edit forms, and polishing the list of defined automations.
This commit changes the display of category hashtag
autocomplete to show the parent category name in this
format:
* Parent Name > Child Name
This helps further distinguish categories in the autocomplete
where there may be multiple different parent categories with
the same name child category, e.g. if every category has an
Announcements subcategory.
In #31012 we deprecated this nav mode option when registering a plugin in a backwards compatible way.
We have now removed its use in all relevant plugins and should be ready to completely remove it from core.
This is a follow-up to 71eb2f6cda9ad8a69ba1ae7d506440c3ff0bc9cb, we have
outlets in this wrapper too — so best to re-enable pointer events on all
immediate children of the disabled wrapper.
This is the first in a series of PRs to introduce a
ProseMirror-based
WYSIWYM editor experience
alongside our current textarea Markdown editor.
Behind a hidden site setting, this PR adds a toggle to the composer
toolbar, allowing users to switch between the two options.
Our implementation builds upon the excellent ProseMirror and its
non-core Markdown
module, using the
module's schema, parsing, and serialization definitions as the base for
further Discourse-specific features.
An extension API is included to enable further customizations.
The necessary extensions to support all Discourse's core and core
plugins features **will be implemented in subsequent PRs**.
---------
Co-authored-by: David Taylor <david@taylorhq.com>
In core, `escapeExpression` was being applied during the model loading phase. However, plugin consumers of the UserStreamItem component were not necessarily doing the same.
This commit moves the emoji-replacement logic (which also safely handles escaping) into the component template, so that it is safe-by-default, regardless of how it's used by plugins.
This commit drops the `before_action :preload_json` callback in `ApplicationController` as it adds unnecessary complexity to `ApplicationController` as well as other controllers which has to skip this callback. The source of the complexity comes mainly from the following two conditionals in the `preload_json` method:
```
# We don't preload JSON on xhr or JSON request
return if request.xhr? || request.format.json?
# if we are posting in makes no sense to preload
return if request.method != "GET"
```
Basically, the conditionals solely exists for optimization purposes to ensure that we don't run the preloading code when the request is not a GET request and the response is not expected to be HTML. The key problem here is that the conditionals are trying to expect what the content type of the response will be and this has proven to be hard to get right. Instead, we can simplify this problem by running the preloading code in a more deterministic way which is to preload only when the `application` layout is being rendered and this is main change that this commit introduces.