Followup to 17ba00c395.
Fix for https://meta.discourse.org/t/-/261917
This fixes a usability issue where the user couldn't switch to the user
menu when the search menu was visible and the text in the input was
selected.
Explanation: The `click` event is triggered both when clicking and when
selecting some text and clicking. This means that when selecting text in
the search input, at the end of the selection event, a click event was
triggered. And if that click event happened to be outside of the search
menu, then the menu would be dismissed.
Previously, we fixed this by checked if a current text selection was
present. But that results in a small side-effect of not switching to
other menus. This PR switches to setting a flag during `mouseDown` and
then using that flag when evaluating whether to trigger clickOutside or
not.
It's backward compatible so still supports our 3.28 ember-source.
The visible change is finally getting rid of this message:
```
WARNING: Node v18.12.0 is not tested against Ember CLI on your platform. We recommend that you use the most-recent "Active LTS" version of Node.js. See https://git.io/v7S5n for details.
```
---
`@ember/string` dependency is added for future compatibility. See: https://github.com/ember-cli/ember-cli/pull/10125
---
`tests/helpers/index.js` is unused for now, but is a nice pattern. We could move some of our test setup into local `setupApplicationTest/setupRenderingTest/setupTest` helpers.
Co-authored-by: David Taylor <david@taylorhq.com>
All supported browsers use `transitionend` event now, so this code is not necessary and makes it difficult to use that event in tests (you'd have to trigger all variants to cover the bases)
That function was used only in core (no hits in all-the*) in two places, so I think it's rather safe to just trash it without deprecating it first.
(History Corner – this helper was originally added in the initial commit of Discourse! 1839614bcc/app/assets/javascripts/discourse/components/transition_helper.js.coffee)
Following a change in e9f7262813 which prevents the notification level to be returned from the update endpoint, the model couldn't update itself. This commit makes the update manually and adds a test to prevent future regressions.
Note we could also change the backend endpoint, but this should work correctly with minimum risk.
This feature will allow sites to define which emoji are not allowed. Emoji in this list should be excluded from the set we show in the core emoji picker used in the composer for posts when emoji are enabled. And they should not be allowed to be chosen to be added to messages or as reactions in chat.
This feature prevents denied emoji from appearing in the following scenarios:
- topic title and page title
- private messages (topic title and body)
- inserting emojis into a chat
- reacting to chat messages
- using the emoji picker (composer, user status etc)
- using search within emoji picker
It also takes into account the various ways that emojis can be accessed, such as:
- emoji autocomplete suggestions
- emoji favourites (auto populates when adding to emoji deny list for example)
- emoji inline translations
- emoji skintones (ie. for certain hand gestures)
EmberObject's `reopen` feature allows changes to be made to the prototype of the class, but it does not work with native class fields. Native class field values are set on the instance in the constructor, and therefore override any values from the prototype.
This commit implements a workaround which detects possible field overrides and then sets the values during the `init()` function of the EmberObject. This isn't perfect - old field values will still be present while any constructor function is running. But in the vast majority of cases, it should provide parity with old non-native-class EmberObject properties.
This commit also adds a warning when trying to override fields on non-EmberObject classes. There is no change in behavior here - we're just warning about the fact it doesn't work.
When running `yarn install` in a yarn workspace, the lifecycle hooks in the root package.json are not triggered. https://github.com/yarnpkg/yarn/issues/5790
As a workaround, we can additionally run `patch-package` from the `javascripts/discourse/package.json` `postinstall` hook. `patch-package` is idempotent, so it doesn't matter if it is triggered multiple times.
Longer term we intend to move to pnpm, which has built-in patch support.
Fixes the unnecessary message when starting ember server:
```
Invalid watchman found, version: [2023.04.03.00] did not satisfy [>= 3.0.0].
Visit https://ember-cli.com/user-guide/#watchman for more info.
```
Moves a couple things from discourse-boot.js to a different JS file imported from app/app.js.
This is a forwards compatible technique to import and throw data on the window.
One thing to make note of, though, is that if the virtual-dom and discourse-widget-hbs/helpers were previously included in the build elsewhere, they will now become part of the app bundle.
Later, when using embroider, all bundles will be chunks, and webpack will optimize which chunk contains which modules appropriately.
When selecting the "Keep bookmark" in the user preference for what to do after a bookmark reminder is sent, it does not propagate to the drop-down in the "Create bookmark" modal. Instead it defaults to "Keep bookmark and clear reminder". All other options work fine.
We set a default ("Keep bookmark and clear reminder") if no user preference is found, However, this uses the index of the option, and the index of the first option ("Keep bookmark") is 0, which is treated as falsey in JavaScript, thus causing the default to be selected.
This change switches from logical "or" conditional `||` operator to nullish coalescing `??` operator.
Previously, public custom sections were only visible to logged-in users. In this PR, we are making them visible to anonymous as well.
The reason is that Community Section will be moved into custom section model to be easily editable by admins.
Followup to 6ad9e4ad06,
I was not aware that `site.categories` is undefined if
the user is anon and the site is login_required, this
handles that scenario and does not continue trying to
generate CSS.
This commit adds a system to generate CSS variables and classes for categories
and hashtags, which will be used in an effort to remove baked icons for hashtags
and add color to those icons.
This is in two parts. First I added an initializer generate a category color CSS
variable style tag in the head tag that looks like this:
```css
:root {
--category-1-color: #0088CC;
--category-2-color: #808281;
--category-3-color: #E45735;
--category-4-color: #A461EF;
--category-5-color: #ee56c9;
--category-6-color: #da28c2;
--category-7-color: #ab8b0a;
--category-8-color: #45da37;
...
}
```
The number is the category ID. This only generates CSS variables for categories
the user can access based on `site.categories`. If you need the parent color variable
you can just use the `category.parentCategory.id` to get it.
Then, I added an initializer to generate a hashtag CSS style tag using these variables.
Only the category and channel hashtags need this, the category one generates the
background-gradient needed for the swatch, and the channel just generates a color
for the icon. This is done in an extendable way using the new `api.registerHashtagType`
JS plugin API:
```css
hashtag-color--category-1 {
background: linear-gradient(90deg, var(--category-1-color) 50%, var(--category-1-color) 50%);
}
hashtag-color--category-2 {
background: linear-gradient(90deg, var(--category-2-color) 50%, var(--category-2-color) 50%);
}
hashtag-color--category-5 {
background: linear-gradient(90deg, var(--category-5-color) 50%, var(--category-4-color) 50%);
}
...
.hashtag-color--channel-4 {
color: var(--category-12-color);
}
.hashtag-color--channel-92 {
color: var(--category-24-color);
}
```
Note if a category has a parent, its color is used in the gradient correctly. The numbers
here are again IDs (e.g. channel ID, category ID) and the channel’s chatable ID is used
to find the category color variable.
The status should use the word "user" instead of "flag", for example
"approved user" instead of "approved flag". The problem was caused by
a mismatched type.
Using the `mouseDownOutside` event was problematic here because two
events were being triggered consecutively: `mouseDown`
would toggle the menu off and `click` would then toggle it back on. This
switches the logic to use `clickOutside` again, but with two changes:
- it limits the action to the `search-menu` key (so that theme component
overrides can do their own handling)
- it does not trigger the event when there is an active text selection
(this was the original reason for switching to `mouseDownOutside`, see
https://github.com/discourse/discourse/pull/14788)
The translation key is built using the name of the reviewable as it was
defined in Ruby. The chat plugin uses the `Chat` namespace and defines
`Chat::ReviewableMessage`. This was then transformed to
`chat::reviewable_message`, but it should be `chat_reviewable_message`
to resemble the other translation keys.
Back in d0e1c222f7 we added
performance measuring for uppy uploads using the Performance
API in the browser. However we recently discovered that
sometimes performance.measure can fail if for whatever reason
one of the marks passed to it does not exist:
> Failed to upload ... Performance.measure: Given mark name, upload-uppy-....-create-multipart-success, is unknown
This would cause the entire upload to fail, which is unnecessary
for a debugger. Improve the situation so if this happens again
the error does not stop the upload.
The following are the changes being introduced in this commit:
1. Instead of mapping the query language to various query params on the
client side, we've decided that the benefits of having a more robust
query language far outweighs the benefits of having a more human readable query params in the URL.
As such, the `/filter` route will just accept a single `q` query param
and the query string will be parsed on the server side.
1. On the `/filter` route, the tags filtering query language is now
supported in the input per the example provided below:
```
tags:bug+feature tagged both bug and feature
tags:bug,feature tagged either bug or feature
-tags:bug+feature excluding topics tagged bug and feature
-tags:bug,feature excluding topics tagged bug or feature
```
The `tags` filter can also be specified multiple
times in the query string like so `tags:bug tags:feature` which will
filter topics that contain both the `bug` tag and `feature` tag. More
complex query like `tags:bug+feature -tags:experimental` will also work.
Previously, reorder on touch screens was disabled https://github.com/discourse/discourse/pull/20769.
This PR enables it again. However, link has to be hold for 300 ms to enable drag&drop. Otherwise, normal scroll is performed.
As part of another regression, we realized that the plugins tab is visible to moderators, but they cannot interact with anything inside without triggering authorization errors.
This change hides the plugin tab for non-admin users.
When an admin removes all the categories from their personal sidebar configuration, the section should remain visible to them with the “Configure default categories” prompt.
Similar solution for tags.
/t/95036
Instead of being tied to the old implementation and constraints, a
dedicated route and controller for the `discovery.filter` app route will
allow us to iterate on changes much faster.
Before, incorrectly filled fields were marked with red border. Now, additional information under the field is displayed to notify the user what is incorrect.
/t/93696
In some languages, labels on the site settings navigation menu
get truncated. This adds titles to menu items, so users can see
untruncated labels on hover.
Previously we disabled the hamburger reviewable count badge when the redesigned user menu was enabled. This commit updates the logic so that the hamburger reviewable count is tied the legacy navigation mode instead. This ensures that there is always a persistent reviewable count visible. (in the non-legacy navigation modes, the total reviewable count is shown in the sidebar)
In the future we'll be looking at things like tree-shaking and code-splitting. Using 'magic strings' to resolve components is not compatible with those techniques. It makes sense to switch to a more modern pattern now, before the new user-tab API is used too widely.
This commit is backwards-compatible. API consumers which pass a string will see a deprecation message asking them to pass a component class instead.
This commit also turns some unneeded getters into simple class properties (no need to use a getter when it just returns a constant).
This commit turns the new user menu tabs into `<a href` elements. This means that the tab's associated URL is shown on mouseover, and also allows the browser to handle navigation when a modifier key is pressed (e.g. ctrl, shift, mod).
Actions are moved from actions: {} to top-level functions with @action decorator. Previously we had a save() action and a top-level function of the same name, so this commit renames the action to avoid a clash.
Change styling of filter input & remove button.
This follows the same pattern of design we use for search. In the search dropdown we do not have a button to search. We rely on pressing enter. I've also provided an example of Github's PR filter UI at the bottom of this comment.
We also do not have buttons like this on any other topic-list header. On tag and category dropdowns, we also rely on pressing enter to filter the topic list by chosen categories & tags.
Co-authored-by: Jordan Vidrine <jordan@jordanvidrine.com>
Moving the `grantBadge` action out of the actions hash caused it to clash with a method of the same name from the GrantBadgeController mixin. This commit renames the action.
In order to avoid built in browser CORS issues and sites that are using
CDNs this change allows us to generate thumbnail images from videos
directly from the File uploaded instead of reading the already uploaded
file via the `video` tag.
Follow-up to: f144c64e13
a373bf2a updated the behavior of `replace-emoji` so that the input is treated as unsafe-by-default. `fancy_title` is already escaped, so we need to mark it as html-safe to avoid it being double-escaped.
There is no need to html-safe the result of replace-emoji - it's already done as part of the helper.
- Install `@ember/legacy-built-in-components` and update our import statements to use it
- Remove our custom attributeBinding extensions of `TextField` and `TextArea`. Modern ember 'angle bracket syntax' allows us to apply html attributes to a component's element without needing attributeBindings
One of the problems here was coming from the ember-jquery addon. This commit skips the problematic shim from the addon and re-implements in Discourse. This hack will only be required short-term - we'll be totally dropping the ember-jquery integration as part of our upgrade to Ember 4.x.
Removing this shim means we can also remove our `discourse-ensure-deprecation-order` dummy addon which was ensuring that the ember-jquery-triggered deprecation was covered by ember-cli-deprecation-workflow.
Non-markdown tags weren't being escaped in chat excerpts. This could be
triggered by editing a chat message containing a tag (self XSS), or by
replying to a chat message with a tag (XSS).
Co-authored-by: Jan Cernik <jancernik12@gmail.com>
# Context
https://meta.discourse.org/t/timeline-timestamp-not-updating/256447/1
During the upgrade of the topic-timeline to glimmer the "latest post" timestamp was not updating on the timeline in relation to the relative age of the post. It was only updating on a hard refresh.
# Fix
Use the `age-with-tooltip` helper to update the created_at date automatically as time passes.
# Additional
Add the ability to pass params to `age-with-tooltip` so that we can include options like `addAgo` and `defaultFormat`
When a category has default_list_filter=none, there were a number of issues which this commit resolves:
1. When using the breadcrumbs to navigate a `default_list_filter=none` category, adding a tag filter would not apply the no-subcategories filter, but the subcategories dropdown would still say 'none'. This commit adjusts `getCategoryAndTagUrl` so that `/none` is added to the URL
2. When landing on `/tags/c/{slug}/{id}/{tag}`, for a default_list_filter=none category, it would include subcategories. This commit introduces a client-side redirect to match the behavior of `/c/{slug}/{id}`
3. When directly navigating to `/c/{slug}/{id}`, it was correctly redirecting to `/c/{slug}/{id}/none`, BUT it was still using the preloaded data for the old route. This has been happening since e7a84948. Prior to that, the preloaded data was discarded and a new JSON request was made to the server. This commit restores that discarding behavior. In future we may want to look into making this more efficient.
System specs are introduced to provide end-end testing of this functionality
# Context
During the octane upgrade of the Topic Timeline the `summarize-topic` button was neglected, leaving it in a broken state.
# Fix
Update the button to replicate the original functionality
<img width="351" alt="Screenshot 2023-03-13 at 12 41 25 PM" src="https://user-images.githubusercontent.com/50783505/224785657-fc8124fe-f1d9-4cc8-917b-9cd859517da3.png">
_updated timeline with summarize button_
Steps to reproduce:
1. Create a post with a mention of a user that has user status with an end date
2. Try to load the topic with that post as an anonymous user
You'll see a topic with blank content.
It's important to keep our core log output as clean as possible to avoid 'crying wolf', and so that any deprecations triggered by plugin/theme tests are indeed caused by that theme/plugin, and not core.
This commit will make the core test suite fail if any deprecations are triggered. If a new deprecation is introduced (e.g. as part of a dependency update) and we need more time to resolve it it can be silenced via ember-deprecation-workflow.
This does not affect plugin/theme test runs.
By default, Ember uses a babel transformation to strip out calls to `deprecate()` in production builds. Given that Discourse is a development platform for third-party themes/plugins, having deprecation messages visible in production is essential - many themes/plugins do not have comprehensive test-suites, and rely on production feedback to prompt changes. This commit patches Ember to print its deprecation messages to the console in production. In future we intend to improve the visibility of these to hosting providers and/or site admins.
There are two main parts to this commit:
1. Use yarn's 'resolutions' feature to point `babel-plugin-debug-macros` to a discourse-owned fork. This fork prevents `deprecate()` calls from being stripped. Relevant change can be found at https://github.com/discourse/babel-plugin-debug-macros/commit/d179d613bf
2. Introduce a production shim for Ember's deprecation library, including the `registerDeprecationHandler` API. The default implementation is stripped out of production builds via an `if(DEBUG)` wrapper.
Long term we hope that this kind of functionality can be made available in Ember itself via a flag.
Currently the auto-bump cooldown is hard-coded to 24 hours.
This change makes the highlighted 24 hours part configurable (defaulting to 24 hours), and the rest of the process remains the same.
This uses the new CategorySetting model associated with Category. We decided to add this because we want to move away from custom fields due to the lack of type casting and validations, but we want to keep the loading of these optional as they are not needed for almost all of the flows.
Category settings will be back-filled to all categories as part of this change, and creating a new category will now also create a category setting.
* DEV: Change sidebar header dropdown to use wait_for_animation
Introduced in 54351e1b8a, this
helper should remove the need to have to add the .animated
CSS class in JS for the sidebar.
* DEV: Revert spec change
Currently, if a user has opted into the new new experiment (introduced in a509441) and they click on the "See # new or updated topics" banner (screenshot below) at the top of the /new topics list, only new topics are loaded even if there are tracked topics with new replies.
This is unexpected in the new new view experiment because /new in this experiment is supposed to show both new and unread topics so it should listen for both new topics and new replies for existing/tracked topics. This PR addresses this inconsistency and makes it so that clicking the banner load all new and updated topics.
If you set a category to `default_list_filter` none. Information
was not passed to the tag route and routing was incorrect.
This patch fails, cause on reload route does not point to the right place.
```
-- a/app/assets/javascripts/discourse/app/routes/tag-show.js
+++ b/app/assets/javascripts/discourse/app/routes/tag-show.js
@@ -89,6 +89,8 @@ export default DiscourseRoute.extend(FilterModeMixin, {
filter = `tag/${tagId}/l/${topicFilter}`;
}
const list = await findTopicList(
this.store,
this.topicTrackingState,
@@ -123,7 +125,7 @@ export default DiscourseRoute.extend(FilterModeMixin, {
},
setupController(controller, model) {
- const noSubcategories =
+ this.noSubcategories =
this.noSubcategories === undefined
? model.category?.default_list_filter === NONE
: this.noSubcategories;
@@ -133,7 +135,7 @@ export default DiscourseRoute.extend(FilterModeMixin, {
...model,
period: model.list.for_period,
navMode: this.navMode,
- noSubcategories,
+ noSubcategories: this.noSubcategories,
loading: false,
});
```
Long term we don't want to hide this logic from the routing (even in
the category case) it just cause unneeded confusion and fragility.
Navigating to the topic template tab on a new category form resulted in
exceptions because the `form_template_ids` property was undefined.
This fix sets the `form_template_ids` property on new category records.
This reverts commit f6063c684b.
Videos on sites with a cdn enabled aren't playing w/ a default cdn
config. They are showing a "CORS request did not succeed" error.
* DEV: Add crossOrigin to video tag
This is a follow-up commit to f144c64e13
which enables the ability to generate thumbnail images for video
uploads.
In order for the html5 canvas element to create an image or blob the
source video element needs to to have the crossOrigin attribute set to
"anonymous" because a cdn is likely being used in production
environments.
We are already doing something similar in
e292c45924/app/assets/javascripts/discourse/app/lib/update-tab-count.js (L63)
* FEATURE: Generate thumbnail images for uploaded videos
Topics in Discourse have a topic thumbnail feature which allows themes
to show a preview image before viewing the actual Topic.
This PR allows for the ability to generate a thumbnail image from an
uploaded video that can be use for the topic preview.
* DEV: specify type of flag in status
* FIX: passing missing parameter
* DEV: pass type for reviewable score table
* UX: add missing queued-topic styling
* UX: fix img overflow
* UX: add styling for queued user
* UX: fix user flag color
* UX: prevent overflow
* UX: add copy for filters
* FIX: fix typo in css for akismet flagging
* UX: copy change for flag something else
* UX: prevent overflow
* Fixing reviewable-status css classes
* Changes based on no longer using humanType
* Need to use type rather than humanType for reviewable-status
* FIX: linting
---------
Co-authored-by: Martin Brennan <martin@discourse.org>
When using the "review media unless trust level" setting, posts with emojis or quotes will end up in the review queue even though they don't have any uploaded media. That is because our heuristic for this in the new post manager relies on image_sizes. This commit skips sending image_sizes for emojis and avatars.
Co-authored-by: Régis Hanol <regis@hanol.fr>
Select-kit was mutating a passed-in options hash to apply its own deprecations. This commit updates it to apply deprecated changes to the downstream `this.selectKit.options` object instead.
Attaching required tag groups to new categories failed because
`required_tag_group` was undefined on the new category records
This fix sets an empty `required_tag_group` property on the new category
records.
Currently, the global search context suggestion("in all posts and topics") which
also doubles as the default context on pressing Enter is displayed as
the second item in the initial search options suggested.
This changes makes it the first item in the suggested options.
Feature to allow adding new tags from the edit tag synonyms tag search field.
Previously new tags had to be created from the topic composer, and then added via the edit tag synonyms page.
/t/92741
What is the problem?
When constructing the "Messages" section in Sidebar, we call
startTracking() on the pm-topic-tracking-state service in order to
get the counts for new/unread for the private message inboxes for each
user. However, this is unnecessary because the inboxes are in a
collapsed state by default in the sidebar and are only expanded when the
current route correspond to the inbox's route. Therefore, we can avoid
calling startTracking() on the pm-topic-tracking-state service until
an inbox's route is loaded. This allows us to cut out one extra request
to the server on page load and defer it until it is necessarily.
As reported on Meta, the relative time pickers for configuring slow-mode and auto-close durations in category settings are initially showing a "mins" option, which then disappears after you select any other timescale.
Our `RelativeTimePicker` component wasn't equipped to handle `null` values as the initial input. This caused it to go into a code path that set the selected timescale to "mins", even if that is not an allowed option.
There are two things being done here:
1. Add support for `null` input values to `RelativeTimePicker`. This fixes the auto-close setting.
2. Allow minutes for the slow-mode setting. (The user in Meta mentioned they usually set 15-30 minutes to cool down hot topics.
If the whitespace isn't trimmed from the input field the email is
considered invalid, and the button remains greyed out. We should handle
removing any trailing whitespace and not rely on the user trying to see
it themselves.
This was causing unattended effects on other elements. eg: the select-kit header input could lose focus when the list filtered would change size and cause the cursor to be positioned over a row.
Every time we created a topic list we would leak a state change callback
This happens on any topic list -> topic -> topic list sequence
This can cause corruption of tracking state and memory bloating given that
all information may be sent to the sync function.
What is the problem?
We have a hidden site setting `show_category_definitions_in_topic_lists`
which is set to false by default. What this means is that category
definition topics are not shown in the topic list by default. Only the
category definition topic for the category being viewed will be shown.
However, we have a bug where we would show that a category has new
topics when a new child category along with its category definition
topic is created even though the topic list does not list the child
category's category definition topic.
What is the fix here?
This commit fixes the problem by shipping down an additional
`is_category_topic` attribute in `TopicTrackingStateItemSerializer` when
the `show_category_definitions_in_topic_lists` site setting has been set
to false. With the new attribute, we can then exclude counting child
categories' category definition topics when counting new and unread
counts for a category.