We recently had a bug which caused auto-bumping to "not work". The problem was that the value had been set to 0.5, which when coerced to an integer turned into 0. So the feature is "working as intended", but there's a possibility of misconfiguration.
When looking into this, I noticed that the inputs on the category settings page doesn't have any particular sanitisation in the front-end, and also one or two validations missing in the back-end.
This change:
- Takes an existing component, NumberField and enhances that by only allowing numeric input, essentially turning it into a managed input using the same approach as our PasswordField.
- Changes the numeric inputs on category settings page to use this component.
- Adds appropriate min constraints to the fields to disallow out-of-range values.
- Adds missing back-end validations to relevant fields.
Triggers a DiscourseEvent when a message is deleted, similar to
`:chat_message_created` and `:chat_message_edited`. This is not used
in this plugin, but can be used by other plugins to act when a message
is trashed.
* FIX: Remove action buttons if post has already been reviewed
* Change the approve to reject test to expect an error
* Adds a controller spec to ensure you can't edit a non-pending review item
* Remove unnessary conditional
When a CUSTOM_SCHEME is missing a color (e.g. 'Dracula' is missing a 'highlight' color), we need to fallback to `ColorScheme.base_colors`. This regressed in 66256c15bd
This commits adds the ability to add a header to the embedded comments
view. One use case for this is to allow `postMessage` communication
between the comments iframe and the parent frame, for example, when
toggling the theme of the parent webpage.
We caught it in logs, race condition led to this error:
ActiveRecord::RecordNotUnique
(PG::UniqueViolation: ERROR: duplicate key value violates unique constraint "user_statuses_pkey"
DETAIL: Key (user_id)=(15) already exists.)
The reason the problem happened was that we were checking if a user has status and if not inserting status:
if user_status
...
else
self.user_status = UserStatus.create!(status)
end
The problem is that it's possible that another request will insert status just after we check if status exists and just before our request call `UserStatus.create!(status)`. Using `upsert` fixes the problem because under the hood `upsert` generates the only SQL request that uses "INSERT ... ON CONFLICT DO UPDATE". So we do everything in one SQL query, and that query takes care of resolving possible conflicts.
This is an alternative way to use `RenderGlimmer` which can be more ergonomic for iterative updates of a codebase. For documentation, see `widgets/render-glimmer.js`
This removes lots of unused strings. Some of them were never used and some of them weren't removed when features changed...
* `js.pause_notifications.remaining` was removed in 836cbfe7ae
* Looks like `deleted` was added in 651cfba93f but was never used
* Looks like `image` was removed in a9e502936f
Fixed had been added when autocomplete was used in the discourse header. This shouldn't be needed anymore. This was causing the preventOverflow to not work correctly on Android.
This fix fix also adds an optimisation to refer top of the input when on mobile. This is done to avoid cases where the screen is actually slightly taller than the viewport with keyboard visible on Android leading popper to think there's space under the input.
First follow-up to the feature introduced in #19034. We don't want to pollute main components like `chat-live-pane`, so we'll use a service to track and manage the state needed to display before-send warnings while composing a chat message.
We also move from acceptance tests to system specs.
- Move docking logic (intersection / dockAt / etc) from `glimmer-topic-timeline` -> `topic-timeline/container` to live alongside the `postScrolled` hook.
- Toggle `timeline-docked` and `timeline-docked-bottom` when we are at the bottom of a topic. This returns the missing animation to the glimmer-topic-timeline (pictured below).
https://user-images.githubusercontent.com/50783505/216655735-906ccd2a-b77e-45af-9a7b-c22680eca2dc.mov
Previously `helper.renderGlimmer()` would always create a new wrapper element. This is required when using `RenderGlimmer` within widgets, where there is no direct access to DOM elements. However, when using within `decorateCooked`, we have the ability to pass an existing element to `{{#in-element}}` and have the glimmer content appended with no additional wrappers.
This commit makes the `renderInto` accept an existing DOM node for this 'append' behavior. The previous 'new wrapper element' behaviour is still used when a string is passed.
Deleting a message with a mention doesn't clear the associated notification, confusing the mentioned user.
There are different chat notification types, but we only care about `chat_mentioned` since `chat_quoted` is associated with a post, and `chat_message` is only for push notifications.
Unfortunately, this change doesn't fix the chat bubble getting out of sync when a message gets deleted since we track unread/mentions count with an integer, making it a bit hard to manipulate. We can follow up later if we consider it necessary.
This commit implements a requested feature: resizing the chat drawer.
The user can now adjust the drawer size to their liking, and the new size will be stored in localstorage so that it persists across refreshes. In addition to this feature, a bug was fixed where the --composer-right margin was not being correctly computed. This bug could have resulted in incorrectly positioned drawer when the composer was expanded.
Note that it includes support for RTL.
# Context
The class of `widget-button` was kept in the upgraded version of the topic timeline to keep the preexisting logic of how we open / close child and parent modals.
# Problem
<img width="1242" alt="Screenshot 2023-02-02 at 3 45 53 PM" src="https://user-images.githubusercontent.com/50783505/216456778-11a3d0ce-5e33-4b85-89af-a2a32e39a1f6.png">
With the `widget-button` class removed from the topic timeline, clicking the button (highlighted in the image above) would close itself when populating the `jumpToPostPrompt` modal. This is not the behavior we want so class was kept on the button. The upgrade to ember octane entails moving away from widgets and all of its functionality... so we don't want to carry the debt of utilizing the `widget-button` class.
# Solution
Create a new class `.timeline-open-jump-to-post-prompt-btn` to be added to the `_expanded` function. When this class is present on a child or a parent of the button clicked, we do not collapse the modal. This gives us the expected behavior of maintaining both modals open at the same time.
<img width="1176" alt="Screenshot 2023-02-02 at 3 50 59 PM" src="https://user-images.githubusercontent.com/50783505/216457612-ab313758-bfa9-4913-bd29-d5224faf5187.png">
# Other
Obviously adding this as jquery is not ideal, but to prevent scope creep we will need to refactor this in a separate PR.
The algorithm failed to find the correct category by slug when there are multiple sub-sub-categories with the same child-category name and the first child doesn't have the correct grandchild.
So, searching for "child / grandchild" worked in the following case, it found (3):
- (1) parent 1
- (2) child
- (3) grandchild
- (4) parent 2
- (5) child
- (6) grandchild
But it failed to find the grandchild in the following case:
- (1) parent 1
- (2) child
- (4) parent 2
- (5) child
- (6) grandchild
And this also fixes a flaky spec by forcing categories to always order by by `parent_category_id` and `id`.
This makes it possible to partly revert 60990aab55
Allows users to configure their own custom sidebar sections with links withing Discourse instance. Links can be passed as relative path, for example "/tags" or full URL.
Only path is saved in DB, so when Discourse domain is changed, links will be still valid.
Feature is hidden behind SiteSetting.enable_custom_sidebar_sections. This hidden setting determines the group which members have access to this new feature.
Previously due to an error archived topics were more prominent in search
than closed topics.
This amends our internal logic to ensure archived topics are bumped down
the list.
If a post contains domain with a word that stems to a non prefix single
words will not match it.
For example: in happy.com, `happy` stems to `happi`. Thus searches for happy
will not find URLs with it included.
This bloats the index a tiny bit, but impact is limited.
Will require a full reindex of search to take effect.
When we are done refining search we can consider a full version bump.
Previously to_tsquery would split terms and join with &
In PG 14 terms are split and use <-> which means followed directly by.
In PG 13:
discourse_test=# SELECT to_tsquery('english', '''hello world''');
to_tsquery
---------------------
'hello' & 'world'
(1 row)
In PG 14:
discourse_test=# SELECT to_tsquery('english', '''hello world''');
to_tsquery
---------------------
'hello' <-> 'world'
(1 row)
Change is very unobtrosive, we simply amend our to_tsquery to behave like
it used to behave and make no use of the `<->` operator
More detail at: https://akorotkov.github.io/blog/2021/05/22/pg-14-query-parsing/
Note that plainto_tsquery used elsewhere in Discourse keeps the exact
same function.
This also corrects a faulty test that was passing by a fluke on older
version of PG
- Rename `class` getter -> `classes` seeing that we are dealing with multiple classes
- Add `show` class to fullscreen topic timeline via `did-insert` to handle how CSS transitions only apply when an existing element changes its properties. We need to wait until `timeline-fullscreen` is painted to the DOM, and then add the `show` class later.
# Problem
Creating a post on a topic, where the timeline is not shown by default, does not update the visibility state dynamically. You must refresh the page to have the timeline appear.
# Solution
This PR hooks into the `post-stream:posted` app event and checks if we can now display the timeline after a post has been created. This will update the visibility state dynamically.
This PR introduces a proper `action` to the topic timeline `back-button` which will fix the button not being clickable (or functional) as well as removing a duplicate setting of `this.lastReadTop` which was causing odd positionings of the button.
This is very difficult to test due to the fact you have to manage the "read history" for a user to have the back button populate. We will have to move forward without one (as we did in the last version of the timeline 😅) for now.
* FIX: Emoji autocomplete “more” button not working
* Rely on setting an intial value on the filter input
This commit removes custom logic applied on initial filter and instead gives a param to use as value for the input, automatically triggering the existing filtering handler.
Other notes:
- Slightly changes the API to be able to set a filter and open the composer in one go
- Adds a very simple service spec
- Adds a system spec to fully validate the behavior
---------
Co-authored-by: Joffrey JAFFEUX <j.jaffeux@gmail.com>
Currently, when doing `@mention` for users we have 0 tolerance for typos and misspellings.
With this patch, if a user search doesn't return enough results we go and use `pg_trgm` features to try and find more matches based on trigrams of usernames and names.
It also introduces GiST indexes on those fields in order to improve performance of this search, going from 130ms down to 15ms in my tests.
This is all gated in a feature flag and can be enabled by running `SiteSetting.user_search_similar_results = true` in the rails console.
`helper.renderGlimmer` will return an HTML element which can be added to a post's `cooked`
Example usage:
```
import { hbs } from "ember-cli-htmlbars";
api.decorateCookedElement((cooked, helper) => {
const glimmerElement = helper.renderGlimmer(
"div.my-wrapper-class",
hbs`<DButton @icon={{@data.param}} @translatedLabel="Hello world from Glimmer Component"/>`,
{ param: "user-plus" }
);
cooked.appendChild(glimmerElement);
}, { onlyStream: true, id: "my-id" });
```
See `widgets/render-glimmer.js` for more detailed usage information.