import { cached, tracked } from "@glimmer/tracking"; import Controller, { inject as controller } from "@ember/controller"; import { action, getProperties } from "@ember/object"; import { service } from "@ember/service"; import { ajax } from "discourse/lib/ajax"; import { popupAjaxError } from "discourse/lib/ajax-error"; import getURL from "discourse-common/lib/get-url"; import I18n from "discourse-i18n"; import BadgePreviewModal from "../../components/modal/badge-preview"; const FORM_FIELDS = [ "allow_title", "multiple_grant", "listable", "auto_revoke", "enabled", "show_posts", "target_posts", "name", "description", "long_description", "icon", "image_upload_id", "image_url", "query", "badge_grouping_id", "trigger", "badge_type_id", ]; export default class AdminBadgesShowController extends Controller { @service router; @service toasts; @service dialog; @service modal; @controller adminBadges; @tracked model; @tracked previewLoading = false; @tracked selectedGraphicType = null; @tracked userBadges; @tracked userBadgesAll; @cached get formData() { const data = getProperties(this.model, ...FORM_FIELDS); if (data.icon === "") { data.icon = undefined; } return data; } @action currentBadgeGrouping(data) { return this.badgeGroupings.find((bg) => bg.id === data.badge_grouping_id) ?.name; } get badgeTypes() { return this.adminBadges.badgeTypes; } get badgeGroupings() { return this.adminBadges.badgeGroupings; } get badgeTriggers() { return this.adminBadges.badgeTriggers; } get protectedSystemFields() { return this.adminBadges.protectedSystemFields; } get readOnly() { return this.model.system; } setup() { // this is needed because the model doesnt have default values // Using `set` here isn't ideal, but we don't know that tracking is set up on the model yet. if (this.model) { if (!this.model.badge_type_id) { this.model.set("badge_type_id", this.badgeTypes?.[0]?.id); } if (!this.model.badge_grouping_id) { this.model.set("badge_grouping_id", this.badgeGroupings?.[0]?.id); } if (!this.model.trigger) { this.model.set("trigger", this.badgeTriggers?.[0]?.id); } } } hasQuery(query) { return query?.trim?.()?.length > 0; } get textCustomizationPrefix() { return `badges.${this.model.i18n_name}.`; } @action onSetImage(upload, { set }) { if (upload) { set("image_upload_id", upload.id); set("image_url", getURL(upload.url)); set("icon", null); } else { set("image_upload_id", ""); set("image_url", ""); } } @action onSetIcon(value, { set }) { set("icon", value); set("image_upload_id", ""); set("image_url", ""); } @action showPreview(badge, explain, event) { event?.preventDefault(); this.preview(badge, explain); } @action validateForm(data, { addError }) { if (!data.icon && !data.image_url) { addError("icon", { title: "Icon", message: I18n.t("admin.badges.icon_or_image"), }); addError("image_url", { title: "Image", message: I18n.t("admin.badges.icon_or_image"), }); } } @action async preview(badge, explain) { try { this.previewLoading = true; const model = await ajax("/admin/badges/preview.json", { type: "POST", data: { sql: badge.query, target_posts: !!badge.target_posts, trigger: badge.trigger, explain, }, }); this.modal.show(BadgePreviewModal, { model: { badge: model } }); } catch (e) { // eslint-disable-next-line no-console console.error(e); this.dialog.alert("Network error"); } finally { this.previewLoading = false; } } @action async handleSubmit(formData) { let fields = FORM_FIELDS; if (formData.system) { const protectedFields = this.protectedSystemFields || []; fields = fields.filter((f) => !protectedFields.includes(f)); } const data = {}; fields.forEach(function (field) { data[field] = formData[field]; }); const newBadge = !this.model.id; try { this.model = await this.model.save(data); this.toasts.success({ data: { message: I18n.t("saved") } }); if (newBadge) { const adminBadges = this.get("adminBadges.model"); if (!adminBadges.includes(this.model)) { adminBadges.pushObject(this.model); } return this.router.transitionTo("adminBadges.show", this.model.id); } } catch (error) { return popupAjaxError(error); } } @action async handleDelete() { if (!this.model?.id) { return this.router.transitionTo("adminBadges.index"); } const adminBadges = this.adminBadges.model; return this.dialog.yesNoConfirm({ message: I18n.t("admin.badges.delete_confirm"), didConfirm: async () => { try { await this.model.destroy(); adminBadges.removeObject(this.model); this.router.transitionTo("adminBadges.index"); } catch { this.dialog.alert(I18n.t("generic_error")); } }, }); } }