* DEV: unsilence deprecation warnings for old Font Awesome icon names
* update fa-user to user font awesome icon name
* update pencil-alt to pencil font awesome 6 icon name
Adds setupEditor to ComposerEditor so it can setup/destroy events when the underlying editorComponent is switched.
Moves putCursorAtEnd uses (which implementation is textarea-specific) to TextareaTextManipulation.
Moves insertCurrentTime and a corresponding test, which is discourse-local-dates specific, to the plugin.
Moves applyList and formatCode from DEditor to the TextareaTextManipulation.
Moves DEditor._applySurround to TextareaTextManipulation.applySurroundSelection
Avoids resetting the textarea value on applyList and formatCode, keeping the undo history.
BEFORE: if you click the "reply" button on a post and then decided that you want to "edit" the same post, clicking the "edit" button would do nothing. Clicking "edit" on another post works, but editing the same post would appear broken.
AFTER: if you click the "edit" button, it will properly load the content of the post you're trying to edit. No matter which one it is.
This was somewhat tricky to track down as the system specs seemed to contradict the qunit tests until I realized that the qunit tests were only testing the edit on the 1st post and the system specs were testing on replies.
I improved the qunit tests to test both editing OP and a reply and (hopefully) made the system specs a little bit clearer.
This is a follow up to bbe62d88d2.
Uses the `htmlClass` to automagically set the `modal-open` class to
`<html>` so that we can do `overflow: hidden` and prevent the
"background" behind the modal from scrolling while the modal is open.
Internal ref - t/142760
- Use `requestAnimationFrame` when transitioning from `ready` -> `loading`. The previous `next()` implementation was unreliable, particularly in Safari, and would cause the loading slider to jump backwards instead of forwards
- Double the minimum transition time to 200ms. This avoids the rolling average being skewed too much by routes which load quickly without network access.
This commit ensures that tracked properties added to the post model are correctly synced when using `post.updateFromPost`.
It also introduces a plugin API to allow plugins to register new tracked properties in the post model without needing to modify the class.
Animating the background-color property like this is not compositable for the browser, which means the animation is not smooth, and can contribute to the Cumulative Layout Shift web vital.
For now, we're removing this, and may consider re-introducing an alternative version in future based on user feedback.
Non-admin/moderator users can bulk select items in new/unread, but not in
latest/top/hot. This commit ensures that when the user can no longer
bulk select items in a list, the bulk select checkboxes in the topic list
rows are hidden.
A lot of the data of fields is decided at insertion time and is not dynamic afterwards, this commit attempts to solve this problem by making the fk-field-data a component with getters on the all the properties we need. It allows for example to implement a dynamic @disabled without having to pass @disabled everywhere. Generally speaking this solution limits props-drilling.
@format has received the same treatment than @disabled.
Followup ccc8e37dde
The fix above was good, but I would prefer to give
the option of untranslated vs translated label like
I have for other admin components for consistency.
The chart component was not rerendering if the chart
config passed to it was changed, this commit fixes the issue
by getting the config from `this.args` before trying to
access it inside an async call, so if the args change Ember
correctly rerenders. Also adds tests for this and general
chart rendering.
---------
Co-authored-by: Martin Brennan <martin@discourse.org>
Sometimes changes to "What's new?" feed items are made or the feed items are
removed altogether, and the polling interval to check for new features is 1 day.
This is quite long, so this commit introduces a "Check for updates"
button for admins to click on the "What's new?" page which will bust
the cache for the feed and check again at the new features endpoint.
This is limited to 5 times per minute to avoid rapid sending of
requests.
Using Ember's `<template>` dynamically is not supported. For every invocation, glimmer-vm has to run one-time setup, and will cache the result indefinitely. This leads to significant memory leaks, and eventual OOM errors.
This commit updates a handful of cases. We'll be following up with the more complex ones, and a linting rule to avoid re-introducing the problem in future.
The Admin UI guidelines states that buttons should have text, not icons. This was an oversight on the admin emoji listing.
Part of this change is also opportunistically removing the CSS file for admin emojis, none of which is used any more since the conversion.
This unlocks the ability to use that function directly in templates:
```hbs
{{applyValueTransformer
"foo-bar"
@defaultValue
(hash arg1=@arg1 arg2=@arg2)
}}
```
This PR simply moves the call to remove in progress uploads **after** the async markdown resolvers finish resolving. This is specifically for the case when markdown resolvers are async functions, such as in the case of Discourse AI's image caption feature. This ensures that the in progress upload doesn't get removed causing replace text having nothing to replace once the async call is finished.
No tests as there currently are no tests for this plugin API function, and it's a little tricky to test, especially with in progress uploads being a private property.
This commit introduces a new feature that allows staff to bulk select and delete users directly from the users list at `/admin/users/list`. The main use-case for this feature is make deleting spammers easier when a site is under a large spam attack.
Internal topic: t/140321.
- Clicking the channel title of a collapsed drawer will only open the drawer, and not open settings
- Remove the back button when the drawer is collapsed
- Uses same icon for toggling on chat that composer
- add max-width to minimised drawer + add hover effect
---------
Co-authored-by: chapoi <101828855+chapoi@users.noreply.github.com>
This moves the logic of setting the correct permalink values back into the controller. And it replaces the validation with a simpler one, that always works, even when the model is loaded from the DB.
Follow-up to #29634 which broke import scripts and lots of documentation on Meta.
1. `addRawTemplate` is called too early for deprecation handlers to process its deprecation call, so toggle the hbr flag directly
2. move the deprecation handler to an initializer so that other (non-template) calls are always handled
3. move the debug logging to the handler
- Add bulk actions component on /filter page for both desktop & mobile view.
- Add system specs to assert bulk actions to be available on /filter page.
Most of it is removing the ComposerContainer > ComposerEditor indirect references to the composer service, so ComposerEditor now deals with the service directly.
Form template was moved from DEditor to ComposerEditor.
Prior to this fix the menu would not close if a child was in focus, and the search suggestions had a special implementation to handle this. The fix now relies on trapping the keydown escape event on the top dip of the search menu.
* DEV: add outlet wrapper for small user list
* DEV: use value transformer to extend small user attrs function
* Update app/assets/javascripts/discourse/app/components/small-user-list.gjs
Co-authored-by: Jarek Radosz <jradosz@gmail.com>
---------
Co-authored-by: Jarek Radosz <jradosz@gmail.com>
In particular, this applies:
- new `discourse/no-implicit-this` template-lint rule
- `init`/`willDestroy` ordering enforcement
- `lines-between-class-members`
Because of an oversight in a previous PR, the breadcrumb link when visiting Admin > Emoji > Settings was broken. The correct path is customize, not config.
The current breadcrumb separators are ">" characters that are added as pseudo-elements. These become part of the clickable area for the links, which causes mis-clicks.
This PR does two things:
- Replace the pseudo-element with a DIcon.
- Make sure the separator is not clickable.
Blocks allow BOTS to augment the capacities of a chat message. At the moment only one block is available: `actions`, accepting only one type of element: `button`.
<img width="708" alt="Screenshot 2024-11-15 at 19 14 02" src="https://github.com/user-attachments/assets/63f32a29-05b1-4f32-9edd-8d8e1007d705">
# Usage
```ruby
Chat::CreateMessage.call(
params: {
message: "Welcome!",
chat_channel_id: 2,
blocks: [
{
type: "actions",
elements: [
{ value: "foo", type: "button", text: { text: "How can I install themes?", type: "plain_text" } }
]
}
]
},
guardian: Discourse.system_user.guardian
)
```
# Documentation
## Blocks
### Actions
Holds interactive elements: button.
#### Fields
| Field | Type | Description | Required? |
|--------|--------|--------|--------|
| type | string | For an actions block, type is always `actions` | Yes |
| elements | array | An array of interactive elements, maximum 10 elements | Yes |
| block_id | string | An unique identifier for the block, will be generated if not specified. It has to be unique per message | No |
#### Example
```json
{
"type": "actions",
"block_id": "actions_1",
"elements": [...]
}
```
## Elements
### Button
#### Fields
| Field | Type | Description | Required? |
|--------|--------|--------|--------|
| type | string | For a button, type is always `button` | Yes |
| text | object | A text object holding the type and text. Max 75 characters | Yes |
| value | string | The value returned after the interaction has been validated. Maximum length is 2000 characters | No |
| style | string | Can be `primary` , `success` or `danger` | No |
| action_id | string | An unique identifier for the action, will be generated if not specified. It has to be unique per message | No |
#### Example
```json
{
"type": "actions",
"block_id": "actions_1",
"elements": [
{
"type": "button",
"text": {
"type": "plain_text",
"text": "Ok"
},
"value": "ok",
"action_id": "button_1"
}
]
}
```
## Interactions
When a user interactions with a button the following flow will happen:
- We send an interaction request to the server
- Server checks if the user can make this interaction
- If the user can make this interaction, the server will:
* `DiscourseEvent.trigger(:chat_message_interaction, interaction)`
* return a JSON document
```json
{
"interaction": {
"user": {
"id": 1,
"username": "j.jaffeux"
},
"channel": {
"id": 1,
"title": "Staff"
},
"message": {
"id": 1,
"text": "test",
"user_id": -1
},
"action": {
"text": {
"text": "How to install themes?",
"type": "plain_text"
},
"type": "button",
"value": "click_me_123",
"action_id": "bf4f30b9-de99-4959-b3f5-632a6a1add04"
}
}
}
```
* Fire a `appEvents.trigger("chat:message_interaction", interaction)`
When a parent category shows topics from subcategories, dismissing
should dismiss posts in both parent and subcategories.
Co-authored-by: Alan Guo Xiang Tan <gxtan1990@gmail.com>
- Uses a more appropriate image, with immutable tag (so update prompts work correctly)
- Updates port forwarding
- Improves mount setup (inc. persistant PG/Redis when rebuilding)
- Fixes ember-cli live reload
- Automatically configures VSCode & extensions
Redesign the permalinks page to follow the UX guide. In addition, the ability to edit permalinks was added.
This change includes:
- move to RestModel
- added Validations
- update endpoint and clear old values after the update
- system specs and improvements for unit tests
When running a development environment behind a proxy (e.g. when using a cloud development environment, or a service like ngrok), the ember-cli port & protocol may not match the one in the browser. `livereload.js` knows how to auto-configure itself based on the current browser environment... but Ember CLI overrides that autoconfiguration with some hard-coded values.
The intention there is to allow running the livereload server on a different port to the ember-cli web proxy. We don't need that functionality.
This commit stops loading `ember-cli-live-reload.js`, and instead loads `_lr/livereload.js` directly.
This commit:
- Adds back the target drop options to enable the feature
- Applies the css to every elements and not just the one for admin emojis, also fixes the style as it was flashing and preventing it to work. For now we just change the color of the image icon.
- Adds a test to ensure we don't regress.
It splits the hide_profile_and_presence user option and the default_hide_profile_and_presence site setting for more granular control. It keeps the option to hide the profile under /u/username/preferences/interface and adds the presence toggle in the quick user menu.
Co-authored-by: Régis Hanol <regis@hanol.fr>
This commit modernizes the post menu by migrating it from the existing widget-based implementation to Glimmer components. This transition aims to improve the maintainability, performance, and overall developer experience.
It also introduces a new DAG-based transformer API for customizations that aims to be more flexible than the widget base one.
---------
Co-authored-by: David Taylor <david@taylorhq.com>
This commit removes the new optimized category style introduced in
previous commits (d37a0d40, 9a80d718 and 430c42ac), in favour of the
existent `categories_only`.
Overriding computed properties with arguments is no longer supported by Ember, so we need to rename this computed property and add fallback logic manually.
This fixes the styleguide 'buttons' page. Ref https://meta.discourse.org/t/styleguide-bugs/335211?u=david
When performing bulk dismissal in Unread and New views, the dismiss button stays at the top of the UI. Because of this we want to provide the dismiss action also in the "sticky" menu that's always in view, even when scrolling a long list of topics.
Follow-up to a5497b74be
In the linked commit, as part of simplifying the invite modal, we removed the option to skip sending an email when creating an invite restricted to a specific address. This has caused confusion about whether an email will be sent by Discourse or not, so we're adding back the option to create a restricted invite without emailing.
Internal topic: t/134023/48.
This PR ensures that admins are shown a confirmation dialog when clicking to disable 2FA for a user. The 2FA button is right below the "Grant Badge" button and as such it can easily be clicked accidentally. It's also good practice to ask for confirmation before removing important functionality.
"Resume editing" would do nothing when going through the `/new-message` flow.
This seems to be broken since [this commit](b0f6d074be). which moved `this._setModel` calls around – the same we're doing now, but to different places: the first one needs to happen after the `draft.data` has been set , while the second needs to happen before the `this.open` call.
This PR adds a small visual change to the new feature item on the `/admin/whats-new` page. When features are marked with an experimental site setting, they should show an indication on the feature item that it is "Experimental"
When replying to a topic, the @-mention userSearch needs the topicId and the categoryId so they can trigger immediately, with sane suggestions.
This was broken when the mentions were moved from ComposerEditor to DEditor.
* UX: Apply admin table classes for consistent mobile styling on the emojis page
* UX: remove icon from the button
* UX: styling tweaks on the emoji uploader form
* UX: right align table button controls
* apply prettier
I was skimming through existing pages to get a feel for the admin UI guidelines. I noticed that this part was missing its margin. On some further investigation, it seems that a single CSS selector, .award-badge was being used both for the section and for the button in the header, so I decided to 1) separate the two and 2) add in the missing margin.
Prior to Uppy, the `uploads#create` endpoint used to receive a `type` param that indicated the purpose/target of the upload, such as `avatar`, `site_setting` and so on. With the introduction of Uppy, the `type` param became the MIME type of the file being uploaded, and the purpose/target of the upload became a new param called `upload_type`, however the backend could still use the `type` param (which now contains MIME type) as the purpose/target of the upload if `upload_type` is absent.
We technically don't need to send the MIME type over the network, but it seems like it's done by Uppy and we have no control over the `type` param that Uppy includes:
758de8167b/app/assets/javascripts/discourse/app/lib/uppy/uppy-upload.js (L146-L151)
This commit does a couple of things:
1. It amends the `uploads#create` endpoint so it always requires the `upload_type` param and doesn't fallback to `type` if `upload_type` is absent
2. It forces consumers of the `UppyUpload` class (and by extension `UppyImageUploader`) to specify `type` of the upload
Internal topic: t/140945.
This commit switches the route for the about config page to retrieve the list of site settings that control the /about page by their area instead of their individual names.
Internal topic: t/136384.
In some cases, on Safari iOS, we would recompute the "--composer-vh" variable due to a minimal change in the viewport. This ends up triggering a loop where setting this variable triggers another viewport resize event, which triggers another change of the variable...
In order to fix (patch?) this issue, we now have a 1px leeway when checking the difference between the previous and new viewport.
Internal ref - t/141088
Multiple category styles can be used on the same site. The category and
subcategories page will use the "desktop_category_page_style" setting
and individual category pages will use the style selected in settings,
if any.
Commit c1f078ca tried to use the same style for both the category and
subcategories page, but the route matching did not take into account
the "discovery.categoryAll" and "discovery.categoryNone" variants of
the "discovery.category" route.
Template overrides have been advised against for a long time, and are increasingly hard to maintain as Discourse's development accelerates. This commit officially deprecates this customization method, which will be removed in the not-too-distant future (likely in the first half of 2025).
From plugin-api comment:
Registers a new tab to be displayed in "more topics" area at the bottom of a topic page.
```gjs
api.registerMoreTopicsTab({
id: "other-topics",
name: i18n("other_topics.tab"),
component: <template>tbd</template>,
condition: ({ topic }) => topic.otherTopics?.length > 0,
});
```
You can additionally use more-topics-tabs value transformer to conditionally show/hide
specific tabs.
```js
api.registerValueTransformer("more-topics-tabs", ({ value, context }) => {
if (context.user?.aFeatureFlag) {
// Remove "suggested" from the topics page
return value.filter(
(tab) =>
context.currentContext !== "topic" ||
tab.id !== "suggested-topics"
);
}
});
```
Recently we added a new feature for automatically gridding images in the composer (https://github.com/discourse/discourse/pull/29260). After testing this feature under a setting for a short period of time, the feature is no longer experimental anymore.
This PR removes the site setting `experimental_auto_grid_images`.
Allows anonymous users to download the calendar file. Before, they were given the option, but it would fail silently with a `TypeError: Cannot read properties of null (reading 'user_option')`.