Chat drawer was using the `DiscourseURL` hook `afterRouteComplete`. This hook suffer from a very poor implementation which makes it very unreliable:
```javascript
if (typeof opts.afterRouteComplete === "function") {
schedule("afterRender", opts.afterRouteComplete);
}
```
This commit attempts to return the promise from `handleURL` to directly use it and have a very reliable after transition hook.
This PR converts the following modals:
- `dismiss-new`
- `dismiss-read`
- `dismiss-notification-confirmation`
to make use of the new component-based API
# Additional Changes
## Before
By default we display a warning modal when dismissing a notification however we bypass the warning modal for specific notification types when they are a 'low priority' type of notification (eg. likes). To do this we were overwriting `dismissWarningModal` on a given notification type component
```javascript
dismissWarningModal() {
return null
}
```
but in the case we wanted to change the text within the modal we were calling `showModal` and then passing in the respective options all over again, putting the logic of rendering the modal in multiple places.
```javascript
dismissWarningModal() {
const modalController = showModal("dismiss-notification-confirmation");
modalController.set(
"confirmationMessage",
I18n.t("notifications.dismiss_confirmation.body.assigns", {
count: this._unreadAssignedNotificationsCount,
})
);
return modalController;
}
```
## After
I simplified this by adding an extensible `dismissConfirmationText` function that can be updated on a per component basis as that was the only option being overridden.
eg
```javascript
get dismissConfirmationText() {
return I18n.t("notifications.dismiss_confirmation.body.bookmarks", {
count: this.#unreadBookmarkRemindersCount,
});
```
This saves us from importing the entire modal again and keeps the core logic in one place.
Instead of overwriting the `dismissWarningModal` function and returning `null` to bypass the confirmation modal, I added another extension point of `renderDismissConfirmation` (defaults to true) to _toggle_ whether we should display a confirmation when dismissing notifications.
eg
```javascript
get renderDismissConfirmation() {
return false;
}
```
we utilize this in core for specific _low priority_ notification types. When you need the confirmation modal to be displayed no matter the case you can set `alwaysRenderDismissConfirmation` to `true`
```
get alwaysRenderDismissConfirmation(){
return true
}
```
This can be useful when you want to render the confirmation modal on a custom notification type that is not deemed as _high priority_, leading to the confirmation modal never being rendered.
You can see this in use in [Discourse Assign](https://github.com/discourse/discourse-assign/pull/481)
Followup to d51baa3bb3
Also includes: Force full rerender of post-stream widget when switching topics. This ensures that plugin/theme decorators are re-run when we switch between topics with the loading slider enabled.
Previously we were using the `didInsertElement` hook and querying the DOM to check whether the other button was visible. This is problematic from a performance point of view because it forces the browser to render the layout prematurely. It can also lead to subtle bugs based on the current scroll position.
In addition, having this logic on a `didInsertElement` hook makes it totally incompatible with the new 'loading slider' feature (because the component is not re-rendered between different topic lists).
This commit updates the logic to be based simply on the count of topics in the list. If there are fewer than 5 topics, the top button is hidden.
Under certain conditions, this `afterRender` hook can be triggered after the topic-list-item has been removed from the DOM. This is more likely when the 'loading slider' strategy is used on a site.
This introduces a PLATFORM_KEY_MODIFIER const that
can be used both client and server side, to determine
whether we should be using the Meta or Ctrl key based
on whether the user is on Windows/Linux or Mac.
Why this change?
A new component based API for modals was introduced in
b3a23bd9d6. This commit moves the edit
sidebar section modal to the new API.
Reviewer notes
No functionality or visual change is introduced in this PR.
In previous PR https://github.com/discourse/discourse/pull/22340 bug was introduced. Notifications were blocked when, even if topic was watched directly. New query is taking TopicUser into consideration.
In addition, in user interface, when `watched_precedence_over_muted` is not set, then value from SiteSetting should be displayed.
This brings the functionality from https://github.com/discourse/discourse-loading-slider into Discourse core. Default behaviour remains the same - the new slider mode can be enabled using the new 'page_loading_indicator' site setting.
A follow-up to 585a2e4e. A couple of tests with the new rich tooltip were flaky.
We suppose the reason is some problem related to widgets lifecycle. This PR
doesn't fix the issue, but isolates testing of the tooltip related logic related
inside its own test, which should make it not flaky.
This is a temporal solution, we're going to move all these code to using
glimmer components.
Previously, the `@model` argument would be unset before the component's `willDestroy` hook was called. Wrapping up the component and the opts in a single tracked `activeModal` field, and then using the `#each` helper with an array of 1 element means that Glimmer will keep the `@model` argument available until the end of the component's lifecycle.
Recently, site setting watched_precedence_over_muted was introduced - https://github.com/discourse/discourse/pull/22252
In this PR, we are allowing users to override it. The option is only displayed when the user has watched categories and muted tags, or vice versa.
What is the problem?
Before this change, we were relying on the `/tags` endpoint which
returned all the tags that are visible to a give user on the site leading to potential performance problems.
The attribute keys of the response also changes based on the `tags_listed_by_group` site setting.
What is the fix?
This commit fixes the problems listed above by creating a dedicate `#list` action in the
`TagsController` to handle the listing of the tags in the edit
navigation menu tags modal. This is because the `TagsController#index`
action was created specifically for the `/tags` route and the response
body does not really map well to what we need. The `TagsController#list`
action added here is also much safer since the response is paginated and
we avoid loading a whole bunch of tags upfront.
What is the problem?
This regressed in fe294ab1a7 and we did
not have any tests on mobile to catch the regression. The problem was
that we were conditionally rendering the edit nav menu modals component
in the sidebar. However, the sidebar is collapsed on mobile when a
button is clicked. When the sidebar collapses, the edit nav menu modals
ended up being destroyed with it.
Why this change?
A new component based API for modals was introduced in
b3a23bd9d6. This commit moves the edit
navigation menu tags and categories modal to the new API.
This allows us to use `getOwner(this)` on widgets (without needing to resort to our custom `discourse-common/lib/get-owner` implementation which has a hacky fallback)
`_self` is the default, so we should treat it the same as having no value specified. This fixes navigation to links like `/my/...` in custom sidebar links.
- Inline mentions on posts
- Inline mentions on chat messages
- The user autocomplete for the composer
- The user autocomplete for chat
- The chat section of the sidebar
Ember 4.x will be removing the 'named outlet' feature, which were previously relying on to render modal 'controllers' and their associated templates. This commit updates the modal.show API to accept a component class, and also introduces a declarative API which can be used by including the <DModal component directly in your template.
For more information on the API design, and conversion instructions from the current API, see these Meta topics:
DModal API: https://meta.discourse.org/t/268304
Conversion: https://meta.discourse.org/t/268057
What is the problem?
Before this change, the edit navigation menu tags modal was not
displaying tags that belonged to a tag_group when the tags_listed_by_group
site setting was set to true. This is because we are relying on the
/tags endpoint which returned tags in various keys depending on the
tags_listed_by_group site setting. When the site setting is set to
true, tags under belonging to tag groups were returned in the
extra.tag_groups attribute.
What is the fix?
This commit fixes it by pushing all tags in returned under the
`tag_groups` attribute into the list of tags to displayed. In a
following commit, we will move away from the `/tags` endpoint to a
dedicated route to handle the listing of tags in the modal.
]When changing fonts in the `/wizard/steps/styling` step of
the wizard, users would not see the font loaded straight away,
having to switch to another one then back to the original to
see the result. This is because we are using canvas to render
the style preview and this fails with a Chrome-based intervention
when font loading is taking too long:
> [Intervention] Slow network is detected. See
https://www.chromestatus.com/feature/5636954674692096 for more details.
Fallback font will be used while loading:
https://sea2.discourse-cdn.com/business7/fonts/Roboto-Bold.ttf?v=0.0.9
We can get around this by manually loading the fonts selected using
the FontFace JS API when the user selects them and before rerendering
the canvas. This just requires preloading more information about the
fonts if the user is admin so the wizard can query this data.
Motivation: aligning us with JS/Ember practices (runtime deps in `dependencies`, build/dev-time deps in `devDependencies`)
1. Move deps to devDeps where applicable (rule of thumb: it's a devDep unless it's required at runtime by the rails app or it's imported in the addon's code)
2. Remove unused dependencies and add missing ones (in addons)
3. Remove empty `repository` fields
4. Move `engines` and `ember` fields to the bottom
This reverts commit d8f0f17b50.
This causes errors when uploading to S3 because we are missing
a getFilesByIds function in core which we have not updated
yet c.f. https://github.com/discourse/discourse/pull/22195
Tests don't catch this because tests only try uploads.json
uploading.
Before this change, links which required full reload because they are not in ember routes like `/my/preferences` or links to docs like `/pub/*` were treated as real external links. Therefore, they were opening in self window or new tab based on user `external_links_in_new_tab` setting.
To be consistent with behavior when full reload links are in the post, they are treated as internal and always open in the same window.
Achieved by running `yarn upgrade --latest` both yarn.lock directories, then reverting changes to package.json files and running `yarn` again.
I also de-duped yarn.lock files with `npx yarn-deduplicate && yarn`
This is the first of a number of PRs aimed at helping admins manage their translation overrides. It simply adds a list of available interpolation keys below the input field when editing an override.
It also includes custom interpolation key.
Why this change?
We are currently not fully satisfied with the current way to edit the
categories and tags that appears in the sidebar where the user is
redirected to the tracking preferences tab in the user's profile causing
the user to lose context of the current page. In addition, the dropdown
to select categories or tags limits the amount of information we can
display.
Since editing or adding a custom categories section is already using a
modal, we have decided to switch editing the categories and tags that
appear in the sidebar to use a modal as well.
This commit removes the `new_edit_sidebar_categories_tags_interface_groups` site setting and
make the modals the default for all users.
Updates the interface for implementing summarization strategies and adds a cache layer to summarize topics once.
The cache stores the final summary and each chunk used to build it, which will be useful when we have to extend or rebuild it.
When the composer is open with a draft for a topic and the user clicks the edit button of a post on the same topic, we shouldn't display the "Save Draft" button. Because the edited post's draft will override the existing draft of the same topic even if we saved it.
Why this change?
We want the position of the filters to remain fixed when scrolling
through the list of categories or tags. Otherwise, the user has to
scroll all the way back to othe top in order to access the filters when
the list of categories or tags is large.
Why does this change do?
If the `fixed_category_positions` is `false`, we want to order the
categories in the edit navigation menu categories modal by name. This
makes it easier to filter through a large list of categories.
This commit also fixes a bug where we were unintentionally mutating the
`this.site.categories` array.
Why is this change required?
The `/new-topic` route is a special route which we use to open the
composer by loading a URL. By default, the `new-topic` route is replaced with the
`discovery.latest` route. On a fresh page load, this makes sense since
there is no template for the `new-topic` route to render. However, this
behavior does not make sense if we're transition from another route.
There is no need to replace the current route with the `discovery.latest` when all we want
is to open the composer.
What does this commit do?
This commit fixes the undesirable behaviour described above by aborting
the existing transition to the `new-topic` route if `transition.from` is
present. This indicates that we're navigating from an existing route and
we can just open the composer.
While still in ember-cli new app blueprint, I don't think this package does much for us. It has support for older things like bower and npm-shrinkwrap, but doesn't support checking yarn.lock and doesn't necessarily work well with our project structure.
This commit adds data attributes to identify the controls in the user settings UI.
Plugins and TCs can use this information to target each setting to highlight or hide
them.
Although most of the settings also have specific classes identifying them, using data
attributes is more future proof as it is less likely to change them classes, specially
as we increase the adoption of the BEM methodology in CSS.
Using data attributes also are semantically correct as the setting name is data not really related to the classes used.
The user card is always present in the DOM. Therefore we only need to
add the `aria-labelledby` attribute when there is a user (and a title)
to point to.
What does this change do?
This change adds a dropdown filter that allows a user to filter by
selected or unselected categories/tags in the edit navigation menu
modal.
For the categories modal, parent categories that do not match the
dropdown filter will be displayed as disabled since those parent
categories need to be displayed to maintain the hieracy of the child
child categories.
Why this change?
There was alot of duplication between the edit navigation menu tags/categories modal which
was making it hard to introduce new changes as the work had to be
duplicated into multiple places.
This commit mainly extracts the duplicated code into common components
such that it is easier to make styling changes across both modals.
This PR splits up the preference that controls the count vs dot and destination of sidebar links, which is really hard to understand, into 2 simpler checkboxes:
The new preferences/checkboxes are off by default, but there are database migrations to switch the old preference to the new ones so that existing users don't have to update their preferences to keep their preferred behavior of sidebar links when this changed is rolled out.
Internal topic: t/103529.
Introduces a new above-latest-topic-list-item-post-count outlet, providing a clean way to add other useful elements to the topic-stats section of the latest-topic-list-item template.
What this change?
When a user opens the modal to edit tags or categories for the
navigation menu, we want to input filter to have focus. This commit
fixes that by doing the following:
1. Changes <DModal> component such that it prioritises elements with the
autofocus attribute first.
2. Adds `autofocus` to the input elements on the edit tags/categories
modal form.
When a site does not have `default_navigation_menu_tags`
site setting set, anonymous users should be shown the site's top tags as
a default in the tags section. However, this regressed in 9fad71809c
and we ended up showing anonymous users a tags section with only the
`All Tags` section link.
As part of this commit, I have also refactored the QUnit acceptance
tests to system tests which are much easier to work with.
What does this change do?
This change adds the deselect all and reset to defaults buttons to the
edit navigation menu tags modal. The deselect all button when
clicked deselects all the selected tags in the modal. If the user
saves with no tags selected, the user's tags section in the
navigation menu will be set to the site's top tags.
The reset to defaults button is only shown when the
`default_navigation_menu_tags` site setting has been configured.
When clicked, the user's tags section in the navigation menu is
automatically set to the tags defined by the
`default_navigation_menu_tags` site setting.
What does this change do?
This change adds a loading spinner to the edit navigation menu tags
modal when the request to fetch all the tags for a site is in progress.
This mainly to improve the user experience such that we indicate that
something is being loaded instead of just displaying a large empty
space.
What are there no tests for this change?
This change is kind of hard to test and since it is mostly a UX change,
we can live with such regressions in the future. It is still bad to
regress UX wise but impact of such a regression is likely to be low.
There is a problem that unread and new count is not updated to reflecting topicTrackingState.
It is because discourseComputed on Category is not working properly with topicTrackingState. Moving it to component level is making counter reliable.
What does this change do?
This commit adds an input filter to filter through the tag checkboxes in the
modal to edit tags that are shown in the user's navigation menu. The
filtering is a simple matching of the given filter term against the
names of the tags.
What does this change do?
This change is a first pass for adding a modal used to edit tags that appears in
the navigation menu. As the feature is being worked on in phases, it is
currently hidden behind the `new_edit_sidebar_categories_tags_interface_groups` site setting.
The following features will be worked on in future commits:
1. Input filter to filter through the tgas
2. Button to reset tag selection to default navigation menu tags site
settings
3. Button to deselect all current selection
When searching in the context of a topic the <kbd>in all topics</kbd> link would not search globally for the given term and instead it would always search within the current topic. This PR fixes the link to properly update the search context and search globally for the given term.
This fix reveals some _secretly_ broken tests. Update these as well.
This commit adds an aria-label attribute to cooked hashtags using
the post/chat message decorateCooked functionality. I have just used
the inner content of the hashtag (the tag/category/channel name) for
the label -- we can reexamine at some point if we want something
different like "Link to dev category" or something, but from what I
can tell things like Twitter don't even have aria-labels for hashtags
so the text would be read out directly.
This commit also refactors any ruby specs checking the HTML of hashtags
to use rspec-html-matchers which is far clearer than having to maintain
the HTML structure in a HEREDOC for comparison, and gives better spec
failures.
c.f. https://meta.discourse.org/t/hashtags-are-getting-a-makeover/248866/23?u=martin
* Revert "Build(deps): Bump message-bus-client from 4.3.2 to 4.3.3 in /app/assets/javascripts (#22194)"
This reverts commit cdcf6cf0dd.
* Revert "Build(deps): Bump message_bus from 4.3.2 to 4.3.3 (#22188)"
This reverts commit c7a9da1f10.
What does this change do?
This change adds the deselect all and reset to defaults buttons to the
edit navigation menu categories modal. The deselect all button when
click deselects all the selected categories in the modal. If the user
saves with no categories selected, the user's categories section in the
navigation menu will be set to the site's top categories.
The reset to defaults button is only shown when the
`default_navigation_menu_categories` site setting has been configured.
When clicked, the user's categories section in the navigation menu is
automatically set to the categories defined by the
`default_navigation_menu_categories` site setting.
Fixes an issue where saving a theme translation would reset unsaved
changes made to other theme translations.
Also cleans up unused `saveSettings` and `saveTranslations` actions.
Co-authored-by: Jarek Radosz <jradosz@gmail.com>
1. `everything` was changed to `topics`
2. Path for my posts translation is `sidebar.sections.community.links.my_posts.content` not `sidebar.sections.community.links.my/posts.content`
The work in fa509224f0 updated our initializer patterns to match modern Ember. This caused the initializer from the (deprecated) ember-export-application-global addon to change its behavior from exporting the ApplicationInstance to exporting the Application. This affects customizations which were using some long-deprecated APIs we had attached to the ApplicationInstance.
This commit removes the deprecated addon, restores the previous ApplicationInstance behavior which we've come to depend on, and adds a test for the expected behavior. It also bumps the `dropFrom` version to make it clear that we do not intend to remove these APIs during this release cycle.
# Top level view
This PR is the first version of converting the search menu and its logic from (deprecated) widgets to glimmer components. The changes are hidden behind a group based feature flag. This will give us the ability to test the new implementation in a production setting before fully committing to the new search menu.
# What has changed
The majority of the logic from the widget implementation has been updated to fit within the context of a glimmer component, but it has not fundamentally changed. Instead of having a single widget - [search-menu.js](https://github.com/discourse/discourse/blob/main/app/assets/javascripts/discourse/app/widgets/search-menu.js) - that built the bulk of the search menu logic, we split the logic into (20+) bite size components. This greatly increases the readability and makes extending a component in the search menu much more straightforward.
That being said, certain pieces needed to be rewritten from scratch as they did not translate from widget -> glimmer, or there was a general code upgraded needed. There are a few of these changes worth noting:
### Search Service
**Search Term** -> In the widget implementation we had a overly complex way of managing the current search term. We tracked the search term across multiple different states (`term`, `opts.term`, `searchData.term`) causing headaches. This PR introduces a single source of truth:
```js
this.search.activeGlobalSearchTerm
```
This tracked value is available anywhere the `search` service is injected. In the case the search term should be needs to be updated you can call
```js
this.search.activeGlobalSearchTerm = "foo"
```
**event listeners** -> In the widget implementation we defined event listeners **only** on the search input to handle things such as
- keyboard navigation / shortcuts
- closing the search menu
- performing a search with "enter"
Having this in one place caused a lot of bloat in our logic as we had to handle multiple different cases in one location. Do _x_ if it is this element, but do _y_ if it is another. This PR updates the event listeners to be attached to individual components, allowing for a more fine tuned set of actions per element. To not duplicate logic across multiple components, we have condensed shared logic to actions on the search service to be reused. For example - `this.search.handleArrowUpOrDown` - to handle keyboard navigation.
### Search Context
We have unique logic based on the current search context (topic / tag / category / user / etc). This context is set within a models route file. We have updated the search service with a tracked value `searchContext` that can be utilized and updated from any component where the search service is injected.
```js
# before
this.searchService.set("searchContext", user.searchContext);
# after
this.searchService.searchContext = user.searchContext;
```
# Views
<img width="434" alt="Screenshot 2023-06-15 at 11 01 01 AM" src="https://github.com/discourse/discourse/assets/50783505/ef57e8e6-4e7b-4ba0-a770-8f2ed6310569">
<img width="418" alt="Screenshot 2023-06-15 at 11 04 11 AM" src="https://github.com/discourse/discourse/assets/50783505/2c1e0b38-d12c-4339-a1d5-04f0c1932b08">
<img width="413" alt="Screenshot 2023-06-15 at 11 04 34 AM" src="https://github.com/discourse/discourse/assets/50783505/b871d164-88cb-405e-9b78-d326a6f63686">
<img width="419" alt="Screenshot 2023-06-15 at 11 07 51 AM" src="https://github.com/discourse/discourse/assets/50783505/c7309a19-f541-47f4-94ef-10fa65658d8c">
<img width="424" alt="Screenshot 2023-06-15 at 11 04 48 AM" src="https://github.com/discourse/discourse/assets/50783505/f3dba06e-b029-431c-b3d0-36727b9e6dce">
<img width="415" alt="Screenshot 2023-06-15 at 11 08 57 AM" src="https://github.com/discourse/discourse/assets/50783505/ad4e7250-040c-4d06-bf06-99652f4c7b7c">
- FIX: improves reactions and thread indicator touch event on mobile
These "buttons" are located inside a scroll list which makes them very specific. The general idea is to ensure these events are passive and are not bubbling to the parent.
- DEV: moves state on top level message node
- FIX: ensures popover arrow has the correct border
- FIX: makes a message expanded by default
- FIX applies the same ios scroll fix on thread and channel
- UI: better active/hover state for thread indicator
- UI: attempts to follow more closely our BEM naming scheme
- FIX: reduces bottom padding on message with thread indicator and user info hidden
- UI: add padding for first message in thread
- FIX: prevents actions backdrop to open thread
- UI: makes thread indicator resizable
This commit adds a tracking dropdown to each individual thread, similar to topics,
that allows the user to change the notification level for a thread manually. Previously
the user had to reply to a thread to track it and see unread indicators.
Since the user can now manually track threads, the thread index has also been changed
to only show threads that the user is a member of, rather than threads that they had sent
messages in.
Unread indicators also respect the notification level -- Normal level thread tracking
will not show unread indicators in the UI when new messages are sent in the thread.
What this change?
Previous solution relied on CSS to hide the header which is first
wasteful since we're still rendering the header and second makes it
untestable. If we don't want the header to show, we should avoid
rendering it in the first place.
Why is this change required?
When a site is newly setup and a user has just been created, the
categories and tags sections are hidden from the user. This happens
because the admin has not configured the `default_navigation_menu_categories` or
`default_navigation_menu_tags` site settings. When the categories and tags
sections are hidden from the user, the sidebar looks extremely bare and
does not create a good experience.
What is being change?
In this commit, we're changing the logic such that the site's top
categories and tags are displayed if the user does not have any
categories/tags configured in each respective section. The only
regression introduced in this change is that the categories and tags
section can no longer be hidden as a result. However, we have plans to
address this in the future by allowing sidebar sections to be configured
to be hidden by each individual user.
https://meta.discourse.org/t/updating-our-initializer-naming-patterns/241919
For historical reasons, Discourse has different initializers conventions than standard Ember:
```
| Ember | Discourse | |
| initializers | pre-initializers | runs once per app load |
| instance-initializers | (api-)initializers | runs once per app boot |
```
In addition, the arguments to the initialize function is different – Ember initializers get either the `Application` or `ApplicationInstance` as the only argument, but the "Discourse style" gets an extra container argument preceding that.
This is confusing, but it also causes problems with Ember addons, which expects the standard naming and argument conventions:
1. Typically, V1 addons will define their (app, instance) initializers in the `addon/(instance-)initializers/*`, which appears as `ember-some-addon-package-name/(instance-)initializers/*` in the require registry.
2. Just having those modules defined isn't supposed to do anything, so typically they also re-export them in `app/(instance-)initializers/*`, which gets merged into `discourse/(instance-)initializers/*` in the require registry.
3. The `ember-cli-load-initializers` package supplies a function called `loadInitializers`, which typically gets called in `app.js` to load the initializers according to the conventions above. Since we don't follow the same conventions, we can't use this function and instead have custom code in `app.js`, loosely based on official version but attempts to account for the different conventions.
The custom code that loads initializers is written with Discourse core and plug-ins/themes in mind, but does not take into account the fact that addons can also bring initializers, which causes the following problems:
* It does not check for the `discourse/` module prefix, so initializers in the `addon/` folders (point 1 above) get picked up as well. This means the initializer code is probably registered twice (once from the `addon/` folder, once from the `app/` re-export). This either causes a dev mode assertion (if they have the same name) or causes the code to run twice (if they have different names somehow).
* In modern Ember blueprints, it is customary to omit the `"name"` of the initializer since `ember-cli-load-initializers` can infer it from the module name. Our custom code does not do this and causes a dev mode assertion instead.
* It runs what then addon intends to be application initializers as instance initializers due to the naming difference. There is at least one known case of this where the `ember-export-application-global` application initialize is currently incorrectly registered as an instance initializer. (It happens to not use the `/addon` folder convention and explicitly names the initializer, so it does not trigger the previous error scenarios.)
* It runs the initializers with the wrong arguments. If all the addon initializer does is lookup stuff from the container, it happens to work, otherwise... ???
* It does not check for the `/instance-initializers/` module path so any instance initializers introduced by addons are silently ignored.
These issues were discovered when trying to install an addon that brings an application initializer in #22023.
To resolve these issues, this commit:
* Migrates Discourse core to use the standard Ember conventions – both in the naming and the arguments of the initialize function
* Updates the custom code for loading initializers:
* For Discourse core, it essentially does the same thing as `ember-cli-load-initializers`
* For plugins and themes, it preserves the existing Discourse conventions and semantics (to be revisited at a later time)
This ensures that going forward, Ember addons will function correctly.
Communities can use sidebar or header dropdown, therefore navigation menu is a better name settings in 2 places:
- Old user sidebar preferences;
- Site setting about default tags and categories.
* FEATURE: Content custom summarization strategies.
This PR establishes a pattern for plugins to register alternative ways of summarizing content by extending a class that defines an interface.
Core controls which strategy we'll use and who has access to it through the `summarization_strategy` and `custom_summarization_allowed_groups`. It also defines the UI for summarizing topics.
Other plugins can access this summarization mechanism and implement their features, removing cross-plugin customizations, as it currently happens between chat and the discourse-ai plugin.
* Group membership validation and rate limiting
* Work with objects instead of classes
* Port summarization feature from discourse-ai to chat
* Rename available summaries to 'Top Replies' and 'Summary'
When we introduced unicode support in the regular expressions used in watched words (9a27803) we didn't realize the cost adding the `u` flag would be.
Turns out, it's pretty bad when you have lots of regular expressions to test. A customer had slightly less than 200 watched words, and it would freeze the browser for about 2s on the first check of those regular expressions (roughly 10ms per regular expression).
This commit introduces a new field (`word`) to the serialized watched words which is then converted to a very fast and cheap regular expression on the client-side. We use that regexp to quicly check whether a matcher is even worth trying so that we don't incure the cost of compiling the expensive unicode regexp.
This commit also busts the `WordWatcher` cache since we added a new field to be serialized.
One nice side effect of using `matchAll` instead of a `while / exec` loop is that the likeliness of having a bad regexp matching infinitely is vastly reduced 🙌
Improves the layout of most grids in posts, by using `object-fit: cover` for most images. This allows images to better fill up the space, without changing their aspect ratio.
Clicking on TOC heading anchors in a subfolder setup was breaking the current URL for users.
Other than the fix this change introduces the ability to test the subfolder setup in system specs.
1. ember proxy stuff still isn't in a great shape, live-reload doesn't work yet, uploads made w/o subfolder won't work, custom fonts don't work, service worker doesn't work. But otherwise it's fine :P
2. I don't know why `HTTP_IF_MODIFIED_SINCE` can be an empty string. Don't have time to investigate, and fast_blank makes this fix an easy solution ;)
When we get to really big files, it's better to not have thousands
of small chunks, since we don't have a resume functionality if the
upload fails. Better to try upload less chunks even if those chunks
are bigger.
For example, with this change a 20GB file would go from 4000 chunks
of the default 5mb to 1000 chunks of the new 20mb size. Still a lot,
but perhaps more manageable.
This is somewhat experimental -- if we still don't see improvements
we can always change back.
Why this change?
Currently, we're interpolating within a string to set the class for the
`DButton` component. However, the interpolation and formatting of our
handlebars templates result in unnecessary spaces being added to the
class attribute.
```
<button class="sidebar-section-header sidebar-section-header-collapsable btn-flat
btn
no-text
" aria-controls="sidebar-section-content-categories" aria-expanded="true" title="Toggle section" type="button">
...
</button>
```
This makes the HTML elements for buttons hard to read especially when
we're debugging issues in the console. After this change, this is what
we get:
```
<button class="sidebar-section-header sidebar-section-header-collapsable btn-flat btn no-text" aria-controls="sidebar-section-content-categories" aria-expanded="true" title="Toggle section" type="button">
...
</button>
```
Previously workbox JS was vendored into our git repository, and would be loaded from the `public/javascripts` directory with a 1 day cache lifetime. The main aim of this commit is to add 'cachebuster' to the workbox URL so that the cache lifetime can be increased.
- Remove vendored copies of workbox.
- Use ember-cli/broccoli to collect workbox files from node_modules into assets/workbox-{digest}
- Add assets to sprockets manifest so that they're collected from the ember-cli output directory (and uploaded to s3 when configured)
Some of the sprockets-related changes in this commit are not ideal, but we hope to remove sprockets in the not-too-distant future.
These spec are flaky only in CI, not locally and not in GitHub actions.
The previous attempt was in 44eabde, but actually the failure happens
a bit earlier. This is another attempt to fix these specs. Quite a lot of
async logic is happening in emulateAutocomplete(), a call to settled()
in the end should help make it more reliable.
What does this change do?
This change is a continuation of
2191b879c6 and adds an input filter to the
edit sidebar categories modal which the user can use to filter through
the list of categories by the category's name.
Note that if a child category is being shown, all of its ancestors will
be shown even if the names of the ancestors do not match the given
filter. This is to ensure that we continue to display the hierarchy of a
child category even if the parent category does not match the filter.
Why does this commit do?
This commit adds support for sub-subcategories in the new edit sidebar
categories modal added in fc296b9a81. Note
that sub-subcategories are enabled when `max_category_nesting` is set to
`3`.
Adds a new `[grid]` tag that can arrange images (or other media) into a grid in posts.
The grid defaults to a 3-column with a few exceptions:
- if there are only 2 or 4 items, it defaults to a 2-column grid (because it generally looks better)
- on mobile, it defaults to a 2-column grid
- if there is only one item, the grid has no effect
This removes the modal container named-outlet/controller/template and replaces it with a component. Named outlets will be removed in Ember 4.x, so this change is part of that upgrade project.
Smaller changes include:
- update some of the computed values to be getters rather than calculated during `show()`.
- update tests which were previously depending on the modal class persisting after the modal was closed
Much of the logic in the service will be deprecated once we introduce component-based modals.
This work is split out from https://github.com/discourse/discourse/pull/21304
Previously merged in 80b77b2e and then reverted due to issues with the PM invite modal. This PR fixes the issue, and introduces a test which would have caught the issue.
Why is this change required?
Right now, we're awaiting on the promise returned by
`this.pmTopicTrackingState.startTracking()` which blocks the rendering
of the template until the promise resolves. However, this blocking of
the rendering ends up introducing yet another intermediate loading state
in the UI which we find unsightly. Instead of blocking the rendering, we
allow the promise to resolve in the background and display the
new/unread counts when the promise resolves.
What this change?
We are currently not fully satisfied with the current way to edit the
categories and tags that appears in the sidebar where the user is
redirected to the tracking preferences tab in the user's profile causing
the user to lose context of the current page. In addition, the dropdown
to select categories or tags limits the amount of information we can
display.
Since editing or adding a custom categories section is already using a
modal, we have decided to switch editing the categories and tags that
appear in the sidebar to use a modal as well.
This commit ships a first pass of the edit categories modal such that we
can keep the commit small and reviewable. The incomplete nature of the
feature is also reflected in the fact that the feature is hidden behind
a new `new_edit_sidebar_categories_tags_interface_groups` site setting.
One user can create a post or chat message with a hashtag they
have permission to use, but then when other users look at that
post they will see an empty space next to the hashtag because they
do not have the permission to load the colors in CSS classes for
the related category.
This fixes the issue by adding a default color with a special
CSS class if the user doesn't have permission to see the linked
channel/category on the hashtag.
Display modal for combined new and unread view with options:
- [x] Dismiss new topics
- [x] Dismiss new posts
- [ ] Stop tracking these topics so they stop appearing in my new list
Previously, the topic is pinned/unpinned even when the bookmark icon is pressed in the topic list page. Because we didn't check the class names of topic status icons.
What is this change required?
The `enable_offline_indicator` site setting is disabled by default so
there is no need for us to be rendering an extra Ember component when
the site setting is not enabled.
Why this change?
Before this change, the `GroupNotificationsButton` is rendered in the
template of `userPrivateMessages` route based on a conditional that
checks if the `isGroup` property is true. However, the `isGroup`
property is determined based on the child route that is rendered.
However, this leads to "jankiness" in the UI because the
`GroupNotificationsButton` will be rendered once the route is entered
even if the model for the child route has not been resolved yet.
What is the solution?
In order to avoid this, we move the rendering of the
`GroupNotificationsButton` into the template of the
`userPrivateMessages.group` route and rely on the `in-element` helper to
render it into the right spot in the template of the
`userPrivateMessages` route.
This removes the modal container named-outlet/controller/template and replaces it with a component. Named outlets will be removed in Ember 4.x, so this change is part of that upgrade project.
Smaller changes include:
- update some of the computed values to be getters rather than calculated during `show()`.
- update tests which were previously depending on the modal class persisting after the modal was closed
Much of the logic in the service will be deprecated once we introduce component-based modals.
This work is split out from https://github.com/discourse/discourse/pull/21304
Why does this change do?
This commit updates the educate message displayed when there are no new
topics on the `/new` route when the experimental new new view site setting is enabled.
The commit also fixes a couple of bugs:
1. Correct default auto track minutes used in the copy for unread
topics from the 4 minutes to 5 minutes.
2. Correct link to user's preference in copy to go to tracking tab
instead of notifications tab.
Before, the review button was shown in `primary section` when there were items to review. Otherwise, it was hidden in `more section`.
Because we are allowing admins to customize community section and reorder link, it makes sense to simplify that logic and review link should follow admin's decision.
What is the problem?
When opening the composer, we are seeing multiple requests made to
the `/composer_messages` endpoint. This is due to our use of the
`transitionend` event on the `#reply-control` element. The event is
fired once for each transition event and the `#reply-control` element
has multiple transition events.
What is the solution?
Since are only interested in the `height` transition event, we add a
condition to check that the callback function is only triggered when the
`propertyName` of the `transitionend` event is `height`.
Why is there no tests for this change?
In QUnit, we have `transition: none !important` set in the stylesheet
with no easy way to disable. We'll have to accept the risk of not
writing test for this performance fix.
Meta topic: https://meta.discourse.org/t/mention-suggestion-list-box-in-the-rtl-website-in-wrong-place/266763?u=osama.
Our autocomplete box doesn't currently take into account the user's locale and places itself off-screen when using an RTL locale. This commit changes the placement logic for the autocomplete box when an RTL locale is used to make sure that:
1. the autocomplete box's right side is near and to the left of the caret
2. the autocomplete box doesn't go beyond the composer's left side.
* FEATURE: reduce avatar sizes to 6 from 20
This PR introduces 3 changes:
1. SiteSetting.avatar_sizes, now does what is says on the tin.
previously it would introduce a large number of extra sizes, to allow for
various DPIs. Instead we now trust the admin with the size list.
2. When `avatar_sizes` changes, we ensure consistency and remove resized
avatars that are not longer allowed per site setting. This happens on the
12 hourly job and limited out of the box to 20k cleanups per cycle, given
this may reach out to AWS 20k times to remove things.
3.Our default avatar sizes are now "24|48|72|96|144|288" these sizes were
very specifically picked to limit amount of bluriness introduced by webkit.
Our avatars are already blurry due to 1px border, so this corrects old blur.
This change heavily reduces storage required by forums which simplifies
site moves and more.
Co-authored-by: David Taylor <david@taylorhq.com>
What is the problem?
There are two problems being fixed here:
1. When opening the composer, we are seeing multiple requests made to
the `/composer_messages` endpoint. This is due to our use of the
`transitionend` event on the `#reply-control` element. The event is
fired once for each transition event and the `#reply-control` element
has multiple transition events.
2. System tests have animations disabled so the `transitionend` event
does not fire at all.
What is the solution?
Instead of relying on the `transitionend` event, we can instead just
observer the `composerState` property of the `ComposerBody` component
and trigger the `composer:opened` appEvent with a delay that is similar
to the transition duration used for the `ComposerBody` component.
We were calling reset without the proper params which was causing errors in the console. This commit does the following changes:
- ensures `composer.cancel()` is the only way to cancel editing/reply
- adds a `draftSaved` property to chat message to allow for better tests
- writes a spec to ensure the flow is correct
- adds more page objects for better tests
- homogenize the default state of objects on chat message
Co-authored-by: Martin Brennan <martin@discourse.org>
Privacy Policy and Terms of Service topics are no longer created by
default for communities that have not set a company name. For this
reason, some URLs were pointing to 404 page.
Allow admins to edit Community section. This includes drag and drop reorder, change names, delete and reset to default.
Visual improvements introduced in edit community section modal are available in edit custom section form as well. For example:
- drag and drop links to change their position;
- smaller icon picker.
Why is this change required?
The flaky system test was due to the fact that we had to poll for the
user preferences interface page to reload after saving. However, this
turns out to be a bug on the user perferences interface page because the
page should only reload if the user has selected a new theme that is
different from the site's default but we were reloading the page for
users that did not have any user theme selected. Therefore there was an
unnecessary reload happening when saving other fields on the user
preferences interface page.
New headless shares the same implementation as the chrome browser
instead of being a separate implementation of its own.
See https://developer.chrome.com/articles/new-headless/ for more
details
Co-authored-by: Rafael dos Santos Silva <xfalcox@gmail.com>
Why are we making this change?
Currently, we are displaying the value of the `short_site_description`
site setting in the sidebar only for anonymous user. However, the
display of the description seems out of place in both the `sidebar` and
`header dropdown` navigation menu and do not think the sidebar is the
right place to display it anymore.
When a user chooses to move a topic/message to an existing topic/message, they can now opt to merge the posts chronologically (using a checkbox in the UI).
This brings the behaviour in line with our other widget-related APIs like `decorateWidget` and `reopenWidget`. This commit also adds a theme/plugin prefix to the console messages.
For now, state is still stored in the modal controller. Eventually the controller will be replaced with a component, and the state will be stored in the service.
(extracted from https://github.com/discourse/discourse/pull/21304)
What is this change required?
I noticed that actions in `SidebarSectionsController` resulted in
lots of N+1 queries problem and I wanted a solution to
prevent such problems without having to write N+1 queries tests. I have
also used strict loading for `SidebarSection` queries in performance
sensitive spots.
Note that in this commit, I have also set `config.active_record.action_on_strict_loading_violation = :log`
for the production environment so that we have more visibility of
potential N+1 queries problem in the logs. In development and test
environment, we're sticking with the default of raising an error.
Legal topics, such as the Terms of Service and Privacy Policy topics
do not make sense if the entity creating the community is not a company.
These topics will be created and updated only when the company name is
present and deleted when it is not.