DEV: upgrade reject reason reviewable modal to glimmer component (#24073)

* DEV: add system test for rejecting user from review page
* DEV: upgrade reject-reason-reviewable modal to glimmer & DModal
This commit is contained in:
Kelv 2023-10-24 17:44:43 +08:00 committed by GitHub
parent d5e8bd790b
commit 44c84413fb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 116 additions and 56 deletions

View File

@ -0,0 +1,30 @@
<DModal
@bodyClass="reject-reason-reviewable-modal__explain-reviewable"
@closeModal={{@closeModal}}
@title={{i18n "review.reject_reason.title"}}
class="reject-reason-reviewable-modal"
>
<:body>
<Textarea @value={{this.rejectReason}} />
<div class="control-group">
<label>
<Input
@type="checkbox"
class="reject-reason-reviewable-modal__send_email--inline"
@checked={{this.sendEmail}}
/>
{{i18n "review.reject_reason.send_email"}}
</label>
</div>
</:body>
<:footer>
<DButton
@icon="trash-alt"
@action={{this.perform}}
@label="admin.user.delete"
class="btn-danger"
/>
<DButton @action={{@closeModal}} @label="cancel" class="cancel" />
</:footer>
</DModal>

View File

@ -0,0 +1,17 @@
import Component from "@glimmer/component";
import { action } from "@ember/object";
export default class RejectReasonReviewableModal extends Component {
rejectReason;
sendEmail = false;
@action
async perform() {
this.args.model.reviewable.setProperties({
rejectReason: this.rejectReason,
sendEmail: this.sendEmail,
});
this.args.closeModal();
await this.args.model.performConfirmed(this.args.model.action);
}
}

View File

@ -4,11 +4,11 @@ import { action, set } from "@ember/object";
import { inject as service } from "@ember/service";
import { classify, dasherize } from "@ember/string";
import ExplainReviewableModal from "discourse/components/modal/explain-reviewable";
import RejectReasonReviewableModal from "discourse/components/modal/reject-reason-reviewable";
import ReviseAndRejectPostReviewable from "discourse/components/modal/revise-and-reject-post-reviewable";
import { ajax } from "discourse/lib/ajax";
import { popupAjaxError } from "discourse/lib/ajax-error";
import optionalService from "discourse/lib/optional-service";
import showModal from "discourse/lib/show-modal";
import Category from "discourse/models/category";
import discourseComputed, { bind } from "discourse-common/utils/decorators";
import I18n from "discourse-i18n";
@ -299,22 +299,15 @@ export default Component.extend({
const requireRejectReason = performableAction.get(
"require_reject_reason"
);
const actionModalClass =
actionModalClassMap[performableAction.server_action];
const actionModalClass = requireRejectReason
? RejectReasonReviewableModal
: actionModalClassMap[performableAction.server_action];
if (message) {
this.dialog.confirm({
message,
didConfirm: () => this._performConfirmed(performableAction),
});
} else if (requireRejectReason) {
showModal("reject-reason-reviewable", {
title: "review.reject_reason.title",
model: this.reviewable,
}).setProperties({
performConfirmed: this._performConfirmed,
action: performableAction,
});
} else if (actionModalClass) {
this.modal.show(actionModalClass, {
model: {

View File

@ -1,22 +0,0 @@
import Controller from "@ember/controller";
import { action } from "@ember/object";
import ModalFunctionality from "discourse/mixins/modal-functionality";
export default Controller.extend(ModalFunctionality, {
rejectReason: null,
sendEmail: false,
onShow() {
this.setProperties({ rejectReason: null, sendEmail: false });
},
@action
perform() {
this.model.setProperties({
rejectReason: this.rejectReason,
sendEmail: this.sendEmail,
});
this.send("closeModal");
this.performConfirmed(this.action);
},
});

View File

@ -1,23 +0,0 @@
<DModalBody @class="explain-reviewable">
<Textarea @value={{this.rejectReason}} />
<div class="control-group">
<label>
<Input @type="checkbox" class="inline" @checked={{this.sendEmail}} />
{{i18n "review.reject_reason.send_email"}}
</label>
</div>
</DModalBody>
<div class="modal-footer">
<DButton
@icon="trash-alt"
@action={{this.perform}}
@label="admin.user.delete"
class="btn-danger"
/>
<DButton
@action={{route-action "closeModal"}}
@label="cancel"
class="cancel"
/>
</div>

View File

@ -0,0 +1,25 @@
# frozen_string_literal: true
module PageObjects
module Modals
class RejectReasonReviewable < PageObjects::Modals::Base
def modal
find(".reject-reason-reviewable-modal")
end
def select_send_rejection_email_checkbox
modal.find(".reject-reason-reviewable-modal__send_email--inline").check
end
def fill_in_rejection_reason(reason)
modal.find(".reject-reason-reviewable-modal__explain-reviewable textarea").fill_in(
with: reason,
)
end
def delete_user
modal.find(".modal-footer .btn.btn-danger").click
end
end
end
end

View File

@ -64,6 +64,13 @@ module PageObjects
within(reviewable_by_id(reviewable.id)) { page.has_css?(".status .rejected") }
end
def has_reviewable_with_rejection_reason?(reviewable, rejection_reason)
reviewable_by_id(reviewable.id).has_css?(
".reviewable-user-details.reject-reason .value",
text: rejection_reason,
)
end
def has_error_dialog_visible?
page.has_css?(".dialog-container .dialog-content")
end

View File

@ -56,6 +56,39 @@ describe "Reviewables", type: :system do
end
end
describe "when there is a reviewable user" do
fab!(:user) { Fabricate(:user) }
let(:rejection_reason_modal) { PageObjects::Modals::RejectReasonReviewable.new }
before do
SiteSetting.must_approve_users = true
Jobs.run_immediately!
user.update!(approved: false)
user.activate
end
it "Rejecting user sends rejection email and updates reviewable with rejection reason" do
rejection_reason = "user is spamming"
reviewable = ReviewableUser.find_by_target_id(user.id)
# cache it for later assertion instead of querying UserHistory
user_email = user.email
review_page.visit_reviewable(reviewable)
review_page.select_bundled_action(reviewable, "user-delete_user")
rejection_reason_modal.fill_in_rejection_reason(rejection_reason)
rejection_reason_modal.select_send_rejection_email_checkbox
rejection_reason_modal.delete_user
expect(review_page).to have_reviewable_with_rejected_status(reviewable)
expect(review_page).to have_reviewable_with_rejection_reason(reviewable, rejection_reason)
mail = ActionMailer::Base.deliveries.first
expect(mail.to).to eq([user_email])
expect(mail.subject).to match(/You've been rejected on Discourse/)
expect(mail.body.raw_source).to include rejection_reason
end
end
context "when performing a review action from the show route" do
context "with a ReviewableQueuedPost" do
fab!(:queued_post_reviewable) { Fabricate(:reviewable_queued_post) }