diff --git a/app/assets/javascripts/discourse/app/components/admin-post-menu.gjs b/app/assets/javascripts/discourse/app/components/admin-post-menu.gjs
index 0dd0fe1e927..e5686a1f70e 100644
--- a/app/assets/javascripts/discourse/app/components/admin-post-menu.gjs
+++ b/app/assets/javascripts/discourse/app/components/admin-post-menu.gjs
@@ -52,7 +52,7 @@ export default class AdminPostMenu extends Component {
@@ -68,7 +68,7 @@ export default class AdminPostMenu extends Component {
}}
@icon="shield-alt"
class={{concatClass
- "btn popup-menu-btn toggle-post-type"
+ "btn btn-transparent toggle-post-type"
(if @data.transformedPost.isModeratorAction "btn-success")
}}
@action={{fn this.topicAction "togglePostType"}}
@@ -87,7 +87,7 @@ export default class AdminPostMenu extends Component {
}}
title="post.controls.unhide"
class={{concatClass
- "btn popup-menu-btn"
+ "btn btn-transparent"
(if @data.transformedPost.notice "change-notice" "add-notice")
(if @data.transformedPost.notice "btn-success")
}}
@@ -101,7 +101,7 @@ export default class AdminPostMenu extends Component {
@@ -121,7 +121,7 @@ export default class AdminPostMenu extends Component {
@label="post.controls.change_owner"
@icon="user"
title="post.controls.lock_post_description"
- class="btn popup-menu-btn change-owner"
+ class="btn btn-transparent change-owner"
@action={{fn this.topicAction "changePostOwner"}}
/>
@@ -133,7 +133,7 @@ export default class AdminPostMenu extends Component {
@@ -146,7 +146,7 @@ export default class AdminPostMenu extends Component {
@icon="unlock"
title="post.controls.unlock_post_description"
class={{concatClass
- "btn popup-menu-btn unlock-post"
+ "btn btn-transparent unlock-post"
(if @data.post.locked "btn-success")
}}
@action={{fn this.topicAction "unlockPost"}}
@@ -158,7 +158,7 @@ export default class AdminPostMenu extends Component {
@label="post.controls.lock_post"
@icon="lock"
title="post.controls.lock_post_description"
- class="btn popup-menu-btn lock-post"
+ class="btn btn-transparent lock-post"
@action={{fn this.topicAction "lockPost"}}
/>
@@ -170,7 +170,7 @@ export default class AdminPostMenu extends Component {
@@ -183,7 +183,7 @@ export default class AdminPostMenu extends Component {
@label="post.controls.unwiki"
@icon="far-edit"
class={{concatClass
- "btn popup-menu-btn wiki wikied"
+ "btn btn-transparent wiki wikied"
(if @data.transformedPost.wiki "btn-success")
}}
@action={{fn this.topicAction "toggleWiki"}}
@@ -194,7 +194,7 @@ export default class AdminPostMenu extends Component {
@@ -206,7 +206,7 @@ export default class AdminPostMenu extends Component {
@@ -217,7 +217,7 @@ export default class AdminPostMenu extends Component {
@@ -229,7 +229,7 @@ export default class AdminPostMenu extends Component {
@label={{button.label}}
@translatedLabel={{button.translatedLabel}}
@icon={{button.icon}}
- class={{concatClass "btn popup-menu-btn" button.className}}
+ class={{concatClass "btn btn-transparent" button.className}}
@action={{fn this.extraAction button}}
/>
diff --git a/app/assets/javascripts/discourse/app/components/topic-admin-menu-button.js b/app/assets/javascripts/discourse/app/components/topic-admin-menu-button.js
deleted file mode 100644
index ef58dfdad79..00000000000
--- a/app/assets/javascripts/discourse/app/components/topic-admin-menu-button.js
+++ /dev/null
@@ -1,11 +0,0 @@
-import MountWidget from "discourse/components/mount-widget";
-
-export default MountWidget.extend({
- classNames: "topic-admin-menu-button-container",
- tagName: "span",
- widget: "topic-admin-menu-button",
-
- buildArgs() {
- return this.getProperties("topic", "openUpwards", "rightSide");
- },
-});
diff --git a/app/assets/javascripts/discourse/app/components/topic-admin-menu.gjs b/app/assets/javascripts/discourse/app/components/topic-admin-menu.gjs
new file mode 100644
index 00000000000..e185e31de15
--- /dev/null
+++ b/app/assets/javascripts/discourse/app/components/topic-admin-menu.gjs
@@ -0,0 +1,311 @@
+import Component from "@glimmer/component";
+import { fn } from "@ember/helper";
+import { action } from "@ember/object";
+import { inject as service } from "@ember/service";
+import { and, not, or } from "truth-helpers";
+import DButton from "discourse/components/d-button";
+import concatClass from "discourse/helpers/concat-class";
+import icon from "discourse-common/helpers/d-icon";
+import getURL from "discourse-common/lib/get-url";
+import DMenu from "float-kit/components/d-menu";
+
+export default class TopicAdminMenu extends Component {
+ @service adminTopicMenuButtons;
+ @service currentUser;
+
+ @action
+ onRegisterApi(api) {
+ this.dMenu = api;
+ }
+
+ @action
+ onButtonAction(buttonAction) {
+ this.args[buttonAction]?.();
+ this.dMenu.close();
+ }
+
+ @action
+ onExtraButtonAction(buttonAction) {
+ buttonAction?.();
+ this.dMenu.close();
+ }
+
+ get extraButtons() {
+ return this.adminTopicMenuButtons.callbacks
+ .map((callback) => {
+ return callback(this.args.topic);
+ })
+ .filter(Boolean);
+ }
+
+ get details() {
+ return this.args.topic.get("details");
+ }
+
+ get isPrivateMessage() {
+ return this.args.topic.get("isPrivateMessage");
+ }
+
+ get featured() {
+ return (
+ !!this.args.topic.get("pinned_at") || this.args.topic.get("isBanner")
+ );
+ }
+
+ get visible() {
+ return this.args.topic.get("visible");
+ }
+
+ get canDelete() {
+ return this.details.get("can_delete");
+ }
+
+ get canRecover() {
+ return this.details.get("can_recover");
+ }
+
+ get archived() {
+ return this.args.topic.get("archived");
+ }
+
+ get topicModerationHistoryUrl() {
+ return getURL(`/review?topic_id=${this.args.topic.id}&status=all`);
+ }
+
+
+
+
+}
diff --git a/app/assets/javascripts/discourse/app/components/topic-footer-buttons.hbs b/app/assets/javascripts/discourse/app/components/topic-footer-buttons.hbs
index 5e57f6057e3..007f58cb0f4 100644
--- a/app/assets/javascripts/discourse/app/components/topic-footer-buttons.hbs
+++ b/app/assets/javascripts/discourse/app/components/topic-footer-buttons.hbs
@@ -1,5 +1,5 @@
-
-
{{#if @mobileView}}
- {
+ * return {
+ * action: () => {
+ * alert('You clicked on the coffee button!');
+ * },
+ * icon: 'coffee',
+ * className: 'hot-coffee',
+ * label: 'coffee.title',
+ * };
+ * });
+ * ```
+ **/
+ addTopicAdminMenuButton(callback) {
+ this.container
+ .lookup("service:admin-topic-menu-buttons")
+ .addButton(callback);
+ }
+
/**
* Remove existing button below a post with your plugin.
*
diff --git a/app/assets/javascripts/discourse/app/services/admin-topic-menu-buttons.js b/app/assets/javascripts/discourse/app/services/admin-topic-menu-buttons.js
new file mode 100644
index 00000000000..ede8be551a4
--- /dev/null
+++ b/app/assets/javascripts/discourse/app/services/admin-topic-menu-buttons.js
@@ -0,0 +1,9 @@
+import Service from "@ember/service";
+
+export default class AdminTopicMenuButtons extends Service {
+ callbacks = [];
+
+ addButton(callback) {
+ this.callbacks.push(callback);
+ }
+}
diff --git a/app/assets/javascripts/discourse/app/templates/topic.hbs b/app/assets/javascripts/discourse/app/templates/topic.hbs
index 8b68b353754..b9ea218fb88 100644
--- a/app/assets/javascripts/discourse/app/templates/topic.hbs
+++ b/app/assets/javascripts/discourse/app/templates/topic.hbs
@@ -280,7 +280,7 @@
}}
/>
- "topic-admin-menu-button",
-
- defaultState() {
- return { expanded: false, position: null };
- },
-
- html(attrs, state) {
- const result = [];
-
- const menu = this.attach("topic-admin-menu", {
- position: state.position,
- topic: attrs.topic,
- openUpwards: attrs.openUpwards,
- rightSide: this.site.desktopView && attrs.rightSide,
- actionButtons: [],
- });
-
- // We don't show the button when expanded on the right side on desktop
- if (
- menu.attrs.actionButtons.length &&
- (!(attrs.rightSide && state.expanded) || this.site.mobileView)
- ) {
- result.push(
- this.attach("button", {
- className:
- "btn-default popup-menu-button toggle-admin-menu" +
- (attrs.addKeyboardTargetClass ? " keyboard-target-admin-menu" : ""),
- title: "topic_admin_menu",
- icon: "wrench",
- action: "showAdminMenu",
- sendActionEvent: true,
- })
- );
- }
-
- if (state.expanded) {
- result.push(menu);
- }
-
- return result;
- },
-
- hideAdminMenu() {
- this.state.expanded = false;
- this.state.position = null;
- },
-
- showAdminMenu(e) {
- this.state.expanded = true;
- let button;
-
- if (e === undefined) {
- button = document.querySelector(".keyboard-target-admin-menu");
- } else {
- button = e.target.closest("button");
- }
-
- const position = { top: button.offsetTop, left: button.offsetLeft };
- const spacing = 3;
- const menuWidth = 212;
-
- const rtl = document.documentElement.classList.contains("html.rtl");
- const buttonDOMRect = button.getBoundingClientRect();
- position.outerHeight = buttonDOMRect.height;
-
- if (this.attrs.openUpwards) {
- if (rtl) {
- position.left -= buttonDOMRect.width + spacing;
- } else {
- position.left += buttonDOMRect.width + spacing;
- }
- } else {
- if (rtl) {
- if (buttonDOMRect.left < menuWidth) {
- position.left += 0;
- } else {
- position.left -= menuWidth - buttonDOMRect.width;
- }
- } else {
- const offsetRight = window.innerWidth - buttonDOMRect.right;
-
- if (offsetRight < menuWidth) {
- position.left -= menuWidth - buttonDOMRect.width;
- }
- }
-
- position.top += buttonDOMRect.height + spacing;
- }
-
- this.state.position = position;
- },
-
- didRenderWidget() {
- let menuButtons = document.querySelectorAll(
- ".topic-admin-popup-menu button"
- );
-
- if (menuButtons && menuButtons[0]) {
- menuButtons[0].focus();
- }
- },
-
- topicToggleActions() {
- this.state.expanded ? this.hideAdminMenu() : this.showAdminMenu();
- },
-});
-
-export default createWidget("topic-admin-menu", {
- tagName: "div.popup-menu.topic-admin-popup-menu",
-
- buildClasses(attrs) {
- if (attrs.rightSide) {
- return "right-side";
- }
- },
-
- init(attrs) {
- const topic = attrs.topic;
- const details = topic.get("details");
- const isPrivateMessage = topic.get("isPrivateMessage");
- const featured = topic.get("pinned_at") || topic.get("isBanner");
- const visible = topic.get("visible");
-
- // Admin actions
- if (
- this.get("currentUser.canManageTopic") ||
- details.can_split_merge_topic
- ) {
- this.addActionButton({
- className: "topic-admin-multi-select",
- buttonClass: "popup-menu-btn",
- action: "toggleMultiSelect",
- icon: "tasks",
- label: "actions.multi_select",
- button_group: "topic",
- });
- }
-
- if (
- this.get("currentUser.canManageTopic") ||
- details.get("can_moderate_category")
- ) {
- if (details.get("can_delete")) {
- this.addActionButton({
- className: "topic-admin-delete",
- buttonClass: "popup-menu-btn-danger",
- action: "deleteTopic",
- icon: "far-trash-alt",
- label: "actions.delete",
- button_group: "topic",
- });
- }
-
- if (topic.get("deleted") && details.get("can_recover")) {
- this.addActionButton({
- className: "topic-admin-recover",
- buttonClass: "popup-menu-btn",
- action: "recoverTopic",
- icon: "undo",
- label: "actions.recover",
- button_group: "topic",
- });
- }
- }
-
- if (this.currentUser && details.get("can_close_topic")) {
- if (topic.get("closed")) {
- this.addActionButton({
- className: "topic-admin-open",
- buttonClass: "popup-menu-btn",
- action: "toggleClosed",
- icon: "unlock",
- label: "actions.open",
- button_group: "topic",
- });
- } else {
- this.addActionButton({
- className: "topic-admin-close",
- buttonClass: "popup-menu-btn",
- action: "toggleClosed",
- icon: "lock",
- label: "actions.close",
- button_group: "topic",
- });
- }
- }
-
- if (this.get("currentUser.canManageTopic")) {
- this.addActionButton({
- className: "admin-topic-timer-update",
- buttonClass: "popup-menu-btn",
- action: "showTopicTimerModal",
- icon: "far-clock",
- label: "actions.timed_update",
- button_group: "time",
- });
- }
-
- if (
- details.get("can_pin_unpin_topic") &&
- !isPrivateMessage &&
- (topic.get("visible") || featured)
- ) {
- this.addActionButton({
- className: "topic-admin-pin",
- buttonClass: "popup-menu-btn",
- action: "showFeatureTopic",
- icon: "thumbtack",
- label: featured ? "actions.unpin" : "actions.pin",
- button_group: "topic",
- });
- }
-
- if (this.get("currentUser.canManageTopic")) {
- if (this.currentUser.get("staff")) {
- this.addActionButton({
- className: "topic-admin-change-timestamp",
- buttonClass: "popup-menu-btn",
- action: "showChangeTimestamp",
- icon: "calendar-alt",
- label: "change_timestamp.title",
- button_group: "time",
- });
- }
-
- this.addActionButton({
- className: "topic-admin-reset-bump-date",
- buttonClass: "popup-menu-btn",
- action: "resetBumpDate",
- icon: "anchor",
- label: "actions.reset_bump_date",
- button_group: "time",
- });
- }
-
- if (this.currentUser && details.get("can_archive_topic")) {
- if (!isPrivateMessage) {
- this.addActionButton({
- className: "topic-admin-archive",
- buttonClass: "popup-menu-btn",
- action: "toggleArchived",
- icon: "folder",
- label: topic.get("archived")
- ? "actions.unarchive"
- : "actions.archive",
- button_group: "topic",
- });
- }
- }
-
- if (details.get("can_toggle_topic_visibility")) {
- this.addActionButton({
- className: "topic-admin-visible",
- buttonClass: "popup-menu-btn",
- action: "toggleVisibility",
- icon: visible ? "far-eye-slash" : "far-eye",
- label: visible ? "actions.invisible" : "actions.visible",
- button_group: "topic",
- });
- }
-
- if (this.get("currentUser.canManageTopic")) {
- if (details.get("can_convert_topic")) {
- this.addActionButton({
- className: "topic-admin-convert",
- buttonClass: "popup-menu-btn",
- action: isPrivateMessage
- ? "convertToPublicTopic"
- : "convertToPrivateMessage",
- icon: isPrivateMessage ? "comment" : "envelope",
- label: isPrivateMessage
- ? "actions.make_public"
- : "actions.make_private",
- button_group: "topic",
- });
- }
-
- this.addActionButton({
- className: "topic-admin-slow-mode",
- buttonClass: "popup-menu-btn",
- action: "showTopicSlowModeUpdate",
- icon: "hourglass-start",
- label: "actions.slow_mode",
- button_group: "time",
- });
-
- if (this.currentUser.get("staff")) {
- this.addActionButton({
- icon: "list",
- buttonClass: "popup-menu-btn",
- fullLabel: "review.moderation_history",
- url: `/review?topic_id=${topic.id}&status=all`,
- });
- }
- }
- },
-
- buildAttributes(attrs) {
- let { top, left, outerHeight } = attrs.position;
- const position = this.site.mobileView ? "fixed" : "absolute";
- const approxMenuHeight = attrs.actionButtons.length * 42;
-
- if (attrs.rightSide) {
- return;
- }
-
- if (attrs.openUpwards) {
- const documentHeight = $(document).height();
- const mainHeight = $(".ember-application").height();
- let bottom =
- documentHeight - top - 70 - $(".ember-application").offset().top;
-
- if (documentHeight > mainHeight) {
- bottom = bottom - (documentHeight - mainHeight) - outerHeight;
- }
-
- if (top < approxMenuHeight) {
- bottom =
- bottom - (approxMenuHeight - outerHeight - top) - headerOffset();
- }
-
- if (this.site.mobileView) {
- bottom = 50;
- left = 0;
- }
-
- return {
- style: `position: ${position}; bottom: ${bottom}px; left: ${left}px;`,
- };
- } else {
- return {
- style: `position: ${position}; top: ${top}px; left: ${left}px;`,
- };
- }
- },
-
- addActionButton(button) {
- this.attrs.actionButtons.push(button);
- },
-
- html(attrs) {
- const extraButtons = applyDecorators(
- this,
- "adminMenuButtons",
- this.attrs,
- this.state
- );
-
- const actionButtons = attrs.actionButtons
- .concat(extraButtons)
- .filter(Boolean);
-
- const buttonMap = actionButtons.reduce(
- (prev, current) =>
- prev.set(current.button_group, [
- ...(prev.get(current.button_group) || []),
- current,
- ]),
- new Map()
- );
-
- let combinedButtonLists = [];
-
- for (const [group, buttons] of buttonMap.entries()) {
- let buttonList = [];
- buttons.forEach((button) => {
- buttonList.push(this.attach("admin-menu-button", button));
- });
- combinedButtonLists.push(h(`ul.topic-admin-menu-${group}`, buttonList));
- }
-
- return h("ul", combinedButtonLists);
- },
-
- clickOutside() {
- this.sendWidgetAction("hideAdminMenu");
- },
-});
diff --git a/app/assets/javascripts/discourse/tests/acceptance/topic-admin-menu-test.js b/app/assets/javascripts/discourse/tests/acceptance/topic-admin-menu-test.js
index 8ce2041f8d1..02b9e38a3de 100644
--- a/app/assets/javascripts/discourse/tests/acceptance/topic-admin-menu-test.js
+++ b/app/assets/javascripts/discourse/tests/acceptance/topic-admin-menu-test.js
@@ -1,10 +1,12 @@
import { click, visit } from "@ember/test-helpers";
import { test } from "qunit";
+import { withPluginApi } from "discourse/lib/plugin-api";
import {
acceptance,
exists,
updateCurrentUser,
} from "discourse/tests/helpers/qunit-helpers";
+import I18n from "discourse-i18n";
acceptance("Topic - Admin Menu Anonymous Users", function () {
test("Enter as a regular user", async function (assert) {
@@ -44,16 +46,34 @@ acceptance("Topic - Admin Menu", function (needs) {
);
});
- test("Toggle the menu as admin focuses the first item", async function (assert) {
+ test("Button added using addTopicAdminMenuButton", async function (assert) {
updateCurrentUser({ admin: true });
+ this.set("actionCalled", false);
+
+ withPluginApi("1.31.0", (api) => {
+ api.addTopicAdminMenuButton(() => {
+ return {
+ className: "extra-button",
+ icon: "heart",
+ label: "yes_value",
+ action: () => {
+ this.set("actionCalled", true);
+ },
+ };
+ });
+ });
await visit("/t/internationalization-localization/280");
assert.ok(exists("#topic"), "The topic was rendered");
await click(".toggle-admin-menu");
-
- assert.strictEqual(
- document.activeElement,
- document.querySelector(".topic-admin-multi-select > button")
+ assert.ok(
+ exists(".extra-button svg.d-icon-heart"),
+ "The icon was rendered"
);
+ assert
+ .dom(".extra-button .d-button-label")
+ .hasText(I18n.t("yes_value"), "The label was rendered");
+ await click(".extra-button");
+ assert.ok(this.actionCalled, "The action was called");
});
});
diff --git a/app/assets/javascripts/discourse/tests/integration/components/widgets/topic-admin-menu-test.js b/app/assets/javascripts/discourse/tests/integration/components/widgets/topic-admin-menu-test.js
deleted file mode 100644
index 23dbc292b24..00000000000
--- a/app/assets/javascripts/discourse/tests/integration/components/widgets/topic-admin-menu-test.js
+++ /dev/null
@@ -1,79 +0,0 @@
-import { getOwner } from "@ember/application";
-import { render } from "@ember/test-helpers";
-import { hbs } from "ember-cli-htmlbars";
-import { module, test } from "qunit";
-import Category from "discourse/models/category";
-import { setupRenderingTest } from "discourse/tests/helpers/component-test";
-import { exists } from "discourse/tests/helpers/qunit-helpers";
-
-const createArgs = (topic) => {
- return {
- topic,
- openUpwards: "true",
- toggleMultiSelect: () => {},
- deleteTopic: () => {},
- recoverTopic: () => {},
- toggleClosed: () => {},
- toggleArchived: () => {},
- toggleVisibility: () => {},
- showTopicTimerModal: () => {},
- showFeatureTopic: () => {},
- showChangeTimestamp: () => {},
- resetBumpDate: () => {},
- convertToPublicTopic: () => {},
- convertToPrivateMessage: () => {},
- };
-};
-
-module(
- "Integration | Component | Widget | topic-admin-menu-button",
- function (hooks) {
- setupRenderingTest(hooks);
-
- test("topic-admin-menu-button is present for admin/moderators", async function (assert) {
- this.currentUser.setProperties({
- admin: true,
- moderator: true,
- id: 123,
- });
-
- const store = getOwner(this).lookup("service:store");
- const topic = store.createRecord("topic", {
- user_id: this.currentUser.id,
- });
- topic.set("category_id", Category.create({ read_restricted: true }).id);
-
- this.siteSettings.allow_featured_topic_on_user_profiles = true;
- this.set("args", createArgs(topic));
-
- await render(
- hbs``
- );
-
- assert.ok(exists(".toggle-admin-menu"), "admin wrench is present");
- });
-
- test("topic-admin-menu-button hides for non-admin when there is no action", async function (assert) {
- this.currentUser.setProperties({
- admin: false,
- moderator: false,
- id: 123,
- });
-
- const store = getOwner(this).lookup("service:store");
- const topic = store.createRecord("topic", {
- user_id: this.currentUser.id,
- });
- topic.set("category_id", Category.create({ read_restricted: true }).id);
-
- this.siteSettings.allow_featured_topic_on_user_profiles = true;
- this.set("args", createArgs(topic));
-
- await render(
- hbs``
- );
-
- assert.ok(!exists(".toggle-admin-menu"), "admin wrench is not present");
- });
- }
-);
diff --git a/app/assets/javascripts/float-kit/addon/components/d-inline-float.gjs b/app/assets/javascripts/float-kit/addon/components/d-inline-float.gjs
index 68c1860df49..74d8b76d932 100644
--- a/app/assets/javascripts/float-kit/addon/components/d-inline-float.gjs
+++ b/app/assets/javascripts/float-kit/addon/components/d-inline-float.gjs
@@ -1,26 +1,50 @@
+import Component from "@glimmer/component";
+import { inject as service } from "@ember/service";
+import { and } from "truth-helpers";
+import DModal from "discourse/components/d-modal";
import DFloatBody from "float-kit/components/d-float-body";
-const DInlineFloat =
- {{#if @instance.expanded}}
-
- {{#if @instance.options.component}}
- <@instance.options.component
- @data={{@instance.options.data}}
- @close={{@instance.close}}
- />
- {{else}}
- {{@instance.options.content}}
- {{/if}}
-
- {{/if}}
-;
+export default class DInlineFloat extends Component {
+ @service site;
-export default DInlineFloat;
+
+ {{#if @instance.expanded}}
+ {{#if (and this.site.mobileView @instance.options.modalForMobile)}}
+
+ {{#if @instance.options.component}}
+ <@instance.options.component
+ @data={{@instance.options.data}}
+ @close={{@instance.close}}
+ />
+ {{else}}
+ {{@instance.options.content}}
+ {{/if}}
+
+ {{else}}
+
+ {{#if @instance.options.component}}
+ <@instance.options.component
+ @data={{@instance.options.data}}
+ @close={{@instance.close}}
+ />
+ {{else}}
+ {{@instance.options.content}}
+ {{/if}}
+
+ {{/if}}
+ {{/if}}
+
+}
diff --git a/app/assets/javascripts/float-kit/addon/components/d-menu.gjs b/app/assets/javascripts/float-kit/addon/components/d-menu.gjs
index 5711f748e70..e4b157ecf53 100644
--- a/app/assets/javascripts/float-kit/addon/components/d-menu.gjs
+++ b/app/assets/javascripts/float-kit/addon/components/d-menu.gjs
@@ -77,6 +77,7 @@ export default class DMenu extends Component {
"fk-d-menu__trigger"
(if this.menuInstance.expanded "-expanded")
(concat this.options.identifier "-trigger")
+ @triggerClass
}}
id={{this.menuInstance.id}}
data-identifier={{this.options.identifier}}
diff --git a/app/assets/stylesheets/common/base/_index.scss b/app/assets/stylesheets/common/base/_index.scss
index 5f4cea26a9d..467de2b22f5 100644
--- a/app/assets/stylesheets/common/base/_index.scss
+++ b/app/assets/stylesheets/common/base/_index.scss
@@ -37,7 +37,6 @@
@import "not-found";
@import "onebox";
@import "personal-message";
-@import "popup-menu";
@import "redirection";
@import "reviewables";
@import "revise-and-reject-post-reviewable";
diff --git a/app/assets/stylesheets/common/base/popup-menu.scss b/app/assets/stylesheets/common/base/popup-menu.scss
deleted file mode 100644
index 6ad14250579..00000000000
--- a/app/assets/stylesheets/common/base/popup-menu.scss
+++ /dev/null
@@ -1,66 +0,0 @@
-.popup-menu {
- background-color: var(--secondary);
- width: 14em;
- border: 1px solid var(--primary-low);
- z-index: z("dropdown");
- box-shadow: var(--shadow-card);
-
- ul {
- margin: 0;
- list-style: none;
-
- li {
- border-bottom: 1px solid rgba(var(--primary-low-rgb), 0.5);
-
- &:last-child {
- border: none;
- }
- }
- }
-
- .btn {
- justify-content: left;
- text-align: left;
- background: none;
- width: 100%;
- padding: 0.5em;
- border-radius: 0;
- margin: 0;
-
- .d-icon {
- color: var(--primary-medium);
- align-self: flex-start;
- margin-right: 0.75em;
- margin-top: 0.1em; // vertical alignment
- }
-
- &:focus,
- &:hover {
- color: var(--primary);
- background: var(--d-hover);
-
- .d-icon {
- color: var(--primary-medium);
- }
- }
-
- &.popup-menu-btn-danger {
- .d-icon {
- color: var(--danger);
- }
-
- .d-button-label {
- color: var(--primary);
- }
-
- &:focus,
- &:hover {
- .d-icon,
- .d-button-label {
- color: var(--danger);
- }
- background: var(--danger-low);
- }
- }
- }
-}
diff --git a/app/assets/stylesheets/common/base/topic-admin-menu.scss b/app/assets/stylesheets/common/base/topic-admin-menu.scss
index afafb09ab9b..3a8ba416128 100644
--- a/app/assets/stylesheets/common/base/topic-admin-menu.scss
+++ b/app/assets/stylesheets/common/base/topic-admin-menu.scss
@@ -1,42 +1,10 @@
// Styles for the topic admin menu
.topic-admin-popup-menu {
- @include breakpoint(mobile-extra-large) {
- width: calc(100% - 20px);
- margin: 0 10px;
- padding: 0;
- padding-bottom: env(safe-area-inset-bottom);
- z-index: z("modal", "popover");
-
- @keyframes slideUp {
- 0% {
- transform: translateY(100%);
- }
- 100% {
- transform: translateY(0);
- }
- }
- animation: slideUp 0.3s;
- @media (prefers-reduced-motion) {
- animation-duration: 0s;
- }
- }
-
- .mobile-view & {
- z-index: z("modal", "popover");
- }
-
- .btn {
- padding: 0.5rem;
-
- .d-icon {
- font-size: var(--font-down-1);
- margin-top: 2px; // vertical alignment
- margin-right: 0.75em;
- }
- }
-
ul {
+ margin: 0;
+ list-style: none;
+
li {
border: none;
&:not(:last-of-type) {
@@ -45,81 +13,22 @@
}
}
ul {
- padding: 0.5rem;
+ padding: 0.5em;
&:not(:last-of-type) {
border-bottom: 1px solid var(--primary-low);
}
}
- }
-}
-.modal-body.feature-topic {
- max-height: 70vh !important;
- padding: 0 1em;
- input.date-picker {
- margin: 0;
- }
- .feature-section {
- display: block;
- padding: 1.25em 0;
- &:not(:last-of-type) {
- border-bottom: 1px solid var(--primary-low);
- }
- .desc {
- display: inline-block;
- vertical-align: middle;
- p:first-of-type {
- margin: 0;
- }
- p {
- margin: 10px 0 0;
- max-width: 31em;
- }
- }
- .with-validation {
- position: relative;
-
- > span {
- display: flex;
- align-items: flex-start;
- > .d-icon {
- padding-top: 0.75em;
- margin-right: 0.5em;
- }
- }
+ .btn {
+ justify-content: left;
+ text-align: left;
+ width: 100%;
+ padding: 0.5em;
}
}
}
-
-// Select posts
-
-.selected-posts {
- border: 1px solid var(--tertiary-medium);
- background-color: var(--tertiary-low);
- .btn {
- border: none;
- color: var(--secondary);
- font-weight: normal;
- margin-bottom: 10px;
- &:not(.btn-danger) {
- background: var(--tertiary);
- border-color: var(--tertiary);
- &[href] {
- color: var(--secondary);
- }
- &:hover {
- color: var(--secondary);
- background: var(--tertiary-high);
- }
- &:active {
- @include linear-gradient(var(--tertiary-hover), var(--tertiary));
- color: var(--secondary);
- }
- }
- &[disabled] {
- text-shadow: 0 1px 0 rgba(var(--primary-rgb), 0.2);
- @include linear-gradient(var(--tertiary), var(--tertiary-hover));
- box-shadow: inset 0 1px 0 rgba(0, 0, 0, 0.33);
- }
+.fk-d-menu {
+ .topic-admin-popup-menu {
+ width: 14em;
}
}
diff --git a/app/assets/stylesheets/common/base/topic.scss b/app/assets/stylesheets/common/base/topic.scss
index 95de7b4d9ec..25e3941c4d4 100644
--- a/app/assets/stylesheets/common/base/topic.scss
+++ b/app/assets/stylesheets/common/base/topic.scss
@@ -148,23 +148,9 @@
display: flex;
}
}
- .topic-admin-popup-menu.right-side {
- position: absolute;
- bottom: 0;
- right: 0;
- left: auto;
- transition: bottom 0.5s;
- transform: translateZ(
- 0
- ); // iOS11 Rendering bug https://meta.discourse.org/t/wrench-menu-not-disappearing-on-ios/94297
- }
&.docked {
position: initial;
- .topic-admin-popup-menu.right-side {
- bottom: unset;
- right: 10px;
- }
}
html:not(.footer-nav-visible) & {
diff --git a/app/assets/stylesheets/common/components/admin-post-menu.scss b/app/assets/stylesheets/common/components/admin-post-menu.scss
index 521f4cf040a..3e1654ae0f9 100644
--- a/app/assets/stylesheets/common/components/admin-post-menu.scss
+++ b/app/assets/stylesheets/common/components/admin-post-menu.scss
@@ -1,4 +1,8 @@
[data-content][data-identifier="admin-post-menu"] {
+ .d-modal__body {
+ padding: 0;
+ }
+
ul {
padding: 0.5rem;
margin: 0;
@@ -17,5 +21,12 @@
margin-bottom: 0;
}
}
+
+ .btn {
+ justify-content: left;
+ text-align: left;
+ width: 100%;
+ padding: 0.5em;
+ }
}
}
diff --git a/app/assets/stylesheets/mobile/topic.scss b/app/assets/stylesheets/mobile/topic.scss
index 1ed8b5c2389..a7b79f5dad5 100644
--- a/app/assets/stylesheets/mobile/topic.scss
+++ b/app/assets/stylesheets/mobile/topic.scss
@@ -135,39 +135,6 @@ sub sub {
flex-wrap: wrap;
}
-@media screen and (max-height: 600px) {
- .topic-admin-popup-menu {
- box-sizing: border-box;
- padding: 0.25em;
- width: unset;
- ul {
- display: grid;
- grid-template-columns: 1fr 1fr 1fr;
-
- @media screen and (max-width: 550px) {
- grid-template-columns: 1fr 1fr;
- }
-
- ul {
- display: contents;
- }
-
- .d-button-label {
- @include ellipsis;
- }
-
- .popup-menu-btn {
- @include ellipsis;
- }
-
- li {
- border: 0;
- min-width: 0;
- }
- }
- }
-}
-
.container.posts .topic-navigation {
// better positioning for the docked progress bar on large screens using mobile view
grid-area: posts;
diff --git a/docs/CHANGELOG-JAVASCRIPT-PLUGIN-API.md b/docs/CHANGELOG-JAVASCRIPT-PLUGIN-API.md
index 275ce996ee1..307d8a0b86f 100644
--- a/docs/CHANGELOG-JAVASCRIPT-PLUGIN-API.md
+++ b/docs/CHANGELOG-JAVASCRIPT-PLUGIN-API.md
@@ -7,6 +7,10 @@ in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
+## [1.31.0] - 2024-04-22
+
+- Adds `addTopicAdminMenuButton` which allows to register a new button in the topic admin menu.
+
## [1.30.0] - 2024-03-20
- Added `addAdminPluginConfigurationNav`, which defines a list of links used in the adminPlugins.show page for a specific plugin, and displays them either in an inner sidebar or in a top horizontal nav.