From 026cd3e53208c4d4da18a57660da882be6acf95b Mon Sep 17 00:00:00 2001
From: Isaac Janzen <50783505+janzenisaac@users.noreply.github.com>
Date: Mon, 28 Aug 2023 16:51:58 -0500
Subject: [PATCH] DEV: Convert `flag` modal to component-based API (#23279)
# Topic Flag
# Post Flag
# Chat Flag
---
.../app/components/flag-action-type.hbs | 22 +-
.../discourse/app/components/modal/flag.hbs | 80 ++++++
.../discourse/app/components/modal/flag.js | 208 ++++++++++++++
.../components/reviewable-bundled-action.hbs | 7 +-
.../components/reviewable-bundled-action.js | 6 +-
.../discourse/app/controllers/flag.js | 261 ------------------
.../discourse/app/lib/flag-targets/flag.js | 35 +--
.../app/lib/flag-targets/post-flag.js | 13 +-
.../app/lib/flag-targets/topic-flag.js | 18 +-
.../javascripts/discourse/app/routes/topic.js | 19 +-
.../discourse/app/services/modal.js | 1 -
.../discourse/app/templates/modal/flag.hbs | 76 -----
.../tests/acceptance/flag-post-test.js | 12 +-
.../discourse/lib/chat-message-flag.js | 40 +--
.../discourse/lib/chat-message-interactor.js | 11 +-
15 files changed, 379 insertions(+), 430 deletions(-)
create mode 100644 app/assets/javascripts/discourse/app/components/modal/flag.hbs
create mode 100644 app/assets/javascripts/discourse/app/components/modal/flag.js
delete mode 100644 app/assets/javascripts/discourse/app/controllers/flag.js
delete mode 100644 app/assets/javascripts/discourse/app/templates/modal/flag.hbs
diff --git a/app/assets/javascripts/discourse/app/components/flag-action-type.hbs b/app/assets/javascripts/discourse/app/components/flag-action-type.hbs
index 684a7f8bc58..cbb7136b7e4 100644
--- a/app/assets/javascripts/discourse/app/components/flag-action-type.hbs
+++ b/app/assets/javascripts/discourse/app/components/flag-action-type.hbs
@@ -20,14 +20,21 @@
@value={{this.message}}
/>
{{this.customMessageLength}}
+ class={{concat-class
+ "custom-message-length"
+ this.customMessageLengthClasses
+ }}
+ >
+ {{this.customMessageLength}}
+
{{/if}}
- {{#if this.staffFlagsAvailable}}
+ {{#if @includeSeparator}}
+ {{/if}}
+ {{#if this.staffFlagsAvailable}}
{{i18n "flagging.notify_staff"}}
{{/if}}
{{else}}
@@ -53,8 +60,13 @@
@value={{this.message}}
/>
{{this.customMessageLength}}
+ class={{concat-class
+ "custom-message-length"
+ this.customMessageLengthClasses
+ }}
+ >
+ {{this.customMessageLength}}
+
{{/if}}
diff --git a/app/assets/javascripts/discourse/app/components/modal/flag.hbs b/app/assets/javascripts/discourse/app/components/modal/flag.hbs
new file mode 100644
index 00000000000..c3ba55825ae
--- /dev/null
+++ b/app/assets/javascripts/discourse/app/components/modal/flag.hbs
@@ -0,0 +1,80 @@
+
+ <:body>
+
+
+
+ <:footer>
+
+
+ {{#if this.canSendWarning}}
+
+ {{/if}}
+
+ {{#if this.canTakeAction}}
+
+
+
+ {{/if}}
+
+ {{#if this.showDeleteSpammer}}
+
+ {{/if}}
+
+
\ No newline at end of file
diff --git a/app/assets/javascripts/discourse/app/components/modal/flag.js b/app/assets/javascripts/discourse/app/components/modal/flag.js
new file mode 100644
index 00000000000..cee26af1a70
--- /dev/null
+++ b/app/assets/javascripts/discourse/app/components/modal/flag.js
@@ -0,0 +1,208 @@
+import Component from "@glimmer/component";
+import { action } from "@ember/object";
+import { inject as service } from "@ember/service";
+import { tracked } from "@glimmer/tracking";
+import I18n from "I18n";
+import { MAX_MESSAGE_LENGTH } from "discourse/models/post-action-type";
+import User from "discourse/models/user";
+import { reload } from "discourse/helpers/page-reloader";
+
+const NOTIFY_MODERATORS_ID = 7;
+
+export default class Flag extends Component {
+ @service adminTools;
+ @service currentUser;
+ @service siteSettings;
+ @service site;
+ @service appEvents;
+
+ @tracked userDetails;
+ @tracked selected;
+ @tracked message;
+ @tracked isWarning = false;
+ @tracked spammerDetails;
+
+ constructor() {
+ super(...arguments);
+
+ this.adminTools
+ ?.checkSpammer(this.args.model.flagModel.user_id)
+ .then((result) => (this.spammerDetails = result));
+ }
+
+ get flagActions() {
+ return {
+ icon: "gavel",
+ label: I18n.t("flagging.take_action"),
+ actions: [
+ {
+ id: "agree_and_keep",
+ icon: "thumbs-up",
+ label: I18n.t("flagging.take_action_options.default.title"),
+ description: I18n.t("flagging.take_action_options.default.details"),
+ },
+ {
+ id: "agree_and_suspend",
+ icon: "ban",
+ label: I18n.t("flagging.take_action_options.suspend.title"),
+ description: I18n.t("flagging.take_action_options.suspend.details"),
+ client_action: "suspend",
+ },
+ {
+ id: "agree_and_silence",
+ icon: "microphone-slash",
+ label: I18n.t("flagging.take_action_options.silence.title"),
+ description: I18n.t("flagging.take_action_options.silence.details"),
+ client_action: "silence",
+ },
+ ],
+ };
+ }
+
+ get canSendWarning() {
+ return (
+ !this.args.model.flagTarget.targetsTopic() &&
+ this.currentUser.staff &&
+ this.selected?.name_key === "notify_user"
+ );
+ }
+
+ get submitLabel() {
+ if (this.selected?.is_custom_flag) {
+ return this.args.model.flagTarget.customSubmitLabel();
+ }
+
+ return this.args.model.flagTarget.submitLabel();
+ }
+
+ get includeSeparator() {
+ return (
+ this.staffFlagsAvailable ||
+ this.args.model.flagTarget.includeSeparator?.()
+ );
+ }
+
+ get title() {
+ return this.args.model.flagTarget.title();
+ }
+
+ get flagsAvailable() {
+ return this.args.model.flagTarget.flagsAvailable(this);
+ }
+
+ get staffFlagsAvailable() {
+ return this.args.model.flagModel.flagsAvailable?.length > 1;
+ }
+
+ get submitEnabled() {
+ if (!this.selected) {
+ return false;
+ }
+
+ if (!this.selected.is_custom_flag) {
+ return true;
+ }
+
+ const len = this.message?.length || 0;
+ return (
+ len >= this.siteSettings.min_personal_message_post_length &&
+ len <= MAX_MESSAGE_LENGTH
+ );
+ }
+
+ get notifyModeratorsFlag() {
+ return this.flagsAvailable.find((f) => f.id === NOTIFY_MODERATORS_ID);
+ }
+
+ get canTakeAction() {
+ return (
+ !this.args.model.flagTarget.targetsTopic() &&
+ !this.selected?.is_custom_flag &&
+ this.currentUser.staff
+ );
+ }
+
+ @action
+ onKeydown(event) {
+ if (
+ this.submitEnabled &&
+ event.key === "Enter" &&
+ (event.ctrlKey || event.metaKey)
+ ) {
+ this.createFlag();
+ return false;
+ }
+ }
+
+ @action
+ async penalize(adminToolMethod, performAction) {
+ if (!this.adminTools) {
+ return;
+ }
+
+ const createdBy = await User.findByUsername(
+ this.args.model.flagModel.username
+ );
+ const opts = { before: performAction };
+
+ if (this.args.model.flagTarget.editable()) {
+ opts.postId = this.args.model.flagModel.id;
+ opts.postEdit = this.args.model.flagModel.cooked;
+ }
+
+ return this.adminTools[adminToolMethod](createdBy, opts);
+ }
+
+ @action
+ async deleteSpammer() {
+ if (this.spammerDetails) {
+ await this.spammerDetails.deleteUser();
+ reload();
+ }
+ }
+
+ @action
+ async takeAction(actionable) {
+ if (actionable.client_action === "suspend") {
+ await this.penalize("showSuspendModal", () =>
+ this.createFlag({ takeAction: true, skipClose: true })
+ );
+ } else if (actionable.client_action === "silence") {
+ await this.penalize("showSilenceModal", () =>
+ this.createFlag({ takeAction: true, skipClose: true })
+ );
+ } else if (actionable.client_action) {
+ // eslint-disable-next-line no-console
+ console.error(`No handler for ${actionable.client_action} found`);
+ } else {
+ this.args.model.setHidden();
+ this.createFlag({ takeAction: true });
+ }
+ }
+
+ @action
+ createFlag(opts = {}) {
+ if (this.selected.is_custom_flag) {
+ opts.message = this.message;
+ }
+ this.args.model.flagTarget.create(this, opts);
+ }
+
+ @action
+ createFlagAsWarning() {
+ this.createFlag({ isWarning: true });
+ this.args.model.setHidden();
+ }
+
+ @action
+ flagForReview() {
+ this.selected ||= this.notifyModeratorsFlag;
+ this.createFlag({ queue_for_review: true });
+ this.args.model.setHidden();
+ }
+
+ @action
+ changePostActionType(actionType) {
+ this.selected = actionType;
+ }
+}
diff --git a/app/assets/javascripts/discourse/app/components/reviewable-bundled-action.hbs b/app/assets/javascripts/discourse/app/components/reviewable-bundled-action.hbs
index 6c1efeed032..d4566708028 100644
--- a/app/assets/javascripts/discourse/app/components/reviewable-bundled-action.hbs
+++ b/app/assets/javascripts/discourse/app/components/reviewable-bundled-action.hbs
@@ -17,13 +17,12 @@
/>
{{else}}
diff --git a/app/assets/javascripts/discourse/app/components/reviewable-bundled-action.js b/app/assets/javascripts/discourse/app/components/reviewable-bundled-action.js
index 27b3942f433..bc892b078db 100644
--- a/app/assets/javascripts/discourse/app/components/reviewable-bundled-action.js
+++ b/app/assets/javascripts/discourse/app/components/reviewable-bundled-action.js
@@ -18,11 +18,11 @@ export default Component.extend({
actions: {
performById(id) {
- this.attrs.performAction(this.get("bundle.actions").findBy("id", id));
+ this.performAction(this.get("bundle.actions").findBy("id", id));
},
- perform(action) {
- this.attrs.performAction(action);
+ performFirst() {
+ this.performAction(this.first);
},
},
});
diff --git a/app/assets/javascripts/discourse/app/controllers/flag.js b/app/assets/javascripts/discourse/app/controllers/flag.js
deleted file mode 100644
index 8d2f6bbbe9d..00000000000
--- a/app/assets/javascripts/discourse/app/controllers/flag.js
+++ /dev/null
@@ -1,261 +0,0 @@
-import { schedule } from "@ember/runloop";
-import Controller from "@ember/controller";
-import I18n from "I18n";
-import { MAX_MESSAGE_LENGTH } from "discourse/models/post-action-type";
-import ModalFunctionality from "discourse/mixins/modal-functionality";
-import { Promise } from "rsvp";
-import User from "discourse/models/user";
-import discourseComputed, { bind } from "discourse-common/utils/decorators";
-import { not } from "@ember/object/computed";
-import optionalService from "discourse/lib/optional-service";
-import { classify } from "@ember/string";
-
-export default Controller.extend(ModalFunctionality, {
- adminTools: optionalService(),
- userDetails: null,
- selected: null,
- message: null,
- isWarning: false,
- topicActionByName: null,
- spammerDetails: null,
- flagActions: null,
- flagTarget: null,
-
- init() {
- this._super(...arguments);
- this.flagActions = {
- icon: "gavel",
- label: I18n.t("flagging.take_action"),
- actions: [
- {
- id: "agree_and_keep",
- icon: "thumbs-up",
- label: I18n.t("flagging.take_action_options.default.title"),
- description: I18n.t("flagging.take_action_options.default.details"),
- },
- {
- id: "agree_and_suspend",
- icon: "ban",
- label: I18n.t("flagging.take_action_options.suspend.title"),
- description: I18n.t("flagging.take_action_options.suspend.details"),
- client_action: "suspend",
- },
- {
- id: "agree_and_silence",
- icon: "microphone-slash",
- label: I18n.t("flagging.take_action_options.silence.title"),
- description: I18n.t("flagging.take_action_options.silence.details"),
- client_action: "silence",
- },
- ],
- };
- },
-
- @bind
- keyDown(event) {
- // CTRL+ENTER or CMD+ENTER
- if (event.key === "Enter" && (event.ctrlKey || event.metaKey)) {
- if (this.submitEnabled) {
- this.send("createFlag");
- return false;
- }
- }
- },
-
- clientSuspend(performAction) {
- this._penalize("showSuspendModal", performAction);
- },
-
- clientSilence(performAction) {
- this._penalize("showSilenceModal", performAction);
- },
-
- _penalize(adminToolMethod, performAction) {
- if (this.adminTools) {
- return User.findByUsername(this.model.username).then((createdBy) => {
- const opts = { before: performAction };
-
- if (this.flagTarget.editable()) {
- opts.postId = this.model.id;
- opts.postEdit = this.model.cooked;
- }
-
- return this.adminTools[adminToolMethod](createdBy, opts);
- });
- }
- },
-
- onShow() {
- this.setProperties({
- selected: null,
- spammerDetails: null,
- });
-
- if (this.adminTools) {
- this.adminTools.checkSpammer(this.get("model.user_id")).then((result) => {
- this.set("spammerDetails", result);
- });
- }
-
- schedule("afterRender", () => {
- const element = document.querySelector(".flag-modal");
- element.addEventListener("keydown", this.keyDown);
- });
- },
-
- onClose() {
- const element = document.querySelector(".flag-modal");
- element.removeEventListener("keydown", this.keyDown);
- },
-
- @discourseComputed("spammerDetails.canDelete", "selected.name_key")
- showDeleteSpammer(canDeleteSpammer, nameKey) {
- return canDeleteSpammer && nameKey === "spam";
- },
-
- @discourseComputed("flagTarget")
- title(flagTarget) {
- return flagTarget.title();
- },
-
- @discourseComputed(
- "post",
- "flagTarget",
- "model.actions_summary.@each.can_act"
- )
- flagsAvailable() {
- return this.flagTarget.flagsAvailable(this, this.site, this.model);
- },
-
- @discourseComputed(
- "post",
- "flagTarget",
- "model.actions_summary.@each.can_act"
- )
- staffFlagsAvailable() {
- return (
- this.get("model.flagsAvailable") &&
- this.get("model.flagsAvailable").length > 1
- );
- },
-
- @discourseComputed("selected.is_custom_flag", "message.length")
- submitEnabled() {
- const selected = this.selected;
- if (!selected) {
- return false;
- }
-
- if (selected.get("is_custom_flag")) {
- const len = this.get("message.length") || 0;
- return (
- len >= this.siteSettings.min_personal_message_post_length &&
- len <= MAX_MESSAGE_LENGTH
- );
- }
- return true;
- },
-
- submitDisabled: not("submitEnabled"),
- cantFlagForReview: not("notifyModeratorsFlag"),
-
- @discourseComputed("flagsAvailable")
- notifyModeratorsFlag(flagsAvailable) {
- const notifyModeratorsID = 7;
- return flagsAvailable.find((f) => f.id === notifyModeratorsID);
- },
-
- // Staff accounts can "take action"
- @discourseComputed("flagTarget", "selected.is_custom_flag")
- canTakeAction(flagTarget, isCustomFlag) {
- return (
- !flagTarget.targetsTopic() &&
- !isCustomFlag &&
- this.currentUser.get("staff")
- );
- },
-
- @discourseComputed("selected.is_custom_flag")
- submitIcon(isCustomFlag) {
- return isCustomFlag ? "envelope" : "flag";
- },
-
- @discourseComputed("selected.is_custom_flag", "flagTarget")
- submitLabel(isCustomFlag, flagTarget) {
- if (isCustomFlag) {
- return flagTarget.customSubmitLabel();
- }
-
- return flagTarget.submitLabel();
- },
-
- actions: {
- deleteSpammer() {
- let details = this.spammerDetails;
- if (details) {
- details.deleteUser().then(() => window.location.reload());
- }
- },
-
- takeAction(action) {
- let performAction = (o = {}) => {
- o.takeAction = true;
- this.send("createFlag", o);
- return Promise.resolve();
- };
-
- if (action.client_action) {
- let actionMethod = this[`client${classify(action.client_action)}`];
- if (actionMethod) {
- return actionMethod.call(this, () =>
- performAction({ skipClose: true })
- );
- } else {
- // eslint-disable-next-line no-console
- console.error(`No handler for ${action.client_action} found`);
- return;
- }
- } else {
- this.set("model.hidden", true);
- return performAction();
- }
- },
-
- createFlag(opts) {
- const params = opts || {};
-
- if (this.get("selected.is_custom_flag")) {
- params.message = this.message;
- }
-
- this.flagTarget.create(this, params);
- },
-
- createFlagAsWarning() {
- this.send("createFlag", { isWarning: true });
- this.set("model.hidden", true);
- },
-
- flagForReview() {
- if (!this.selected) {
- this.set("selected", this.get("notifyModeratorsFlag"));
- }
-
- this.send("createFlag", { queue_for_review: true });
- this.set("model.hidden", true);
- },
-
- changePostActionType(action) {
- this.set("selected", action);
- },
- },
-
- @discourseComputed("flagTarget", "selected.name_key")
- canSendWarning(flagTarget, nameKey) {
- return (
- !flagTarget.targetsTopic() &&
- this.currentUser.get("staff") &&
- nameKey === "notify_user"
- );
- },
-});
diff --git a/app/assets/javascripts/discourse/app/lib/flag-targets/flag.js b/app/assets/javascripts/discourse/app/lib/flag-targets/flag.js
index b2affe83496..dd1d59b0a51 100644
--- a/app/assets/javascripts/discourse/app/lib/flag-targets/flag.js
+++ b/app/assets/javascripts/discourse/app/lib/flag-targets/flag.js
@@ -9,41 +9,24 @@ export default class Flag {
return true;
}
- create(controller, opts) {
+ create(flagModal, opts) {
// an instance of ActionSummary
- let postAction = this.postActionFor(controller);
-
- controller.appEvents.trigger(
+ const postAction = this.postActionFor(flagModal);
+ flagModal.appEvents.trigger(
this.flagCreatedEvent,
- controller.model,
+ flagModal.args.model.flagModel,
postAction,
opts
);
- controller.send("hideModal");
-
+ flagModal.args.closeModal();
postAction
- .act(controller.model, opts)
+ .act(flagModal.args.model.flagModel, opts)
.then(() => {
- if (controller.isDestroying || controller.isDestroyed) {
- return;
- }
-
- if (!opts.skipClose) {
- controller.send("closeModal");
- }
- if (opts.message) {
- controller.set("message", "");
- }
- controller.appEvents.trigger("post-stream:refresh", {
- id: controller.get("model.id"),
+ flagModal.appEvents.trigger("post-stream:refresh", {
+ id: flagModal.args.model.flagModel.id,
});
})
- .catch((error) => {
- if (!controller.isDestroying && !controller.isDestroyed) {
- controller.send("closeModal");
- }
- popupAjaxError(error);
- });
+ .catch((error) => popupAjaxError(error));
}
}
diff --git a/app/assets/javascripts/discourse/app/lib/flag-targets/post-flag.js b/app/assets/javascripts/discourse/app/lib/flag-targets/post-flag.js
index f30fd72ba27..aee12e73807 100644
--- a/app/assets/javascripts/discourse/app/lib/flag-targets/post-flag.js
+++ b/app/assets/javascripts/discourse/app/lib/flag-targets/post-flag.js
@@ -17,8 +17,8 @@ export default class PostFlag extends Flag {
return "post:flag-created";
}
- flagsAvailable(_flagController, _site, model) {
- let flagsAvailable = model.flagsAvailable;
+ flagsAvailable(flagModal) {
+ let flagsAvailable = flagModal.args.model.flagModel.flagsAvailable;
// "message user" option should be at the top
const notifyUserIndex = flagsAvailable.indexOf(
@@ -34,9 +34,10 @@ export default class PostFlag extends Flag {
return flagsAvailable;
}
- postActionFor(controller) {
- return controller
- .get("model.actions_summary")
- .findBy("id", controller.get("selected.id"));
+ postActionFor(flagModal) {
+ return flagModal.args.model.flagModel.actions_summary.findBy(
+ "id",
+ flagModal.selected.id
+ );
}
}
diff --git a/app/assets/javascripts/discourse/app/lib/flag-targets/topic-flag.js b/app/assets/javascripts/discourse/app/lib/flag-targets/topic-flag.js
index e8df5440fd9..45887e92bbb 100644
--- a/app/assets/javascripts/discourse/app/lib/flag-targets/topic-flag.js
+++ b/app/assets/javascripts/discourse/app/lib/flag-targets/topic-flag.js
@@ -23,24 +23,24 @@ export default class TopicFlag extends Flag {
return "topic:flag-created";
}
- flagsAvailable(flagController, site, model) {
+ flagsAvailable(flagModal) {
let lookup = EmberObject.create();
- model.actions_summary.forEach((a) => {
- a.flagTopic = model;
- a.actionType = site.topicFlagTypeById(a.id);
+ flagModal.args.model.flagModel.actions_summary.forEach((a) => {
+ a.flagTopic = flagModal.args.model.flagModel;
+ a.actionType = flagModal.site.topicFlagTypeById(a.id);
lookup.set(a.actionType.name_key, ActionSummary.create(a));
});
- flagController.set("topicActionByName", lookup);
+ flagModal.topicActionByName = lookup;
- return site.topic_flag_types.filter((item) => {
- return model.actions_summary.some((a) => {
+ return flagModal.site.topic_flag_types.filter((item) => {
+ return flagModal.args.model.flagModel.actions_summary.some((a) => {
return a.id === item.id && a.can_act;
});
});
}
- postActionFor(controller) {
- return controller.get(`topicActionByName.${controller.selected.name_key}`);
+ postActionFor(flagModal) {
+ return flagModal.topicActionByName[flagModal.selected.name_key];
}
}
diff --git a/app/assets/javascripts/discourse/app/routes/topic.js b/app/assets/javascripts/discourse/app/routes/topic.js
index 499d1a50f9c..b7c71c74339 100644
--- a/app/assets/javascripts/discourse/app/routes/topic.js
+++ b/app/assets/javascripts/discourse/app/routes/topic.js
@@ -16,6 +16,7 @@ import EditSlowModeModal from "discourse/components/modal/edit-slow-mode";
import ChangeTimestampModal from "discourse/components/modal/change-timestamp";
import EditTopicTimerModal from "discourse/components/modal/edit-topic-timer";
import FeatureTopicModal from "discourse/components/modal/feature-topic";
+import FlagModal from "discourse/components/modal/flag";
const SCROLL_DELAY = 500;
@@ -103,15 +104,25 @@ const TopicRoute = DiscourseRoute.extend({
@action
showFlags(model) {
- let controller = showModal("flag", { model });
- controller.setProperties({ flagTarget: new PostFlag() });
+ this.modal.show(FlagModal, {
+ model: {
+ flagTarget: new PostFlag(),
+ flagModel: model,
+ setHidden: () => model.set("hidden", true),
+ },
+ });
},
@action
showFlagTopic() {
const model = this.modelFor("topic");
- let controller = showModal("flag", { model });
- controller.setProperties({ flagTarget: new TopicFlag() });
+ this.modal.show(FlagModal, {
+ model: {
+ flagTarget: new TopicFlag(),
+ flagModel: model,
+ setHidden: () => model.set("hidden", true),
+ },
+ });
},
@action
diff --git a/app/assets/javascripts/discourse/app/services/modal.js b/app/assets/javascripts/discourse/app/services/modal.js
index ad454f48b57..c817cbe923b 100644
--- a/app/assets/javascripts/discourse/app/services/modal.js
+++ b/app/assets/javascripts/discourse/app/services/modal.js
@@ -18,7 +18,6 @@ const KNOWN_LEGACY_MODALS = [
"create-account",
"create-invite-bulk",
"create-invite",
- "flag",
"grant-badge",
"group-default-notifications",
"login",
diff --git a/app/assets/javascripts/discourse/app/templates/modal/flag.hbs b/app/assets/javascripts/discourse/app/templates/modal/flag.hbs
deleted file mode 100644
index c118abc5adc..00000000000
--- a/app/assets/javascripts/discourse/app/templates/modal/flag.hbs
+++ /dev/null
@@ -1,76 +0,0 @@
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/assets/javascripts/discourse/tests/acceptance/flag-post-test.js b/app/assets/javascripts/discourse/tests/acceptance/flag-post-test.js
index 0446e958e39..7413af87a54 100644
--- a/app/assets/javascripts/discourse/tests/acceptance/flag-post-test.js
+++ b/app/assets/javascripts/discourse/tests/acceptance/flag-post-test.js
@@ -158,31 +158,31 @@ acceptance("flagging", function (needs) {
await visit("/t/internationalization-localization/280");
await openFlagModal();
- const modal = query("#discourse-modal");
+ const modal = query(".d-modal");
await pressEnter(modal, "ctrlKey");
assert.ok(
- exists("#discourse-modal:visible"),
+ exists(".d-modal:visible"),
"The modal wasn't closed because the accept button was disabled"
);
await click("#radio_inappropriate"); // this enables the accept button
await pressEnter(modal, "ctrlKey");
- assert.ok(!exists("#discourse-modal:visible"), "The modal was closed");
+ assert.ok(!exists(".d-modal:visible"), "The modal was closed");
});
test("CMD or WINDOWS-KEY + ENTER accepts the modal", async function (assert) {
await visit("/t/internationalization-localization/280");
await openFlagModal();
- const modal = query("#discourse-modal");
+ const modal = query(".d-modal");
await pressEnter(modal, "metaKey");
assert.ok(
- exists("#discourse-modal:visible"),
+ exists(".d-modal:visible"),
"The modal wasn't closed because the accept button was disabled"
);
await click("#radio_inappropriate"); // this enables the accept button
await pressEnter(modal, "ctrlKey");
- assert.ok(!exists("#discourse-modal:visible"), "The modal was closed");
+ assert.ok(!exists(".d-modal:visible"), "The modal was closed");
});
});
diff --git a/plugins/chat/assets/javascripts/discourse/lib/chat-message-flag.js b/plugins/chat/assets/javascripts/discourse/lib/chat-message-flag.js
index 9bd86b4ab40..6e45404d4aa 100644
--- a/plugins/chat/assets/javascripts/discourse/lib/chat-message-flag.js
+++ b/plugins/chat/assets/javascripts/discourse/lib/chat-message-flag.js
@@ -24,6 +24,10 @@ export default class ChatMessageFlag {
return false;
}
+ includeSeparator() {
+ return true;
+ }
+
_rewriteFlagDescriptions(flags) {
return flags.map((flag) => {
flag.set(
@@ -34,11 +38,13 @@ export default class ChatMessageFlag {
});
}
- flagsAvailable(_controller, site, model) {
- let flagsAvailable = site.flagTypes;
+ flagsAvailable(flagModal) {
+ let flagsAvailable = flagModal.site.flagTypes;
flagsAvailable = flagsAvailable.filter((flag) => {
- return model.availableFlags.includes(flag.name_key);
+ return flagModal.args.model.flagModel.availableFlags.includes(
+ flag.name_key
+ );
});
// "message user" option should be at the top
@@ -55,37 +61,19 @@ export default class ChatMessageFlag {
return this._rewriteFlagDescriptions(flagsAvailable);
}
- create(controller, opts) {
- controller.send("hideModal");
+ create(flagModal, opts) {
+ flagModal.args.closeModal();
return ajax("/chat/flag", {
method: "PUT",
data: {
- chat_message_id: controller.get("model.id"),
- flag_type_id: controller.get("selected.id"),
+ chat_message_id: flagModal.args.model.flagModel.id,
+ flag_type_id: flagModal.selected.id,
message: opts.message,
is_warning: opts.isWarning,
take_action: opts.takeAction,
queue_for_review: opts.queue_for_review,
},
- })
- .then(() => {
- if (controller.isDestroying || controller.isDestroyed) {
- return;
- }
-
- if (!opts.skipClose) {
- controller.send("closeModal");
- }
- if (opts.message) {
- controller.set("message", "");
- }
- })
- .catch((error) => {
- if (!controller.isDestroying && !controller.isDestroyed) {
- controller.send("closeModal");
- }
- popupAjaxError(error);
- });
+ }).catch((error) => popupAjaxError(error));
}
}
diff --git a/plugins/chat/assets/javascripts/discourse/lib/chat-message-interactor.js b/plugins/chat/assets/javascripts/discourse/lib/chat-message-interactor.js
index 0eba137a036..5ef9ab528a0 100644
--- a/plugins/chat/assets/javascripts/discourse/lib/chat-message-interactor.js
+++ b/plugins/chat/assets/javascripts/discourse/lib/chat-message-interactor.js
@@ -1,6 +1,5 @@
import getURL from "discourse-common/lib/get-url";
import { bind } from "discourse-common/utils/decorators";
-import showModal from "discourse/lib/show-modal";
import ChatMessageFlag from "discourse/plugins/chat/discourse/lib/chat-message-flag";
import Bookmark from "discourse/models/bookmark";
import BookmarkModal from "discourse/components/modal/bookmark";
@@ -18,6 +17,7 @@ import { tracked } from "@glimmer/tracking";
import ChatMessage from "discourse/plugins/chat/discourse/models/chat-message";
import { MESSAGE_CONTEXT_THREAD } from "discourse/plugins/chat/discourse/components/chat-message";
import I18n from "I18n";
+import FlagModal from "discourse/components/modal/flag";
const removedSecondaryActions = new Set();
@@ -338,8 +338,13 @@ export default class ChatMessageInteractor {
const model = new ChatMessage(this.message.channel, this.message);
model.username = this.message.user?.username;
model.user_id = this.message.user?.id;
- const controller = showModal("flag", { model });
- controller.set("flagTarget", new ChatMessageFlag());
+ this.modal.show(FlagModal, {
+ model: {
+ flagTarget: new ChatMessageFlag(),
+ flagModel: model,
+ setHidden: () => model.set("hidden", true),
+ },
+ });
}
@action