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.

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)
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 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.
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.
This PR raises an error on any deprecated icon names being converted by
svg_sprite.rb, which will result in any deprecated icons being processed
by the ruby lib to fail tests.
While introducing the new drafts dropdown menu component, we also made
some changes to how the sidebar link works for Drafts. However, after
following user feedback and internal discussions we decided to revert
back to the shared link approach that combines My Posts and My Drafts.
This change adds a sidebar link for each plugin that fulfils the following criteria:
- Does not have an explicit admin route defined in the plugin.
- Has at least one site setting (not including enabled/disabled.)
That sidebar link leads to the automatically generated plugin show settings page.
This moves the "hide my public profile" checkbox from the
/my/preferences/interface > other section into the top of the
/my/preferences/profile section.
Internal ref - t/146570
This change ensures we use the base62 sha1 for videos when quoting
because this is what the composer is used to using. With a valid base62
sha1 the composer already knows how to fetch the placeholder image for
it.
Fallbacks have been created to continue to support the old way as well
as a fix for the old way so that the thumbnail continues to display when
quoting. These fallbacks are in place so that we don't have to rebake
all posts that contain videos. If we ever do that we may remove these
fallbacks.
The group has `grant_trust_level` setting which automatically updates
the trust level when the user is added to the group.
Similarly, when the user is removed from the group, the trust level is
recalculated.
There was a bug that when the trust level was downgraded, the user was
not removed from automatic groups like for example `trust_level_3`.
Changing a tag name and reverting it to a previous tag name choice on
the same screen (meaning, without reloading the page) causes a 404
error.
Reproduction steps:
* Open an existing tag page https://your-discourse.com/tag/a
* Click the wrench, change the name and save
* Open edit again, revert the name to the original tag name
* 404 error
This was happening because of the way we find existing objects
in our store. Tags are using the name as the id/primary key
unlike other records in the UI. When we get the existing object
from the store we throw away the "new" ID, so we ended up with
the old tag ID on the existing object, which led to a 404. To
fix it we can just manually set the tag ID to what it is supposed
to be from params in the tag show route.
c.f.
https://meta.discourse.org/t/404-error-when-you-revert-a-tag-name-after-changing-it-without-reloading-the-page/342559
Allows users to save multiple topic and personal message drafts,
allowing more flexibility around content creation.
The "New Topic" button will now always start a fresh topic. Drafts can
be resumed from the drafts dropdown menu or using the "My Drafts" link
in the sidebar.
Since drafts require a unique `draft_key` and `user_id` combination, we
have updated the format of the draft key for both topics and personal
messages. They will now have a prefix like "new_topic_" or
"new_message_" with the timestamp of when the composer was first opened
appended.
We have many problem check trackers, and some of them
like `OutOfDateThemes` can have a message which has variable
data in it shown to admins. In this case, a list of themes
that need updating. Currently if you resolve one of these
out of date themes and refresh the list of problems, you
do not see any change.
This is happening because we are only updating the `details`
of the `ProblemCheckTracker` record, not the corresponding
`AdminNotice` record which is what is displayed to the admins
on their dashboard. This commit fixes the issue by updating the
details of the notice at the same time as the problem check
tracker details.
Previously, for a search query with `page=11` or higher, we were quietly
returning the page 10 results. The frontend app isn't affected because
it sets its own limit to 10 pages, but still, this response from the
search endpoint does not make sense.
This change switches to returning a 400 error when the `page` parameter
is above the allowed limit (a max of 10).
It seems from the original commit notes that this was only included as a query
optimisation, but doing so leads to confusion: https://meta.discourse.org/t/348688
Searching for outbound mail to an address should find that address regardless
of whether or not the mail type to search for is explicitly `group_smtp`.
Rename `min_first_post_typing_time` to `fast_typing_threshold` and
provide admin 4 options:
- disabled
- low - 1 second
- standard - 3 seconds
- high - 5 seconds
Related PRs:
- https://github.com/discourse/discourse-zoom/pull/112
This commit narrows down the list of fonts we offer
in our setup wizard and simplifies things to only
show a single font dropdown. This selection will then
set the `base_font` and `heading_font` site setting to
the same value.
For existing sites that may have set different values,
we will still show 2 dropdowns when visiting the wizard.
We are also changing our default font to the more modern
selection Inter, replacing Arial. Arial is very dependent
on system installed fonts, whereas Inter we can package
to everyone in Discourse.
Finally, for existing sites that have not changed their default
from Arial, we will keep that value via a migration so we do
not surprise site owners with a completely new font.
When suspending a user, we check for similar users by
IP address and show a number of and a list of them.
However we were checking this if the current user had a
NULL IP address, which found all other users with a NULL
IP. This doesn't make sense, this commit fixes the issue.
This commit fixes an SQL syntax error in
`UserBadge.update_featured_ranks!` when
the `user_ids` param is an empty array `[]`.
This was causing the `Jobs::BackfillBadge` job to raise the following
exceptions:
```
Job exception: ERROR: syntax error at or near ")"
LINE 6: AND user_id IN ()
```
This commit fixes the same error in
`UserState.update_distinct_badge_count` as well
Follow-up to 3e4eac0fed05daedcdea50d6275e143469d55eda
As we start to translate more pages, we'll need a way for other sites to
link back to our translated topics.
This commit gives us the ability to use the "lang" URL param to define what
language a site should be in.
Related: https://github.com/discourse/discourse-translator/pull/199
This update makes some small improvements to the posts route front-end.
Specifically, it adds a title to the page, and it improves the
positioning of expand/collapse caret.
This commit updates the `Jobs::BadgeGrant` scheduled job to enqueue on
`Job::BackfillBadge` regular job for each enabled badge on the site.
The rationale for this change is that we started seeing the
`Jobs::BadgeGrant` job taking hours on sites with lots of enabled badges
as well as users because the job was backfilling all enabled badges
serially within the job. This is bad as it means that a `mini_scheduler`
thread is tied up
by this job thus reducing the overall capacity of `mini_scheduler` for
hours.
The name "Staff Notice" was not quite right since TL4 users
can also add these notices. This commit changes the wording to
"Official Notice".
In addition to this, currently you have to go look into the staff
action logs to see who is responsible for a notice. This commit
stores the ID of the user who created the notice, then shows this
information on each notice to staff users.
Finally, I migrated the ChangePostNoticeModal component to gjs.
The GDPR requires all users to be able to export their data, or request an export of their data. This is fine for active users as we have a data export button on user profiles, but suspended users have no way of accessing the data export function, and the workaround for admins to export data for suspended users involves temporarily unsuspending them, then impersonating the user to export the data as them.
Since suspended users no longer have access to their account, we can safely assume that the export request will be coming via a medium outside of Discourse (eg, email). This change is built with this workflow in mind.
This change adds a new "User exports" section to the admin user page, allowing admins to start a new export, and to download the latest export file.
Recently we introduced a new `PostList` component (d886c55f63). In this update, we make broader adoption of this component. In particular, these areas include using the new component in the user activity stream pages, user's deleted posts, and pending posts page. This update also takes the existing `posts` route and adds a barebones front-end for it to view posts all in one page.
---------
Co-authored-by: David Taylor <david@taylorhq.com>
adds a hidden site setting, "prioritize_full_names_in_ux", whose effect is to prefer full names in user-menu notifications
Co-authored-by: Mark VanLandingham <markvanlan@gmail.com>
Co-authored-by: Alan Guo Xiang Tan <gxtan1990@gmail.com>
We're embarking on a project for overhauling the color palette and theme
systems in Discourse. As part of this project, we're making each color
palette include light and dark modes instead of the status quo of
requiring 2 separate color palettes to implement light and dark modes.
This commit is a first step towards that goal; it adds a code path for
generating and serving `color_definitions` stylesheets using the
built-in dark variant of a color palette. All of this code path is
behind a default-off site setting `use_overhauled_theme_color_palette`,
so there's no change in behavior unless the setting is enabled.
Internal topic: t/141467.