This commit optimises the database query generated by
`TopicsFilter#filter_categories` when the `-category:*` filter is used.
Previously, the method will add the `topics.category_id NOT IN
(<category ids to be excluded>)` filter to the resulting query. However,
we noticed that the performance of the query degrades as the number of
rows in the `topics` table grow and when the number of category ids to be
excluded is large.
Sample of query we ran on a large database in production to demonstrate
the improvement:
Before:
```
SELECT topics.id FROM topics WHERE topics.category_id NOT IN (83, 136, 149, 143, 153, 165, 161, 123, 155, 163, 144, 134, 69, 135, 158, 141, 151, 160, 131, 133, 89, 104, 150, 147, 132, 145, 108, 146, 122, 100, 128, 154, 95, 102, 140, 139, 88, 91, 87) ORDER BY topics.id DESC LIMIT 5;
QUERY PLAN
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Limit (cost=27795.34..27795.34 rows=1 width=4) (actual time=29.317..30.165 rows=5 loops=1)
-> Sort (cost=27795.34..27795.34 rows=1 width=4) (actual time=29.316..30.163 rows=5 loops=1)
Sort Key: id DESC
Sort Method: top-N heapsort Memory: 25kB
-> Gather (cost=1000.10..27795.33 rows=1 width=4) (actual time=0.187..26.132 rows=73478 loops=1)
Workers Planned: 2
Workers Launched: 2
-> Parallel Seq Scan on topics (cost=0.10..26795.23 rows=1 width=4) (actual time=0.013..22.252 rows=24493 loops=3)
Filter: (category_id <> ALL ('{83,136,149,143,153,165,161,123,155,163,144,134,69,135,158,141,151,160,131,133,89,104,150,147,132,145,108,146,122,100,128,154,95,102,140,139,88,91,87}'::integer[]))
Rows Removed by Filter: 77276
Planning Time: 0.140 ms
Execution Time: 30.181 ms
```
After:
```
SELECT topics.id FROM topics WHERE NOT EXISTS (
SELECT 1
FROM unnest(array[83, 136, 149, 143, 153, 165, 161, 123, 155, 163, 144, 134, 69, 135, 158, 141, 151, 160, 131, 133, 89, 104, 150, 147, 132, 145, 108, 146, 122, 100, 128, 154, 95, 102, 140, 139, 88, 91, 87]) AS excluded_categories(category_id)
WHERE topics.category_id IS NULL OR excluded_categories.category_id = topics.category_id
) ORDER BY topics.id DESC LIMIT 5 ;
QUERY PLAN
-----------------------------------------------------------------------------------------------------------------------------------------------------------
Limit (cost=0.42..13.52 rows=5 width=4) (actual time=0.028..0.110 rows=5 loops=1)
-> Nested Loop Anti Join (cost=0.42..179929.62 rows=68715 width=4) (actual time=0.027..0.109 rows=5 loops=1)
Join Filter: ((topics.category_id IS NULL) OR (excluded_categories.category_id = topics.category_id))
Rows Removed by Join Filter: 239
-> Index Scan Backward using forum_threads_pkey on topics (cost=0.42..108925.71 rows=305301 width=8) (actual time=0.012..0.062 rows=44 loops=1)
-> Function Scan on unnest excluded_categories (cost=0.00..0.39 rows=39 width=4) (actual time=0.000..0.001 rows=6 loops=44)
Planning Time: 0.126 ms
Execution Time: 0.124 ms
(8 rows)
```
The users directory is updated on a daily cadence. However, when a site is new and doesn't have many users, it can be confusing that a user who has just joined doesn't show up in the users until a day after they join. To eliminate this confusion, this commit triggers a refresh for the users directory as soon as as a user joins, if the site is in bootstrap mode. The reason for the conditional trigger is that refreshing the users directory is an expensive operation and doing it often on a large site with many users could lead to performance problems.
Internal topic: t/126076.
Resolves the following deprecation warnings when running Discourse on
Ruby 3.3
```
warning: /Users/tgxworld/.asdf/installs/ruby/3.3.1/lib/ruby/3.3.0/mutex_m.rb was loaded from the standard library, but will no longer be part of the default gems since Ruby 3.4.0. Add mutex_m to your Gemfile or gemspec. Also contact author of activesupport-7.0.8.1 to add mutex_m into its gemspec.
warning: /Users/tgxworld/.asdf/installs/ruby/3.3.1/lib/ruby/3.3.0/drb.rb was loaded from the standard library, but will no longer be part of the default gems since Ruby 3.4.0. Add drb to your Gemfile or gemspec. Also contact author of activesupport-7.0.8.1 to add drb into its gemspec.
```
This commit adds a different message to the users directory (`/u`) that's shown when there are no results for the search term instead of showing the one for when there are no users on the site yet.
Internal topic: t/126076.
Sorting a topics list in user activities wasn't working because the query parameters weren't passed to `findFiltered()` that does the request to the server.
Made the `sortIcon` more resilient to "input" by always converting the value to a string and checking against `"true"`.
Moved `cleanNullQueryParams()` inside `findFiltered` so we're always removing `null` query parameters.
Internal ref - t/127068
Some of the old (pre-dag) header logic was accidently re-introduced as part of 9bcbfbba43 (presumably by mistake while resolving a merge conflict). This causes sites on the old header implementation to end up with duplicate user menu icons.
Prior to this fix all menus with empty identifier or groupIdentifier would be considered to be part of the same identifiers/groupIdentifiers and would auto close any existing d-menu with no identifier/groupIdentifier when opened.
Per https://developers.google.com/search/docs/crawling-indexing/overview-google-crawlers
> GoogleOther is the generic crawler that may be used by various product teams for fetching publicly accessible content from sites. For example, it may be used for one-off crawls for internal research and development.
This commit will ensure it's served the crawler view, and included in crawler metrics
This commit changes request method for "categories/search" from GET to
POST to make sure that long filters can be passed to the server. For
example, category selectors with many categories are setting the full
list of selected category IDs to ensure these are filtered out from the
list of choices. This can result in a long URL that exceeds the maximum
length.
The following warning is being printed when running Discourse with Ruby
3.3
`warning: /usr/local/lib/ruby/3.3.0/csv.rb was loaded from the standard
library, but will no longer be part of the default gems since Ruby
3.4.0. Add csv to your Gemfile or gemspec.`
Some sites are still on the legacy "hamburger dropdown"
navigation_menu setting. In this case to avoid confusion,
we want to show both the sidebar icon and the header dropdown
hamburger when visiting the admin portal. Otherwise, the
hamburger switches sides from right to left for admins
and takes on different behaviour.
The hamburger in this case _only_ shows the main panel, not
other sidebar panels like the admin one.
For both `chat_allowed_groups` and `chat_message_flag_allowed_groups`,
this commit removes the `is_staff?` guardian check, and instead
adds both `moderators` and `admins` auto groups as `mandatory_values`
to those settings, as part of an ongoing effort to do this for
group-based setting values.
Recently a bug was introduced when the admin sidebar section was made bold.
When the admin sidebar is disabled, we display the original sidebar in the admin panel. In that case, an incorrect CSS rule is executed.
```CSS
.admin-area .sidebar-wrapper {
background-color: var(--d-sidebar-admin-background);
.sidebar-section-header-text {
font-weight: bold;
}
}
```
Bug in this PR: https://github.com/discourse/discourse/pull/26801
To solve it, a custom CSS class with a panel key was added which will allow granular customisations.
It used to embed the objects which could lead to duplicated objects
when the same user or category was used multiple times (user was admin,
moderator and category or category was parent for multiple categories).
The automation plugin has 4 custom field types that are array typed. However, array typed custom fields are deprecated and should be migrated to JSON type.
This commit does a couple of things:
1. Migrate all four custom fields to JSON
2. Fix a couple of small bugs that have been discovered while migrating the custom fields to JSON (see the comments on this commit's PR for details https://github.com/discourse/discourse/pull/26939)
The watched word group's create, update and delete action logs were missing the translations. This PR will add those strings and will use the group key instead of watched word key where needed.