With the refactoring of the user messages routes in
4da2e3fef4, we can now depend on the top
level routes like `userPrivateMessages.user`, `userPrivateMessages.group` and `userPrivateMessages.tags`
to determine what the active value for the dropdown should be which
greatly simplifies the logic.
In an effort to modernize our codebase to the latest Ember version we have selected the Topic Timeline as a candidate to be refactored. The topic timeline component was originally built with `Widgets` and this PR will upgrade it to `Glimmer Components`.
The refactored timeline is hidden by default behind a group flag, `SiteSetting.enable_experimental_topic_timeline_groups`. Being part of a group included in this site setting will make the new timeline available for testing.
## Other points of interest
This PR introduces a `Draggable Modifier` available to all components, which will take the place of the existing _drag functionality_ exclusive to widgets.
It can be included like so:
```
{{draggable didStartDrag=@didStartDrag didEndDrag=@didEndDrag dragMove=@dragMove }}
```
Currently this is how the navigation structure looks like on the messages page:
#### When personal inbox route is active
```
Inbox
sent
new
unread
archive
Group 1 Inbox
Group 2 Inbox
Tags
<Plugin Outlet>
```
#### When group inbox route is active
```
Inbox
Group 1 Inbox
sent
new
unread
archive
Group 2 Inbox
Tags
<Plugin Outlet>
```
With the existing structure, it is very easy for plugins to add additional navigation links by using the plugin outlet. In the redesigned user page navigation, the navigation structure on the messages page has been changed to look like this:
#### When personal inbox route is active
```
---dropdown-------
| Inbox | Latest | Sent | New | Unread | Archive
------------------
```
#### When group inbox route is active
```
---dropdown------
| Group 1 Inbox | Latest | New | Unread | Archive
-----------------
```
With the new navigation structure, we can no longer rely on a simple plugin outlet to extend the navigation structure. Instead, we will need to introduce a plugin API for plugins to extend the navigation structure. The API needs to allow two things to happen:
1. The plugin API needs to allow the plugin to register an item in the drop down and for the registered item to be "selected" whenever the plugin's routes are active.
1. The plugin API needs to allow the plugin to register items into the secondary horizontal navigation menu beside the drop down.
While trying to design the API, I struggle with trying to determine the "context" of the current route. In order words, it was hard to figure out if the current user is viewing the personal inbox, group inbox or tags. This is attributed to the fact that our current routing structure looks like this:
```
this.route(
"userPrivateMessages",
{ path: "/messages", resetNamespace: true },
function () {
this.route("new");
this.route("unread");
this.route("archive");
this.route("sent");
this.route("warnings");
this.route("group", { path: "group/:name" });
this.route("groupArchive", { path: "group/:name/archive" });
this.route("groupNew", { path: "group/:name/new" });
this.route("groupUnread", { path: "group/:name/unread" });
this.route("tags");
this.route("tagsShow", { path: "tags/:id" });
}
);
```
In order to provide context of the current route, we currently require all child routes under the `userPrivateMessages` route to set a `pmView` property on the `userPrivateMessages` controller. If the route requires additional context like the group currently active on the group inbox routes, the child routes would then have to set the `group` property on the `userPrivateMessages` controller. The problems with this approach is that we end up with many permutations of state on the `userPrivateMessages` controller and have to always clean up the state when navigating between the child routes. Basically, data is flowing upwards from the child routes into the parent controller which is not an ideal approach because we cannot easily determine where the "data" setup happens. Instead, we want to follow something similar to the "Data down, actions up" pattern where data flows downwards. In this commit, the `userPrivateMessages` routes have been changed to look like this:
```
this.route(
"userPrivateMessages",
{ path: "/messages", resetNamespace: true },
function () {
this.route("user", { path: "/" }, function () {
this.route("new");
this.route("unread");
this.route("archive");
this.route("sent");
this.route("warnings");
});
this.route("group", { path: "group/:name" }, function () {
this.route("archive");
this.route("new");
this.route("unread");
});
this.route("tags", { path: "/tags" }, function () {
this.route("show", { path: ":id" });
});
}
);
```
Basically, we group the child routes based on the purpose each route servers. User inbox routes are grouped together while group inbox routes are grouped together. A big benefit of this is that now have a different Ember router and controller for each grouping of child routes. The context of the current route is then tied directly to the route name instead of requiring each child route to set an attribute on the parent controller.
The second reason for why we needed to group the child routes together is because it allows us to pass the responsibility of rendering the secondary navigation links to the child routes. In this commit, we use the `{{in-element}}` modifier in the child route to render the secondary navigation links.
```
---dropdown--------
| Group 1 Inbox | Latest | New | Unread | Archive
------------------------
<parent template> <horizontal secondary navigation links element>
```
This means that each child route with its own model and context can then handle the responsibility of rendering the secondary navigation links without having to pass its context up to the `userPrivateMessages` controller. While this should have simplified by the `userPrivateMessages` controller, we can't do that in this commit because our current navigation structure requires all links for all message inboxes to remain on screen at all times. Once we fully transition to the redesigned user menu navigation, we will be able to greatly simplify things around the routes and controllers for `userPrivateMessages`.
In an ideal world, we would deprecate the old routes but I have done a quick search through all known plugins and no plugins are currently relying on those routes. There is a chance we could break plugins here but I'll like to see some smoke first before committing to the effort of deprecating client side routes.
Users who can access the review queue can claim a pending reviewable(s) which means that the claimed reviewable(s) can only be handled by the user who claimed it. Currently, we show claimed reviewables in the user menu, but this can be annoying for other reviewers because they can't do anything about a reviewable claimed by someone. So this PR makes sure that we only show in the user menu reviewables that are claimed by nobody or claimed by the current user.
Internal topic: t/77235.
This PR adds separate notification indicators for PMs and reviewables that have arrived since the last time the user opened the notifications menu.
The PM indicator is the strongest one of all three indicators followed by the reviewable indicator and then finally the blue indicator. This means that if there's a new PM and a new reviewable, then the PM indicator will be shown.
Meta topic: https://meta.discourse.org/t/no-green-or-red-notification-bubbles/242783?u=osama.
Internal topic: t/82995.
Fixes broken behaviour of arrow buttons for certain users as the interval to scroll menu can be cancelled before the scrolling actually happens.
Co-authored-by: Joffrey JAFFEUX <j.jaffeux@gmail.com>
regression commit: bec76f937c
In case when the user navigates away between async actions that code would error out on a missing element. This adds a simple sanity check.
`ember-cached-decorator-polyfill` uses a Babel transformation to apply this polyfill in core. Adding that Babel transformation to themes and plugins will be complex, so we use this to patch it at runtime. This can be removed once `@glimmer/tracking` is updated to a version
with native `@cached` support.
1. "What Goes Up Must Come Down" – if you subscribe to message bus, make sure you also unsubscribe
2. When you unsubscribe - remove only your subscription, not **all** subscriptions on given channel
`Route#render` and `Route#renderTemplate` have been deprecated and are removed in Ember 4.x (see: https://deprecations.emberjs.com/v3.x#toc_route-render-template)
The templates of modified routes in this PR are already automatically inserted into `{{outlet}}`s.
To theme/plugin developers, the process is the same as for overriding non-colocated component templates. Once merged, this should allow us to seamlessly convert all of core's component templates to be colocated.
The akismet plugin defines the `reviewable-akismet-post` component using a template under `discourse/templates/components/reviewable-akismet-post.hbs` without an associated `.js` file. The change to our resolution logic in c1397670 wasn't considering this.
It used to fail without displaying an error message if no upload
extensions were authorized. This also disables the button in the
first place to avoid displaying an error to the user (the error
will be displayed only when drag and dropping a file).
In the past, the result of template compilation would be stored directly in `Ember.TEMPLATES`. Following the move to more modern ember-cli-based compilation, templates are now compiled to es6 modules. To handle forward/backwards compatibility during these changes we had logic in `discourse-boot` which would extract templates from the es6 modules and store them into the legacy-style `Ember.TEMPLATES` object.
This commit removes that shim, and updates our resolver to fetch templates directly from es6 modules. This is closer to how 'vanilla' Ember handles template resolution. We still have a lot of discourse-specific logic, but now it is centralised in one location and should be easier to understand and normalize in future.
This commit should not introduce any behaviour change.
This change only affects the redesign user page navigation menu. The
dismiss button was incorrectly positioned below the user notifications
stream. A side effect of this is that it affected our infinite loading
code for the notifications stream.
No tests have been added in this commit as we have yet to quite figure
out how we can reliabily test for behaviours which requires us to scroll
the page.
Back when we introduced hashtag autocomplete in
c1dbf5c1c4 we had to
disallow triggering it using # at the start of the
line because our old markdown engine rendered headers
with `#abc`, but now our new engine does `# abc` so
it is safe to allow hashtag autocompletion straight
away.
When a client "reads" a post, we do no immediately send the data of the
post for processing on the server. Instead, read posts data is batched
together and sent to the server for processing at regular intervals. On
the server side, processing of read posts data is done in the
background. As such, there is a small window of delay before a post is
marked as read by a user on the server side.
If a client reads a topic and loads the messages topic list before the
server has processed the read post, the unread posts count for the topic
which the client just read will appear to be incorrect/outdated.
As part of tracking a post as read, we are already tracking the highest
read post number for the last read topic by the client. Therefore, we
can use this information to correct the highest post read number in the
scenario that was described above. This solution is the same as what
we've been doing for the regular topics list.
We were re-patching the deprecated bootbox methods during every app initialization, which would lead to hundreds of deprecation messages being printed for a single invocation.
When sidebar was enabled before going to narrow screen, it should be brought back when screen is enlarged.
Also, narrow screen value is changed to 1000px instead of 1100px.
- better handling of drawer state using chat state manager
- removes various float and topic occurrences to use drawer
- ensures user can chat before doing a lot of chat setup
- fixes a bug which was creating presence errors in tests
- removes dead code
The `decodedMap` prop comes from https://github.com/terser/terser/pull/1190
> This also exposes a new `decodedMap` property on the result object. Decoded maps are free to create (it's a shallow clone of the `GenMapping` instance), and passing them to `@jridgewell/trace-mapping` is copy-free. With Babel [recently](https://github.com/babel/babel/pull/14497) adding a `decodedMap` field, a dev could pass from the Babel transpilation to Terser without any added memory use for sourcemaps.
Opening of links in a new tab was difficult because it used a hack to
remove the 'href' attribute and adding it back to prevent the event
taking place instead of calling preventDefault.
This hack is no longer necessary because event handling has been
normalized since it has been implemented (see commit
0221855ba7).
Some plugins store their connectors under `{plugin}/assets/javascripts/templates/connectors`, which is read as `templates/connectors` relative to the base of the JS directory. Our connector checking logic was looking for strings including the leading slash (`/templates`), which not be the case here. Instead we can split on `/` and take the last element. This matches the logic we have for themes in https://github.com/discourse/discourse/blob/1dadf4381f/lib/theme_javascript_compiler.rb#L111
This wasn't actually breaking anything, so this is just a housekeeping commit.
In 1279966f we started namespacing modules based on the plugin's defined name rather than the directory name. This commit updates the argument name to match what we're passing in. This it just a readability change - there is no change in behaviour.
Adds the description as a title="" attribute on the hashtag
autocomplete search items for tags, categories, and channels.
These descriptions can be seen by the user since they are
able to see the results that are returned by the search via
Guardian checks.
This makes it so the new hashtags are not tracked,
same as the old ones. Also slight commenting in click-track
to explain mention clicks rejection mechanics.
Also deleted the single acceptance spec
since everything is covered better by the unit spec.
This commit unescapes the :emoji: and expands into
an image within hashtag autocomplete results, and
also makes some style tweaks to make sure the emoji
is not too big.
This fix changes the hashtag-raw hashtags, which are
the ones that do not actually match anything, back
to the old style which does not look like mentions.
The user attributes are not updated between clients and that is a
problem with user tips because the same user tip will be displayed
multiple times, once for every client.
Update `release_notes_link` to the current version.
<!-- NOTE: All pull requests should have tests (rspec in Ruby, qunit in
JavaScript). If your code does not include test coverage, please include
an explanation of why it was omitted. -->
This will be used by plugins to handle the client side of their custom
post validations without having to overwrite the whole composer save
action as it was done in other plugins.
Co-authored-by: Penar Musaraj <pmusaraj@gmail.com>
Our `triggerAction` backwards-compatibility was firing the action on
`parentView`. In most cases this worked, but it doesn't match the
classic behaviour when the DButton is included inside a 'wrapper'
component. In that case, the action should be triggered on the current
'this' context of the template that called the DButton.
This commit mimics the Ember Classic Component manager's behaviour. It
adds the `createCaller` capability to the custom component manager, and
then uses the `callerSelfRef` for dispatching the action.
We automatically refresh the page 'on the next navigation' whenever a
new version of the JS client is available. If the composer is open when
this happens then it will be closed and you'll have to reopen the draft.
In some circumstances, this refresh can also cause some composer content
to be lost.
This commit updates the auto-refresh logic so that it doesn't trigger
while the composer is open, and adds an acceptance test for the
behaviour.
<!-- NOTE: All pull requests should have tests (rspec in Ruby, qunit in
JavaScript). If your code does not include test coverage, please include
an explanation of why it was omitted. -->
Product has decided that the tracked section link provides very little
value at this moment in time so we're removing it.
See https://meta.discourse.org/t/245374 for more context.
The user preferences tracking page is only present when the redesign
user navigation menu is enabled. During the first pass of
implementation, some old bugs were introduced and this commit fixes
that. Regression tests have also been added.
Follow up from d3f02a1270
This commit fixes post quoting so that if the new
hashtag-cooked HTML is selected, we convert back to
a regular plain text #hashtag with the correct type and ref.
Bumps [jsdom](https://github.com/jsdom/jsdom) from 20.0.2 to 20.0.3.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/jsdom/jsdom/releases">jsdom's
releases</a>.</em></p>
<blockquote>
<h2>Version 20.0.3</h2>
<ul>
<li>Updated dependencies, notably <code>w3c-xmlserializer</code>, which
fixes using <code>DOMParser</code> on XML documents containing
emoji.</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/jsdom/jsdom/blob/master/Changelog.md">jsdom's
changelog</a>.</em></p>
<blockquote>
<h2>20.0.3</h2>
<ul>
<li>Updated dependencies, notably <code>w3c-xmlserializer</code>, which
fixes using <code>DOMParser</code> on XML documents containing
emoji.</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="22f7c3c518"><code>22f7c3c</code></a>
Version 20.0.3</li>
<li><a
href="c540630669"><code>c540630</code></a>
Update dependencies and dev dependencies</li>
<li><a
href="cdf07a1f0e"><code>cdf07a1</code></a>
Slight tweaks to GitHub Actions</li>
<li><a
href="bd77578169"><code>bd77578</code></a>
Try to make the issue template clearer</li>
<li>See full diff in <a
href="https://github.com/jsdom/jsdom/compare/20.0.2...20.0.3">compare
view</a></li>
</ul>
</details>
<br />
[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=jsdom&package-manager=npm_and_yarn&previous-version=20.0.2&new-version=20.0.3)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)
Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.
[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)
---
<details>
<summary>Dependabot commands and options</summary>
<br />
You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
</details>
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
This commit fleshes out and adds functionality for the new `#hashtag` search and
lookup system, still hidden behind the `enable_experimental_hashtag_autocomplete`
feature flag.
**Serverside**
We have two plugin API registration methods that are used to define data sources
(`register_hashtag_data_source`) and hashtag result type priorities depending on
the context (`register_hashtag_type_in_context`). Reading the comments in plugin.rb
should make it clear what these are doing. Reading the `HashtagAutocompleteService`
in full will likely help a lot as well.
Each data source is responsible for providing its own **lookup** and **search**
method that returns hashtag results based on the arguments provided. For example,
the category hashtag data source has to take into account parent categories and
how they relate, and each data source has to define their own icon to use for the
hashtag, and so on.
The `Site` serializer has two new attributes that source data from `HashtagAutocompleteService`.
There is `hashtag_icons` that is just a simple array of all the different icons that
can be used for allowlisting in our markdown pipeline, and there is `hashtag_context_configurations`
that is used to store the type priority orders for each registered context.
When sending emails, we cannot render the SVG icons for hashtags, so
we need to change the HTML hashtags to the normal `#hashtag` text.
**Markdown**
The `hashtag-autocomplete.js` file is where I have added the new `hashtag-autocomplete`
markdown rule, and like all of our rules this is used to cook the raw text on both the clientside
and on the serverside using MiniRacer. Only on the server side do we actually reach out to
the database with the `hashtagLookup` function, on the clientside we just render a plainer
version of the hashtag HTML. Only in the composer preview do we do further lookups based
on this.
This rule is the first one (that I can find) that uses the `currentUser` based on a passed
in `user_id` for guardian checks in markdown rendering code. This is the `last_editor_id`
for both the post and chat message. In some cases we need to cook without a user present,
so the `Discourse.system_user` is used in this case.
**Chat Channels**
This also contains the changes required for chat so that chat channels can be used
as a data source for hashtag searches and lookups. This data source will only be
used when `enable_experimental_hashtag_autocomplete` is `true`, so we don't have
to worry about channel results suddenly turning up.
------
**Known Rough Edges**
- Onebox excerpts will not render the icon svg/use tags, I plan to address that in a follow up PR
- Selecting a hashtag + pressing the Quote button will result in weird behaviour, I plan to address that in a follow up PR
- Mixed hashtag contexts for hashtags without a type suffix will not work correctly, e.g. #ux which is both a category and a channel slug will resolve to a category when used inside a post or within a [chat] transcript in that post. Users can get around this manually by adding the correct suffix, for example ::channel. We may get to this at some point in future
- Icons will not show for the hashtags in emails since SVG support is so terrible in email (this is not likely to be resolved, but still noting for posterity)
- Additional refinements and review fixes wil
Uses `module()` instead of `discourseModule()`, native getters instead of `.get()`, fixes some assertions, uses the store instead of creating models directly
Long story short - bumping ember-qunit upgrades webpack, and sinon is not compatible with webpack v5. It uses node's `util` module and that is no longer polyfilled by webpack by default.
This PR adds the `util` polyfill (😑, but what can you do) and also injects a stub of `process` (so polyfill + sinon actually work)
Trying out changes to reduce the number of nav items in the experimental horizontal user nav. These changes should only appear with the redesigned_user_page_nav_enabled feature flag.
1. Created a new "Tracking" route. This combines some tracking-related settings from Notifications and Category and Tag tracking (which were separate tabs previously). Don't love the layout yet, but it's something that we can work on.
2. Moved some user-related settings out of Notifications and to the
Users tab. These seem more user-related to me, and it's nice that we can
associate enabling messages with the setting to limit who can send
messages.
3. Moved the App tab (lists app permissions) to be within the Security tab. It's very similar to Recently Used Devices.
* FIX: allow tl4 to bulk select
- Also allows tl4 to perform batch tagging
---
Long term this needs to be rewritten to account for "bulk action" permission
given from the server.
Co-authored-by: Martin Brennan <martin@discourse.org>
TrackedObject allows us to reference SiteSettings in autotracking contexts (e.g. JS getters referenced from a Glimmer template) without the need for EmberObject's `get()` function. TrackedObject is backwards-compatible with Ember's legacy reactivity model, so it can be referenced in things like computed properties.
Co-authored-by: David Taylor <david@taylorhq.com>
This change is intended to be backwards-compatible with all the previous arguments to `DButton`.
A deprecation warning will be triggered when a string is passed to the `@action` argument. This kind of action bubbling has been deprecated in Ember for some time, and should be updated to use closure actions.
Co-authored-by: Dan Gebhardt <dan@cerebris.com>
Co-authored-by: David Taylor <david@taylorhq.com>
When opening the invite acceptance page when the user
was already logged in, we were still showing the Accept
Invitation prompt even if the user had already redeemed
the invitation and was present in the `InvitedUser` table.
This would lead to errors when the user clicked on the button.
This commit fixes the issue by hiding the Accept Invitation
button and showing an error message instead indicating that
the user had already redeemed the invitation. This only applies
to multi-use invite links.
* FIX: Update user options only once
Performing actions that updated list of seen popups used to update user
options everytime instead of checking if the change has any effect.
* FIX: Load updated user data from response