FEATURE: add agree and edit (#27088)

* FEATURE: add agree and edit

adds agree and edit - an alias for agree and keep -- but with a client action to
edit the post in the composer before the flag is agreed with

---------

Co-authored-by: Juan David Martinez <juan@discourse.org>
This commit is contained in:
Jeff Wong 2024-05-23 11:21:42 -07:00 committed by GitHub
parent 3f099ad268
commit 755f8de6d4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 77 additions and 1 deletions

View File

@ -10,6 +10,8 @@ import { ajax } from "discourse/lib/ajax";
import { popupAjaxError } from "discourse/lib/ajax-error";
import optionalService from "discourse/lib/optional-service";
import Category from "discourse/models/category";
import Composer from "discourse/models/composer";
import Topic from "discourse/models/topic";
import discourseComputed, { bind } from "discourse-common/utils/decorators";
import I18n from "discourse-i18n";
@ -45,6 +47,7 @@ export default Component.extend({
modal: service(),
siteSettings: service(),
currentUser: service(),
composer: service(),
tagName: "",
updating: null,
editing: false,
@ -225,6 +228,34 @@ export default Component.extend({
this._penalize("showSilenceModal", reviewable, performAction);
},
async clientEdit(reviewable, performAction) {
if (!this.currentUser) {
return this.dialog.alert(I18n.t("post.controls.edit_anonymous"));
}
const post = await this.store.find("post", reviewable.post_id);
const topic_json = await Topic.find(post.topic_id, {});
const topic = Topic.create(topic_json);
post.set("topic", topic);
if (!post.can_edit) {
return false;
}
const opts = {
post,
action: Composer.EDIT,
draftKey: post.get("topic.draft_key"),
draftSequence: post.get("topic.draft_sequence"),
skipDraftCheck: true,
skipJumpOnSave: true,
};
this.composer.open(opts);
return performAction();
},
_penalize(adminToolMethod, reviewable, performAction) {
let adminTools = this.adminTools;
if (adminTools) {

View File

@ -9,6 +9,7 @@ class ReviewableFlaggedPost < Reviewable
agree_and_keep_hidden: :agree_and_keep,
agree_and_silence: :agree_and_keep,
agree_and_suspend: :agree_and_keep,
agree_and_edit: :agree_and_keep,
disagree_and_restore: :disagree,
ignore_and_do_nothing: :ignore,
}
@ -59,6 +60,13 @@ class ReviewableFlaggedPost < Reviewable
build_action(actions, :agree_and_keep_hidden, icon: "thumbs-up", bundle: agree_bundle)
else
build_action(actions, :agree_and_keep, icon: "thumbs-up", bundle: agree_bundle)
build_action(
actions,
:agree_and_edit,
icon: "pencil-alt",
bundle: agree_bundle,
client_action: "edit",
)
end
if guardian.can_delete_post_or_topic?(post)

View File

@ -5524,6 +5524,9 @@ en:
agree_and_hide:
title: "Hide post"
description: "Agree with flag and hide this post + automatically send the user a message urging them to edit it."
agree_and_edit:
title: "Agree and Edit Post"
description: "Agree with flag and open a composer window to edit the post."
delete_single:
title: "Delete"
delete:

View File

@ -27,6 +27,7 @@ RSpec.describe ReviewableFlaggedPost, type: :model do
actions = reviewable.actions_for(guardian)
expect(actions.has?(:agree_and_hide)).to eq(true)
expect(actions.has?(:agree_and_keep)).to eq(true)
expect(actions.has?(:agree_and_edit)).to eq(true)
expect(actions.has?(:agree_and_keep_hidden)).to eq(false)
expect(actions.has?(:agree_and_silence)).to eq(true)
expect(actions.has?(:agree_and_suspend)).to eq(true)
@ -56,6 +57,7 @@ RSpec.describe ReviewableFlaggedPost, type: :model do
post.hidden = true
actions = reviewable.actions_for(guardian)
expect(actions.has?(:agree_and_keep)).to eq(false)
expect(actions.has?(:agree_and_edit)).to eq(false)
expect(actions.has?(:agree_and_keep_hidden)).to eq(true)
end
@ -123,6 +125,13 @@ RSpec.describe ReviewableFlaggedPost, type: :model do
expect(post).not_to be_hidden
end
it "agree_and_keep agrees with the flags and edits the post" do
reviewable.perform(moderator, :agree_and_keep)
expect(reviewable).to be_approved
expect(score.reload).to be_agreed
expect(post).not_to be_hidden
end
describe "with reviewable claiming enabled" do
fab!(:claimed) { Fabricate(:reviewable_claimed_topic, topic: post.topic, user: moderator) }
it "clears the claimed topic on resolve" do

View File

@ -5,6 +5,8 @@ describe "Reviewables", type: :system do
fab!(:admin)
fab!(:theme)
fab!(:long_post) { Fabricate(:post_with_very_long_raw_content) }
fab!(:post)
let(:composer) { PageObjects::Components::Composer.new }
before { sign_in(admin) }
@ -23,13 +25,36 @@ describe "Reviewables", type: :system do
end
describe "when there is a flagged post reviewable with a short post" do
fab!(:short_reviewable) { Fabricate(:reviewable_flagged_post) }
fab!(:short_reviewable) { Fabricate(:reviewable_flagged_post, target: post) }
it "should not show a button to expand/collapse the post content" do
visit("/review")
expect(review_page).to have_no_post_body_collapsed
expect(review_page).to have_no_post_body_toggle
end
describe "reviewable actions" do
it "should have agree_and_edit action" do
visit("/review")
select_kit =
PageObjects::Components::SelectKit.new(".dropdown-select-box.post-agree-and-hide")
select_kit.expand
expect(page).to have_selector("[data-value='post-agree_and_edit']")
end
it "agree_and_edit should open the composer" do
visit("/review")
select_kit =
PageObjects::Components::SelectKit.new(".dropdown-select-box.post-agree-and-hide")
select_kit.expand
find("[data-value='post-agree_and_edit']").click
expect(composer).to be_opened
expect(composer.composer_input.value).to eq(post.raw)
end
end
end
describe "when there is a queued post reviewable with a short post" do