FEATURE: admin UI to merge two users. (#9509)

This commit is contained in:
Vinoth Kannan
2020-04-22 14:07:51 +05:30
committed by GitHub
parent 13956017da
commit a511bea4cc
13 changed files with 238 additions and 1 deletions
@@ -9,6 +9,7 @@ import { popupAjaxError } from "discourse/lib/ajax-error";
import discourseComputed from "discourse-common/utils/decorators";
import { fmt } from "discourse/lib/computed";
import { htmlSafe } from "@ember/template";
import showModal from "discourse/lib/show-modal";
export default Controller.extend(CanCheckEmails, {
adminTools: service(),
@@ -207,6 +208,27 @@ export default Controller.extend(CanCheckEmails, {
}
},
promptTargetUser() {
showModal("admin-merge-users-prompt", {
admin: true,
model: this.model
});
},
showMergeConfirmation(targetUsername) {
showModal("admin-merge-users-confirmation", {
admin: true,
model: {
username: this.model.username,
targetUsername: targetUsername
}
});
},
merge(targetUsername) {
return this.model.merge({ targetUsername: targetUsername });
},
viewActionLogs() {
this.adminTools.showActionLogs(this, {
target_user: this.get("model.username")
@@ -0,0 +1,35 @@
import Controller, { inject as controller } from "@ember/controller";
import ModalFunctionality from "discourse/mixins/modal-functionality";
import discourseComputed from "discourse-common/utils/decorators";
import { alias } from "@ember/object/computed";
export default Controller.extend(ModalFunctionality, {
adminUserIndex: controller(),
username: alias("model.username"),
targetUsername: alias("model.targetUsername"),
onShow() {
this.set("value", null);
},
@discourseComputed("username", "targetUsername")
text(username, targetUsername) {
return `transfer @${username} to @${targetUsername}`;
},
@discourseComputed("value", "text")
mergeDisabled(value, text) {
return !value || text !== value;
},
actions: {
merge() {
this.adminUserIndex.send("merge", this.targetUsername);
this.send("closeModal");
},
cancel() {
this.send("closeModal");
}
}
});
@@ -0,0 +1,29 @@
import Controller, { inject as controller } from "@ember/controller";
import ModalFunctionality from "discourse/mixins/modal-functionality";
import discourseComputed from "discourse-common/utils/decorators";
import { alias } from "@ember/object/computed";
export default Controller.extend(ModalFunctionality, {
adminUserIndex: controller(),
username: alias("model.username"),
onShow() {
this.set("targetUsername", null);
},
@discourseComputed("username", "targetUsername")
mergeDisabled(username, targetUsername) {
return !targetUsername || username === targetUsername;
},
actions: {
merge() {
this.send("closeModal");
this.adminUserIndex.send("showMergeConfirmation", this.targetUsername);
},
cancel() {
this.send("closeModal");
}
}
});
@@ -503,6 +503,43 @@ const AdminUser = User.extend({
bootbox.dialog(message, buttons, { classes: "delete-user-modal" });
},
merge(opts) {
const user = this;
const location = document.location.pathname;
bootbox.dialog(I18n.t("admin.user.merging_user"));
let formData = { context: location };
if (opts && opts.targetUsername) {
formData["target_username"] = opts.targetUsername;
}
return ajax(`/admin/users/${user.get("id")}/merge.json`, {
type: "POST",
data: formData
})
.then(function(data) {
if (data.merged) {
if (/^\/admin\/users\/list\//.test(location)) {
document.location = location;
} else {
document.location = Discourse.getURL(
`/admin/users/${data.user.id}/${data.user.username}`
);
}
} else {
bootbox.alert(I18n.t("admin.user.merge_failed"));
if (data.user) {
user.setProperties(data.user);
}
}
})
.catch(function() {
AdminUser.find(user.get("id")).then(u => user.setProperties(u));
bootbox.alert(I18n.t("admin.user.merge_failed"));
});
},
loadDetails() {
if (this.loadedDetails) {
return Promise.resolve(this);
@@ -0,0 +1,21 @@
<div>
{{#d-modal-body rawTitle=(i18n "admin.user.merge.confirmation.title" username=username)}}
<p>{{html-safe (i18n "admin.user.merge.confirmation.description" username=username targetUsername=targetUsername text=text)}}</p>
{{input type="text" value=value}}
{{/d-modal-body}}
<div class="modal-footer">
{{#d-button
class="btn-danger"
action=(action "merge")
icon="trash-alt"
disabled=mergeDisabled
}}
{{i18n "admin.user.merge.confirmation.transfer_and_delete" username=username}}
{{/d-button}}
{{d-button
action=(action "cancel")
label="admin.user.merge.confirmation.cancel"
}}
</div>
</div>
@@ -0,0 +1,24 @@
<div>
{{#d-modal-body rawTitle=(i18n "admin.user.merge.prompt.title" username=username)}}
<p>{{html-safe (i18n "admin.user.merge.prompt.description" username=username)}}</p>
{{user-selector single=true
placeholderKey="admin.user.merge.prompt.target_username_placeholder"
usernames=targetUsername
autocomplete="discourse"}}
{{/d-modal-body}}
<div class="modal-footer">
{{#d-button
class="btn-primary"
action=(action "merge")
icon="trash-alt"
disabled=mergeDisabled
}}
{{i18n "admin.user.merge.prompt.transfer_and_delete" username=username}}
{{/d-button}}
{{d-button
action=(action "cancel")
label="admin.user.merge.prompt.cancel"
}}
</div>
</div>
@@ -680,9 +680,13 @@
{{#if model.canBeDeleted}}
{{d-button label="admin.user.delete"
icon="exclamation-triangle"
icon="trash-alt"
class="btn-danger"
action=(action "destroy")}}
{{d-button label="admin.user.merge.transfer_and_delete"
icon="trash-alt"
class="btn-danger"
action=(action "promptTargetUser")}}
{{/if}}
</div>