diff --git a/app/assets/javascripts/admin/addon/controllers/admin-badges-award.js b/app/assets/javascripts/admin/addon/controllers/admin-badges-award.js
deleted file mode 100644
index 4318575a34..0000000000
--- a/app/assets/javascripts/admin/addon/controllers/admin-badges-award.js
+++ /dev/null
@@ -1,99 +0,0 @@
-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"));
- }
- },
-});
diff --git a/app/assets/javascripts/admin/addon/controllers/admin-badges-show.js b/app/assets/javascripts/admin/addon/controllers/admin-badges-show.js
deleted file mode 100644
index 91a2687346..0000000000
--- a/app/assets/javascripts/admin/addon/controllers/admin-badges-show.js
+++ /dev/null
@@ -1,216 +0,0 @@
-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 { next } 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
- 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() {
- 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"));
- });
- }
- }
- );
- },
- },
-});
diff --git a/app/assets/javascripts/admin/addon/controllers/admin-badges.js b/app/assets/javascripts/admin/addon/controllers/admin-badges.js
index 11d78fc4cc..50af52d17f 100644
--- a/app/assets/javascripts/admin/addon/controllers/admin-badges.js
+++ b/app/assets/javascripts/admin/addon/controllers/admin-badges.js
@@ -1,18 +1,23 @@
import Controller from "@ember/controller";
-import discourseComputed from "discourse-common/utils/decorators";
import { inject as service } from "@ember/service";
+import { tracked } from "@glimmer/tracking";
-export default Controller.extend({
- routing: service("-routing"),
+export default class AdminBadgesController extends Controller {
+ @service router;
- @discourseComputed("routing.currentRouteName")
- selectedRoute() {
- const currentRoute = this.routing.currentRouteName;
+ // Set by the route
+ @tracked badgeGroupings;
+ @tracked badgeTypes;
+ @tracked protectedSystemFields;
+ @tracked badgeTriggers;
+
+ get selectedRoute() {
+ const currentRoute = this.router.currentRouteName;
const indexRoute = "adminBadges.index";
if (currentRoute === indexRoute) {
return "adminBadges.show";
} else {
- return this.routing.currentRouteName;
+ return currentRoute;
}
- },
-});
+ }
+}
diff --git a/app/assets/javascripts/admin/addon/controllers/admin-badges/award.js b/app/assets/javascripts/admin/addon/controllers/admin-badges/award.js
new file mode 100644
index 0000000000..e564840115
--- /dev/null
+++ b/app/assets/javascripts/admin/addon/controllers/admin-badges/award.js
@@ -0,0 +1,90 @@
+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 { tracked } from "@glimmer/tracking";
+
+export default class AdminBadgesAwardController extends Controller {
+ @tracked saving = false;
+ @tracked replaceBadgeOwners = false;
+ @tracked grantExistingHolders = false;
+ @tracked fileSelected = false;
+ @tracked unmatchedEntries = null;
+ @tracked resultsMessage = null;
+ @tracked success = false;
+ @tracked unmatchedEntriesCount = 0;
+
+ resetState() {
+ this.saving = false;
+ this.unmatchedEntries = null;
+ this.resultsMessage = null;
+ this.success = false;
+ this.unmatchedEntriesCount = 0;
+
+ this.updateFileSelected();
+ }
+
+ get massAwardButtonDisabled() {
+ return !this.fileSelected || this.saving;
+ }
+
+ get unmatchedEntriesTruncated() {
+ let count = this.unmatchedEntriesCount;
+ let length = this.unmatchedEntries.length;
+ return count && length && count > length;
+ }
+
+ @action
+ updateFileSelected() {
+ this.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.saving = true;
+
+ ajax(`/admin/badges/award/${this.model.id}`, options)
+ .then(
+ ({
+ matched_users_count: matchedCount,
+ unmatched_entries: unmatchedEntries,
+ unmatched_entries_count: unmatchedEntriesCount,
+ }) => {
+ this.resultsMessage = I18n.t("admin.badges.mass_award.success", {
+ count: matchedCount,
+ });
+ this.success = true;
+ if (unmatchedEntries.length) {
+ this.unmatchedEntries = unmatchedEntries;
+ this.unmatchedEntriesCount = unmatchedEntriesCount;
+ }
+ }
+ )
+ .catch((error) => {
+ this.resultsMessage = extractError(error);
+ this.success = false;
+ })
+ .finally(() => (this.saving = false));
+ } else {
+ bootbox.alert(I18n.t("admin.badges.mass_award.aborted"));
+ }
+ }
+}
diff --git a/app/assets/javascripts/admin/addon/controllers/admin-badges/index.js b/app/assets/javascripts/admin/addon/controllers/admin-badges/index.js
new file mode 100644
index 0000000000..a2981cc4a0
--- /dev/null
+++ b/app/assets/javascripts/admin/addon/controllers/admin-badges/index.js
@@ -0,0 +1,8 @@
+import Controller from "@ember/controller";
+import { tracked } from "@glimmer/tracking";
+
+export default class AdminBadgesIndexController extends Controller {
+ // Set by the route
+ @tracked badgeIntroLinks;
+ @tracked badgeIntroEmoji;
+}
diff --git a/app/assets/javascripts/admin/addon/controllers/admin-badges/show.js b/app/assets/javascripts/admin/addon/controllers/admin-badges/show.js
new file mode 100644
index 0000000000..29d95f2c0f
--- /dev/null
+++ b/app/assets/javascripts/admin/addon/controllers/admin-badges/show.js
@@ -0,0 +1,238 @@
+import Controller, { inject as controller } from "@ember/controller";
+import { 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 { next } from "@ember/runloop";
+import { action } from "@ember/object";
+import { inject as service } from "@ember/service";
+import getURL from "discourse-common/lib/get-url";
+import { tracked } from "@glimmer/tracking";
+
+const IMAGE = "image";
+const ICON = "icon";
+
+// TODO: Stop using Mixin here
+export default class AdminBadgesShowController extends Controller.extend(
+ bufferedProperty("model")
+) {
+ @controller adminBadges;
+ @service router;
+
+ @tracked saving = false;
+ @tracked savingStatus = "";
+ @tracked selectedGraphicType = null;
+
+ 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.buffered.get("system");
+ }
+
+ get showDisplayName() {
+ return this.name !== this.displayName;
+ }
+
+ get iconSelectorSelected() {
+ return this.selectedGraphicType === ICON;
+ }
+
+ get imageUploaderSelected() {
+ return this.selectedGraphicType === IMAGE;
+ }
+
+ init() {
+ super.init(...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
+ next(() => {
+ // 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);
+ }
+ }
+ });
+ }
+
+ get hasQuery() {
+ let modelQuery = this.model.query;
+ let bufferedQuery = this.bufferedQuery;
+
+ if (bufferedQuery) {
+ return bufferedQuery.trim().length > 0;
+ }
+ return modelQuery && modelQuery.trim().length > 0;
+ }
+
+ get textCustomizationPrefix() {
+ return `badges.${this.model.i18n_name}.`;
+ }
+
+ // FIXME: Remove observer
+ @observes("model.id")
+ _resetSaving() {
+ this.saving = false;
+ this.savingStatus = "";
+ }
+
+ showIconSelector() {
+ this.selectedGraphicType = ICON;
+ }
+
+ showImageUploader() {
+ this.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.set("image_upload_id", upload.id);
+ this.buffered.set("image_url", getURL(upload.url));
+ }
+
+ @action
+ removeImage() {
+ this.buffered.set("image_upload_id", null);
+ this.buffered.set("image_url", null);
+ }
+
+ @action
+ 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.buffered.get("system")) {
+ let protectedFields = this.protectedSystemFields || [];
+ fields = fields.filter((f) => !protectedFields.includes(f));
+ }
+
+ this.saving = true;
+ this.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.savingStatus = I18n.t("saved");
+ }
+ })
+ .catch(popupAjaxError)
+ .finally(() => {
+ this.saving = false;
+ this.savingStatus = "";
+ });
+ }
+ }
+
+ @action
+ destroyBadge() {
+ const adminBadges = this.adminBadges.model;
+ const model = this.model;
+
+ if (!model?.get("id")) {
+ this.router.transitionTo("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"));
+ });
+ }
+ }
+ );
+ }
+}
diff --git a/app/assets/javascripts/admin/addon/routes/admin-badges-show.js b/app/assets/javascripts/admin/addon/routes/admin-badges-show.js
deleted file mode 100644
index 2727046762..0000000000
--- a/app/assets/javascripts/admin/addon/routes/admin-badges-show.js
+++ /dev/null
@@ -1,64 +0,0 @@
-import Badge from "discourse/models/badge";
-import I18n from "I18n";
-import Route from "@ember/routing/route";
-import { ajax } from "discourse/lib/ajax";
-import bootbox from "bootbox";
-import { get } from "@ember/object";
-import showModal from "discourse/lib/show-modal";
-
-export default Route.extend({
- serialize(m) {
- return { badge_id: get(m, "id") || "new" };
- },
-
- model(params) {
- if (params.badge_id === "new") {
- return Badge.create({
- name: I18n.t("admin.badges.new_badge"),
- });
- }
- return this.modelFor("adminBadges").findBy(
- "id",
- parseInt(params.badge_id, 10)
- );
- },
-
- setupController(controller, model) {
- this._super(...arguments);
- if (model.image_url) {
- controller.showImageUploader();
- } else if (model.icon) {
- controller.showIconSelector();
- }
- },
-
- actions: {
- editGroupings() {
- const model = this.controllerFor("admin-badges").get("badgeGroupings");
- showModal("admin-edit-badge-groupings", { model, admin: true });
- },
-
- preview(badge, explain) {
- badge.set("preview_loading", true);
- ajax("/admin/badges/preview.json", {
- type: "POST",
- data: {
- sql: badge.get("query"),
- target_posts: !!badge.get("target_posts"),
- trigger: badge.get("trigger"),
- explain,
- },
- })
- .then(function (model) {
- badge.set("preview_loading", false);
- showModal("admin-badge-preview", { model, admin: true });
- })
- .catch(function (error) {
- badge.set("preview_loading", false);
- // eslint-disable-next-line no-console
- console.error(error);
- bootbox.alert("Network error");
- });
- },
- },
-});
diff --git a/app/assets/javascripts/admin/addon/routes/admin-badges.js b/app/assets/javascripts/admin/addon/routes/admin-badges.js
index c966b7a161..b316996635 100644
--- a/app/assets/javascripts/admin/addon/routes/admin-badges.js
+++ b/app/assets/javascripts/admin/addon/routes/admin-badges.js
@@ -4,15 +4,14 @@ import DiscourseRoute from "discourse/routes/discourse";
import I18n from "I18n";
import { ajax } from "discourse/lib/ajax";
-export default DiscourseRoute.extend({
- _json: null,
+export default class AdminBadgesRoute extends DiscourseRoute {
+ _json = null;
- model() {
- return ajax("/admin/badges.json").then((json) => {
- this._json = json;
- return Badge.createFromJson(json);
- });
- },
+ async model() {
+ let json = await ajax("/admin/badges.json");
+ this._json = json;
+ return Badge.createFromJson(json);
+ }
setupController(controller, model) {
const json = this._json;
@@ -31,12 +30,11 @@ export default DiscourseRoute.extend({
badgeGroupings.push(BadgeGrouping.create(badgeGroupingJson));
});
- controller.setProperties({
- badgeGroupings,
- badgeTypes: json.badge_types,
- protectedSystemFields: json.admin_badges.protected_system_fields,
- badgeTriggers,
- model,
- });
- },
-});
+ controller.badgeGroupings = badgeGroupings;
+ controller.badgeTypes = json.badge_types;
+ controller.protectedSystemFields =
+ json.admin_badges.protected_system_fields;
+ controller.badgeTriggers = badgeTriggers;
+ controller.model = model;
+ }
+}
diff --git a/app/assets/javascripts/admin/addon/routes/admin-badges-award.js b/app/assets/javascripts/admin/addon/routes/admin-badges/award.js
similarity index 72%
rename from app/assets/javascripts/admin/addon/routes/admin-badges-award.js
rename to app/assets/javascripts/admin/addon/routes/admin-badges/award.js
index 6fe72a6bf1..957bb1ba17 100644
--- a/app/assets/javascripts/admin/addon/routes/admin-badges-award.js
+++ b/app/assets/javascripts/admin/addon/routes/admin-badges/award.js
@@ -1,6 +1,6 @@
import Route from "discourse/routes/discourse";
-export default Route.extend({
+export default class AdminBadgesAwardRoute extends Route {
model(params) {
if (params.badge_id !== "new") {
return this.modelFor("adminBadges").findBy(
@@ -8,10 +8,10 @@ export default Route.extend({
parseInt(params.badge_id, 10)
);
}
- },
+ }
setupController(controller) {
- this._super(...arguments);
+ super.setupController(...arguments);
controller.resetState();
- },
-});
+ }
+}
diff --git a/app/assets/javascripts/admin/addon/routes/admin-badges-index.js b/app/assets/javascripts/admin/addon/routes/admin-badges/index.js
similarity index 70%
rename from app/assets/javascripts/admin/addon/routes/admin-badges-index.js
rename to app/assets/javascripts/admin/addon/routes/admin-badges/index.js
index 0f44e83d04..d16f408c23 100644
--- a/app/assets/javascripts/admin/addon/routes/admin-badges-index.js
+++ b/app/assets/javascripts/admin/addon/routes/admin-badges/index.js
@@ -14,11 +14,9 @@ const badgeIntroLinks = [
},
];
-export default Route.extend({
+export default class AdminBadgesIndexRoute extends Route {
setupController(controller) {
- controller.setProperties({
- badgeIntroLinks,
- badgeIntroEmoji: emojiUrlFor("woman_student:t4"),
- });
- },
-});
+ controller.badgeIntroLinks = badgeIntroLinks;
+ controller.badgeIntroEmoji = emojiUrlFor("woman_student:t4");
+ }
+}
diff --git a/app/assets/javascripts/admin/addon/routes/admin-badges/show.js b/app/assets/javascripts/admin/addon/routes/admin-badges/show.js
new file mode 100644
index 0000000000..4d1eb1db76
--- /dev/null
+++ b/app/assets/javascripts/admin/addon/routes/admin-badges/show.js
@@ -0,0 +1,64 @@
+import Badge from "discourse/models/badge";
+import I18n from "I18n";
+import Route from "@ember/routing/route";
+import { ajax } from "discourse/lib/ajax";
+import bootbox from "bootbox";
+import { action, get } from "@ember/object";
+import showModal from "discourse/lib/show-modal";
+
+export default class AdminBadgesShowRoute extends Route {
+ serialize(m) {
+ return { badge_id: get(m, "id") || "new" };
+ }
+
+ model(params) {
+ if (params.badge_id === "new") {
+ return Badge.create({
+ name: I18n.t("admin.badges.new_badge"),
+ });
+ }
+ return this.modelFor("adminBadges").findBy(
+ "id",
+ parseInt(params.badge_id, 10)
+ );
+ }
+
+ setupController(controller, model) {
+ super.setupController(...arguments);
+ if (model.image_url) {
+ controller.showImageUploader();
+ } else if (model.icon) {
+ controller.showIconSelector();
+ }
+ }
+
+ @action
+ editGroupings() {
+ const model = this.controllerFor("admin-badges").get("badgeGroupings");
+ showModal("admin-edit-badge-groupings", { model, admin: true });
+ }
+
+ @action
+ preview(badge, explain) {
+ badge.set("preview_loading", true);
+ ajax("/admin/badges/preview.json", {
+ type: "POST",
+ data: {
+ sql: badge.get("query"),
+ target_posts: !!badge.get("target_posts"),
+ trigger: badge.get("trigger"),
+ explain,
+ },
+ })
+ .then(function (model) {
+ badge.set("preview_loading", false);
+ showModal("admin-badge-preview", { model, admin: true });
+ })
+ .catch(function (error) {
+ badge.set("preview_loading", false);
+ // eslint-disable-next-line no-console
+ console.error(error);
+ bootbox.alert("Network error");
+ });
+ }
+}
diff --git a/app/assets/javascripts/admin/addon/templates/badges.hbs b/app/assets/javascripts/admin/addon/templates/admin-badges.hbs
similarity index 100%
rename from app/assets/javascripts/admin/addon/templates/badges.hbs
rename to app/assets/javascripts/admin/addon/templates/admin-badges.hbs
diff --git a/app/assets/javascripts/admin/addon/templates/badges-award.hbs b/app/assets/javascripts/admin/addon/templates/admin-badges/award.hbs
similarity index 100%
rename from app/assets/javascripts/admin/addon/templates/badges-award.hbs
rename to app/assets/javascripts/admin/addon/templates/admin-badges/award.hbs
diff --git a/app/assets/javascripts/admin/addon/templates/badges-index.hbs b/app/assets/javascripts/admin/addon/templates/admin-badges/index.hbs
similarity index 100%
rename from app/assets/javascripts/admin/addon/templates/badges-index.hbs
rename to app/assets/javascripts/admin/addon/templates/admin-badges/index.hbs
diff --git a/app/assets/javascripts/admin/addon/templates/badges-show.hbs b/app/assets/javascripts/admin/addon/templates/admin-badges/show.hbs
similarity index 98%
rename from app/assets/javascripts/admin/addon/templates/badges-show.hbs
rename to app/assets/javascripts/admin/addon/templates/admin-badges/show.hbs
index 520790be3b..1cf2bbab5a 100644
--- a/app/assets/javascripts/admin/addon/templates/badges-show.hbs
+++ b/app/assets/javascripts/admin/addon/templates/admin-badges/show.hbs
@@ -159,7 +159,7 @@