Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
20ff23e
DEV: remove redundant translations for disabled new topic btn (#33929)
dbattersby Jul 29, 2025
8eddd6d
UX: show navigate to post button on ignored quotes (#33904)
awesomerobot Jul 29, 2025
d8141d1
UX: on plugin index, unlink preinstall, simplify install banner (#33910)
awesomerobot Jul 29, 2025
75d10a3
UX: fix-overflow (#33914)
jordanvidrine Jul 29, 2025
9e65d5c
UX: Content border variables 2 (#33911)
jordanvidrine Jul 29, 2025
fa742b8
UX: Horizon > chat-drawer z-index adjustments for popup content (#33932)
chapoi Jul 29, 2025
3c71404
UX: clarify color palette activation button (#33909)
awesomerobot Jul 29, 2025
a7bd3e2
DEV: Standardize x & y spacing variables (#33934)
jordanvidrine Jul 29, 2025
f9d2a68
FIX: correct variable name (#33935)
jordanvidrine Jul 29, 2025
e508ba7
UX: Modernize footnote implementation and enable in preview (#33928)
davidtaylorhq Jul 29, 2025
393cb96
UX: show 0% instead of em dash in percent-type report columns (#33931)
arpitjalan Jul 29, 2025
4a0875b
UX: improve admin width restriction, fix theme setting width (#33938)
awesomerobot Jul 29, 2025
3220565
FIX: Move custom digest text to correct spot (#33912)
brrusselburg Jul 29, 2025
3739c82
Revert: FEATURE: create new topic while viewing restricted category o…
dbattersby Jul 29, 2025
5b9649c
UX: Update styling of inline footnotes (#33933)
davidtaylorhq Jul 29, 2025
4948748
DEV: Add Chat page variables (#33936)
jordanvidrine Jul 29, 2025
d791e60
UX: hashtag alignment in text and autocomplete (#33902)
chapoi Jul 29, 2025
909e65b
FIX: Also show native names when editing category localizations (#33930)
nattsw Jul 29, 2025
e2f45e0
DEV: Get completion rates of each translatable type (#33927)
nattsw Jul 29, 2025
216df43
DEV: Reduce unnecessary UI updates when posts change (#33918)
megothss Jul 29, 2025
b075a54
UX: Ability to customize border colors of oneboxes (#33939)
jordanvidrine Jul 29, 2025
accb1b4
DEV: remove transparent pixels (#33941)
jordanvidrine Jul 29, 2025
dc905ce
UX: Fix tabs in new notification panel (#33871)
CvX Jul 29, 2025
feebe69
FIX: ensure usage report is timezone aware to prevent gaps (#33913)
keegangeorge Jul 29, 2025
702cafd
FIX: Remove old code reference on Discourse AI migration (#33943)
xfalcox Jul 29, 2025
db78786
DEV: Misc variable additions (#33942)
jordanvidrine Jul 29, 2025
78cf093
Build(deps-dev): Bump @swc/core from 1.13.2 to 1.13.3 (#33950)
dependabot[bot] Jul 29, 2025
9d7f283
Build(deps): Bump json from 2.13.1 to 2.13.2 (#33954)
dependabot[bot] Jul 29, 2025
50f80d9
DEV: floatkit autocomplete for d-editor (#33513)
tyb-talks Jul 30, 2025
7abad10
FIX: composer link modal ENTER event (#33945)
renato Jul 30, 2025
7f5d25e
Build(deps): Bump @rollup/browser from 4.46.1 to 4.46.2 (#33951)
dependabot[bot] Jul 30, 2025
5646e97
Build(deps-dev): Bump mime-types-data from 3.2025.0722 to 3.2025.0729…
dependabot[bot] Jul 30, 2025
ecfd35f
Build(deps-dev): Bump ember-cli from 6.5.0 to 6.6.0 (#33949)
dependabot[bot] Jul 30, 2025
602efbd
FIX: Check tag group names in form template validator (#33850)
Lhcfl Jul 30, 2025
0f78e29
DEV: avoid calling sidekiq in migration (#33957)
SamSaffron Jul 30, 2025
dd710ba
FEATURE: Reset bump date when unhiding a post (#33926)
Lhcfl Jul 30, 2025
c53cf93
DEV: Fix flaky test when editing category logo image (#33961)
pento Jul 30, 2025
822e5d6
DEV: Fix flaky test for form template (#33960)
Lhcfl Jul 30, 2025
8763cdb
FIX: Composer mode was not being remembered on new PM (#33962)
martin-brennan Jul 30, 2025
62c711b
DEV: Fix a flaky chat shortcut test (#33966)
pento Jul 30, 2025
a18ce75
DEV: Prevent allow_personal_messages from flaking surrounding tests (…
nattsw Jul 30, 2025
5873ea1
DEV: Fix interaction between `htmlClass` and `bodyClass` (#33969)
davidtaylorhq Jul 30, 2025
dfd0c52
FIX: Completion rate double-count and normalize (#33963)
nattsw Jul 30, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ GEM
reline (>= 0.4.2)
iso8601 (0.13.0)
jmespath (1.6.2)
json (2.13.1)
json (2.13.2)
json-schema (5.2.1)
addressable (~> 2.8)
bigdecimal (~> 3.1)
Expand Down Expand Up @@ -286,7 +286,7 @@ GEM
mime-types (3.7.0)
logger
mime-types-data (~> 3.2025, >= 3.2025.0507)
mime-types-data (3.2025.0722)
mime-types-data (3.2025.0729)
mini_mime (1.1.5)
mini_racer (0.19.0)
libv8-node (~> 24.1.0.0)
Expand Down Expand Up @@ -991,7 +991,7 @@ CHECKSUMS
irb (1.15.2) sha256=222f32952e278da34b58ffe45e8634bf4afc2dc7aa9da23fed67e581aa50fdba
iso8601 (0.13.0) sha256=298c2b15b7be5fa95a1372813d36a2257656cd8e906dfbc1f5cb409851425aa2
jmespath (1.6.2) sha256=238d774a58723d6c090494c8879b5e9918c19485f7e840f2c1c7532cf84ebcb1
json (2.13.1) sha256=8e7cf4bb44a789ac5fc62869c7187986251c3172d9bdfa60b92c63d6ecab0ffc
json (2.13.2) sha256=02e1f118d434c6b230a64ffa5c8dee07e3ec96244335c392eaed39e1199dbb68
json-schema (5.2.1) sha256=1ef39286c4771e7a71661d955fec9b66d1d1708547a0071c130af7c0a9264898
json_schemer (2.4.0) sha256=56cb6117bb5748d925b33ad3f415b513d41d25d0bbf57fe63c0a78ff05597c24
jwt (2.10.1) sha256=e6424ae1d813f63e761a04d6284e10e7ec531d6f701917fadcd0d9b2deaf1cc5
Expand Down Expand Up @@ -1021,7 +1021,7 @@ CHECKSUMS
messageformat-wrapper (1.1.0) sha256=ecea879626e412d1bc841c457dacfcbb1a62cf88ca83573e4ea34bb371f160bc
method_source (1.1.0) sha256=181301c9c45b731b4769bc81e8860e72f9161ad7d66dd99103c9ab84f560f5c5
mime-types (3.7.0) sha256=dcebf61c246f08e15a4de34e386ebe8233791e868564a470c3fe77c00eed5e56
mime-types-data (3.2025.0722) sha256=f9d1fd57ecc5688a66d9811d45981ee58e2dca012e352a1eaa7299e8c0f482f4
mime-types-data (3.2025.0729) sha256=8d7e1ab1ab756ebba91354ff4e35bcf23c39ed86dc5abba6cf32ce66ee9e5aad
mini_mime (1.1.5) sha256=8681b7e2e4215f2a159f9400b5816d85e9d8c6c6b491e96a12797e798f8bccef
mini_racer (0.19.0) sha256=9152694738db8b145ced843126e2a391f908732c069cb97bbc909c2bac16bbc1
mini_scheduler (0.18.0) sha256=d2f084f38da8d76c5844a92f0d6bd01fc9982a8b5e6c7679b6cf44c82da33503
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,14 +121,9 @@ export default class AdminPluginsListItem extends Component {
>
{{@plugin.version}}<br />
{{#if this.isPreinstalled}}
<a
href="https://meta.discourse.org/t/bundling-more-popular-plugins-with-discourse-core/373574"
rel="noopener noreferrer"
target="_blank"
class="admin-plugins-list__preinstalled-link"
>
<span class="admin-plugins-list__preinstalled">
{{i18n "admin.plugins.preinstalled"}}
</a>
</span>
{{else}}
<PluginCommitHash @plugin={{@plugin}} />
{{/if}}
Expand Down
2 changes: 1 addition & 1 deletion app/assets/javascripts/admin/addon/models/report.js
Original file line number Diff line number Diff line change
Expand Up @@ -622,7 +622,7 @@ export default class Report extends EmberObject {
_percentLabel(value) {
return {
value: toNumber(value),
formattedValue: value ? `${value}%` : "—",
formattedValue: value === null || value === undefined ? "—" : `${value}%`,
};
}

Expand Down
20 changes: 10 additions & 10 deletions app/assets/javascripts/admin/addon/templates/plugins-index.gjs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { concat } from "@ember/helper";
import { htmlSafe } from "@ember/template";
import RouteTemplate from "ember-route-template";
import DBreadcrumbsItem from "discourse/components/d-breadcrumbs-item";
import DPageHeader from "discourse/components/d-page-header";
import NavItem from "discourse/components/nav-item";
import PluginOutlet from "discourse/components/plugin-outlet";
import icon from "discourse/helpers/d-icon";
import lazyHash from "discourse/helpers/lazy-hash";
import { i18n } from "discourse-i18n";
import AdminFilterControls from "admin/components/admin-filter-controls";
Expand All @@ -15,8 +16,14 @@ export default RouteTemplate(

<DPageHeader
@titleLabel={{i18n "admin.config.plugins.title"}}
@descriptionLabel={{i18n "admin.config.plugins.header_description"}}
@learnMoreUrl="https://www.discourse.org/plugins"
@descriptionLabel={{htmlSafe
(concat
(i18n "admin.config.plugins.header_description")
'<a class="admin-plugins-howto" href="https://meta.discourse.org/t/install-a-plugin/19157">'
(i18n "admin.plugins.howto")
"</a>"
)
}}
>
<:breadcrumbs>
<DBreadcrumbsItem @path="/admin" @label={{i18n "admin_title"}} />
Expand Down Expand Up @@ -48,13 +55,6 @@ export default RouteTemplate(
</:tabs>
</DPageHeader>

<div class="alert alert-info admin-plugins-howto">
<a href="https://meta.discourse.org/t/install-a-plugin/19157">
{{icon "circle-info"}}
{{i18n "admin.plugins.howto"}}
</a>
</div>

{{#if @controller.model.length}}
<AdminFilterControls
@array={{@controller.model}}
Expand Down
2 changes: 1 addition & 1 deletion app/assets/javascripts/admin/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
"@types/qunit": "^2.19.12",
"@types/rsvp": "^4.0.9",
"broccoli-asset-rev": "^3.0.0",
"ember-cli": "~6.5.0",
"ember-cli": "~6.6.0",
"ember-cli-inject-live-reload": "^2.1.0",
"ember-cli-sri": "^2.1.1",
"ember-cli-terser": "^4.0.2",
Expand Down
2 changes: 1 addition & 1 deletion app/assets/javascripts/discourse-plugins/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
"ember-this-fallback": "^0.4.0"
},
"devDependencies": {
"ember-cli": "~6.5.0",
"ember-cli": "~6.6.0",
"webpack": "^5.101.0"
},
"engines": {
Expand Down
2 changes: 1 addition & 1 deletion app/assets/javascripts/discourse-widget-hbs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
"@glimmer/component": "^1.1.2",
"@glimmer/syntax": "0.93.1",
"broccoli-asset-rev": "^3.0.0",
"ember-cli": "~6.5.0",
"ember-cli": "~6.6.0",
"ember-cli-inject-live-reload": "^2.1.0",
"ember-cli-sri": "^2.1.1",
"ember-cli-terser": "^4.0.2",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,44 @@ import Component from "@ember/component";
import { tagName } from "@ember-decorators/component";
import DButton from "discourse/components/d-button";
import TopicDraftsDropdown from "discourse/components/topic-drafts-dropdown";
import { i18n } from "discourse-i18n";
import DButtonTooltip from "float-kit/components/d-button-tooltip";
import DTooltip from "float-kit/components/d-tooltip";

@tagName("")
export default class CreateTopicButton extends Component {
label = "topic.create";
btnClass = "btn-default";

get disallowedReason() {
if (this.canCreateTopicOnTag === false) {
return "topic.create_disabled_tag";
} else if (this.disabled) {
return "topic.create_disabled_category";
}
}

<template>
{{#if this.canCreateTopic}}
<DButtonTooltip>
<:button>
<DButton
@action={{this.action}}
@icon="far-pen-to-square"
@disabled={{this.disabled}}
@label={{this.label}}
id="create-topic"
class={{this.btnClass}}
/>
</:button>
<:tooltip>
{{#if @disabled}}
<DTooltip
@icon="circle-info"
@content={{i18n this.disallowedReason}}
/>
{{/if}}
</:tooltip>
</DButtonTooltip>

{{#if @showDrafts}}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
import Component from "@glimmer/component";
import { on } from "@ember/modifier";
import { action } from "@ember/object";
import didInsert from "@ember/render-modifiers/modifiers/did-insert";
import didUpdate from "@ember/render-modifiers/modifiers/did-update";
import { htmlSafe } from "@ember/template";

// CSS selectors for autocomplete result items
const RESULT_ITEM_SELECTOR = "li a";
const SELECTED_RESULT_SELECTOR = "li a.selected";
const SELECTED_CLASS = "selected";

/**
* Component for rendering autocomplete results in a d-menu
*
* @component DAutocompleteResults
* @param {Array} data.results - Array of autocomplete results
* @param {number} data.selectedIndex - Currently selected index
* @param {Function} data.onSelect - Callback for item selection
* @param {Function} data.template - Template function for rendering
*/
export default class DAutocompleteResults extends Component {
isInitialRender = true;

get results() {
return this.args.data.getResults?.() || [];
}

get selectedIndex() {
return this.args.data.getSelectedIndex?.() || 0;
}

_applySelectedClass(wrapperElement, selectedIndex) {
const links = wrapperElement.querySelectorAll(RESULT_ITEM_SELECTOR);

// Always remove existing selected classes first
const selectedElements = wrapperElement.querySelectorAll(
SELECTED_RESULT_SELECTOR
);
selectedElements.forEach((element) =>
element.classList.remove(SELECTED_CLASS)
);

if (selectedIndex >= 0 && links[selectedIndex]) {
links[selectedIndex].classList.add(SELECTED_CLASS);
}

return links;
}

scrollToSelected(wrapperElement) {
// This is a more imperative approach that's meant to be compatible with the pre-existing autocomplete templates,
// we should refactor in future to use component templates that are more declarative in setting the `selected` class.

if (!wrapperElement) {
return;
}
// Find all links in the autocomplete menu and update selection
const links = this._applySelectedClass(wrapperElement, this.selectedIndex);

if (!links || links.length === 0 || !links[this.selectedIndex]) {
return;
}

links[this.selectedIndex].scrollIntoView({
block: "nearest",
behavior: "smooth",
});
}

@action
handleInitialRender() {
this.args.data.onRender?.(this.results);
}

@action
handleClick(event) {
if (!this.args.data.template) {
return;
}

try {
event.preventDefault();
event.stopPropagation();

const clickedLink = event.target.closest(RESULT_ITEM_SELECTOR);
if (!clickedLink) {
return;
}

// Find the index of the clicked link
const links = event.currentTarget.querySelectorAll(RESULT_ITEM_SELECTOR);
const index = Array.from(links).indexOf(clickedLink);

if (index >= 0) {
// Call onSelect and handle any promise returned
const result = this.args.data.onSelect(
this.results[index],
index,
event
);
if (result && typeof result.then === "function") {
result.catch((e) => {
// eslint-disable-next-line no-console
console.error("[autocomplete] onSelect promise rejected: ", e);
});
}
}
} catch (e) {
// eslint-disable-next-line no-console
console.error("[autocomplete] Click handler error: ", e);
}
}

@action
handleUpdate(wrapperElement) {
this.isInitialRender = false;
this.scrollToSelected(wrapperElement);
// Call onRender callback after DOM is ready
this.args.data.onRender?.(this.results);
}

get templateHTML() {
if (!this.args.data.template) {
return "";
}

const template = this.args.data.template({ options: this.results });

if (!this.isInitialRender || this.selectedIndex < 0) {
return htmlSafe(template);
}

const tempDiv = document.createElement("div");
tempDiv.innerHTML = template;
this._applySelectedClass(tempDiv, this.selectedIndex);

return htmlSafe(tempDiv.innerHTML);
}

<template>
<div
{{didInsert this.handleInitialRender}}
{{didUpdate this.handleUpdate this.selectedIndex this.templateHTML}}
{{on "click" this.handleClick}}
tabindex="-1"
>
{{this.templateHTML}}
</div>
</template>
}
6 changes: 3 additions & 3 deletions app/assets/javascripts/discourse/app/components/d-editor.gjs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ import EmojiPickerDetached from "discourse/components/emoji-picker/detached";
import UpsertHyperlink from "discourse/components/modal/upsert-hyperlink";
import PluginOutlet from "discourse/components/plugin-outlet";
import PopupInputTip from "discourse/components/popup-input-tip";
import { SKIP } from "discourse/lib/autocomplete";
import renderEmojiAutocomplete from "discourse/lib/autocomplete/emoji";
import userAutocomplete from "discourse/lib/autocomplete/user";
import Toolbar from "discourse/lib/composer/toolbar";
Expand All @@ -44,6 +43,7 @@ import {
initUserStatusHtml,
renderUserStatusHtml,
} from "discourse/lib/user-status-on-autocomplete";
import { SKIP } from "discourse/modifiers/d-autocomplete";
import { i18n } from "discourse-i18n";

let _createCallbacks = [];
Expand Down Expand Up @@ -94,9 +94,9 @@ export default class DEditor extends Component {

this.setupToolbar();

// TODO (martin) Remove this once we are sure all users have migrated
// to the new rich editor preference, or a few months after the 3.5 release.
if (this.siteSettings.rich_editor) {
// TODO (martin) Remove this once we are sure all users have migrated
// to the new rich editor preference, or a few months after the 3.5 release.
await this.handleOldRichEditorPreference();

if (this.currentUser.useRichEditor) {
Expand Down
Loading