FEATURE: Ask user to confirm topic deletion when views exceed a certain amount (#11006)
Before deleting a topic that has a high number of views (default of 5000), the user will be prompted with a confirmation popup. This works for all delete buttons on the topic located in: topic-timeline, topic-admin-menu, topic-footer-buttons, and post-menu if the post's ID is 1. The delete button will be disabled while deletion is in progress, to prevent any unwanted behavior. A site setting is also available to change the minimum amount of views required to display the confirmation popup. All kudos are going to @RickyC0626. I only rebased with master and added few qunit tests to ensure that this feature works as expected. Original PR: #10459
This commit is contained in:
parent
72810853ea
commit
8e7c746e56
|
@ -0,0 +1,38 @@
|
|||
import I18n from "I18n";
|
||||
import { action } from "@ember/object";
|
||||
import discourseComputed from "discourse-common/utils/decorators";
|
||||
import Controller, { inject } from "@ember/controller";
|
||||
import ModalFunctionality from "discourse/mixins/modal-functionality";
|
||||
|
||||
// Modal that displays confirmation text when user deletes a topic
|
||||
// The modal will display only if the topic exceeds a certain amount of views
|
||||
export default Controller.extend(ModalFunctionality, {
|
||||
topicController: inject("topic"),
|
||||
deletingTopic: false,
|
||||
|
||||
@discourseComputed("deletingTopic")
|
||||
buttonTitle(deletingTopic) {
|
||||
return deletingTopic
|
||||
? I18n.t("deleting")
|
||||
: I18n.t("post.controls.delete_topic_confirm_modal_yes");
|
||||
},
|
||||
|
||||
onShow() {
|
||||
this.set("deletingTopic", false);
|
||||
},
|
||||
|
||||
@action
|
||||
deleteTopic() {
|
||||
this.set("deletingTopic", true);
|
||||
|
||||
this.topicController.model
|
||||
.destroy(this.currentUser)
|
||||
.then(() => this.send("closeModal"))
|
||||
.catch(() => {
|
||||
this.flash(I18n.t("post.controls.delete_topic_error"), "alert-error");
|
||||
this.set("deletingTopic", false);
|
||||
});
|
||||
|
||||
return false;
|
||||
},
|
||||
});
|
|
@ -1295,7 +1295,20 @@ export default Controller.extend(bufferedProperty("model"), {
|
|||
},
|
||||
|
||||
deleteTopic() {
|
||||
this.model.destroy(this.currentUser);
|
||||
if (
|
||||
this.model.views > this.siteSettings.min_topic_views_for_delete_confirm
|
||||
) {
|
||||
this.deleteTopicModal();
|
||||
} else {
|
||||
this.model.destroy(this.currentUser);
|
||||
}
|
||||
},
|
||||
|
||||
deleteTopicModal() {
|
||||
showModal("delete-topic-confirm", {
|
||||
model: this.model,
|
||||
title: "topic.actions.delete",
|
||||
});
|
||||
},
|
||||
|
||||
retryOnRateLimit(times, promise, topicId) {
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
{{#d-modal-body}}
|
||||
<p>{{i18n "post.controls.delete_topic_confirm_modal" minViews=siteSettings.min_topic_views_for_delete_confirm}}</p>
|
||||
{{/d-modal-body}}
|
||||
|
||||
<div class="modal-footer">
|
||||
{{d-button action=(action "deleteTopic")
|
||||
disabled=deletingTopic
|
||||
translatedLabel=buttonTitle
|
||||
class="btn-danger"}}
|
||||
{{d-button action=(route-action "closeModal")
|
||||
label="post.controls.delete_topic_confirm_modal_no"
|
||||
class="btn-primary"}}
|
||||
</div>
|
|
@ -4,7 +4,7 @@ import { test } from "qunit";
|
|||
import I18n from "I18n";
|
||||
import { withPluginApi } from "discourse/lib/plugin-api";
|
||||
import selectKit from "discourse/tests/helpers/select-kit-helper";
|
||||
import { acceptance } from "discourse/tests/helpers/qunit-helpers";
|
||||
import { acceptance, visible } from "discourse/tests/helpers/qunit-helpers";
|
||||
import { IMAGE_VERSION as v } from "pretty-text/emoji/version";
|
||||
|
||||
function selectText(selector) {
|
||||
|
@ -209,6 +209,35 @@ acceptance("Topic", function (needs) {
|
|||
);
|
||||
});
|
||||
|
||||
test("Deleting a topic", async (assert) => {
|
||||
await visit("/t/internationalization-localization/280");
|
||||
await click(".topic-post:eq(0) button.show-more-actions");
|
||||
await click(".widget-button.delete");
|
||||
await click(".toggle-admin-menu");
|
||||
assert.ok(exists(".topic-admin-recover"), "it shows the recover button");
|
||||
});
|
||||
|
||||
test("Deleting a popular topic displays confirmation modal", async function (assert) {
|
||||
this.siteSettings.min_topic_views_for_delete_confirm = 10;
|
||||
await visit("/t/internationalization-localization/280");
|
||||
await click(".topic-post:eq(0) button.show-more-actions");
|
||||
await click(".widget-button.delete");
|
||||
assert.ok(
|
||||
visible(".delete-topic-confirm-modal"),
|
||||
"it shows the delete confirmation modal"
|
||||
);
|
||||
|
||||
await click(".delete-topic-confirm-modal .btn-primary");
|
||||
assert.ok(
|
||||
!visible(".delete-topic-confirm-modal"),
|
||||
"it hides the delete confirmation modal"
|
||||
);
|
||||
await click(".widget-button.delete");
|
||||
await click(".delete-topic-confirm-modal .btn-danger");
|
||||
await click(".toggle-admin-menu");
|
||||
assert.ok(exists(".topic-admin-recover"), "it shows the recover button");
|
||||
});
|
||||
|
||||
test("Group category moderator posts", async (assert) => {
|
||||
await visit("/t/topic-for-group-moderators/2480");
|
||||
|
||||
|
|
|
@ -62,6 +62,34 @@ test("editTopic", function (assert) {
|
|||
);
|
||||
});
|
||||
|
||||
test("deleteTopic", function (assert) {
|
||||
const model = Topic.create();
|
||||
let destroyed = false;
|
||||
let modalDisplayed = false;
|
||||
model.destroy = () => {
|
||||
destroyed = true;
|
||||
return Promise.resolve();
|
||||
};
|
||||
const controller = this.subject({
|
||||
model,
|
||||
siteSettings: {
|
||||
min_topic_views_for_delete_confirm: 5,
|
||||
},
|
||||
deleteTopicModal: () => {
|
||||
modalDisplayed = true;
|
||||
},
|
||||
});
|
||||
|
||||
model.set("views", 10000);
|
||||
controller.send("deleteTopic");
|
||||
assert.not(destroyed, "don't destroy popular topic");
|
||||
assert.ok(modalDisplayed, "display confirmation modal for popular topic");
|
||||
|
||||
model.set("views", 3);
|
||||
controller.send("deleteTopic");
|
||||
assert.ok(destroyed, "destroy not popular topic");
|
||||
});
|
||||
|
||||
test("toggleMultiSelect", function (assert) {
|
||||
const model = Topic.create();
|
||||
const controller = this.subject({ model });
|
||||
|
|
|
@ -360,6 +360,8 @@ en:
|
|||
preview: "preview"
|
||||
cancel: "cancel"
|
||||
|
||||
deleting: "Deleting..."
|
||||
|
||||
save: "Save Changes"
|
||||
saving: "Saving..."
|
||||
saved: "Saved!"
|
||||
|
@ -2813,6 +2815,10 @@ en:
|
|||
unlock_post_description: "allow the poster to edit this post"
|
||||
delete_topic_disallowed_modal: "You don't have permission to delete this topic. If you really want it to be deleted, submit a flag for moderator attention together with reasoning."
|
||||
delete_topic_disallowed: "you don't have permission to delete this topic"
|
||||
delete_topic_confirm_modal: "This topic currently has over %{minViews} views and may be a popular search destination. Are you sure you want to delete this topic entirely, instead of editing it to improve it?"
|
||||
delete_topic_confirm_modal_yes: "Yes, delete this topic"
|
||||
delete_topic_confirm_modal_no: "No, keep this topic"
|
||||
delete_topic_error: "An error occurred while deleting this topic"
|
||||
delete_topic: "delete topic"
|
||||
add_post_notice: "Add Staff Notice"
|
||||
remove_post_notice: "Remove Staff Notice"
|
||||
|
|
|
@ -1425,6 +1425,7 @@ en:
|
|||
max_post_length: "Maximum allowed post length in characters"
|
||||
topic_featured_link_enabled: "Enable posting a link with topics."
|
||||
show_topic_featured_link_in_digest: "Show the topic featured link in the digest email."
|
||||
min_topic_views_for_delete_confirm: "Minimum amount of views a topic must have for a confirmation popup to appear when it gets deleted"
|
||||
min_topic_title_length: "Minimum allowed topic title length in characters"
|
||||
max_topic_title_length: "Maximum allowed topic title length in characters"
|
||||
min_personal_message_title_length: "Minimum allowed title length for a message in characters"
|
||||
|
|
|
@ -700,6 +700,9 @@ posting:
|
|||
ja: 3
|
||||
zh_CN: 3
|
||||
zh_TW: 3
|
||||
min_topic_views_for_delete_confirm:
|
||||
client: true
|
||||
default: 5000
|
||||
min_topic_title_length:
|
||||
client: true
|
||||
default: 15
|
||||
|
|
Loading…
Reference in New Issue