Follow up to refactoring the generic utils mixin used in select-kit
components in https://github.com/discourse/discourse/pull/32594.
This PR follows a different approach as the util functions related to
properties here aren't easily extracted without a major change to the
interface due to the dependency on `this.selectKit`. These util
functions are instead declared on the prototype with a class decorator
which ensures the same behaviour is maintained without relying on a
mixin.
It's largely a lift-and-shift with some minor refactoring of the
conditional logic to reduce nesting and improve readability of the
functions.
## 🔍 Overview
This update add an _optional_ attribute to the `toolbar.addButton()` API
so that we can conditionally hide the shortcut showing up in the title.
Although for most cases, showing the shortcut in the title is fine. For
complex uses of `toolbar.addButton` where it triggers a menu, it isn't
ideal. For example, in Discourse AI, the toolbar API is used to show a
menu for the AI composer helper. The shortcut in the API is used to
trigger the proofreading item, but not necessarily for all other items.
As such, we want the shortcut hidden in the title.
## 🛠️ Usage
```diff
withPluginApi((api) => {
api.onToolbarCreate((toolbar) => {
toolbar.addButton({
id: "smile",
group: "extras",
name: "smile",
icon: "far-face-smile",
title: "cheese",
shortcut: "ALT+S",
+ hideShortcutInTitle: true,
});
});
});
```
### ← Before
Title shows:
> Cheese (Ctrl + Alt + S)
### → After
Title shows:
> Cheese
Marking mixed-decls as silenced & fatal simultaneously is causing a
warning "Ignoring setting to silence mixed-decls deprecation, since it
has also been made fatal"
The intention is for it to be silenced for themes/plugins, but fatal for
core.
This is a more efficient version of `{{hash`, where the values are only evaluated when they're actually accessed. Also enables a new lint rule which will ensure `{{hash` is not reintroduced on PluginOutlets
We recently added a new themes and components page. We didn't port over the code that enables the Install theme button on Meta. It works by looking for certain query parameters and opening a special version of the install modal.
This PR is a lift-and-shift of that code from the old themes page.
In this PR, filter was removed and replaced by search.
#32485
However, moderator should still be able to filter sidebar. Also, plugins like doc-category should have filterable sidebar.
We use ampersand to concatenate sidebar sections, e.g. Login & authentication, Logs & screening, etc.
This updates Themes & components to have the same.
In some cases, Google crawlers don't output the meta description but
rather they output the first bit of text in the UI. Sometimes that is a
mix of table headings, topic titles and excerpts, which don't reflect
the site's mission. Adding the description to the homepage header might
help.
Internal ticket t/154372
Currently, topic excerpts are not localized.
This commit adds the excerpt column into topic_localization and displays the
localized excerpt if present.
```
rspec --seed 52075 spec/models/site_spec.rb spec/lib/freedom_patches/translate_accelerator_spec.rb
Randomized with seed 52075
....................................................F
Failures:
1) translate accelerator plugins loads plural rules from plugins
Failure/Error: self.locale_no_cache = value
I18n::InvalidLocale:
:foo is not a valid locale
# ./lib/freedom_patches/translate_accelerator.rb:254:in 'I18n.locale='
# ./spec/lib/freedom_patches/translate_accelerator_spec.rb:118:in 'block (3 levels) in <main>'
```
This is because setting `I18n.config.available_locales` is equivalent to
hard coding the
locales for the entire process. It should not be set so that `I18n` will
fallback to `backend.locales`.
Some cases are more complex than the default behavior of
`this.router.isActive(this.args.route)`, in this case you can give use
`@currentWhen` on your `NavItem` component.
Example:
```gjs
get isItCurrent() {
return true;
}
<template>
<NavItem @i18nLabel="test" @currentWhen={{this.isItCurrent}} />
</template>
<template>
<NavItem @i18nLabel="test" @currentWhen="foo" />
</template>
<template>
<NavItem @i18nLabel="test" @currentWhen="foo.show foo.index" />
</template>
```
No test as I can't write a component test for this as it relies on the
router.
These lines of code would output "Period - Site name" as the page title
for the crawlier view only for Top routes. This is too specific and
unnecessary, since the top route isn't highly prioritized for crawlers.
Without this, the page title defaults to "Site name" for these routes.
One major advantage of this change is that when the homepage is set to
the Top route, the page title for crawlers on the homepage is now "Site
name", which is a lot better.
This improves the error message(s) displayed when an error happens while
using a social login to log in / sign up into a Discourse community.
Unfortunately, we can't be super precise in the reason behind the error
(it can be the user clicked "cancel" during the authorization phase, or
any of the plethora of other possible errors) because the reason isn't
provided (either for security reasons, or because it's just hard to do
so in a reliable & consistent way accross all social logins).
The best I could do was to
- add the name of the "social login" provider in the error message
- tweak the copy a bit for the different cases handle
- fix the CSS/HTML to match the one used by the main application
In order to show the name of the provider, we use either the "provider"
or the "strategy" query parameter, or use the name of the authenticator
(if it's the only one enabled).
Internal ref - t/153662
---
**BEFORE**

**AFTER**

This error sometimes includes a filepath in the middle, which has a
random tmp/ prefix. To workaround this, we can just assert for the
"Missed semicolon" part
Technically we want to follow DDAU but most of our usage in the code
base are just mutating `@checked`. This will eventually get converted to
form-kit but in the meantime we can just remove this bit of code as it's
doing two times the same thing and you could even end up in the
situation where they both fight for what is the correct value.