This PR adds a feature to help admins stay up-to-date with their translations. We already have protections preventing admins from problems when they update their overrides. This change adds some protection in the other direction (where translations change in core due to an upgrade) by creating a notice for admins when defaults have changed.
Terms:
- In the case where Discourse core changes the default translation, the translation override is considered "outdated".
- In the case above where interpolation keys were changed from the ones the override is using, it is considered "invalid".
- If none of the above applies, the override is considered "up to date".
How does it work?
There are a few pieces that makes this work:
- When an admin creates or updates a translation override, we store the original translation at the time of write. (This is used to detect changes later on.)
- There is a background job that runs once every day and checks for outdated and invalid overrides, and marks them as such.
- When there are any outdated or invalid overrides, a notice is shown in admin dashboard with a link to the text customization page.
Known limitations
The link from the dashboard links to the default locale text customization page. Given there might be invalid overrides in multiple languages, I'm not sure what we could do here. Consideration for future improvement.
Follow-up to b27e12445d
This commit adds 2 new site settings `default_sidebar_link_to_filtered_list` and `default_sidebar_show_count_of_new_items` to control the default values for the navigation menu preferences that were added in the linked commit (`sidebar_link_to_filtered_list` and `sidebar_show_count_of_new_items` respectively).
Chat drawer was using the `DiscourseURL` hook `afterRouteComplete`. This hook suffer from a very poor implementation which makes it very unreliable:
```javascript
if (typeof opts.afterRouteComplete === "function") {
schedule("afterRender", opts.afterRouteComplete);
}
```
This commit attempts to return the promise from `handleURL` to directly use it and have a very reliable after transition hook.
This PR converts the following modals:
- `dismiss-new`
- `dismiss-read`
- `dismiss-notification-confirmation`
to make use of the new component-based API
# Additional Changes
## Before
By default we display a warning modal when dismissing a notification however we bypass the warning modal for specific notification types when they are a 'low priority' type of notification (eg. likes). To do this we were overwriting `dismissWarningModal` on a given notification type component
```javascript
dismissWarningModal() {
return null
}
```
but in the case we wanted to change the text within the modal we were calling `showModal` and then passing in the respective options all over again, putting the logic of rendering the modal in multiple places.
```javascript
dismissWarningModal() {
const modalController = showModal("dismiss-notification-confirmation");
modalController.set(
"confirmationMessage",
I18n.t("notifications.dismiss_confirmation.body.assigns", {
count: this._unreadAssignedNotificationsCount,
})
);
return modalController;
}
```
## After
I simplified this by adding an extensible `dismissConfirmationText` function that can be updated on a per component basis as that was the only option being overridden.
eg
```javascript
get dismissConfirmationText() {
return I18n.t("notifications.dismiss_confirmation.body.bookmarks", {
count: this.#unreadBookmarkRemindersCount,
});
```
This saves us from importing the entire modal again and keeps the core logic in one place.
Instead of overwriting the `dismissWarningModal` function and returning `null` to bypass the confirmation modal, I added another extension point of `renderDismissConfirmation` (defaults to true) to _toggle_ whether we should display a confirmation when dismissing notifications.
eg
```javascript
get renderDismissConfirmation() {
return false;
}
```
we utilize this in core for specific _low priority_ notification types. When you need the confirmation modal to be displayed no matter the case you can set `alwaysRenderDismissConfirmation` to `true`
```
get alwaysRenderDismissConfirmation(){
return true
}
```
This can be useful when you want to render the confirmation modal on a custom notification type that is not deemed as _high priority_, leading to the confirmation modal never being rendered.
You can see this in use in [Discourse Assign](https://github.com/discourse/discourse-assign/pull/481)
Followup to d51baa3bb3
Also includes: Force full rerender of post-stream widget when switching topics. This ensures that plugin/theme decorators are re-run when we switch between topics with the loading slider enabled.
Previously we were using the `didInsertElement` hook and querying the DOM to check whether the other button was visible. This is problematic from a performance point of view because it forces the browser to render the layout prematurely. It can also lead to subtle bugs based on the current scroll position.
In addition, having this logic on a `didInsertElement` hook makes it totally incompatible with the new 'loading slider' feature (because the component is not re-rendered between different topic lists).
This commit updates the logic to be based simply on the count of topics in the list. If there are fewer than 5 topics, the top button is hidden.
Under certain conditions, this `afterRender` hook can be triggered after the topic-list-item has been removed from the DOM. This is more likely when the 'loading slider' strategy is used on a site.
This introduces a PLATFORM_KEY_MODIFIER const that
can be used both client and server side, to determine
whether we should be using the Meta or Ctrl key based
on whether the user is on Windows/Linux or Mac.
Why this change?
A new component based API for modals was introduced in
b3a23bd9d6. This commit moves the edit
sidebar section modal to the new API.
Reviewer notes
No functionality or visual change is introduced in this PR.
In previous PR https://github.com/discourse/discourse/pull/22340 bug was introduced. Notifications were blocked when, even if topic was watched directly. New query is taking TopicUser into consideration.
In addition, in user interface, when `watched_precedence_over_muted` is not set, then value from SiteSetting should be displayed.
This brings the functionality from https://github.com/discourse/discourse-loading-slider into Discourse core. Default behaviour remains the same - the new slider mode can be enabled using the new 'page_loading_indicator' site setting.
A follow-up to 585a2e4e. A couple of tests with the new rich tooltip were flaky.
We suppose the reason is some problem related to widgets lifecycle. This PR
doesn't fix the issue, but isolates testing of the tooltip related logic related
inside its own test, which should make it not flaky.
This is a temporal solution, we're going to move all these code to using
glimmer components.
Previously, the `@model` argument would be unset before the component's `willDestroy` hook was called. Wrapping up the component and the opts in a single tracked `activeModal` field, and then using the `#each` helper with an array of 1 element means that Glimmer will keep the `@model` argument available until the end of the component's lifecycle.
Recently, site setting watched_precedence_over_muted was introduced - https://github.com/discourse/discourse/pull/22252
In this PR, we are allowing users to override it. The option is only displayed when the user has watched categories and muted tags, or vice versa.
What is the problem?
Before this change, we were relying on the `/tags` endpoint which
returned all the tags that are visible to a give user on the site leading to potential performance problems.
The attribute keys of the response also changes based on the `tags_listed_by_group` site setting.
What is the fix?
This commit fixes the problems listed above by creating a dedicate `#list` action in the
`TagsController` to handle the listing of the tags in the edit
navigation menu tags modal. This is because the `TagsController#index`
action was created specifically for the `/tags` route and the response
body does not really map well to what we need. The `TagsController#list`
action added here is also much safer since the response is paginated and
we avoid loading a whole bunch of tags upfront.
What is the problem?
This regressed in fe294ab1a7 and we did
not have any tests on mobile to catch the regression. The problem was
that we were conditionally rendering the edit nav menu modals component
in the sidebar. However, the sidebar is collapsed on mobile when a
button is clicked. When the sidebar collapses, the edit nav menu modals
ended up being destroyed with it.
Why this change?
A new component based API for modals was introduced in
b3a23bd9d6. This commit moves the edit
navigation menu tags and categories modal to the new API.
This allows us to use `getOwner(this)` on widgets (without needing to resort to our custom `discourse-common/lib/get-owner` implementation which has a hacky fallback)
`_self` is the default, so we should treat it the same as having no value specified. This fixes navigation to links like `/my/...` in custom sidebar links.
- Inline mentions on posts
- Inline mentions on chat messages
- The user autocomplete for the composer
- The user autocomplete for chat
- The chat section of the sidebar