As we’re currently using a namespace for Sidekiq, in order to upgrade to
the latest version, we need to drop it as it’s not supported anymore.
The recommended way is to use a different Redis DB for Sidekiq.
This patch uses a different config for Sidekiq and also takes care of
migrating existing jobs (in queues and the retry and scheduled sets).
Adds `.json` a suffix everywhere and makes it clear that's it's a json
route.
Also adds a missing spec for this endpoint and updates the underlying
discourse-emojis gem for better symlinking
- Hide seldom-used fields behind an 'advanced' checkbox. This replaces
the old 'only show edited' checkbox, since the number of fields shown by
default is now so small that 'only show edited' isn't useful.
Mobile/desktop targets are included in that list because we now
recommend people use CSS breakpoints for handling different device
sizes.
- Update names & descriptions of fields to be more descriptive
- Show the descriptions of fields at the top of the editor. Previously
they were only shown as tooltips.
Before:
<img width="1109" alt="SCR-20250228-lunn"
src="https://github.com/user-attachments/assets/8faebba1-39c1-491a-b236-411cfb6d9c74"
/>
After, default view:
<img width="1102" alt="SCR-20250303-kayr"
src="https://github.com/user-attachments/assets/1e483845-613f-44d6-83d6-ade628251fe5"
/>
After, advanced view:
<img width="1122" alt="SCR-20250303-kazn"
src="https://github.com/user-attachments/assets/45b8933d-2271-42ba-b5b4-81b326709adb"
/>
This commit moves most of emoji logic into the discourse-emojis gem:
https://github.com/discourse/discourse-emojis/
Most notably:
- images are now symlinked from the gem
- the gem provides path to the json files
Search aliases have also been made asynchronous and memoized. When you
will search for an emoji we will now load the aliases and store the list
for future use.
---------
Co-authored-by: David Taylor <david@taylorhq.com>
Followup to 8615fc6cbbd1085b37b5ec251e4acd39b16cb839
Stubbing things which are memoized means we'd need to clear the caches
before & after the tests to be safe. Easier to just avoid the stubs
altogether.
In some error paths, headers that were set earlier can get overwritten
(e.g. `Cross-Origin-Opener-Policy`) by middleware such as
ActionDispatch::ShowExceptions.
This PR sets the `Cross-Origin-Opener-Policy` header to the value of the
SiteSetting `cross_origin_opener_policy_header` if it's missing and if
the response is for HTML.
In future, this DefaultHeaders middleware can be used to set other
default headers that relate to security or other purposes.
### Testing
<img width="631" alt="test"
src="https://github.com/user-attachments/assets/05106a40-2bc7-435d-91a2-4dd2a098f349"
/>
The API docs is incorrect as the `active` param is only permitted when
an admin API key
is used. This has always been the case since
429f27ec96c090d9054c498263f0cb635b665d99
Prevents deprecation warning of sass mixed declarations. We should move
declarations above nested styles.
We get the following message from logs:
```
DEPRECATION WARNING [mixed-decls]: Sass's behavior for declarations that appear after nested
rules will be changing to match the behavior specified by CSS in an upcoming
version. To keep the existing behavior, move the declaration above the nested
rule. To opt into the new behavior, wrap the declaration in `& {}`.
```
For more info see:
https://sass-lang.com/documentation/breaking-changes/mixed-decls/
This change improves the alignment and placement of the search spinner
and icons (ie. clear search / advanced search). Having a fixed width on
desktop prevents the search field from changing width when the loading
icon is toggled.
This change standardises the `User-Agent` header that Discourse will send when talking to other sites.
`Discourse.user_agent` is now the authority on what the user agent value should be. For Onebox requests, this changes the user agent from their existing value to match the new value (unless overridden).
For all other requests, `Net::HTTPHeader` is monkey-patched to add a default `User-Agent` header when one hasn't been provided.
Followup e26a1175d7c33746bddbc858ad89e68cc14beefe
Adds extra functionality and tests for the admin search modal.
* Show third level plugin config pages in search, e.g. AI Usage
* Remember last used search filters
* Allow navigating search results with keyboard, using tab or up/down
and enter to go to result
* Add a placeholder beneath search input to tell the admin what to do
* Add a full page search at `/admin/search` which can be reached from
pressing Enter on the search input
* Add specs for modal and full page search
* Change admin sidebar filter "no results found" to point to full page
search
* Add keyboard shortcut help to modal for admin search
In #31366, we added the ability for admins to remove people from group chats. However, that only works as long as the admin is already in the group chat.
For forum-side group messages, admins can join any of them at will. This PR extends that same ability to chat for parity.
We have a native dependency, Rinku, that's used only to make links in one place. We can get rid of this and use PrettyText instead.
This is almost a one-for-one replacement, but PrettyText adds rel="noopener nofollow ugc" to external links, which I suspect is actually what we want. It also wraps the result in a <p> tag, which we strip out for parity with Rinku.
If we have a custom content for a `DMenu` trigger the `DButton` has no
way to know there's text in this custom content so it will output the
"no-text" class on the `DButton`. The correct way to fix this is to use
our own `DButton` and the `@triggerComponent` so we can fully replace
the behavior and set the correct classes.
Adds a new plugin outlet below the `flagging.review_process_description`
customizable text.
The customizable text only accepts plain-text. This plugin outlet would
allow developers to add additional description with any rich-text
content they need, such as paragraphs and links.
This change adjusts the markup and aria tags so that the like and read
counts on posts will read who liked/read when clicked. Previously this
content was inaccessible to screen readers.

This change required:
* Keeping the empty containing divs present and adding `aria-live` tags
(if the `aria-live` tag isn't initially present in the DOM, it will not
read changes to the content within)
* Adjusting some styles to avoid extra margin from the empty div (added
a conditional class to add the margin back when expanded)
* Cleaned up the aria tags, we don't need to hide the "liked this" text,
as it will be read naturally after the usernames like "username1,
username2, liked this" This allows us to remove the screenreader only
description.
* Removed "Click to view" from the button label, the interactivity is
inherent because the screenreader identifies it as a button
Adds a search field to the page header on desktop that is controlled by
a site setting (within Search).
The search field toggles back to the search icon (magnifying class) when
the header is minimized (ie. scrolling in topics) and restores to the
field again when header is no longer minimized.
On mobile the search experience is still the same.
EmailToken.confirm is called in a number of contexts (hence the need for
the `scope`) and this is sometimes needed in `user_confirmed_email`
callbacks to distinguish those contexts.
Here we correctly focus a mid-stream post for screenreaders so they know
where to start, but once focus is removed NVDA becomes unmoored and will
jump back up the post stream to a previous post if someone tries to
navigate with the arrow keys.
Retaining the focus prevents this and shouldn't have any major
side-effects.
Tested using Chrome and NVDA
The zero width space added here as a layout fix seems to get noticed by
screenreaders (tested in NVDA) and gets "read" as text.
This means that instead of falling back to the button title, which is
the normal behavior for textless buttons, the screenreader reads the
blank space. This results in buttons like the post controls being read
simply as "button" with no other description.
Wrapping the space in `aria-hidden` corrects this, and results in the
button title being read properly.
Having them under `mobile/` means they're loaded for all users. Better
to put them in the admin-only bundle, and scope with `.mobile-view`
See also: ffdc97f37296e9568d7a5dcec4d1e90e973a6893
This reverts commit 38de3d7bd1f503743c5d0237bc8a8d9d89effb8e. This
changed seemed to be blocking our own AI helper as well if it has the
“Search” tool.
This commit fixes an issue where if you tried to post
2 chat messages in quick succession which only contained
uploads (both `message` fields would be `""`), then we
would show the "You posted an identical message too recently."
error.
We should not do this for upload-only messages, they
are not identical messages.
Followup b5147a4634f0fd5c98262f949a8c766bfd73d290
When we aliased `leave` to `remove` and renamed
the method in `DirectMessageChannel` in the previous
commit, this inadvertantly caused an error when
unfollowing group channels in the channel list.
When clicking the X in the channel list, we hit
ChannelsCurrentUserMembershipFollowsController for the
current user and the channel, which is supposed to only
unfollow the channel for all channel types including DMs.
Group DMs have a different Leave behaviour vs Unfollow.
Leaving the channel altogether is done from the channel
settings page, the "Leave channel" button, and that
deletes the user's membership and DM user record from that
channel.
So, we were trying to do the leave channel behaviour in the
unfollow channel controller, which was returning the wrong
record for the serializer (a User not a Membership)
This fixes the issue and removes a bit of delegate/alias indirection
which was making the code a bit harder to fllow and search, even
though it was more succinct. Also adds missing specs that would
have caught this regression.
When secure uploads are enabled, we need to send images that are rendered in the digest e-mail as attachments. Before this change, we would indiscriminately attach all images in the relevant topic's first post, whether they were rendered the e-mail body or not.
This change fixes that by only attaching images that are referenced in the e-mail body.
This change detects if a crawler is trying to load a search results page, and returns a simple response that should indicate to them that there's no content of interest available there.
In modern embroider, `app-js` files need to be exported by the module.
We need to keep the separate `app/` directory because this v2 addon
doesn't have a build step, and therefore the relative imports in the
`src/helpers` files would break if loaded as-is into the app bundle.
These files are managed automatically via crowdin, so they should never
be edited locally. Adding them to `.ignore` will stop them polluting
search results in IDEs which support `.ignore` (e.g. VSCode)
This commit introduces a new `Calendar` control for form-kit. This
control will render a date picker and a time input. On mobile the date
picker will be replaced by a native input of type date.
The following validation options have also been added:
- `dateAfterOrEqual`
- `dateBeforeOrEqual`
The control has two options:
- `includeTime` - show or hide the time input (default true)
- `expandedDatePickerOnDesktop` - show an expanded datepicker on
desktop, or not (default true)