DEV: convert change owner modal to glimmer component (#23668)

* DEV: convert change owner modal to glimmer component

* DEV: add system test for change owner modal
This commit is contained in:
Kelv 2023-09-29 11:46:31 +08:00 committed by GitHub
parent b267c1054d
commit 3f6adca2d7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 174 additions and 106 deletions

View File

@ -0,0 +1,45 @@
<DModal
@bodyClass="change-ownership"
@closeModal={{@closeModal}}
@title={{i18n "topic.change_owner.title"}}
@flash={{this.flash}}
@flashType="error"
class="change-ownership-modal"
>
<:body>
<span>
{{html-safe
(i18n
(if
this.selectedPostsUsername
"topic.change_owner.instructions"
"topic.change_owner.instructions_without_old_user"
)
count=this.selectedPostsCount
old_user=this.selectedPostsUsername
)
}}
</span>
<form>
<label></label>
<EmailGroupUserChooser
@value={{this.newOwner}}
@autofocus={{true}}
@onChange={{this.updateNewOwner}}
@options={{hash
maximum=1
filterPlaceholder="topic.change_owner.placeholder"
}}
/>
</form>
</:body>
<:footer>
<DButton
{{on "click" this.changeOwnershipOfPosts}}
@disabled={{this.buttonDisabled}}
@label={{if this.saving "saving" "topic.change_owner.action"}}
class="btn-primary"
/>
</:footer>
</DModal>

View File

@ -0,0 +1,57 @@
import Component from "@glimmer/component";
import { action } from "@ember/object";
import { tracked } from "@glimmer/tracking";
import DiscourseURL from "discourse/lib/url";
import I18n from "I18n";
import Topic from "discourse/models/topic";
import { isEmpty } from "@ember/utils";
export default class ChangeOwnerModal extends Component {
@tracked saving = false;
@tracked newOwner = null;
get buttonDisabled() {
return this.saving || isEmpty(this.newOwner);
}
get selectedPostsUsername() {
return this.args.model.selectedPostsUsername;
}
get selectedPostIds() {
return this.args.model.selectedPostIds;
}
get selectedPostsCount() {
return this.args.model.selectedPostsCount;
}
@action
async changeOwnershipOfPosts() {
this.saving = true;
const options = {
post_ids: this.selectedPostIds,
username: this.newOwner,
};
try {
await Topic.changeOwners(this.args.model.topic.id, options);
this.args.closeModal();
this.args.model.deselectAll();
if (this.args.model.multiSelect) {
this.args.model.toggleMultiSelect();
}
DiscourseURL.routeTo(this.args.model.topic.url);
} catch (error) {
this.flash = I18n.t("topic.change_owner.error");
this.saving = false;
}
return false;
}
@action
async updateNewOwner(selected) {
this.newOwner = selected.firstObject;
}
}

View File

@ -1,65 +0,0 @@
import Controller, { inject as controller } from "@ember/controller";
import DiscourseURL from "discourse/lib/url";
import I18n from "I18n";
import ModalFunctionality from "discourse/mixins/modal-functionality";
import Topic from "discourse/models/topic";
import { alias } from "@ember/object/computed";
import discourseComputed from "discourse-common/utils/decorators";
import { isEmpty } from "@ember/utils";
import { next } from "@ember/runloop";
export default Controller.extend(ModalFunctionality, {
topicController: controller("topic"),
saving: false,
newOwner: null,
selectedPostsCount: alias("topicController.selectedPostsCount"),
selectedPostsUsername: alias("topicController.selectedPostsUsername"),
@discourseComputed("saving", "newOwner")
buttonDisabled(saving, newUser) {
return saving || isEmpty(newUser);
},
onShow() {
this.setProperties({
saving: false,
newOwner: null,
});
},
actions: {
changeOwnershipOfPosts() {
this.set("saving", true);
const options = {
post_ids: this.get("topicController.selectedPostIds"),
username: this.newOwner,
};
Topic.changeOwners(this.get("topicController.model.id"), options).then(
() => {
this.send("closeModal");
this.topicController.send("deselectAll");
if (this.get("topicController.multiSelect")) {
this.topicController.send("toggleMultiSelect");
}
next(() =>
DiscourseURL.routeTo(this.get("topicController.model.url"))
);
},
() => {
this.flash(I18n.t("topic.change_owner.error"), "error");
this.set("saving", false);
}
);
return false;
},
updateNewOwner(selected) {
this.set("newOwner", selected.firstObject);
},
},
});

View File

@ -7,12 +7,12 @@ import { action, get } from "@ember/object";
import { isEmpty } from "@ember/utils";
import { inject as service } from "@ember/service";
import { setTopicId } from "discourse/lib/topic-list-tracker";
import showModal from "discourse/lib/show-modal";
import TopicFlag from "discourse/lib/flag-targets/topic-flag";
import PostFlag from "discourse/lib/flag-targets/post-flag";
import HistoryModal from "discourse/components/modal/history";
import PublishPageModal from "discourse/components/modal/publish-page";
import EditSlowModeModal from "discourse/components/modal/edit-slow-mode";
import ChangeOwnerModal from "discourse/components/modal/change-owner";
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";
@ -226,9 +226,17 @@ const TopicRoute = DiscourseRoute.extend({
@action
changeOwner() {
showModal("change-owner", {
model: this.modelFor("topic"),
title: "topic.change_owner.title",
const topicController = this.controllerFor("topic");
this.modal.show(ChangeOwnerModal, {
model: {
deselectAll: topicController.deselectAll,
multiSelect: topicController.multiSelect,
selectedPostsCount: topicController.selectedPostsCount,
selectedPostIds: topicController.selectedPostIds,
selectedPostUsername: topicController.selectedPostsUsername,
toggleMultiSelect: topicController.toggleMultiSelect,
topic: this.modelFor("topic"),
},
});
},

View File

@ -1,37 +0,0 @@
<DModalBody @class="change-ownership">
<span>
{{html-safe
(i18n
(if
this.selectedPostsUsername
"topic.change_owner.instructions"
"topic.change_owner.instructions_without_old_user"
)
count=this.selectedPostsCount
old_user=this.selectedPostsUsername
)
}}
</span>
<form>
<label></label>
<EmailGroupUserChooser
@value={{this.newOwner}}
@autofocus={{true}}
@onChange={{action "updateNewOwner"}}
@options={{hash
maximum=1
filterPlaceholder="topic.change_owner.placeholder"
}}
/>
</form>
</DModalBody>
<div class="modal-footer">
<DButton
@action={{action "changeOwnershipOfPosts"}}
@disabled={{this.buttonDisabled}}
@label={{if this.saving "saving" "topic.change_owner.action"}}
class="btn-primary"
/>
</div>

View File

@ -0,0 +1,30 @@
# frozen_string_literal: true
describe "Change Owner Modal", type: :system do
fab!(:post) { Fabricate(:post, raw: "This is some post to change owner for") }
fab!(:other_user) { Fabricate(:user) }
fab!(:admin) { Fabricate(:admin) }
let(:user) { post.user }
let(:topic) { post.topic }
let(:topic_page) { PageObjects::Pages::Topic.new }
let(:change_owner_modal) { PageObjects::Modals::ChangeOwner.new }
before { sign_in(admin) }
def visit_topic_and_open_change_owner_modal(post)
topic_page.visit_topic(topic)
topic_page.expand_post_actions(post)
topic_page.expand_post_admin_actions(post)
topic_page.click_post_admin_action_button(post, :change_owner)
end
it "changes owner of a post" do
visit_topic_and_open_change_owner_modal(post)
change_owner_modal.select_new_owner(other_user)
change_owner_modal.confirm_new_owner
expect(page).not_to have_css ".change-ownership-modal"
displayed_username = topic_page.post_by_number(post).find(".first.username").text
expect(displayed_username).to eq other_user.username
end
end

View File

@ -0,0 +1,28 @@
# frozen_string_literal: true
module PageObjects
module Modals
class ChangeOwner < PageObjects::Pages::Base
USERS_DROPDOWN = ".select-kit"
def modal
find(".change-ownership-modal")
end
def select_new_owner(user)
within(modal) do
users_dropdown.expand
users_dropdown.search(user.username)
users_dropdown.select_row_by_value(user.username)
end
end
def confirm_new_owner
within(modal) { find(".modal-footer .btn").click }
end
def users_dropdown
@users_dropdown ||= PageObjects::Components::SelectKit.new(USERS_DROPDOWN)
end
end
end
end

View File

@ -96,6 +96,8 @@ module PageObjects
case button
when :grant_badge
element_klass += " .grant-badge"
when :change_owner
element_klass += " .change-owner"
end
find(element_klass).click