Firstly, we need to understand that ActiveRecord can be
connected to a role which prevent writes and this happens in Discourse when a
replica database has been setup for failover purposes. When a role
prevent writes from happening, ActiveRecord will raise the
`ActiveRecord::ReadOnlyError` if a write query is attempted.
Secondly, theme fields are baked at runtime within GET requests. The
baking process involves writing the baked value to the
`ThemeField#baked_value` column in the database.
If we combine the two points above, we can see how the writing of the
baked value to the database will trigger a `ActiveRecord::ReadOnlyError`
in a GET requests when the database is connected to a role preventing
writes. However, failing to bake a theme is not the end of the world and
should not cause GET requests to fail. Therefore, this commit adds a rescue
for `ActiveRecord::ReadOnlyError` in the `ThemeField#ensure_baked!`
method.
Followup 0568d36133
Followup 97cf069a06
Due to the S3 dualstack endpoint change, sites with
S3 backups configured but _not_ S3 uploads were erroring,
with admins unable to access the backups page. This
commit fixes the error by not enabling S3 dualstack
endpoints if S3 uploads have not been enabled, backups
don't need to use them.
c.f. https://meta.discourse.org/t/unable-to-backup-or-navigate-to-backups/335899
* FEATURE: Add skip notification option to group invite to topic
* DEV: rename `skip_notification` to `should_notify`
* DEV: update `should_notify` param to be default `true` in controllers
* DEV: update spec to use `greater than` instead of `equal to` to prevent flakiness
* Update app/controllers/topics_controller.rb
Co-authored-by: David Taylor <david@taylorhq.com>
* DEV: merged two `#invite_group` specs into one
* DEV: Added test case for `invite-group` in requests spec
---------
Co-authored-by: David Taylor <david@taylorhq.com>
When a parent category shows topics from subcategories, dismissing
should dismiss posts in both parent and subcategories.
Co-authored-by: Alan Guo Xiang Tan <gxtan1990@gmail.com>
- Uses a more appropriate image, with immutable tag (so update prompts work correctly)
- Updates port forwarding
- Improves mount setup (inc. persistant PG/Redis when rebuilding)
- Fixes ember-cli live reload
- Automatically configures VSCode & extensions
Redesign the permalinks page to follow the UX guide. In addition, the ability to edit permalinks was added.
This change includes:
- move to RestModel
- added Validations
- update endpoint and clear old values after the update
- system specs and improvements for unit tests
When running a development environment behind a proxy (e.g. when using a cloud development environment, or a service like ngrok), the ember-cli port & protocol may not match the one in the browser. `livereload.js` knows how to auto-configure itself based on the current browser environment... but Ember CLI overrides that autoconfiguration with some hard-coded values.
The intention there is to allow running the livereload server on a different port to the ember-cli web proxy. We don't need that functionality.
This commit stops loading `ember-cli-live-reload.js`, and instead loads `_lr/livereload.js` directly.
Follow up to 6f8f6a7726
Prior to the linked commit, the `uploads#create` endpoint had a `upload_type` and `type` param that acted as aliases for each other and raised an error if both of them were missing. In the linked commit, we removed the `type` param and always required the `upload_type` param which break API consumers that only included `type` in their requests.
This commit adds back the `type` param temporarily and introduces a deprecation message for it so that API consumers are made aware of the eventual removal of the `type` param.
This commit:
- Adds back the target drop options to enable the feature
- Applies the css to every elements and not just the one for admin emojis, also fixes the style as it was flashing and preventing it to work. For now we just change the color of the image icon.
- Adds a test to ensure we don't regress.
It splits the hide_profile_and_presence user option and the default_hide_profile_and_presence site setting for more granular control. It keeps the option to hide the profile under /u/username/preferences/interface and adds the presence toggle in the quick user menu.
Co-authored-by: Régis Hanol <regis@hanol.fr>
This is a very simple change, which creates a permanent table in the DB, rather than generating a temporary table when moving posts. This change is about capturing data and any usage will appear in a follow-up.
I did include a new column created_new_topic in the new table, so that it can be easily audited without having to compare destination topic created_at with moved_post records.
This commit modernizes the post menu by migrating it from the existing widget-based implementation to Glimmer components. This transition aims to improve the maintainability, performance, and overall developer experience.
It also introduces a new DAG-based transformer API for customizations that aims to be more flexible than the widget base one.
---------
Co-authored-by: David Taylor <david@taylorhq.com>
This commit removes the new optimized category style introduced in
previous commits (d37a0d40, 9a80d718 and 430c42ac), in favour of the
existent `categories_only`.
Primary is a more appropriate color here than "danger". Authorizing is
important, but we usually use "danger" for destructive actions and
nothing is being destroyed here.
Overriding computed properties with arguments is no longer supported by Ember, so we need to rename this computed property and add fallback logic manually.
This fixes the styleguide 'buttons' page. Ref https://meta.discourse.org/t/styleguide-bugs/335211?u=david
When performing bulk dismissal in Unread and New views, the dismiss button stays at the top of the UI. Because of this we want to provide the dismiss action also in the "sticky" menu that's always in view, even when scrolling a long list of topics.
This reverts commit 5a00a041f1.
Implementation is currently not correct. Multiple uploads can share the
same etag but have different paths in the S3 bucket.
Follow-up to a5497b74be
In the linked commit, as part of simplifying the invite modal, we removed the option to skip sending an email when creating an invite restricted to a specific address. This has caused confusion about whether an email will be sent by Discourse or not, so we're adding back the option to create a restricted invite without emailing.
Internal topic: t/134023/48.
Followup 0568d36133
S3 itself and other S3-compatible providers do not
allow using an S3 custom endpoint and dualstack at
the same time, so this commit fixes that by not using
dualstack when the endpoint is present.
This PR ensures that admins are shown a confirmation dialog when clicking to disable 2FA for a user. The 2FA button is right below the "Grant Badge" button and as such it can easily be clicked accidentally. It's also good practice to ask for confirmation before removing important functionality.
A "bad upload" in this context is a upload with a mismatched URL. This can happen when changing the S3 bucket used for uploads and the upload records in the database have not been remapped correctly.
"Resume editing" would do nothing when going through the `/new-message` flow.
This seems to be broken since [this commit](b0f6d074be). which moved `this._setModel` calls around – the same we're doing now, but to different places: the first one needs to happen after the `draft.data` has been set , while the second needs to happen before the `this.open` call.
When we added direct S3 uploads to Discourse, which use
presigned URLs, we never took into account the dualstack
endpoints for IPv6 on S3.
This commit fixes the issue by using the dualstack endpoints
for presigned URLs and requests, which are used in the
get-presigned-put and batch-presign-urls endpoints used when
directly uploading to S3.
It also makes regular S3 requests for `put` and so on use
dualstack URLs. It doesn't seem like there is a downside to
doing this, but a bunch of specs needed to be updated to reflect this.
This PR adds a small visual change to the new feature item on the `/admin/whats-new` page. When features are marked with an experimental site setting, they should show an indication on the feature item that it is "Experimental"
When replying to a topic, the @-mention userSearch needs the topicId and the categoryId so they can trigger immediately, with sane suggestions.
This was broken when the mentions were moved from ComposerEditor to DEditor.
* UX: Apply admin table classes for consistent mobile styling on the emojis page
* UX: remove icon from the button
* UX: styling tweaks on the emoji uploader form
* UX: right align table button controls
* apply prettier
Currently, if an association is added as a tracked field in
`PostRevisor`, the `PostRevisionSerializer` class will try to serialize
it somehow. This will raise an error as ActiveRecord collection proxies
can't be serialized.
This patch addresses this issue by skipping any association tracked by
the `PostRevisor` class.
I was skimming through existing pages to get a feel for the admin UI guidelines. I noticed that this part was missing its margin. On some further investigation, it seems that a single CSS selector, .award-badge was being used both for the section and for the button in the header, so I decided to 1) separate the two and 2) add in the missing margin.
Prior to Uppy, the `uploads#create` endpoint used to receive a `type` param that indicated the purpose/target of the upload, such as `avatar`, `site_setting` and so on. With the introduction of Uppy, the `type` param became the MIME type of the file being uploaded, and the purpose/target of the upload became a new param called `upload_type`, however the backend could still use the `type` param (which now contains MIME type) as the purpose/target of the upload if `upload_type` is absent.
We technically don't need to send the MIME type over the network, but it seems like it's done by Uppy and we have no control over the `type` param that Uppy includes:
758de8167b/app/assets/javascripts/discourse/app/lib/uppy/uppy-upload.js (L146-L151)
This commit does a couple of things:
1. It amends the `uploads#create` endpoint so it always requires the `upload_type` param and doesn't fallback to `type` if `upload_type` is absent
2. It forces consumers of the `UppyUpload` class (and by extension `UppyImageUploader`) to specify `type` of the upload
Internal topic: t/140945.
This commit switches the route for the about config page to retrieve the list of site settings that control the /about page by their area instead of their individual names.
Internal topic: t/136384.
In some cases, on Safari iOS, we would recompute the "--composer-vh" variable due to a minimal change in the viewport. This ends up triggering a loop where setting this variable triggers another viewport resize event, which triggers another change of the variable...
In order to fix (patch?) this issue, we now have a 1px leeway when checking the difference between the previous and new viewport.
Internal ref - t/141088
Multiple category styles can be used on the same site. The category and
subcategories page will use the "desktop_category_page_style" setting
and individual category pages will use the style selected in settings,
if any.
Commit c1f078ca tried to use the same style for both the category and
subcategories page, but the route matching did not take into account
the "discovery.categoryAll" and "discovery.categoryNone" variants of
the "discovery.category" route.
Template overrides have been advised against for a long time, and are increasingly hard to maintain as Discourse's development accelerates. This commit officially deprecates this customization method, which will be removed in the not-too-distant future (likely in the first half of 2025).
From plugin-api comment:
Registers a new tab to be displayed in "more topics" area at the bottom of a topic page.
```gjs
api.registerMoreTopicsTab({
id: "other-topics",
name: i18n("other_topics.tab"),
component: <template>tbd</template>,
condition: ({ topic }) => topic.otherTopics?.length > 0,
});
```
You can additionally use more-topics-tabs value transformer to conditionally show/hide
specific tabs.
```js
api.registerValueTransformer("more-topics-tabs", ({ value, context }) => {
if (context.user?.aFeatureFlag) {
// Remove "suggested" from the topics page
return value.filter(
(tab) =>
context.currentContext !== "topic" ||
tab.id !== "suggested-topics"
);
}
});
```
Recently we added a new feature for automatically gridding images in the composer (https://github.com/discourse/discourse/pull/29260). After testing this feature under a setting for a short period of time, the feature is no longer experimental anymore.
This PR removes the site setting `experimental_auto_grid_images`.
Allows anonymous users to download the calendar file. Before, they were given the option, but it would fail silently with a `TypeError: Cannot read properties of null (reading 'user_option')`.
I have been unable to figure out a way of testing this usefully (as I fear it would require creating several thousands of objects), but existing tests pass and a manual test with ~400k topics succeeds after the fix, while it would hang indefinitely and/or consume all disk space before the fix.
I have reported the initial problem and my findings in https://meta.discourse.org/t/topic-reset-all-highest-exhausts-all-available-disk-space/333837
The primary key is usually a bigint column, but the foreign key columns
are usually of integer type. This can lead to issues when joining these
columns due to mismatched types and different value ranges.
This was using a temporary plugin / test API to make tests pass. After
more careful consideration, we concluded that it is safe to alter the
tables directly.
We are moving away from the mobile-specific template pattern in favor of logical `{{#if}}` statements. This brings us closer to a standard Ember app, makes testing easier, and reduces duplicate code.
This commit includes some minor refactoring in the resolver & component-templates initializer, so that the mobile lookups happen on desktop, without actually being used. This allows us to print the deprecation message consistently, to improve visibility to developers.
This commit fixes the (?) tooltips for reports on
the admin dashboard on mobile.
The fix is that float-kit instances can now have different triggers
and un-triggers for mobile and desktop, and float-kit is now aware
of the site being in mobile view.
Example usage:
```
@triggers={{hash mobile=(array "click")}}
```
So now, if you press on the tooltip trigger on mobile it shows
correctly, and on desktop both hover and click can be used.
---------
Co-authored-by: Joffrey JAFFEUX <j.jaffeux@gmail.com>
Currently the tracking for clicked links are injected into the HTML in a span tag. This leads to the link counter value being highlighted when copying and pasting. Additionally, any means for using CSS to hide link counters result in a gap due to it occupying a specific width.
With this change, we make link counters appear in a data attribute on the link element and visually shown with CSS `::after` element.
We are moving away from the mobile-specific template pattern in favor of logical `{{#if}}` statements. This brings us closer to a standard Ember app, makes testing easier, and reduces duplicate code.
We are moving away from the mobile-specific template pattern in favor of logical `{{#if}}` statements. This brings us closer to a standard Ember app, makes testing easier, and reduces duplicate code.
We are moving away from the mobile-specific template pattern in favor of logical `{{#if}}` statements. This brings us closer to a standard Ember app, makes testing easier, and reduces duplicate code.
We are moving away from the mobile-specific template pattern in favor of logical `{{#if}}` statements. This brings us closer to a standard Ember app, makes testing easier, and reduces duplicate code.
We are moving away from the mobile-specific template pattern in favor of logical `{{#if}}` statements. This brings us closer to a standard Ember app, makes testing easier, and reduces duplicate code.
Docking is a leftover from older header code, it looks like it is no
longer used in the app. This helper was registering a scroll event
listener to check if the header should be docked or not. Initially, a
"docked" class was added to the body element. This class persisted
through the lifecycle of the app and the scroll event was doing no
useful work.
Some older themes may still use it in CSS, that will cause a regression,
from a quick look at existing code, the surface area should be small
(2-3 themes). It's worth removing the event listener for performance
reasons. We could possibly add the class "docked" statically to the body
element, but it's redundant. It's best to clean up the relevant CSS in
themes, where applicable.
This commit adds a new "Community title" field to the about config page. This field controls the `short_site_description` setting, which is shown in the browser tab for key pages such categories pages and topic lists.
Internal topic: t/140812.
Followup bd4e8422fe
In the previous commit, we introduced the `page_view_legacy_total_reqs`
report. However this was not tested properly, and due to a typo
the report returned no data.
This commit fixes the issue and adds a spec to catch this.
* DEV:refactor user badges create to get grant opts from method
* Replace method overwrite with plugin modifier
* Add aditional params
* change modifier name
The `categories_only_optimized` category page style has been introduced
in commit d37a0d401c. This commit makes
sure that style is enforced for users who can see over 1000 categories
in order to keep `/categories` page functional.
This commit adds a new "Invite" link to the sidebar for all users who can invite to the site. Clicking the link opens the invite modal without changing the current route the user is on. Admins can customize the new link or remove it entirely if they wish by editing the sidebar section.
Internal topic: t/129752.
This commit removes the feature flag for the new /about page, enabling it for all sites, and removes the code for old the /about page.
Internal topic: t/140413.
This change makes use of service workers to determine if we should play chat sounds in the current browser tab. Since users can have multiple tabs open, we currently attempt to play sound across all active tabs.
With this change we iterate over all clients and check if client.focused is true (ie. the current tab/window we have open), if so we allow playing the audio in the current tab and for all other hidden tabs/windows we return false.
---------
Co-authored-by: Bianca Nenciu <nbianca@users.noreply.github.com>
This PR:
- Removes components from being displayed in the card
- Adds a DMenu to house previous footer actions
- Allows themes to be updated from this grid, with an animation and different border to show the update is happening
- Stops position of cards changing when default changes
- Fixes outline colour not changing when default changes
- Show a global notice on the page when previewing a theme
- Allows updating a theme from the grid, and showing an indicator of what theme needs to be updated
- Moves "Set as default" to the dropdown for the theme
- Show screenshot for theme if it is available
- Prevent page reloading when updating the theme
- Fixes theme install modal on grid page
- Temporarily remove sorting of default theme to the top
A common pattern in the industry for bypassing smart lists is detection of
the shift key.
This information is not available in the "beforeinput" event but it always
fires afer keydown, so we track if shift is pressed on keydown.
These are unsupported by modern tooling (including ts/glint parsers), so we are working to remove them. The easiest path for mixins is to switch back to the mega-legacy EmberObject syntax for computed/on)
Key changes include:
- `@uppy/aws-s3-multipart` is now part of `@uppy/aws-s3`, and controlled with a boolean
- Some minor changes/renames to Uppy APIs
- Uppy has removed batch signing from their S3 multipart implementation. This commit implements a batching system outside of Uppy to avoid needing one-signing-request-per-part
- Reduces concurrent part uploads to 6, because S3 uses HTTP/1.1 and browsers limit concurrent connections to 6-per-host.
- Upstream drop-target implementation has changed slightly, so we now need `pointer-events: none` on the hover element
Followup 30fdd7738e
Adds a new site setting and corresponding user preference
to disable smart lists. By default they are enabled, because
this is a better experience for most users. A small number of
users would prefer to not have this enabled.
Smart lists automatically append new items to each
list started in the composer when enter is pressed. If
enter is pressed on an empty list item, it is cleared.
This setting will be removed when the new composer is complete.
This commit allows themes to define up to 2 screenshots
in about.json. These should be paths within the theme's
git repository, images with a 1MB max file size and max width 3840x2160.
These screenshots will be downloaded and stored against a theme
field, and we will use these in the redesigned theme grid UI.
These screenshots will be updated when the theme is updated
in the same way the additional theme files are.
For now this is gated behind a hidden `theme_download_screenshots`
site setting, to allow us to test this on a small number of sites without
making other sites make unnecessary uploads.
**Future considerations:**
* We may want to have a specialized naming system for screenshots. E.g. having light.png/dark.png/some_palette.png
* We may want to show more than one screenshot for the theme, maybe in a carousel or reacting to dark mode or color palette changes
* We may want to allow clicking on the theme screenshot to show a lightbox
* We may want to make an optimized thumbnail image for the theme grid
---------
Co-authored-by: Ted Johansson <ted@discourse.org>
Followup 9762e65758
When we added the Revise... option for posts/new topics
in the review queue, which sends a PM to the user, we used
`SystemMessage.create_from_system_user`, which always sends
the PM from the system user. However, this makes it so if the
user replies to the PM, which they are encouraged to do,
no one will see it unless they actively monitor the system inbox.
This commit changes it so `SystemMessage.create` is used,
which uses the `site_contact_username` and `site_contact_group`
site settings as participants in the sent PM. Then, when the
user replies, it will send to that inbox instead.
If `site_contact_username` is blank, the system user is used.
# Context
Add `disableDefaultKeyboardShortcuts` function to the plugin API to allow for disabling [default bindings](e4941278b2/app/assets/javascripts/discourse/app/lib/keyboard-shortcuts.js (L49)).
# Details
This function is used to disable a "default" keyboard shortcut. You can pass an array of shortcut bindings as strings to disable them.
**Please note that this function must be called from a pre-initializer.**
Example:
```js
api.disableDefaultKeyboardShortcuts(['command+f', 'shift+c']);
```
- Added system spec, displaying intended behavior
Using execCommand to replace the entire contents of the textarea is very slow for larger posts (it seems the browser does a reflow after every 'virtual keypress').
This commit updates the `maybeContinueList()` function to be more surgical when removing the bullet. Now it only selects & removes the characters which actually need to be deleted
Similar to a7cd220704
This patch replaces the parameters provided to a service through
`params` by the contract object.
That way, it allows better consistency when accessing input params. For
example, if you have a service without a contract, to access a
parameter, you need to use `params[:my_parameter]`. But with a contract,
you do this through `contract.my_parameter`. Now, with this patch,
you’ll be able to access it through `params.my_parameter` or
`params[:my_parameter]`.
Some methods have been added to the contract object to better mimic a
Hash. That way, when accessing/using `params`, you don’t have to think
too much about it:
- `params.my_key` is also accessible through `params[:my_key]`.
- `params.my_key = value` can also be done through `params[:my_key] =
value`.
- `#slice` and `#merge` are available.
- `#to_hash` has been implemented, so the contract object will be
automatically cast as a hash by Ruby depending on the context. For
example, with an AR model, you can do this: `user.update(**params)`.
This adds several improvements to the signup/login forms. Some of them include:
- Added a minimal signup progress bar design for mobile.
- Made the signup/login modals full height on mobile.
- Improved the activation, account creation, and login-required pages on mobile.
- Removed the subheader and emoji from the welcome component.
- Removed most input instructions.
- Used consistent font size for text below the inputs.
- Displayed input instructions only when the field is focused.
- Improved the vertical alignment of input labels.
- Increased the spacing between inputs.
- Fixed label positioning for custom fields.
- Moved the "(optional)" text for the name input outside the instructions.
- Disabled buttons during login to prevent layout shifts.
- Reused the CTA component for modals as well.
- Matched the invite CTA styles with the signup form.
---------
Co-authored-by: Jan Cernik <jancernik12@gmail.com>
Co-authored-by: Joffrey JAFFEUX <j.jaffeux@gmail.com>
Currently in services, we don’t make a distinction between input
parameters, options and dependencies.
This can lead to user input modifying the service behavior, whereas it
was not the developer intention.
This patch addresses the issue by changing how data is provided to
services:
- `params` is now used to hold all data coming from outside (typically
user input from a controller) and a contract will take its values from
`params`.
- `options` is a new key to provide options to a service. This typically
allows changing a service behavior at runtime. It is, of course,
totally optional.
- `dependencies` is actually anything else provided to the service (like
`guardian`) and available directly from the context object.
The `service_params` helper in controllers has been updated to reflect
those changes, so most of the existing services didn’t need specific
changes.
The options block has the same DSL as contracts, as it’s also based on
`ActiveModel`. There aren’t any validations, though. Here’s an example:
```ruby
options do
attribute :allow_changing_hidden, :boolean, default: false
end
```
And here’s an example of how to call a service with the new keys:
```ruby
MyService.call(params: { key1: value1, … }, options: { my_option: true }, guardian:, …)
```
PR #26784 adds the scroll lock in the modal which renders this second scroll lock for SK component redundant. Having it there in fact causes issues on iPads, where it isn't necessary.
Background
When creating webhooks on a site without the Discourse Category Experts plugin installed, the category_experts_unapproved_event and category_experts_approved_event webhook events are getting automatically added to webhooks without a way to disable them.
The category_experts_unapproved_event and category_experts_approved_event webhook events are associated with the Discourse Category Experts plugin so I am moving these webhook events into the Category Experts plugin.
Changes
This PR deletes Category Experts plugin specific webhook event types added into core.
The new style is called `categories_only_optimized` and it is designed
to show only the parent categories, without any subcategories. This
works best for communities with many categories (over a thousand).
* UX: Apply admin table classes for consistent mobile styling on custom flags
* UX: Apply admin table classes for consistent mobile styling on custom flags
* UX: Apply admin table classes for consistent mobile styling on backups
* UX: Apply admin table classes for consistent mobile styling on plugins list
* DEV: tweaks on admin table
* UX: Apply admin table classes for consistent mobile styling on chat plugin
* apply prettier
* apply lint
* DEV: removed commented out code
* DEV: removed unnecessary div element
* scroll to the element
* remove the workaround
* revert
* add an extra assertion
* add enabled check
* improve switching
* rm
---------
Co-authored-by: Jarek Radosz <jradosz@gmail.com>
When rendering the initial search options, we re-use the `AssistantItem` component.
`AssistantItem` requires that you pass in the required params to define what _type_ of component it will be - category, tag, tag intersection, user, etc. This flexibility is nice, as we can just loop through all `@results` and pass in params, without having to predefine what _type_ of result it is.
It is is not very good when it comes to seperating the html strucutre of each unique _type_. This is an example of the initial search results:
<img width="408" alt="Screenshot 2024-10-23 at 9 04 18 AM" src="https://github.com/user-attachments/assets/46795697-6246-4b60-be18-fea200a57baa">
You can see that both categories **and** tags are being rendered. The HTML strcuture looks like so:
```html
<ul class="search-menu-assistant">
<li class="search-menu-assistant-item">
<a class="search-link" href="#"> CATEGORY </a>
</li>
<li class="search-menu-assistant-item">
<a class="search-link" href="#"> CATEGORY </a>
</li>
<li class="search-menu-assistant-item">
<a class="search-link" href="#"> TAG </a>
</li>
<li class="search-menu-assistant-item">
<a class="search-link" href="#"> TAG </a>
</li>
</ul>
```
There is no way to differentiate between the types, even though some are categories and others tags.
This PR adds a _typeClass_ to each component, that will be a additional class included at the top level of the component HTML structure.
```html
<ul class="search-menu-assistant">
<li class="category search-menu-assistant-item">
<a class="search-link" href="#"> CATEGORY </a>
</li>
<li class="category search-menu-assistant-item">
<a class="search-link" href="#"> CATEGORY </a>
</li>
<li class="tag search-menu-assistant-item">
<a class="search-link" href="#"> TAG </a>
</li>
<li class="tag search-menu-assistant-item">
<a class="search-link" href="#"> TAG </a>
</li>
</ul>
```
_See `.category` and `.tag` attached to each `search-menu-assistant-item`._
This will help us identify which _type_ it is, and allow devs to target and customize each element by _type_.
A followup to f05b984208
* modifiers to keep track of components' lifecycles, instead of did-insert/did-update/willDestroy
* proper glimmer-friendly tracking in related models
* caching
* `@outletArgs`
* gjs
We were using a modifier purely for its lifecycle hooks - not to modify an element. This commit switches to using a helper, which provides a similar lifecycle, but without needing to be attached to an element.
Bug introduced in this PR https://github.com/discourse/discourse/pull/29244
When the experiment toggle button was introduced, new features did not look right when the toggle button was not available.
In addition, the plugin name can be an empty string. In that case, information about new features should be displayed.
…or a tip with the highest priority.
This regressed in 597ef11195 where we got rid of `next()` calls, so we'd render the first tip we encounter.
The commit also adds a test and updates existing ones.
Moves the user-tip from the topic-timeline notifications button to the one at the bottom of the topic page.
Three reasons:
1. new users are more likely to use the button that has the full text (and description) rather than the icon-only one
2. we hide the timeline button when scrolled all the way to the bottom of the page, and then the tip doesn't seems to be attached to anything
3. we might be removing the timeline button altogether in the near future
The visitor stats on the /about page were previously showing as `NaN` immediately after enabling the `display_eu_visitor_stats` site setting because the stats for the /about page are cached and updated once every 30 minutes in a sidekiq job. The `NaN` would go away upon the next run of the relevant sidekiq job, but it's not good UX to display a cryptic `NaN` until the job runs. So, this commit ensures that the visitor stats is not displayed at all until the visitor stats is calculated and available.
Internal topic: t/128480.
Currently, when calling a service with its block form, a `#result`
method is automatically created on the caller object. Even if it never
clashed so far, this could happen.
This patch removes that method, and instead use a more classical way of
doing things: the result object is now provided as an argument to the
main block. This means if we need to access the result object in an
outcome block, it will be done like this from now on:
```ruby
MyService.call(params) do |result|
on_success do
# do something with the result object
do_something(result)
end
end
```
In the same vein, this patch introduces the ability to match keys from
the result object in the outcome blocks, like we already do with step
definitions in a service. For example:
```ruby
on_success do |model:, contract:|
do_something(model, contract)
end
```
Instead of
```ruby
on_success do
do_something(result.model, result.contract)
end
```
This PR is a follow-up to ea1473e532. When we initially added the experimental feature for automatically adding `[grid]` to images, we add the [grid] surrounding images after all the uploads have been completed.
This can lead to confusion when `[grid]` is delayed to be added in the composer, as users may try to add grid manually leading to breakage. This also leads to issues with Discourse AI's automatic image caption feature.
**In this PR**: we simply move the logic to be added when the images are uploaded and processing. This way, `[grid]` surrounding images is added immediately. We also apply a fix for an edge-case to prevent images from being wrapped in `[grid]` when they are already inside `[grid]` tags.
As part of #29272 we made a unique index work on PG13 by introducing a dummy string to represent "NULL".
We missed one spot, leading to a potential for duplicate admin notices for problems without a target.
This fixes that.
This commit brings back some reports hidden or changed
by the commit in 14b436923c if
the site setting `use_legacy_pageviews` is false.
* Unhide the old “Consolidated Pageviews” report and rename it
to “Legacy Consolidated Pageviews”
* Add a legacy_page_view_total_reqs report called “Legacy Pageviews”,
which calculates pageviews in the same way the old page_view_total_reqs
report did.
This will allow admins to better compare old and new pageview
stats which are based on browser detection if they have switched
over to _not_ use legacy pageviews.
Toggle the button to enable the experimental site setting from "What's new" announcement.
The toggle button is displayed when:
- site setting exists and is boolean;
- potentially required plugin is enabled.
This PR adds the feature where three or more image uploads in the composer will result in the images being surrounded by `[grid]` tags. This helps take advantage of the grid feature (https://github.com/discourse/discourse/pull/21513) and display images in a more appealing way immediately after upload.
* FIX: participating users statistics...
... was (mis-)counting
- bots
- anonymous users
- suspended users
There's now a "valid_users" function that holds the AR query for valid users and which is used in all "users", "active_users", and "participating_users" queries.
Internal ref - t/138435
These tweaks will help adoption of the non-mixin-based uppy patterns.
- Add `type:` to default arguments list
- Update pick-files-button to support explicit element registration
- Make `cancelSingleUpload` a public API, and add `cancelAllUploads`
- Remove `isDestroyed` logic - it doesn't do anything outside a component
- Add `@bind` to `setup()`
- Allow `additionalParams` to be a function
- Fix `autoStart` mixin shim
This commit simplifies the initial state of the invite modal when it's opened to make it one click away from creating an invite link. The existing options/fields within the invite modal are still available, but are now hidden behind an advanced mode which can be enabled.
On the technical front, this PR also switches the invite modal to use our FormKit library.
Internal topic: t/134023.
When a user is missing required fields, they are required to fill those up before continuing to interact with the forum. This applies to admins as well.
We keep a whitelist of paths that can still be visited in this mode: FAQ, About, 2FA setup, and any admin route for admins.
We concluded that admins should still be able to enable safe mode even with missing required fields. Since plugins etc. can potentially mess with the ability to fill those up.
When staff only mode is enabled - Discourse.enable_readonly_mode(Discourse::STAFF_WRITES_ONLY_MODE_KEY)
Staff members couldn't reset their password via the "forgot password" link.
This fixes it.
Internal ref. t/133990
We're seeing errors in logs due to some sites setting the reserved_usernames setting to nil. This is causing multiple use cases upstream of User#reserved_username? to error out.
This commit changes from using the raw #reserved_usernames to using the #reserved_usernames_map helper which exists on list-type site settings. It returns an empty array if the raw value is nil or empty string.
When adding or updating a custom user field to apply to all users (retroactively) we want to alert the admin that this will force all existing users to fill up the field before they are able to access the forum again.
However, we currently show this prompt when making changes only to other attributes on the custom field, i.e. the requirement hasn't changed.
This commit fixes that.
In #29169 we added a NULLS NOT DISTINCT option to the unique index on problem_check_trackers. This is to enforce uniqueness even when the target is NULL. (Postgres considers all NULLs to be distinct by default.)
However, this only works in PG15. In PG13 it does nothing.
This commit adds a default dummy string value __NULL__ to target. Since it's a string, PG13 will be able to correctly identify duplicate records.
We're expecting the period param to be something that neatly coerces into a symbol. If we receive something like a nested parameter, this will blow up.
This commit raises an InvalidParameters exception in the case of a non-stringy period parameter.
This component will soon be updated to remove the mixin entirely (and add a regression test for it). But for now, this is a quick fix to get it working again.
Since we recently blocked accidental serialization of AR models, we are getting a 500 error in some cases with thumbnails. We can fix this by serializing the thumbnail, previously we just returned a raw OptimizedImage object.
Thumbnails are now attached to the serializer in core, therefore we no longer need to use add_to_serializer within the chat plugin to use thumbnails within chat message uploads.
We're expecting the ID param to be something that neatly coerces into an ID. If we receive something like a nested parameter, this will blow up. (We already handle the case of arrays.)
This commit raises an InvalidParameters exception in the case of a nested ID.
We're expecting the page param to be something that neatly coerces into an integer. If we receive something like a nested parameter, this will blow up. (I'm sure there are other examples as well.)
This commit falls back to a page value of 1 if the coercion fails.
This commit is fixing the path which sets a default value to trigger. We were doing `if (!this.model.trigger)` but `this.model.trigger` can have `0` as value, which would trigger this codepath and this codepath was setting the first value of `badgeTriggers` as a default value for trigger.
The subcategories page was not paginated and it was using the
subcategory style from the category settings. The same page style should
be used for categories and subcategories page.
Theme modifiers can now be defined as theme settings, this allows for
site operators to override behavior of theme modifiers.
New syntax is:
```
{
...
"modifiers": {
"modifier_name": {
"type": "setting",
"value": "setting_name"
}
}
}
```
This also introduces a new theme modifier for serialize_post_user_badges. Name of badge must match the name of the badge in the badges table. The client-side is updated to load this new data from the post-stream serializer.
Co-authored-by: David Taylor <david@taylorhq.com>
When converting the user custom fields admin form in #29070, I accidentally removed the plugin outlet after-admin-user-fields. This is used by the discourse-authentication-validations plugin, which is now broken on main core.
This commit adds back the plugin outlet in core.
Add plugin outlets for each assistant result type - User, Tag and Categories, Groups, etc. This gives us the ability to add content for each _type_ of search suggestion:
<img width="216" alt="Screenshot 2024-10-16 at 10 01 09 AM" src="https://github.com/user-attachments/assets/fbbc71fe-a8fe-499b-8377-480dd0ed5f75">
I would have preferred to add a single plugin outlet at the top of the template and pass `this.suggestionType` and `@results`, but that would then require that we carry over a ton of core logic to plugins to calculate which _type_ is being rendered, and it would get unnecessarily messy quick. So instead I opted to create a plugin outlet for each _type_.
#29209 introduced a bug where columns to the directory added via add_directory_column are not being translated properly.
This fixes the issue and adds an integration test.
This commit replaces all uppy-related mixins with standalone classes. The main entrypoint is now lib/uppy/uppy-upload.js, which has a list of its config options listed at the top of the file. Functionality & logic is completely unchanged.
The uppy-upload mixin is replaced with a backwards-compatibility shim, which will allow us to migrate to the new pattern incrementally.
Constants should always be only assigned once. The logical OR assignment
of a constant is a relic of the past before we used zeitwerk for
autoloading and had bugs where a file could be loaded twice resulting in
constant redefinition warnings.
* UX: More additions
* UX: more
* DEV: Add admin/config/themes route
* UX: Use admin config card
* syntax merge fixes
* cleanup
* cleanup
* checkbox
* more
* error
* save on click
* more
* fix setter
* DEV: Implement vanilla checkbox
* cleanup
* UX: save themes as default
* DEV: Add component list to card
* DEV: Add placeholder for no screenshots
* DEV: Fix default theme reactivity
Also add content/optionalAction yields to config area
card and put the theme user selectable checkbox there,
along with adding styles.
* DEV: Change to generic "look and feel" config area
* DEV: Auto redirect to themes on base look and feel route
* UX: Remove computed from sorted themes
* linting
* UX: Turn update icon into button that routes to settings
* DEV: remove unused function
* UX: center icons with title
* DEV: Lint
* UX: Hook up theme preview button
* DEV: Minor fixes
---------
Co-authored-by: Martin Brennan <martin@discourse.org>
Co-authored-by: Joffrey JAFFEUX <j.jaffeux@gmail.com>
This adds dedicated routes for /login and /signup, replacing the use of modals. Currently, this is behind the experimental_full_page_login feature flag. It also includes some small consistency fixes related to formatting, spacing, icons, and the loading of certain elements
The `id` column of `notifications` table and `notification_id` columns
of the other tables have been migrated to bigint in previous commits
(for example, 799a45a).
In order to run the migrations with zero downtime, the data had to be
copied to new columns and swapped, but the old columns have been kept
to allow for rollback. They are no longer needed now.
Prior to this fix the format class was only applied to the child control, but in case of full we also need to ensure the parent wrapping field is also taking 100% width otherwise we are at risk of having a field of the width of its content.
theme-setting and theme-i18n are not needed in `.gjs` files. This commit adds more helpful error messages to direct developers to the modern alternatives.
Currently the topic timeline tip appears before the suggested topics one only due to a small implementation detail in the latter.
This ensures that tips appear in the expected order when more than one of these components is rendered at the same time.