mirror of
https://github.com/discourse/discourse.git
synced 2024-11-28 22:16:17 +08:00
31aa701518
Currently when bulk-awarding a badge that can be granted multiple times, users in the CSV file are granted the badge once no matter how many times they're listed in the file and only if they don't have the badge already. This PR adds a new option to the Badge Bulk Award feature so that it's possible to grant users a badge even if they already have the badge and as many times as they appear in the CSV file.
100 lines
2.7 KiB
JavaScript
100 lines
2.7 KiB
JavaScript
import Controller from "@ember/controller";
|
|
import I18n from "I18n";
|
|
import { ajax } from "discourse/lib/ajax";
|
|
import bootbox from "bootbox";
|
|
import { extractError } from "discourse/lib/ajax-error";
|
|
import { action } from "@ember/object";
|
|
import discourseComputed from "discourse-common/utils/decorators";
|
|
|
|
export default Controller.extend({
|
|
saving: false,
|
|
replaceBadgeOwners: false,
|
|
grantExistingHolders: false,
|
|
fileSelected: false,
|
|
unmatchedEntries: null,
|
|
resultsMessage: null,
|
|
success: false,
|
|
unmatchedEntriesCount: 0,
|
|
|
|
resetState() {
|
|
this.setProperties({
|
|
saving: false,
|
|
unmatchedEntries: null,
|
|
resultsMessage: null,
|
|
success: false,
|
|
unmatchedEntriesCount: 0,
|
|
});
|
|
this.send("updateFileSelected");
|
|
},
|
|
|
|
@discourseComputed("fileSelected", "saving")
|
|
massAwardButtonDisabled(fileSelected, saving) {
|
|
return !fileSelected || saving;
|
|
},
|
|
|
|
@discourseComputed("unmatchedEntriesCount", "unmatchedEntries.length")
|
|
unmatchedEntriesTruncated(unmatchedEntriesCount, length) {
|
|
return unmatchedEntriesCount && length && unmatchedEntriesCount > length;
|
|
},
|
|
|
|
@action
|
|
updateFileSelected() {
|
|
this.set(
|
|
"fileSelected",
|
|
!!document.querySelector("#massAwardCSVUpload")?.files?.length
|
|
);
|
|
},
|
|
|
|
@action
|
|
massAward() {
|
|
const file = document.querySelector("#massAwardCSVUpload").files[0];
|
|
|
|
if (this.model && file) {
|
|
const options = {
|
|
type: "POST",
|
|
processData: false,
|
|
contentType: false,
|
|
data: new FormData(),
|
|
};
|
|
|
|
options.data.append("file", file);
|
|
options.data.append("replace_badge_owners", this.replaceBadgeOwners);
|
|
options.data.append("grant_existing_holders", this.grantExistingHolders);
|
|
|
|
this.resetState();
|
|
this.set("saving", true);
|
|
|
|
ajax(`/admin/badges/award/${this.model.id}`, options)
|
|
.then(
|
|
({
|
|
matched_users_count: matchedCount,
|
|
unmatched_entries: unmatchedEntries,
|
|
unmatched_entries_count: unmatchedEntriesCount,
|
|
}) => {
|
|
this.setProperties({
|
|
resultsMessage: I18n.t("admin.badges.mass_award.success", {
|
|
count: matchedCount,
|
|
}),
|
|
success: true,
|
|
});
|
|
if (unmatchedEntries.length) {
|
|
this.setProperties({
|
|
unmatchedEntries,
|
|
unmatchedEntriesCount,
|
|
});
|
|
}
|
|
}
|
|
)
|
|
.catch((error) => {
|
|
this.setProperties({
|
|
resultsMessage: extractError(error),
|
|
success: false,
|
|
});
|
|
})
|
|
.finally(() => this.set("saving", false));
|
|
} else {
|
|
bootbox.alert(I18n.t("admin.badges.mass_award.aborted"));
|
|
}
|
|
},
|
|
});
|