* 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.
This patch sets some limits on custom fields:
- an entity can’t have more than 100 custom fields defined on it
- a custom field can’t hold a value greater than 10,000,000 characters
The current implementation of custom fields is relatively complex and
does an upsert in SQL at some point, thus preventing to simply add an
`ActiveRecord` validation on the custom field model without having to
rewrite a part of the existing logic.
That’s one of the reasons this patch is implementing validations in the
`HasCustomField` module adding them to the model including the module.
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.
* move the chat unread indicator to top to match the profile avatar indicator
* add white border to profile avatar indicator (badge notification) to match chat indicator and userstatus styling
* change `.urgent` to BEM
* congregate all styling into mixin
* update chat index to use mixin
* update thread indicator to use mixin
* update header indicator to use mixin
---------
Co-authored-by: Joffrey JAFFEUX <j.jaffeux@gmail.com>
Co-authored-by: Martin Brennan <martin@discourse.org>
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.
At the moment, PMs to groups with default notification level set to
`watching_first_post` do not generate "emailable" notifications. This happens
because, topic user notification level which is indirectly derived
from the group's default notification level is set to `tracking` if the
group's notification level happens to be `watching_first_post`.
This leads to a `group_message_summary` notification being created
instead of a `private_message` notification which results in no email
alerts being sent when a topic is created.
As this `watching_first_post` --> `tracking` switcheroo appears to be
intentional instead being a bug, this change extends `PostAlerter`'s
`notify_pm_users` method to create a `private_message` notification for
first posts created in a `watching_first_post` group even if the topic
user notification level is set to `tracking`
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`.
* DEV: Implement staff logs for user columns edits
* deleted extra space in staff logger detail string, deleted string when no changes are made, added basic test coverage for EditDirectoryColumnsController
* fixed change made to #self.staff_actions un UserHistory
* implemented a method that builds the details, previous_values and new_values in a dynamic way
* removed details of changes
* refactored small merge
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
Calling pluck is instantly making a SELECT, while passing the relationship allows rails to build a correct query.
Before (2 selects):
```
pry(main)> Post.where(topic_id: Topic.where(id: [1,3,4]).pluck(:id)).count
(1.3ms) SELECT "topics"."id" FROM "topics" WHERE "topics"."deleted_at" IS NULL AND "topics"."id" IN (1, 3, 4)
Post Count (0.5ms) SELECT COUNT(*) FROM "posts" WHERE "posts"."deleted_at" IS NULL AND "posts"."topic_id" IN (1, 3, 4)
```
After (1 select):
```
pry(main)> Post.where(topic_id: Topic.where(id: [1,3,4])).count
Post Count (2.7ms) SELECT COUNT(*) FROM "posts" WHERE "posts"."deleted_at" IS NULL AND "posts"."topic_id" IN (SELECT "topics"."id" FROM "topics" WHERE "topics"."deleted_at" IS NULL AND "topics"."id" IN (1, 3, 4))
```