mirror of
https://github.com/discourse/discourse.git
synced 2024-12-12 12:19:36 +08:00
a23d0f9961
Currently the process of adding a custom image to badge is quite clunky; you have to upload your image to a topic, and then copy the image URL and pasting it in a text field. Besides being clucky, if the topic or post that contains the image is deleted, the image will be garbage-collected in a few days and the badge will lose the image because the application is not that the image is referenced by a badge. This commit improves that by adding a proper image uploader widget for badge images.
217 lines
5.7 KiB
JavaScript
217 lines
5.7 KiB
JavaScript
import Controller, { inject as controller } from "@ember/controller";
|
|
import discourseComputed, { observes } from "discourse-common/utils/decorators";
|
|
import I18n from "I18n";
|
|
import bootbox from "bootbox";
|
|
import { bufferedProperty } from "discourse/mixins/buffered-content";
|
|
import { popupAjaxError } from "discourse/lib/ajax-error";
|
|
import { propertyNotEqual } from "discourse/lib/computed";
|
|
import { equal, reads } from "@ember/object/computed";
|
|
import { run } from "@ember/runloop";
|
|
import { action } from "@ember/object";
|
|
import getURL from "discourse-common/lib/get-url";
|
|
|
|
const IMAGE = "image";
|
|
const ICON = "icon";
|
|
|
|
export default Controller.extend(bufferedProperty("model"), {
|
|
adminBadges: controller(),
|
|
saving: false,
|
|
savingStatus: "",
|
|
selectedGraphicType: null,
|
|
badgeTypes: reads("adminBadges.badgeTypes"),
|
|
badgeGroupings: reads("adminBadges.badgeGroupings"),
|
|
badgeTriggers: reads("adminBadges.badgeTriggers"),
|
|
protectedSystemFields: reads("adminBadges.protectedSystemFields"),
|
|
readOnly: reads("buffered.system"),
|
|
showDisplayName: propertyNotEqual("name", "displayName"),
|
|
iconSelectorSelected: equal("selectedGraphicType", ICON),
|
|
imageUploaderSelected: equal("selectedGraphicType", IMAGE),
|
|
|
|
init() {
|
|
this._super(...arguments);
|
|
|
|
// this is needed because the model doesnt have default values
|
|
// and as we are using a bufferedProperty it's not accessible
|
|
// in any other way
|
|
run.next(() => {
|
|
if (this.model) {
|
|
if (!this.model.badge_type_id) {
|
|
this.model.set(
|
|
"badge_type_id",
|
|
this.get("badgeTypes.firstObject.id")
|
|
);
|
|
}
|
|
|
|
if (!this.model.badge_grouping_id) {
|
|
this.model.set(
|
|
"badge_grouping_id",
|
|
this.get("badgeGroupings.firstObject.id")
|
|
);
|
|
}
|
|
|
|
if (!this.model.trigger) {
|
|
this.model.set("trigger", this.get("badgeTriggers.firstObject.id"));
|
|
}
|
|
}
|
|
});
|
|
},
|
|
|
|
@discourseComputed("model.query", "buffered.query")
|
|
hasQuery(modelQuery, bufferedQuery) {
|
|
if (bufferedQuery) {
|
|
return bufferedQuery.trim().length > 0;
|
|
}
|
|
return modelQuery && modelQuery.trim().length > 0;
|
|
},
|
|
|
|
@discourseComputed("model.i18n_name")
|
|
textCustomizationPrefix(i18n_name) {
|
|
return `badges.${i18n_name}.`;
|
|
},
|
|
|
|
@observes("model.id")
|
|
_resetSaving: function () {
|
|
this.set("saving", false);
|
|
this.set("savingStatus", "");
|
|
},
|
|
|
|
showIconSelector() {
|
|
this.set("selectedGraphicType", ICON);
|
|
},
|
|
|
|
showImageUploader() {
|
|
this.set("selectedGraphicType", IMAGE);
|
|
},
|
|
|
|
@action
|
|
changeGraphicType(newType) {
|
|
if (newType === IMAGE) {
|
|
this.showImageUploader();
|
|
} else if (newType === ICON) {
|
|
this.showIconSelector();
|
|
} else {
|
|
throw new Error(`Unknown badge graphic type "${newType}"`);
|
|
}
|
|
},
|
|
|
|
@action
|
|
setImage(upload) {
|
|
this.buffered.setProperties({
|
|
image_upload_id: upload.id,
|
|
image_url: getURL(upload.url),
|
|
});
|
|
},
|
|
|
|
@action
|
|
removeImage() {
|
|
this.buffered.setProperties({
|
|
image_upload_id: null,
|
|
image_url: null,
|
|
});
|
|
},
|
|
|
|
actions: {
|
|
save() {
|
|
if (!this.saving) {
|
|
let fields = [
|
|
"allow_title",
|
|
"multiple_grant",
|
|
"listable",
|
|
"auto_revoke",
|
|
"enabled",
|
|
"show_posts",
|
|
"target_posts",
|
|
"name",
|
|
"description",
|
|
"long_description",
|
|
"icon",
|
|
"image_upload_id",
|
|
"query",
|
|
"badge_grouping_id",
|
|
"trigger",
|
|
"badge_type_id",
|
|
];
|
|
|
|
if (this.get("buffered.system")) {
|
|
let protectedFields = this.protectedSystemFields || [];
|
|
fields = fields.filter((f) => !protectedFields.includes(f));
|
|
}
|
|
|
|
this.set("saving", true);
|
|
this.set("savingStatus", I18n.t("saving"));
|
|
|
|
const boolFields = [
|
|
"allow_title",
|
|
"multiple_grant",
|
|
"listable",
|
|
"auto_revoke",
|
|
"enabled",
|
|
"show_posts",
|
|
"target_posts",
|
|
];
|
|
|
|
const data = {};
|
|
const buffered = this.buffered;
|
|
fields.forEach(function (field) {
|
|
let d = buffered.get(field);
|
|
if (boolFields.includes(field)) {
|
|
d = !!d;
|
|
}
|
|
data[field] = d;
|
|
});
|
|
|
|
const newBadge = !this.id;
|
|
const model = this.model;
|
|
this.model
|
|
.save(data)
|
|
.then(() => {
|
|
if (newBadge) {
|
|
const adminBadges = this.get("adminBadges.model");
|
|
if (!adminBadges.includes(model)) {
|
|
adminBadges.pushObject(model);
|
|
}
|
|
this.transitionToRoute("adminBadges.show", model.get("id"));
|
|
} else {
|
|
this.commitBuffer();
|
|
this.set("savingStatus", I18n.t("saved"));
|
|
}
|
|
})
|
|
.catch(popupAjaxError)
|
|
.finally(() => {
|
|
this.set("saving", false);
|
|
this.set("savingStatus", "");
|
|
});
|
|
}
|
|
},
|
|
|
|
destroy() {
|
|
const adminBadges = this.get("adminBadges.model");
|
|
const model = this.model;
|
|
|
|
if (!model.get("id")) {
|
|
this.transitionToRoute("adminBadges.index");
|
|
return;
|
|
}
|
|
|
|
return bootbox.confirm(
|
|
I18n.t("admin.badges.delete_confirm"),
|
|
I18n.t("no_value"),
|
|
I18n.t("yes_value"),
|
|
(result) => {
|
|
if (result) {
|
|
model
|
|
.destroy()
|
|
.then(() => {
|
|
adminBadges.removeObject(model);
|
|
this.transitionToRoute("adminBadges.index");
|
|
})
|
|
.catch(() => {
|
|
bootbox.alert(I18n.t("generic_error"));
|
|
});
|
|
}
|
|
}
|
|
);
|
|
},
|
|
},
|
|
});
|