DEV: Convert merge-users modals to component-based API (#22727)

This commit is contained in:
Isaac Janzen 2023-08-01 10:35:36 -05:00 committed by GitHub
parent 5be658849b
commit ed000be722
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 164 additions and 210 deletions

View File

@ -0,0 +1,36 @@
<DModal
@title={{html-safe
(i18n "admin.user.merge.confirmation.title" username=@model.username)
}}
@closeModal={{@closeModal}}
>
<:body>
<p>
{{html-safe
(i18n
"admin.user.merge.confirmation.description"
username=@model.username
targetUsername=@model.targetUsername
text=this.text
)
}}
</p>
<Input @type="text" @value={{this.value}} />
</:body>
<:footer>
<DButton
class="btn-danger"
@action={{fn @model.merge @model.targetUsername}}
@icon="trash-alt"
@disabled={{this.mergeDisabled}}
@translatedLabel={{i18n
"admin.user.merge.confirmation.transfer_and_delete"
username=@model.username
}}
/>
<DButton
@action={{@closeModal}}
@label="admin.user.merge.confirmation.cancel"
/>
</:footer>
</DModal>

View File

@ -0,0 +1,18 @@
import Component from "@glimmer/component";
import { tracked } from "@glimmer/tracking";
import I18n from "I18n";
export default class MergeUsersConfirmation extends Component {
@tracked value;
get mergeDisabled() {
return !this.value || this.text !== this.value;
}
get text() {
return I18n.t("admin.user.merge.confirmation.text", {
username: this.args.model.username,
targetUsername: this.args.model.targetUsername,
});
}
}

View File

@ -0,0 +1,9 @@
<DModal
@title={{i18n "admin.user.merge.progress.title"}}
@dismissable={{false}}
@closeModal={{@closeModal}}
>
<:body>
{{this.message}}
</:body>
</DModal>

View File

@ -0,0 +1,38 @@
import Component from "@glimmer/component";
import { tracked } from "@glimmer/tracking";
import { inject as service } from "@ember/service";
import { bind } from "discourse-common/utils/decorators";
import DiscourseURL from "discourse/lib/url";
import I18n from "I18n";
export default class MergeUsersProgress extends Component {
@service messageBus;
@tracked message = I18n.t("admin.user.merging_user");
constructor() {
super(...arguments);
this.messageBus.subscribe("/merge_user", this.onMessage);
}
willDestroy() {
this.messageBus.unsubscribe("/merge_user", this.onMessage);
}
@bind
onMessage(data) {
if (data.merged) {
if (/^\/admin\/users\/list\//.test(location.href)) {
DiscourseURL.redirectTo(location.href);
} else {
DiscourseURL.redirectTo(
`/admin/users/${data.user.id}/${data.user.username}`
);
}
} else if (data.message) {
this.message = data.message;
} else if (data.failed) {
this.message = I18n.t("admin.user.merge_failed");
}
}
}

View File

@ -0,0 +1,39 @@
<DModal
@title={{html-safe
(i18n "admin.user.merge.prompt.title" username=@model.user.username)
}}
@closeModal={{@closeModal}}
>
<:body>
<p>
{{html-safe
(i18n
"admin.user.merge.prompt.description" username=@model.user.username
)
}}
</p>
<EmailGroupUserChooser
@value={{this.targetUsername}}
@options={{hash
maximum=1
filterPlaceholder="admin.user.merge.prompt.target_username_placeholder"
}}
/>
</:body>
<:footer>
<DButton
class="btn-primary"
@action={{fn
@model.showMergeConfirmation
this.targetUsername.firstObject
}}
@icon="trash-alt"
@disabled={{this.mergeDisabled}}
@translatedLabel={{i18n
"admin.user.merge.confirmation.transfer_and_delete"
username=@model.user.username
}}
/>
<DButton @action={{@closeModal}} @label="admin.user.merge.prompt.cancel" />
</:footer>
</DModal>

View File

@ -0,0 +1,13 @@
import Component from "@glimmer/component";
import { tracked } from "@glimmer/tracking";
export default class MergeUsersPrompt extends Component {
@tracked targetUsername;
get mergeDisabled() {
return (
!this.targetUsername ||
this.args.model.user.username === this.targetUsername[0]
);
}
}

View File

@ -13,6 +13,9 @@ import getURL from "discourse-common/lib/get-url";
import { htmlSafe } from "@ember/template";
import { extractError, popupAjaxError } from "discourse/lib/ajax-error";
import showModal from "discourse/lib/show-modal";
import MergeUsersConfirmationModal from "../components/modal/merge-users-confirmation";
import MergeUsersPromptModal from "../components/modal/merge-users-prompt";
import MergeUsersProgressModal from "../components/modal/merge-users-progress";
import DeletePostsConfirmationModal from "../components/modal/delete-posts-confirmation";
export default class AdminUserIndexController extends Controller.extend(
@ -438,19 +441,21 @@ export default class AdminUserIndexController extends Controller.extend(
@action
promptTargetUser() {
showModal("admin-merge-users-prompt", {
admin: true,
model: this.model,
this.modal.show(MergeUsersPromptModal, {
model: {
user: this.model,
showMergeConfirmation: this.showMergeConfirmation,
},
});
}
@action
showMergeConfirmation(targetUsername) {
showModal("admin-merge-users-confirmation", {
admin: true,
this.modal.show(MergeUsersConfirmationModal, {
model: {
username: this.model.username,
targetUsername,
merge: this.merge,
},
});
}
@ -470,10 +475,7 @@ export default class AdminUserIndexController extends Controller.extend(
.merge(formData)
.then((response) => {
if (response.success) {
showModal("admin-merge-users-progress", {
admin: true,
model: this.model,
});
this.modal.show(MergeUsersProgressModal);
} else {
this.dialog.alert(I18n.t("admin.user.merge_failed"));
}

View File

@ -1,50 +0,0 @@
import { alias } from "@ember/object/computed";
import Controller, { inject as controller } from "@ember/controller";
import I18n from "I18n";
import ModalFunctionality from "discourse/mixins/modal-functionality";
import { action } from "@ember/object";
import discourseComputed from "discourse-common/utils/decorators";
export default class AdminMergeUsersConfirmationController extends Controller.extend(
ModalFunctionality
) {
@controller adminUserIndex;
@alias("model.username") username;
@alias("model.targetUsername") targetUsername;
onShow() {
this.set("value", null);
}
@discourseComputed("username", "targetUsername")
text(username, targetUsername) {
return I18n.t(`admin.user.merge.confirmation.text`, {
username,
targetUsername,
});
}
@discourseComputed("username")
mergeButtonText(username) {
return I18n.t(`admin.user.merge.confirmation.transfer_and_delete`, {
username,
});
}
@discourseComputed("value", "text")
mergeDisabled(value, text) {
return !value || text !== value;
}
@action
confirm() {
this.adminUserIndex.send("merge", this.targetUsername);
this.send("closeModal");
}
@action
close() {
this.send("closeModal");
}
}

View File

@ -1,36 +0,0 @@
import Controller from "@ember/controller";
import DiscourseURL from "discourse/lib/url";
import I18n from "I18n";
import ModalFunctionality from "discourse/mixins/modal-functionality";
import { bind } from "discourse-common/utils/decorators";
export default class AdminMergeUsersProgressController extends Controller.extend(
ModalFunctionality
) {
message = I18n.t("admin.user.merging_user");
onShow() {
this.messageBus.subscribe("/merge_user", this.onMessage);
}
onClose() {
this.messageBus.unsubscribe("/merge_user", this.onMessage);
}
@bind
onMessage(data) {
if (data.merged) {
if (/^\/admin\/users\/list\//.test(location)) {
DiscourseURL.redirectTo(location);
} else {
DiscourseURL.redirectTo(
`/admin/users/${data.user.id}/${data.user.username}`
);
}
} else if (data.message) {
this.set("message", data.message);
} else if (data.failed) {
this.set("message", I18n.t("admin.user.merge_failed"));
}
}
}

View File

@ -1,46 +0,0 @@
import { alias } from "@ember/object/computed";
import Controller, { inject as controller } from "@ember/controller";
import I18n from "I18n";
import ModalFunctionality from "discourse/mixins/modal-functionality";
import { action, get } from "@ember/object";
import discourseComputed from "discourse-common/utils/decorators";
export default class AdminMergeUsersPromptController extends Controller.extend(
ModalFunctionality
) {
@controller adminUserIndex;
@alias("model.username") username;
onShow() {
this.set("targetUsername", null);
}
@discourseComputed("username", "targetUsername")
mergeDisabled(username, targetUsername) {
return !targetUsername || username === targetUsername;
}
@discourseComputed("username")
mergeButtonText(username) {
return I18n.t(`admin.user.merge.confirmation.transfer_and_delete`, {
username,
});
}
@action
showConfirmation() {
this.send("closeModal");
this.adminUserIndex.send("showMergeConfirmation", this.targetUsername);
}
@action
close() {
this.send("closeModal");
}
@action
updateUsername(selected) {
this.set("targetUsername", get(selected, "firstObject"));
}
}

View File

@ -1,32 +0,0 @@
<div>
<DModalBody
@rawTitle={{i18n
"admin.user.merge.confirmation.title"
username=this.username
}}
>
<p>{{html-safe
(i18n
"admin.user.merge.confirmation.description"
username=this.username
targetUsername=this.targetUsername
text=this.text
)
}}</p>
<Input @type="text" @value={{this.value}} />
</DModalBody>
<div class="modal-footer">
<DButton
@class="btn-danger"
@action={{action "confirm"}}
@icon="trash-alt"
@disabled={{this.mergeDisabled}}
@translatedLabel={{this.mergeButtonText}}
/>
<DButton
@action={{action "close"}}
@label="admin.user.merge.confirmation.cancel"
/>
</div>
</div>

View File

@ -1,3 +0,0 @@
<DModalBody @title="admin.user.merge.progress.title" @dismissable={{false}}>
{{this.message}}
</DModalBody>

View File

@ -1,31 +0,0 @@
<div>
<DModalBody
@rawTitle={{i18n "admin.user.merge.prompt.title" username=this.username}}
>
<p>{{html-safe
(i18n "admin.user.merge.prompt.description" username=this.username)
}}</p>
<EmailGroupUserChooser
@value={{this.targetUsername}}
@onChange={{action "updateUsername"}}
@options={{hash
maximum=1
filterPlaceholder="admin.user.merge.prompt.target_username_placeholder"
}}
/>
</DModalBody>
<div class="modal-footer">
<DButton
@class="btn-primary"
@action={{action "showConfirmation"}}
@icon="trash-alt"
@disabled={{this.mergeDisabled}}
@translatedLabel={{this.mergeButtonText}}
/>
<DButton
@action={{action "close"}}
@label="admin.user.merge.prompt.cancel"
/>
</div>
</div>

View File

@ -48,7 +48,6 @@ const KNOWN_LEGACY_MODALS = [
"tag-upload",
"topic-summary",
"user-status",
"admin-merge-users-prompt",
"admin-watched-word-test",
"admin-api-key-urls",
"admin-delete-user-posts-progress",
@ -58,12 +57,10 @@ const KNOWN_LEGACY_MODALS = [
"site-setting-default-categories",
"admin-badge-preview",
"admin-edit-badge-groupings",
"admin-merge-users-confirmation",
"admin-reseed",
"admin-theme-item",
"admin-color-scheme-select-base",
"admin-form-template-validation-options",
"admin-merge-users-progress",
"admin-staff-action-log-details",
"admin-uploaded-image-list",
];