We didn't escape the "user status" before inserting in in the title of the "user status badge" next to the current user avatar.
This only affects the current user.
Internal ref - t/130332
In 53b3d2f0dc we introduced a stricter BBCode Tag parser. It prevents having "values" with spaces when they're not surrounded by a valid pair of quotes.
The `[details=` BBCode Tag is popular enough that it's worth adding a special case for it (especially since it doesn't support other parameters).
This also adds the Finnish pair of quotes.
Context - https://meta.discourse.org/t/details-accepts-only-one-word-as-summary/313019
Adds a checkbox to filter untranslated text strings in the admin UI, behind a hidden and default `false` site setting `admin_allow_filter_untranslated_text`.
* Removed the link from the title, so the settings can only be accessed via the settings button on the right
* Added an icon to the "Learn more" link to indicate that it opens a new window
* Made various styling adjustments
…to avoid re-evaulation right before destroying.
With `DeferredTrackedSet` we delay both adding and removing elements from the set. That means when you're transitioning between routes, and breadcrumbs change, both old and new breadcrumbs are rendered (briefly, in a first render pass)
And since the arguments for the old breadcrumbs can be (and often are) destroyed - it would blow up the renderer. By caching the template it will reuse it in that first pass.
---
No test because I couldn't figure out a synthetic test setup where you have breadcrumbs in a deeply nested route and where you navigate from that route to one of the parent routes.
This commit introduces behaviour similar to sites
like GitHub, Notion, and others where, if you
are already typing a list and press enter in the composer,
we continue the list on the next line.
Then, if you press enter again on the next line with
an empty list item, we remove that item on that last line.
This works with the following list types:
* star bullet
- dash bullet
* [] star and dash bullet with checkbox
1. numbered
This also works if you are in the middle of a list, and
with indented sub-lists.
With the numbered lists, we continue with the next number
in the sequence, and if you start a new line in the middle
of the list, we renumber the rest of the list.
Previously filter route was not setting topic list, this meant that
keyboard navigation using "G" "J" was not functioning.
This amends it by ensuring the list is set after looking up the model.
Many site settings can be distructive or have huge side-effects
for a site that the admin may not be aware of when changing it.
This commit introduces a `requires_confirmation` attribute that
can be added to any site setting. When it is true, a confirmation
dialog will open if that setting is changed in the admin UI,
optionally with a custom message that is defined in client.en.yml.
If the admin does not confirm, we reset the setting to its previous
clean value and do not save the new value.
A new admin setting called `enforce_second_factor_on_external_auth`. It allows users to authenticate using external providers even when 2FA is forced with `enforce_second_factor` site setting.
* UX: Add new preview links to Popular Themes
Replace previews for 'Discourse' based ones
* prettier
---------
Co-authored-by: Jarek Radosz <jradosz@gmail.com>
Wasn't quite handling the cases where a closing bracket `]` was used in the value of one of the attributes.
```markdown
[chat quote=user channel="[broken]"]
```
Would not be correctly parsed because we would _greedily_ use the first `]` as the end of the tag even though it might be a valid character when inside proper quotes.
c39a4de139/app/assets/javascripts/discourse-markdown-it/src/features/bbcode-block.js (L62)
Re-wrote the `parseBBCodeTag` to properly handle the following cases
- A closing tag (aka `[/name]`) which are easy since they don't have any attributes
- An old `[quote=...]` format we used that doesn't uses quotes but still has various attributes of the form `key:value`
- All three valid BBCode opening tag formats we support
- `[name]` without any attributes
- `[name=foo]` with a default value
- `[name foo=bar]` with some attributes
Ended up having to fix/rewrite the few bbcode rules that were using the `parseBBCodeTag` function, namely `d-wrap` and `discourse-local-dates`.
While working on this, I think I also found a way to get rid the of shims we had in place so that plugins could use the `parseBBCodeTag` function.
Reference - https://meta.discourse.org/t/having-a-right-bracket-in-a-channel-name-breaks-all-quotes-from-that-channel/308439
* Load search results in displayed order so that when more categories are loaded on scroll, they appear at the end,
* Limit the number of subcategories that are shown per category and display 'show more' links,
This allows modifyClass to be used like this:
```
api.modifyClass(
"model:topic",
(Superclass) =>
class extends Superclass {
static someStaticMethod() {
return `${super.someStaticMethod()} modified`;
}
someFunction() {
return `${super.someFunction()} modified`;
}
get someGetter() {
return `${super.someGetter} modified`;
}
}
);
```
One limitation, which is the same as the old object-literal syntax, is that native class fields and constructors cannot be modified.
`@tracked` properties can be overriden, because the decorator turns them into getters/setters.
There is no need to pass a `pluginId` any more. Changes are automatically rolled back as part of test cleanup 🎉
* use `TrackedSet` instead of `@tracked []`
* correct return type annotations
* move code to outside Promise blocks where possible
* fix an outdated comment
When we turn on settings automatically for customers,
we sometimes use `.set_and_log` which will make a staff
action log for the site setting change. This is fine, but
there is no context for customers.
This change allows setting a message with `.set_and_log`, which
will be stored in the `details` column of the staff action log
created, which will show up on `/admin/logs/staff_action_logs`
---------
Co-authored-by: Kelv <kelv@discourse.org>
This commit introduces the `valueTransformer`API to safely override values defined in Discourse.
Two new plugin APIs are introduced:
- `addValueTransformerName` which allows plugins and theme-components to add a new valid transformer name if they want to provide overridable values;
- `registerValueTransformer` to register a transformer to override values.
It also introduces the function `applyValueTransformer` which can be imported from `discourse/lib/transformer`. This function marks the desired value as overridable and applies the transformer logic.
How does it work?
## Marking a value as overridable:
To mark a value as overridable, in Discourse core, first the transformer name must be added to `app/assets/javascripts/discourse/app/lib/transformer/registry.js`. For plugins and theme-components, use the plugin API `addValueTransformerName` instead.
Then, in your component or class, use the function `applyValueTransformer` to mark the value as overridable and handle the logic:
- example:
```js
export default class HomeLogo extends Component {
@service session;
@service site;
...
get href() {
return applyValueTransformer("home-logo-href", getURL("/"));
}
```
## Overriding a value in plugins or themes
To override a value in plugins, themes, or TCs use the plugin API `registerValueTransformer`:
- Example:
```js
withPluginApi("1.34.0", (api) => {
api.registerValueTransformer("example-transformer", ({ value }) => {
return "new-value";
});
});
```
We were using `autoclose` as the topic status update
when silently closing topics using the bulk
actions (introduced in 0464ddcd9b).
However, this resulted in a message like this showing in
the topic as a small moderator post:
> This topic was automatically closed after X days.
This is not accurate, the topic was bulk closed by someone.
Instead, we can use `closed` as the status, and a more accurate
> Closed on DATE
message is used. `TopicStatusUpdater` needed an additional
option to keep the same "fake read" behaviour as autoclose
so we can keep the same functionality for silently closing
topics in bulk actions.
This commit extracts the content of the `HomeLogo` to a standalone
component. This enables us to utilize the `home-logo-contents` plugin
outlet to render an alternative version of the logo using the new
component to reuse the rendering logic, but using alternative
properties. For example:
```js
const logoSmallUrl = settings
.theme_uploads["theme-alternative-logo-small"];
const logoUrl = settings.theme_uploads["theme-alternative-logo"];
const mobileLogoUrl = settings
.theme_uploads["theme-alternative-logo"];
api.renderInOutlet("home-logo-contents", <template>
<HomeLogoContents
@logoSmallUrl={{logoSmallUrl}}
@logoUrl={{logoUrl}}
@minimized={{@outletArgs.minimized}}
@mobileLogoUrl={{mobileLogoUrl}}
@showMobileLogo={{@outletArgs.showMobileLogo}}
@title={{@outletArgs.title}}
/>
</template>);
``
decorator-transforms (https://github.com/ef4/decorator-transforms) is a modern replacement for babel's plugin-proposal-decorators. It provides a decorator implementation using modern browser features, without needing to enable babel's full suite of class feature transformations. This improves the developer experience and performance.
In local testing with Google's 'tachometer' tool, this reduces Discourse's 'init-to-render' time by around 3-4% (230ms -> 222ms).
It reduces our initial gzip'd JS payloads by 3.2% (2.43MB -> 2.35MB), or 7.5% (14.5MB -> 13.4MB) uncompressed.
This was previously reverted in 97847f6. This version includes a babel transformation which works around the bug in Safari <= 15.
For Cloudflare compatibility issues, check https://meta.discourse.org/t/311390
Inline the helper functions, avoid creating and then immediately destructuring arrays, use complete strings instead of string interpolation, Map instead of a pojo.
* FEATURE: Add Filter for Webhook Events by Status
* Fixing multiple issues
* Lint
* Fixing multiple issues
* Change the range of the status for webhook events
Really fully authored by Jarek, I only made the PR :)
The `DBreadcrumbItem` and `DBreadcrumbContainer` components
introduced in 1239178f49 have
some limitations, mainly that the container has no awareness of
its items, so nothing that requires positional knowledge can
be used. This is needed to use `aria-current` on the last breadcrumb
item, see https://www.w3.org/WAI/ARIA/apg/patterns/breadcrumb/examples/breadcrumb/.
We change `DBreadcrumbItem` to always be a link, removing
the need for `LinkTo`. Then, we introduce a service to keep
track of containers and items (since all items are rendered into
all containers) and make the item itself responsible for registering
to the service, and introduce the needed `aria-current` behaviour.
---------
Co-authored-by: Jarek Radosz <jradosz@gmail.com>
We want to get rid of the old topic bulk actions modal
and use the new dropdown (currently gated behind
experimental_topic_bulk_actions_enabled_groups). To do
this we need to use the new dropdown in all places in the
UI.
This commit changes the full page search UI to use the new
topic bulk actions dropdown if experimental_topic_bulk_actions_enabled_groups
is enabled, and makes some minor refactors to make this work.
Also add a spec for both the old and new functionality.
# Description
Add `addCustomUserFieldValidationCallback` to the user fields validation mixin. This allows you to add a custom validation when checking the validity of custom user field values in the signup form on submit.
```js
addCustomUserFieldValidationCallback((userField) => {
if (userField.field.name === "my custom user field" && userField.value === "foo") {
return EmberObject.create({
failed: true,
reason: I18n.t("value_can_not_be_foo"),
element: userField.field.element,
});
}
});
```
In the case your custom validation deems an input value `failed`, you return an EmberObject with the fields `failed: true`, `reason`, and `element`.
```js
return EmberObject.create({
failed: true,
reason: I18n.t("value_can_not_be_foo"),
element: userField.field.element,
});
```
which will then display your custom `reason` to the user attached to the given user custom field input and will not submit the signup form.
<img width="288" alt="Screenshot 2024-06-06 at 11 08 40 AM" src="https://github.com/discourse/discourse/assets/50783505/11168fb8-8806-43f0-9417-73991bbd1178">
# Other
- Add `addCustomUserFieldValidationCallback` to the plugin api
- Bump plugin api version
- Update plugin api changelog
- Add tests
For cases where you'd be using a TrackedSet to render something and then modifying that set throughout the same render cycle. (specifically it will be used in #27365)
This commit introduces the initial UI for the admin config area for the /about page. The UI isn't wired and doesn't do anything yet, but we're going to iterate on it in future commits.
Internal topic: t/128544.
This commit fixes a problem where the user will not be able to reset
their password when they only have security keys and backup codes
configured.
This commit also makes the following changes/fixes:
1. Splits password reset system tests to
`spec/system/forgot_password_spec.rb` instead of missing the system
tests in `spec/system/login_spec.rb` which is mainly used to test
the login flow.
2. Fixes a UX issue where the `Use backup codes` or `Use authenticator
app` text is shown on the reset password form when the user does
not have either backup codes or an authenticator app configured.
Followup 0434112aa7,
when I introduced the pluralisation for the
password.too_short message I didn't change the
key name to `count`, which is necessary.
This commit includes various UX improvements to the reset
password page:
* Introduce a `hide-application-header-buttons` helper to do the following:
* Hide Sign Up and Log In buttons, they are not necessary on this flow
* Hide the sidebar, it is a distraction on this flow
* Improve messaging when a 2FA confirmation is required first
* Improve display of server-side ActiveRecord model validation errors
in password form, e.g. instead of "is the same as your current password"
we do "The password is the same as your current password"
* Move password tip to next line below input and move caps lock hint
inline with Show/Hide password toggle
* Add system specs for 2FA flow on reset password page
* Fixes a computed property conflict issue on the password reset
page when toggling 2FA methods
Continued work on moderate flags UI.
In this PR admins are allowed to change the order of flags. The notify user flag is always on top but all other flags can be moved.
This reverts commit 0b10e335ae.
I realised that some of these actions are overridden in themes/plugins, so this is going to cause problems (especially because modifyClass doesn't currently work well with the `@action` decorator)
This makes it more obvious what's happening, and makes it much less likely that users will send repeated reset emails (and thereby hit the rate limit)
Followup to e97ef7e9af
Even when the admin sidebar sections are collapsed, they should expand while filtering. When the filter is removed, sections should go back to the previous state.
In addition, trim whitespace from the filter section.
Only remaining ones are `routes/discourse.js` and `routes/application.js`. Those two both contain legacy `actions: {}` hashes which need to be updated before being converted to native class syntax.
This commit removes the `/admin-revamp` routes which were introduced as a part of an experiment to revamp the admin pages. We still want to improve the admin/staff experience, but we're going to do them within the existing `/admin` routes instead of introducing a completely new route.
Our initial efforts to improve the Discourse admin experience is this commit which introduces the foundation for a new subroute `/admin/config` which will house various new pages for configuring Discourse. The first new page (or "config area") will be `/admin/config/about` that will house all the settings and controls for configuring the `/about` page of Discourse.
Internal topic: t/128544
This commit re-introduces the "Move to Inbox" and "Move to Archive"
bulk topic actions, which we had in the old modal but had not yet added
to the new "experimental" dropdown, which isn't really experimental at
this point.
Once this is merged we can remove the old modal and only
rely on the new dropdown.
The issue was simple, we were just not returning the helper in the `user-private-messages` controller which was preventing any action to happen.
Follow up: we should write specs for this toggle.
Prior to this fix we were opening a modal before closing the `DMenu` modal, given `DModal` expects only one modal at a time it was closing the latest modal and instantly closing the one we just opened.
This adds a small indicator of the Ctrl+/ shortcut that
exists for the admin sidebar filter, since it's not very
obvious that you can do that. This should help people
who are struggling with the long list of links -- it's
much faster to use the keyboard and search for what
you are looking for.
Followup 73c6bb2593
The admin sidebar was also disappearing on another
child admin route (in this case the docker_manager
plugin update page). Instead of relying on the route
name which is flaky, we can set a boolean when the
sidebar is forced in the root admin route, then
turn it off when leaving admin.
When uploading a video, the composer will now show a thumbnail image in
the composer preview instead of just the video placeholder image.
If `enable_diffhtml_preview` is enabled the video will be rendered in
the composer preview and is playable.
Delay rendering sidebar sections after sidebar is shown
Showing the popup takes about 100ms, then rendering each section
could take up to and additional 200ms, which leaves the total just
outside of 300ms. If we cheat by rendering the popup first then
the sections in the next frame, it improves our paint time
Introduce DeferredRender to encapsulate 'paint later'
This uses a new nav style with the heirarchy:
```
Breadcrumbs
|- Title
|- Description
|- Third-Level Navigation
```
The navigation bar uses the transparent red-underlined
buttons similar to the user activity page.
Over time all admin pages will use this, but this starts
with the new plugin show page.
---------
Co-authored-by: Ella <ella.estigoy@gmail.com>
We need to register a waiter so that `settled()` will wait for `runAfterFramePaint()` callbacks to be run before proceeding.
Re-lands 63b7b598cb, but wrapped with `isTesting()` to avoid production errors.
# Context
We currently have a tracked value of `topic` in the header service that we utilize across the app for determining the presence of a topic.
A simple example is: If you are in a topic, and scroll down the page, we need to communicate to the header that a topic is present and we change the styling of the header.
The issue with this logic is that when entering a topic (and you are at the top of the page), we **haven't** set the topic on the header service yet. We only set the topic when you have scrolled down on the page (set by `app/components/discourse-topic.js`)
This is unhelpful behavior when you are utilizing a plugin outlet that is receiving the `topic` from the header:
17add599e3/app/assets/javascripts/discourse/app/components/header/topic/info.gjs (L85)
As the `topic` won't be present until you scroll down the page.
# Changes
This PR adds a tracked `inTopic` value to the header service that is a boolean value. This is to let the app know
> Yes, we are scrolled within a topic
And instead sets the tracked `topic` value immediately, if you are loading a topic, to allow the necessary data to be populated to the plugin outlets on page load.
Previously, avatars would be 'sticky' when:
1. The post was longer than the viewport
OR
2. You were scrolling up
The difference in behavior based on scroll direction doesn't 'feel' quite right. This commit makes the behavior consistent, so sticky avatar logic is applied to all posts regardless of scroll direction.
Prior to this fix we had too logic to detect if a user is active or not:
- idle codepath on the frontend
- online user ids on the backend
The frontend solution is not very reliable, and both solution are just trying to be too smart. Making a lot of people questioning why they receive a notification sometimes and sometimes not. This commit removes all this logic and replaces it with a much more simpler logic:
- you can't receive notifications for channel you are actually watching
- we won't play a sound more than once every 3seconds
When selected some text inside a post, we offer the ability to "fast edit" the selected text without opening the composer.
However, there are certain cases where this isn't working quite a expected, due to the fact that we have some text in the "cooked" version of the post that isn't literally in the "raw" version of the post.
This ensures that whenever someone selects the within
- a quote
- a onebox
- an encrypted message
- a "cooked" date
we directly show the composer instead of showing the fast edit modal and then leaving the user with an invisible error.
Internal ref. t/128400
* FIX: When creating new message via URL do not redirect
If a user clicks on `/new-message` route from inside the instance we're
redirecting the user to `/latest` page which is only intended if the
user is coming from an external site. This commit checks for this
condition and only redirects when user is coming from external source.
This also makes the behavior consistent with `new-topic` route.
Internal topic reference: `/t/-/129523/`
We consider that you should always receive a notification sound when someone speaks directly with you in chat.
This commit also refactors the way we play audio in chat to make it simpler and throttle it to 3 seconds.
We also added a safeguard to ensure we won't play sounds for old messages, this case can happen when message bus is catching up the backlog (eg: in an inactive tab for example).
* FEATURE: add agree and edit
adds agree and edit - an alias for agree and keep -- but with a client action to
edit the post in the composer before the flag is agreed with
---------
Co-authored-by: Juan David Martinez <juan@discourse.org>
We're planning to implement a feature that allows adding required fields for existing users. This PR does some preparatory refactoring to make that possible. There should be no changes to existing behaviour. Just a small update to the admin UI.
Before this fix when generating a pm path leading to a group messages inbox we would blindly take the first group of the pm, however, it's possible our current user doesn't have access to this group.
This commit will now try to find the first group the user has access to, and generate a path to this group’s inbox.
For plugins with only an "enabled" site setting, it doesn't
make sense to take them to the site settings page, since the
toggle switch in the list can be used to change enabled/disabled.
This will not be the case for plugins that have their own custom
config page (like Automation), but we will deal with this when
we actually overhaul this plugin to use the new show page.
Also adds another rspec fixture of a test plugin.
This PR aims to add bulk actions to the user's bookmarks.
After this feature, all users should be able to select multiple bookmarks and perform the actions of "deleting" or "clear reminders"