mirror of
https://github.com/discourse/discourse.git
synced 2025-02-25 18:55:32 -06:00
UX: Add image uploader widget for uploading badge images (#12377)
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.
This commit is contained in:
@@ -5,19 +5,27 @@ 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 { reads } from "@ember/object/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);
|
||||
@@ -67,6 +75,41 @@ export default Controller.extend(bufferedProperty("model"), {
|
||||
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) {
|
||||
@@ -82,7 +125,7 @@ export default Controller.extend(bufferedProperty("model"), {
|
||||
"description",
|
||||
"long_description",
|
||||
"icon",
|
||||
"image",
|
||||
"image_upload_id",
|
||||
"query",
|
||||
"badge_grouping_id",
|
||||
"trigger",
|
||||
|
||||
@@ -23,6 +23,15 @@ export default Route.extend({
|
||||
);
|
||||
},
|
||||
|
||||
setupController(controller, model) {
|
||||
this._super(...arguments);
|
||||
if (model.image_url) {
|
||||
controller.showImageUploader();
|
||||
} else if (model.icon) {
|
||||
controller.showIconSelector();
|
||||
}
|
||||
},
|
||||
|
||||
actions: {
|
||||
saveError(e) {
|
||||
let msg = I18n.t("generic_error");
|
||||
|
||||
@@ -15,23 +15,48 @@
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label for="icon">{{i18n "admin.badges.icon"}}</label>
|
||||
{{icon-picker
|
||||
name="icon"
|
||||
value=buffered.icon
|
||||
options=(hash
|
||||
maximum=1
|
||||
)
|
||||
onChange=(action (mut buffered.icon))
|
||||
}}
|
||||
<label for="graphic">{{i18n "admin.badges.graphic"}}</label>
|
||||
<div class="radios">
|
||||
<label class="radio-label" for="badge-icon">
|
||||
{{radio-button
|
||||
name="badge-icon"
|
||||
id="badge-icon"
|
||||
value="icon"
|
||||
selection=selectedGraphicType
|
||||
onChange=(action "changeGraphicType")
|
||||
}}
|
||||
<span>{{i18n "admin.badges.select_an_icon"}}</span>
|
||||
</label>
|
||||
|
||||
<p class="help">{{i18n "admin.badges.icon_help"}}</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label for="image">{{i18n "admin.badges.image"}}</label>
|
||||
{{input type="text" name="image" value=buffered.image}}
|
||||
<p class="help">{{i18n "admin.badges.image_help"}}</p>
|
||||
<label class="radio-label" for="badge-image">
|
||||
{{radio-button
|
||||
name="badge-image"
|
||||
id="badge-image"
|
||||
value="image"
|
||||
selection=selectedGraphicType
|
||||
onChange=(action "changeGraphicType")
|
||||
}}
|
||||
<span>{{i18n "admin.badges.upload_an_image"}}</span>
|
||||
</label>
|
||||
</div>
|
||||
{{#if imageUploaderSelected}}
|
||||
{{image-uploader
|
||||
imageUrl=buffered.image_url
|
||||
onUploadDone=(action "setImage")
|
||||
onUploadDeleted=(action "removeImage")
|
||||
type="badge_image"
|
||||
class="no-repeat contain-image"}}
|
||||
<div class="control-instructions">
|
||||
<p class="help">{{i18n "admin.badges.image_help"}}</p>
|
||||
</div>
|
||||
{{else if iconSelectorSelected}}
|
||||
{{icon-picker
|
||||
name="icon"
|
||||
value=buffered.icon
|
||||
options=(hash maximum=1)
|
||||
onChange=(action (mut buffered.icon))
|
||||
}}
|
||||
{{/if}}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
|
||||
Reference in New Issue
Block a user