Operate a key at a time, to make it clearer what's going on.
This also fixes a bug where array integer fields would get re-written
even when there wasn't a change.
This change converts the `approve_unless_trust_level` site setting to
`approve_unless_allowed_groups`.
See: https://meta.discourse.org/t/283408
- Adds the new site setting
- Adds a deprecation warning
- Updates core to use the new settings.
- Adds a migration to fill in the new setting of the old setting was
changed
- Adds an entry to the site_setting.keywords section
- Updates many tests to account for the new change
After a couple of months we will remove the `approve_unless_trust_level`
setting entirely.
Internal ref: /t/115696
Array custom fields use separate rows for each value, but whenever we
update an array, we have always destroy the existing rows and create new
ones. Therefore, there's no benefit over using the json type.
In the past, our loading spinner implementation used Ember's loading substate. That meant that, when the site setting was toggled, there would be fundamental changes in the routing behavior.
This commit simplifies things so that the (non-default) loading spinner implementation is purely a styling thing, and behaves exactly the same as the spinner which appears under the 'slider' configuration when loading takes too long.
This does involve a slight UX change. Now, the entire page will be replaced by a loading spinner instead of just the relevant `{{outlet}}`. We strongly recommend sites use the new default 'slider' behavior.
* Remove checkmark for official plugins
* Add author for plugin, which is By Discourse for all discourse
and discourse-org github plugins
* Link to meta topic instead of github repo
* Add experimental flag for plugin metadata and show this as a
badge on the plugin list if present
---------
Co-authored-by: chapoi <101828855+chapoi@users.noreply.github.com>
This commit makes it so the fullscreen code modal grows
to fit its content, and doesn't show horizontal scrollbars
unless the entire screen is filled by the modal already.
The code syntax highlighting and copy buttons were also
broken in fullscreen because of modal changes over time.
This reverts commit 20e562bd99, 161256eef8 and a8292d25f8.
It looks like this affected cache-restoration of topic lists in some circumstances. It also looks like routing behavior may vary when toggling the loading indicator between spinner and slider.
More investigation and testing required.
For transitions to nested routes (e.g. /u/blah/activity), where each layer has an async model hook, the `loading` event will be fired twice within the same transition. This was causing the loading slider to jump backwards halfway through loading. This commit fixes things to handle nested loading events with a single animation.
The old heuristic was 'a transition to a URL (i.e. not a named route) which was not triggered by DiscourseURL'. That logic is flawed now that we're increasingly using Ember's routing methods.
This commit extracts the storage part of the route-scroll-manager into a dedicated service. This provides a key/value store which will reset for each navigation, and restore previous values when the user uses the back/forward buttons in their browser.
Should fix https://meta.discourse.org/t/-/285768.
Appending without cloning was causing the item to be removed from the
DOM but on a 1-item grid we skip the rest of the grid's rendering,
hence the item was never re-inserted. Cloning ensures we don't remove
the item during processing (it does get removed later on when rendering
the grid's columns).
Moves the patch from ember-source to ember-cli so that it's easier for us to feature-flag an ember-source upgrade without fighting with patch-package. We'll be able to remove this patch once we're fully on Ember 5.x.
(ref https://github.com/discourse/discourse/pull/21720)
Having async cleanup on a modifier is problematic because it means it might persist beyond the end of a test, leading to flaky 'Test is not isolated' errors.
Discourse already includes version information in a `<meta` tag on the page. This commit surfaces it to the console on boot for easier access, and also adds the Ember version (which will be particularly useful as we start rolling out the upgrade to Ember 5)
This was accidentally selecting the close button on `<DModalLegacy />`, which is present in the DOM with `display: none`. The close button logic would close any active modal, so the test would pass. However, it will stop passing when we remove the legacy modal system.
In the long term we should aim to modernize these places, but for now this change will make them compatible with Ember 5.x (while maintaining compatibility with Ember 3.28)
This commit adds a new `search_default_sort_order` site setting,
set to "relevance" by default, that controls the default sort order
for the full page /search route.
If the user changes the order in the dropdown on that page, we remember
their preference automatically, and it takes precedence over the site
setting as a default from then on. This way people who prefer e.g.
Latest Post as their default can make it so.
Recently, we disabled the option to reorder links directly from the sidebar. Instead, user has to go to edit modal.
https://github.com/discourse/discourse/pull/24188
However, move cursor was left, which is misleading.
en is the only fallback locale we use, so there's no need to invalidate everything when other languages change. Limiting this also helps to prevent circular dependent_field relations which could cause issues in some situations.
Followup to eda79186ee
Currently to use a limit in the notifications index, you have to also pass recent: true as a param.
This PR:
Adds optional limit param to be used in the notifications query, regardless of the presence of recent
Raises the max limit of the response with recent present from 50 -> 60. It is super weird we have a hard-limit of 50 before with recent param, and 60 without the param.
Why this change?
The test has been flaky on CI with the following assertion failing:
```
not ok 302 Firefox 115.0 - [899 ms] - Browser Id 5 - Acceptance: Fast Edit: Works with keyboard shortcut
---
actual: >
Element #fast-edit-input does not exist
expected: >
Element #fast-edit-input exists
```
The hypothesis here is that we are triggering the `E` keypress event
before the `.quote-button` menu has appeared. When that happens, we will
end up opening the composer instead of triggering the fast edit editor.
Why this change?
As the number of themes which the Discourse team supports officially
grows, we want to ensure that changes made to Discourse core do not
break the plugins. As such, we are adding a step to our Github actions
test job to run the QUnit tests for all official themes.
What does this change do?
This change adds a new job to our tests Github actions workflow to run the QUnit
tests for all official plugins. This is achieved with the following
changes:
1. Update `testem.js` to rely on the `THEME_TEST_PAGES` env variable to set the
`test_page` option when running theme QUnit tests with testem. The
`test_page` option [allows an array to be specified](https://github.com/testem/testem#multiple-test-pages) such that tests for
multiple pages can be run at the same time. We are relying on a ENV variable
because the `testem` CLI does not support passing a list of pages
to the `--test_page` option.
2. Support a `/testem-theme-qunit/:testem_id/theme-qunit` Rails route in the development environment. This
is done because testem prefixes the path with a unique ID to the configured `test_page` URL.
This is problematic for us because we proxy all testem requests to the
Rails server and testem's proxy configuration option does not allow us
to easily rewrite the URL to remove the prefix. Therefore, we configure a proxy in testem to prefix `theme-qunit` requests with
`/testem-theme-qunit` which can then be easily identified by the Rails server and routed accordingly.
3. Update `qunit:test` to support a `THEME_IDS` environment variable
which will allow it to run QUnit tests for multiple themes at the
same time.
4. Support `bin/rake themes:qunit[ids,"<theme_id>|<theme_id>"]` to run
the QUnit tests for multiple themes at the same time.
5. Adds a `themes:qunit_all_official` Rake task which runs the QUnit
tests for all the official themes.
Move external login logic from the **Login Modal** -> **Login Service**. This is advantageous as we can utilize the external login logic from both within and outside of the login modal.
A downside of having the external login logic within the login modal is that there is a brief "flash" of the login modal being rendered and then us automatically redirecting to the external login method. This PR will clean up the visual side affects.
This change means that the `/my` redirects will be handled by the ember 'unknown' route, and will therefore function correctly when using pure-ember transition methods like `router.transitionTo`
We want / to display one of our discovery routes/controllers, but we don't want to register it as `discovery.index` because that would break themes/plugins which check the route name. Previously, this was handled using a variety of approaches throughout the codebase (in discourse-location, discourse-url and mapping-router). But even then, it didn't work consistently. For example, if you used an Ember method like `router.transitionTo("/")`, an empty `discovery.index` page would be rendered.
This commit switches up the approach. `discovery.index` is now defined as a real route, and redirects to the desired homepage. To preserve the `/` as a 'vanity url', we patch the method on the router responsible for persisting URLs to the Ember Router and the browser. The patch identifies a relevant transition by looking for a magic query parameter.
In an ideal world, we wouldn't be patching the router at all. But at least with this commit, the workaround is all in one place, and works consistently for all navigation methods. The new strategy is also much better tested.
When we started using NumberField for integer site settings
in e113eff663, we did not end up
passing down a min/max value for the integer to the field, which
meant that for some fields where negative numbers were allowed
we were not accepting that as valid input.
This commit passes down the min/max options from the server for
integer settings then in turn passes them down to NumberField.
c.f. https://meta.discourse.org/t/delete-user-self-max-post-count-not-accepting-1-to-disable/285162
Why this change?
This test has been flaky on CI: https://github.com/discourse/discourse/actions/runs/6880353258/job/18714366795
However, the way the current assertions are written does not really
allow us to easily figure out what went wrong since we only know that
`#post_4` was not selected. It will be useful to know what was selected
instead of `#post_4` when the test fails.
What does this change do?
This change updates the assertion of the flaky test to reveal which post
was selected should the test fail.
This discourse-common decorator was dependent on the core app, hence creating a circular reference that was breaking the embroider upgrade. (see: #24391)
Raised in https://meta.discourse.org/t/keyboard-navigation-messes-up-the-search-menu/285405
We were incorrectly accessing the highlighted search result target's href which caused issues when navigating the topic list (eg /latest) with **j / k** and then immediately after accessing the search menu and navigating to and selecting a search result with the keyboard.
### Current Behavior
Hitting enter on a search result redirects to the href of the topic in the topic list that was previously highlighted.
### Expected Behavior
Hitting enter on a search result redirects to the href of the highlighted search result.
The default for webpack is to keep cached values indefinitely. In discourse, this unbound memory usage causes node to raise an OOM error after 50-100 rebuilds in development mode (with source maps enabled). Setting maxGenerations=1 means that the cache will be cleaned up regularly. With this change, I see no discernible increase in memory after 150+ rebuilds.
Previously, the discourse-hbr plugin took the entire app tree as its input, and the result would then be merged into the app. This is wasteful and more likely to cause problems in the build pipeline.
See also https://github.com/discourse/discourse/pull/24376
Ember-cli has built-in error pages when there is a build error. Previously these were not being used in Discourse because our custom proxy middleware was too early in the stack. This commit reorders things so that the "broccoli-watcher" middleware runs before our custom proxy. It also disables the `historySupportMiddleware`, which doesn't make sense in our 'always proxy' setup.
This PR refactors the following:
* leaving all the CSS applied to the old `modal-body` classes in their respective files
* made new clean styling for `.d-modal` and refactored the template to use the new BEM classes
* `inner-`, `middle-`, `outer-` container classes are gone and replaced with simplified `wrapper` and `container` classes
* use standardised max-sizes with modifiers `-large` and `-max`
* lighter backdrop,
* min-width to prevent puny modals
* other styling changes regarding padding, close button,…
* pulled out all modal overrides into a general `modal-overrides` file + cleanup of outdated CSS
* pulled out login and create account modal styling into their own file, cause it's such a big override
* removed old general login.scss file for mobile & desktop
* only kept some remainders I don't want to touch in `app/assets/stylesheets/common/base/login.scss`
Previously this was being handled in two places:
1. As a monkey-patch to the Ember router. This would 'trick' the router into rendering a different route, but would leave the browser URL bar unchanged. Many possible bugs can come from this state
2. In the DiscourseURL.routeTo function. This functioned fine as a redirect, but wouldn't have any effect when the transition is handled by Ember
This commit refactors things so that the DiscourseURL redirects are handled the same as our permalinks. When the Ember 'unknown' route is hit, we check for a possible rewrite and redirect there. This is a supported way of doing things, and should be more robust going forwards.
Previously we would only recompile a theme locale when its own data changes. However, the output also includes fallback data from other locales, so we need to invalidate all locales when fallback locale data is changed. Building a list of dependent locales is tricky, so let's just invalidate them all.
Previously we had similar logic in two places:
1. A DiscourseURL rewrite, based on a site setting
2. Some logic in the user-index route
This commit moves everything into (2) to make things clearer and more consistent
We ask users to confirm their session if they are making a sensitive
action, such as adding/updating second factors or passkeys. This
commit adds the ability to confirm sessions with passkeys as an option
to the password confirmation.
This allows outlets for the post-text-selection-toolbar to
get just the raw markdown of the selected text for a quote,
rather than opening the composer.
This commit changes some plugin outlets in `<Discovery::Layout>`, `<Discovery::Navigation>` and `Discovery::Topics` to improve compatibility with existing customization, simplifying the migration process to the new discovery routes.
In these components, the standard plugin outlets will receive by default at least the arguments: `category` and `tag`.
Furthermore, two new wrapping plugin outlets were added to enable the conversion of existing template overrides to the new pattern: `discovery-list-area` and `topic-list-bottom`. The new template overrides will receive a `model` argument containing the full model handled by the route.
---------
Co-authored-by: David Taylor <david@taylorhq.com>
Follow-up to #24278 that is slightly less trivial.
* Some were "trivial" usages that were missed in the previous PR because the same file that had at least one other non-trivial usage.
* These involve extra arguments or inheritance but I have checked that they seem correct.
- Remove vendored copy
- Update Rails implementation to look for language definitions in node_modules
- Use webpack-based dynamic import for hljs core
- Use browser-native dynamic import for site-specific language bundle (and fallback to webpack-based dynamic import in tests)
- Simplify markdown implementation to allow all languages into the `lang-{blah}` className
- Now that all languages are passed through, resolve aliases at runtime to avoid the need for the pre-built `highlightjs-aliases` index
Previously, the app HTML served by the Ember-CLI proxy was generated based on a 'bootstrap json' payload generated by Rails. This inevitably leads to differences between the Rails HTML and the Ember-CLI HTML.
This commit overhauls our proxying strategy. Now, we totally ignore the ember-cli `index.html` file. Instead, we take the full HTML from Rails and surgically replace script URLs based on a `data-discourse-entrypoint` attribute. This should be faster (only one request to Rails), more robust, and less confusing for developers.
This updates the behaviour to match ember-cli-htmlbars, and should take care of the handful of themes which were relying on runtime compilation in tests (see 4425e99bf9)
Group channels will allow users to create channels with a name and invite people. It's possible to add people even after creation of the channel. Removing users is not yet possible but will be added in the near future.
Technically a group channel is `direct_message_channel` with a group attribute set to true on its direct message (chatable). This model might evolve in the future but offers much flexibility for now without having to rely on a complex migration.
The commit essentially consists of:
- a migration to set existing direct message channels with more than 2 users to a group
- a new message creator which allows to search, add members, and create groups
- a new `AddUsersToChannel` service
- a modified `SearchChatable` service
Followup to fe05fdae24
For consistency with other S3 settings, make the global setting
the same name as the site setting and use SiteSetting.Upload
too so it reads from the correct place.
This adds the ability to collect stats without exposing them
among other stats via API.
The most important thing I wanted to achieve is to provide
an API where stats are not exposed by default, and a developer
has to explicitly specify that they should be
exposed (`expose_via_api: true`). Implementing an opposite
solution would be simpler, but that's less safe in terms of
potential security issues.
When working on this, I had to refactor the current solution.
I would go even further with the refactoring, but the next steps
seem to be going too far in changing the solution we have,
and that would also take more time. Two things that can be
improved in the future:
1. Data structures for holding stats can be further improved
2. Core stats are hard-coded in the About template (it's hard
to fix it without correcting data structures first, see point 1):
63a0700d45/app/views/about/index.html.erb (L61-L101)
The most significant refactorings are:
1. Introducing the `Stat` model
2. Aligning the way the core and the plugin stats' are registered
There was a registry for preloaded site categories and a new one has
been introduced recently for categories serialized through a
CategoryList.
Having two registries created a lot of friction for developers and this
commit merges them into a single one, providing a unified API.
There is an edge case where the following occurs:
1. The user sets a bookmark reminder on a post/topic
2. The post/topic is changed to a PM before or after the reminder
fires, and the notification remains unread by the user
3. The user opens their bookmark reminder notification list
and they can still see the notification even though they cannot
access the topic anymore
There is a very low chance for information leaking here, since
the only thing that could be exposed is the topic title if it
changes to something sensitive.
This commit filters the bookmark unread notifications by using
the bookmarkable can_see? methods and also prevents sending
reminder notifications for bookmarks the user can no longer see.
When quoting a chat message in a post, if that message contains a mention,
that mention should be ignored. But we've been detecting them and sending
notifications to users. This PR fixes the problem. Since this fix is for
the chat plugin, I had to introduce a new API for plugins:
# We strip posts before detecting mentions, oneboxes, attachments etc.
# We strip those elements that shouldn't be detected. For example,
# a mention inside a quote should be ignored, so we strip it off.
# Using this API plugins can register their own post strippers.
def register_post_stripper(&block)
end
* UX: separate invite-signup styling
* UX: invite page centering
* remove old invites-show css
* UX: invite signup page – mobile
* remove class references in general file
* add styling for instructions
This removes all trivial usages of the `{{action}}` keyword (the helper form, not the modifier form), where trivial means:
1. It's a co-located component (`.hbs` next to `.js`)
2. The JS file has a default export that is native class
3. `{{action "foo"}}` or `(action "foo")` with no extra arguments
4. There is a corresponding `foo()` method defined on the class (not inherited, etc)
There are more usages that is slightly more involved (with arguments, etc) that we can deal with, but this PR seems big enough so I just included the easiest cases here.
To aid review, each file is converted in an individual commit, and the matching method is temporary annotated with `@__action__` instead of the normal `@action`. This forces a git diff when it is already annotated as `@action`.
* DEV: {{action}} -> @action admin-penalty-post-action.hbs
* DEV: {{action}} -> @action admin-report.hbs
* DEV: {{action}} -> @action admin-watched-word.hbs
* DEV: {{action}} -> @action emoji-value-list.hbs
* DEV: {{action}} -> @action bool.hbs
* DEV: {{action}} -> @action category.hbs
* DEV: {{action}} -> @action secret-value-list.hbs
* DEV: {{action}} -> @action category-list.hbs
* DEV: {{action}} -> @action color.hbs
* DEV: {{action}} -> @action compact-list.hbs
* DEV: {{action}} -> @action group-list.hbs
* DEV: {{action}} -> @action host-list.hbs
* DEV: {{action}} -> @action named-list.hbs
* DEV: {{action}} -> @action simple-list.hbs
* DEV: {{action}} -> @action tag-group-list.hbs
* DEV: {{action}} -> @action tag-list.hbs
* DEV: {{action}} -> @action value-list.hbs
* DEV: {{action}} -> @action watched-word-form.hbs
* DEV: {{action}} -> @action composer-messages.hbs
* DEV: {{action}} -> @action section.hbs
* DEV: {{action}} -> @action user-status-picker.hbs
* DEV: cleanup @__action__ -> @action
Followup to 545e92039c
This commit fixes an issue where hashtags on user activity stream
items past page 1 did not get decorated. This is because of a bug
in the user stream component, where it was trying to get stream
items to decorate after the AJAX call but before they had been
rendered by Ember. This can be fixed by wrapping this decoration
logic in later() to run on the next runloop.
This commit adds an /admin/customize/theme-components route,
that opens the theme page with the components tab pre-selected,
so people can navigate to that directly.
Switches to using a dialog to confirm a session (i.e. sudo mode for
account changes where we want to be extra sure the current user is who
they say they are) to match what we do with passkeys.
https://github.com/discourse/discourse/pull/22622 accidentally introduced an `@action` decorator inside the actions hash, which does not work. This commit modernizes the component by removing the actions hash altogether.
Previously, we were parsing webpack JS chunk filenames from the HTML files which ember-cli generates. This worked ok for simple entrypoints, but falls apart once we start using async imports(), which are not included in the HTML.
This commit uses the stats plugin to generate an assets.json file, and updates Rails to parse it instead of the HTML. Caching on the Rails side is also improved to avoid reading from the filesystem multiple times per request in develoment.
Co-authored-by: Godfrey Chan <godfreykfc@gmail.com>
Followup to b53449eac9,
it was too easy to add broken routes which would break
configuration for the whole site, so now we validate ember
routes on save.
This commit fixes an issue where when some actions were done
(deleting/recovering post, moving posts) we updated the
topic_users.bookmarked column to the wrong value. This was happening
because the SyncTopicUserBookmarked job was not taking into account
Topic level bookmarks, so if there was a Topic bookmark and no
Post bookmarks for a user in the topic, they would have
topic_users.bookmarked set to false, which meant the bookmark would
no longer show in the /bookmarks list.
To reproduce before the fix:
* Bookmark a topic and don’t bookmark any posts within
* Delete or recover any post in the topic
c.f. https://meta.discourse.org/t/disappearing-bookmarks-and-expected-behavior-of-bookmarks/264670/36
In some browsers, 2FA login was failing with a "request is already
pending" error. This only applied when `experimental_passkeys` was
enabled and on Chrome only. This was due to the fact that the webauthn
API only supports one auth attempt at a time, so the security key call
needs to abort the passkey's conditional UI request before starting.
I am not sure we can test this. We have system specs that simulate
webauthn credentials and they didn't catch this (probably because the
simulation covers the whole flow).
With Embroider, we can rely on async `import()` to do the splitting
for us.
This commit extracts from `pretty-text` all the parts that are
meant to be loaded async into a new `discourse-markdown-it` package
that is also a V2 addon (meaning that all files are presumed unused
until they are imported, aka "static").
Mostly I tried to keep the very discourse specific stuff (accessing
site settings and loading plugin features) inside discourse proper,
while the new package aims to have some resembalance of a general
purpose library, a MarkdownIt++ if you will. It is far from perfect
because of how all the "options" stuff work but I think it's a good
start for more refactorings (clearing up the interfaces) to happen
later.
With this, pretty-text and app/lib/text are mostly a kitchen sink
of loosely related text processing utilities.
After the refactor, a lot more code related to setting up the
engine are now loaded lazily, which should be a pretty nice win. I
also noticed that we are currently pulling in the `xss` library at
initial load to power the "sanitize" stuff, but I suspect with a
similar refactoring effort those usages can be removed too. (See
also #23790).
This PR does not attempt to fix the sanitize issue, but I think it
sets things up on the right trajectory for that to happen later.
Co-authored-by: David Taylor <david@taylorhq.com>
We have identified some third-party analytics scripts which do things like `window.I18n = window.I18n` 🤦♂️. This leads to the window object having a null I18n property, but `"I18n" in globalThis` returns true.
This commit checks whether `window.I18n` is a truthy value.
When Discourse first introduced brotli support, reverse-proxy/CDN support for passing through the accept-encoding header to our NGINX server was very poor. Therefore, a separate `/brotli_assets/...` path was introduced to serve the brotli assets. This worked well, but introduces additional complexity and inconsistencies.
Nowadays, Brotli encoding is well supported, so we don't need the separate paths any more. Requests can be routed to the asset `.js` URLs, and NGINX will serve the brotli/gzip version of the asset automatically.
Nowadays, themes/plugins have their templates compiled at build-time, so there is no need for us to carry the template compiler on the frontend during tests
The motivation of this PR is to remove our dependence on Ember's 'named outlets', which are removed in Ember 4+.
At a high-level, the changes can be summarized as:
- The top-level `discovery` route is totally emptied of all logic. The HTML structure of the template is moved into the `<Discovery::Layout />` component for use by child routes.
- `AbstractTopicRoute` and `AbstractCategoryRoute` routes now both lean on the `DiscoverySortableController` and associated template. This controller is where most of the logic from the old top-level `discovery` controller has ended up.
- All navigation controllers/templates have been replaced with components. `navigation/categories`, `navigation/category` and `navigation/default` were very similar, and so they've all been combined into `<Navigation::Default>`. `navigation/filter` gets its own component.
- The `discovery/topics` controller/template have been moved into a new `<Discovery::Topics>` component.
Various other parts of the app have been tweaked to support these changes, but I've tried to keep that to a minimum.
Anything from `<TopicList>` down is untouched, which should hopefully mean that a large proportion of topic-list-customizing themes are unaffected.
For more information, see https://meta.discourse.org/t/282816
We updated scheduled admin checks to run concurrently in their own jobs. The main reason for this was so that we can implement re-check functionality for especially flaky checks (e.g. group e-mail credentials check.)
This works in the following way:
1. The check declares its retry policy using class methods.
2. A block can be yielded to if there are problems, but before they are committed to Redis.
3. The job uses this block to either a) schedule a retry if there are any remaining or b) do nothing and let the check commit.
When submitting files through the form template upload field, we were having an issue where, although a validation error message was being presented to the user, the upload was still coming through, because `PickFilesButton`'s validation happens **after** the Uppy mixin finished the upload and hit `uploadDone`.
This PR adds a new overridable method to the Uppy mixin and overrides it with the custom validation, which now happens before the file is sent.
Additionally, we're now also using `uploadingOrProcessing` as the source of truth to show the upload/uploading label, which seems more reliable.
This work includes the following updates for the new lightbox:
- Show carousel by default if there are more than 1 image in a post
- Removes toggling of carousel on mobile - now always open if there are more than 1 image
- Updates swipe down gesture on mobile to close lightbox (previously used to toggle carousel)
- Removes swipe up gesture on mobile (was previously used to close lightbox)
This change removes the background image (which is the small version of the uploaded image) from the lightbox backdrop.
Now a solid color (dark grey) is used for the backdrop so we can distinguish between the lightbox's head, body and footer.
This PR does some preparatory refactoring of scheduled admin checks in order for us to be able to do custom retry strategies for some of them.
Instead of running all checks in sequence inside a single, scheduled job, the scheduled job spawns one new job per check.
In order to be concurrency-safe, we need to change the existing Redis data structure from a string (of serialized JSON) to a list of strings (of serialized JSON).
This aims to help admins and developers identify the cause of loading issues on routes.
As with other theme/plugin errors, the UI banner is only shown to administrators. For non-admins, the information is only written to the browser console.
When uploading images, they are assigned a dominant color which gets used in various places, such as Discourse Hub and the new lightbox. Previously in chat we didn't assign this attribute, so it was defaulting to a null value. We did however use it as an inline CSS style for the image background (which is visible while the image is downloaded).
This change adds data-dominant-color to the uploaded image in chat and uses it correctly within lightbox.
This commit introduces a new feature that allows theme developers to manage the transformation of theme settings over time. Similar to Rails migrations, the theme settings migration system enables developers to write and execute migrations for theme settings, ensuring a smooth transition when changes are required in the format or structure of setting values.
Example use cases for the theme settings migration system:
1. Renaming a theme setting.
2. Changing the data type of a theme setting (e.g., transforming a string setting containing comma-separated values into a proper list setting).
3. Altering the format of data stored in a theme setting.
All of these use cases and more are now possible while preserving theme setting values for sites that have already modified their theme settings.
Usage:
1. Create a top-level directory called `migrations` in your theme/component, and then within the `migrations` directory create another directory called `settings`.
2. Inside the `migrations/settings` directory, create a JavaScript file using the format `XXXX-some-name.js`, where `XXXX` is a unique 4-digit number, and `some-name` is a descriptor of your choice that describes the migration.
3. Within the JavaScript file, define and export (as the default) a function called `migrate`. This function will receive a `Map` object and must also return a `Map` object (it's acceptable to return the same `Map` object that the function received).
4. The `Map` object received by the `migrate` function will include settings that have been overridden or changed by site administrators. Settings that have never been changed from the default will not be included.
5. The keys and values contained in the `Map` object that the `migrate` function returns will replace all the currently changed settings of the theme.
6. Migrations are executed in numerical order based on the XXXX segment in the migration filenames. For instance, `0001-some-migration.js` will be executed before `0002-another-migration.js`.
Here's a complete example migration script that renames a setting from `setting_with_old_name` to `setting_with_new_name`:
```js
// File name: 0001-rename-setting.js
export default function migrate(settings) {
if (settings.has("setting_with_old_name")) {
settings.set("setting_with_new_name", settings.get("setting_with_old_name"));
}
return settings;
}
```
Internal topic: t/109980
Followup to b53449eac9, we cannot
generate the links to plugin admin pages in this way because it
depends on which plugins are installed; we would need to somehow
do it at runtime. Leaving it out for now, for people who need to
find these admin routes the Ember Inspector extension for Chrome
can be used in the meantime.
Since we don't have icons or access to the JS that transforms
hashtag icon placeholders into their proper icons and colours
on embed and publish pages, we need to at least show _something_
and make sure the hashtags are not totally broken on these pages.
NOTE: Most of this is experimental and will be removed at a later
time, which is why things like translations have not been added.
The new /admin-revamp UI uses a sidebar for admin nav. This initial
step adds a script to generate a map of all the current admin nav
into a format the sidebar to read. Then, people can experiment
with different changes to this structure.
The structure can then be edited from `/admin-revamp/config/sidebar-experiment`,
and it is saved to local storage so people can visually experiment with different ways
of showing the admin sidebar links.
Two changes were introduced:
1. Reorder links on sidebar section is removed. Clicking and holding the mouse for 250ms was unintuitive;
2. Fixed bugs when reorder is done in edit modal.
This fixes an edge case where the layout of a onebox with a gif avatar
was broken. Oneboxes have specific styling attached to avatar images and
the pausable animated image treatment was breaking that styling.
Files in `/assets/*` are given digests by sprockets, and we don't have any infrastructure for accessing those URLs in SCSS files. Instead, we should put this image with other similar images in the `public/images` directory, and then use the `absolute-image-url` helper so that it correctly uses the CDN where available.
- Add prefixes to Ember deprecations (previously was just Discourse deprecations)
- Allow logic to work in tests (where window.Discourse is not defined)
- Detect `{plugin}_tests.js` files
- Optimise dev/test regex logic out of the production build using `if(DEBUG)`
As part of #23816, which sought to strip out thousand separators, we also accidentally strip out signs. This is making it impossible to disable some settings which require a -1 to disable. Instead of stripping non-digits, strip anything that isn't a sign or a digit.
* UX: add discourseLater call to add breathing room for animation
Allow for smoother animations on lower end devices.
Create time between render and animations.
extend panel width targets by 20 px to account for shadows as well
This API is not used by any known themes/plugins, and is problematic for a few reasons
- It doesn't work on modern plugin connectors which have no wrapper element
- Making modifications to Ember-rendered DOM elements can lead to catastrophic and surprising errors
- It doesn't re-run when arguments to a plugin outlet change
This commit adds the deprecation notice, and refactors the tests so that they do not rely on any real core plugin outlets
plugin/theme-breaking changes:
1. `controller:create-account` is gone (use `component:modal/create-account` in modifyClass, **if** absolutely necessary)
2. `create-account-body` css class is gone (target `.d-modal.create-account` or any of the inner classes: `.modal-outer-container`, `.modal-middle-container`, `.modal-inner-container`, or `.modal-body`)
This commit fixes an issue where clicking the default
"Take Action" option on a flag for a post doesn't always
end up with the post hidden.
This is because the "take_action" score bonus doesn’t take into account
the final score required to hide the post.
Especially with the `hide_post_sensitivity` site setting set to `low`
sensitivity, there is a likelihood the score needed to hide the post
won’t be reached.
Now, the default "Take Action" button has been changed to "Hide Post"
to reflect what is actually happening and the description has been
improved, and if "Take Action" is clicked we _always_ hide the post
regardless of score and sensitivity settings. This way the action reflects
expectations of the user.
* FEATURE: Add keywords support for site_settings search
This change allows for a new `keywords` field that can be added to site
settings in order to help with searching. Keywords are not visible in
the UI, but site settings matching one of the contained keywords will
appear when searching for that keyword.
Keywords can be added for site settings inside of the
`config/locales/server.en.yml` file under the new `keywords` key.
```
site_settings
example_1: "fancy description"
example_2: "another description"
keywords:
example_1: "capybara"
```
* Add keywords entry for a recently changed site setting and add system specs
* Use page.visit now that we have our own visit
Some browsers still don't support conditional mediation. This PR fixes issues with:
- TOR browser (it doesn't have `PublicKeyCredential` at all)
- Firefox 119 (doesn't support conditional mediation)
We also need to make sure not to call `isConditionalMediationAvailable` on browsers that don't support the method but support the feature (like Safari on iOS).
The User#flag_level column has not been in use for a very long time. The "new" reviewable system dynamically calculates flag scores based on past performance of the user.
This PR removes flag_level from the admin user serializer (since it isn't displayed anywhere in admin user lists) and marks the column as deprecated and targeted for removal in the next minor version.
The message: :signup_not_allowed option to the IP address validator does nothing, because the AllowedIpAddressValidator chooses one of either:
- ip_address.blocked or
- ip_address.max_new_accounts_per_registration_ip
internally. This means that the translation for this was also never used.
This PR removes the ineffectual option and the unused translation. It also moves the translated error messages for blocked and max_new_accounts_per_registration_ip into the correct location so we can pass a symbol to ActiveModel::Errors#add.
There is no actual change in behaviour.
Followup to 9762e65758. This
original commit did not take into account the fact that
new topics can end up in the approval queue as a
ReviewableQueuedPost, and so there was a 500 error raised
when accessing `self.topic` when sending a PM to the user.
Using SiteSetting.queue_jobs= to configure job asynchronicity was deprecated here four years ago and marked for removal in version 2.9.0. This PR removes the fallback method we kept since then. The method was there because it was still being used in a bunch of plugin tests (now fixed.)
The PostAction.remove_act class method has been deprecated and replaced by PostActionDestroyer. It was marked for removal in version 2.9.0. This PR removes the method.
This was just a case of removing the `onlyStream: true`
operation from `decorateCookedElement`, since that restricts
the decoration only to topic page posts.
This regressed in b6dc929. A test to ensure this doesn't regress has
been added as well.
This PR also fixes a flakey system spec. The conditional UI gets
triggered automatically, so the system spec shouldn't explicitly call
`find(".passkey-login-button").click`, because sometimes it isn't
present and that causes a test failure.
- Remove the wildcard crawler. This was already excluding almost all file types, but the exclude list was missing '.gjs' which meant those files were unnecessarily being hoisted into the `public/` directory during precompile
- Automatically include all ember-cli-generated assets without needing them to be listed. The main motivation for this change is to allow us to start using async imports via Embroider/Webpack. The filenames for those new async bundles will not be known in advance.
- Skips sprockets fingerprinting on Embroider/Webpack chunk JS files. Their filenames already include a fingerprint, and having sprockets change the filenames will cause problems for the async import feature (where filenames are included deep inside js bundles)
This commit also updates our ember-cli build so that it skips building plugin tests in the production environment. This should provide a slight build speed improvement.
Previously, focus wasn't being applied correctly on dialogs using named
components. This was because the A11YDialog was being invoked before
the component was completely rendered.
The long-term plan is to move away from A11YDialog doing the rendering
here, but for now this should do.
These have been deprecated for some time, and the vast majority of themes/plugins have already removed their use. The prototype extensions were unexpectedly disabled as a side effect of 895036bd7a (more details in https://github.com/discourse/discourse/pull/24101).
Given that restoring the functionality now involves significant complexity, and would only be delaying the inevitable removal in a matter of months, we've decided to keep them disabled. This commit explicitly sets the flag in the ember environment config to make things clearer.
We already do this check inside `selectionChanged` and this was preventing us to correctly set `isSelecting` to true. This was causing issues when starting your selection from outside cooked.
Applies to passkeys, visible in a dev environment when using a non-standard
host. The error modal should only be shown when invoking the passkey
login button.
The main change made is to use `pointerdown` and `touchstart` for detecting click outside in `FloatKit`, the problem of using `click` is that it will trigger on `mouseup` which is not working well with `FloatKit` shown using `mousedown` (when we change selection with the `mousedown` for example) as the release will be interpreted as a click outside and close the menu. To solve this issue the previous code in `post-text-selection` was going through various hacks for detecting state of mouse which are not always very reliable.
The second fix is to exit earlier when selection didn't change.
This has been tested on chrome/firefox and safari (mobile) and seems to work reliably.
<!-- NOTE: All pull requests should have tests (rspec in Ruby, qunit in JavaScript). If your code does not include test coverage, please include an explanation of why it was omitted. -->
1. Removes accidental bold from `text` and `multiselect` labels/placeholders
2. Adds the animated label/placeholder combo to `multiselect`
3. Makes the `multiselect` placeholder lighter to match other fields
4. Makes the `dropdown` values darker to match other fields
5. Removes the extra 5px spacing before `confirmation` fields
`@ember/jquery` was necessary to automate the `app.import()` but
that is no longer necessary with `ember-auto-import`. A secondary
thing it does is bringing back the `this.$` feature, but with a
deprecation. It is my understanding that the deprecation has long
be fully absorbed into both core and plugins so we shouldn't need
this package anymore.
No plugins or themes rely on anonymous_posting_min_trust_level so we
can just switch straight over to anonymous_posting_allowed_groups
This also adds an AUTO_GROUPS const which can be imported in JS
tests which is analogous to the one defined in group.rb. This can be used
to set the current user's groups where JS tests call for checking these groups
against site settings.
Finally a AtLeastOneGroupValidator validator is added for group_list site
settings which ensures that at least one group is always selected, since if
you want to allow all users to use a feature in this way you can just use
the everyone group.
Back in c31772879b we introduced
SiteSetting.composer_ios_media_optimisation_image_enabled and
disabled media optimization on safari iOS because of performance
issues when rendering to canvas, and OffscreenCanvas support
was not yet available.
Safari now supports OffscreenCanvas, so now we can give this
another go, and also use OffscreenCanvas everywhere it is supported.
This fixes a similar issue to 8b3eca0 where an Errno::ETXTBSY error was raised because the minio_runner gem was trying to install the binary across multiple processes in rspec. If we just make sure the latest version is installed before the tests run, this shouldn't happen, since MinioRunner.start will not do any further attempts at installation if the latest version is installed.
Running addonPostprocessTree manually was causing ember-auto-import's postprocess hook to run and generate extra unnecessary chunks. The only reason called addonPostprocessTree directly was to allow the terser plugin to run on the extra public trees. We can do the terser postprocessing manually instead.
This commit is approximately the inverse of e1d27400f5.
This commit also removes ember-auto-import as dependencies of admin/wizard/discourse-plugins because they are not 'real' ember addons, and so it isn't serving any useful purpose. (see also https://github.com/discourse/discourse/pull/23974)
As much as possible I would like us to avoid having to go the with a global event listener on click/mouseover. For now I have removed all cases of `data-tooltip`, if we clearly identify a use case of a global event listener we might reconsider this.
The following changes are also included:
- by default tooltips won't attempt to focus first focusable element anymore
- tooltip will now use `cursor: pointer` by default
- a new service has been introduced: `InternalTooltip` which is responsible to track the current instance displayed by a `<DTooltip />`. Portal elements when replaced are not properly cleaned and I couldn't figure out a way to have a proper hook to ensure the previous `DTooltipInstance` is properly set as not expanded; this problem was very visible when using a tooltip as interactive and hovering another tooltip, which would replace the interactive tooltip as not closed.
This allows users to see their passkeys recommended by the browser as they type their username.
There's a small refactor here, to make sure the same action is used by both the conditional UI and the passkey login button. The webauthn API only supports one auth attempt at a time, so in this PR we need to add a service singleton to manage the navigator.credentials.get promise so that it can be cancelled and reused as the user picks the conditional UI (i.e. the username login input) or the dedicated passkey login button.
This commit adds a loading spinner that appears immediately after
clicking the play button on a video placeholder and will go away once
the "onCanPlay" event fires for the video.
This prevents a completely empty (no play button) placeholder from
appearing for some amount of time while the video is loading enough to
start playing.
- more subtle animation when showing a toast
- resumes auto close when removing the mouse from the toast
- correctly follows reduced motion
- uses output with role status as element: https://web.dev/articles/building/a-toast-component
- shows toasts inside a section element
- prevents toast to all have the same width
- fixes a bug on mobile where we would limit the width and the close button wouldn't show correctly aligned
I would prefer to have tests for this, but the conjunction of css/animations and our helper changing `discourseLater` to 0 in tests is making it quite challenging for a rather low value. We have system specs using toasts ensuring they show when they should.
Why this change?
When we're in the midst of loading more tags, the filter dropdown
is still enabled and may result in us firing off multiple requests to
the server to load more tags. This makes the loading hard to reason
about in the tests environment and has led to flaky tests.
What does this change do?
This changes disables the filter dropdown when more tags are being
loading.