diff --git a/app/assets/javascripts/admin/controllers/admin_badge_controller.js b/app/assets/javascripts/admin/controllers/admin_badge_controller.js
new file mode 100644
index 00000000000..d45f280d1ed
--- /dev/null
+++ b/app/assets/javascripts/admin/controllers/admin_badge_controller.js
@@ -0,0 +1,19 @@
+/**
+ This is the itemController for `Discourse.AdminBadgesController`. Its main purpose
+ is to indicate which badge was selected.
+
+ @class AdminBadgeController
+ @extends Discourse.ObjectController
+ @namespace Discourse
+ @module Discourse
+**/
+
+Discourse.AdminBadgeController = Discourse.ObjectController.extend({
+ /**
+ Whether this badge has been selected.
+
+ @property selected
+ @type {Boolean}
+ **/
+ selected: Discourse.computed.propertyEqual('model.name', 'parentController.selectedItem.name')
+});
diff --git a/app/assets/javascripts/admin/controllers/admin_badges_controller.js b/app/assets/javascripts/admin/controllers/admin_badges_controller.js
new file mode 100644
index 00000000000..705aad55385
--- /dev/null
+++ b/app/assets/javascripts/admin/controllers/admin_badges_controller.js
@@ -0,0 +1,91 @@
+/**
+ This controller supports the interface for dealing with badges.
+
+ @class AdminBadgesController
+ @extends Ember.ArrayController
+ @namespace Discourse
+ @module Discourse
+**/
+Discourse.AdminBadgesController = Ember.ArrayController.extend({
+ itemController: 'adminBadge',
+
+ /**
+ Show the displayName only if it is different from the name.
+
+ @property showDisplayName
+ @type {Boolean}
+ **/
+ showDisplayName: Discourse.computed.propertyNotEqual('selectedItem.name', 'selectedItem.displayName'),
+
+ /**
+ We don't allow setting a description if a translation for the given badge name
+ exists.
+
+ @property canEditDescription
+ @type {Boolean}
+ **/
+ canEditDescription: Em.computed.none('selectedItem.translatedDescription'),
+
+ actions: {
+
+ /**
+ Create a new badge and select it.
+
+ @method newBadge
+ **/
+ newBadge: function() {
+ var badge = Discourse.Badge.create({
+ name: I18n.t('admin.badges.new_badge')
+ });
+ this.pushObject(badge);
+ this.send('selectBadge', badge);
+ },
+
+ /**
+ Select a particular badge.
+
+ @method selectBadge
+ @param {Discourse.Badge} badge The badge to be selected
+ **/
+ selectBadge: function(badge) {
+ this.set('selectedItem', badge);
+ },
+
+ /**
+ Save the selected badge.
+
+ @method save
+ **/
+ save: function() {
+ var badge = this.get('selectedItem');
+ badge.set('disableSave', true);
+ badge.save().then(function() {
+ badge.set('disableSave', false);
+ });
+ },
+
+ /**
+ Confirm before destroying the selected badge.
+
+ @method destroy
+ **/
+ destroy: function() {
+ var self = this;
+ return bootbox.confirm(I18n.t("admin.badges.delete_confirm"), I18n.t("no_value"), I18n.t("yes_value"), function(result) {
+ if (result) {
+ var selected = self.get('selectedItem');
+ selected.destroy().then(function() {
+ // Success.
+ self.set('selectedItem', null);
+ self.get('model').removeObject(selected);
+ }, function() {
+ // Failure.
+ bootbox.alert(I18n.t('generic_error'));
+ });
+ }
+ });
+ }
+
+ }
+
+});
diff --git a/app/assets/javascripts/admin/controllers/admin_user_controller.js b/app/assets/javascripts/admin/controllers/admin_user_controller.js
index c0674fd6d04..ec146502764 100644
--- a/app/assets/javascripts/admin/controllers/admin_user_controller.js
+++ b/app/assets/javascripts/admin/controllers/admin_user_controller.js
@@ -24,6 +24,10 @@ Discourse.AdminUserIndexController = Discourse.ObjectController.extend({
return Discourse.SiteSettings.must_approve_users;
}.property(),
+ showBadges: function() {
+ return Discourse.SiteSettings.enable_badges;
+ }.property(),
+
primaryGroupDirty: Discourse.computed.propertyNotEqual('originalPrimaryGroupId', 'primary_group_id'),
actions: {
diff --git a/app/assets/javascripts/admin/routes/admin_badges_route.js b/app/assets/javascripts/admin/routes/admin_badges_route.js
new file mode 100644
index 00000000000..1c606b5578e
--- /dev/null
+++ b/app/assets/javascripts/admin/routes/admin_badges_route.js
@@ -0,0 +1,14 @@
+Discourse.AdminBadgesRoute = Discourse.Route.extend({
+
+ model: function() {
+ return Discourse.Badge.findAll();
+ },
+
+ setupController: function(controller, model) {
+ Discourse.ajax('/admin/badges/types').then(function(json) {
+ controller.set('badgeTypes', json.badge_types);
+ });
+ controller.set('model', model);
+ }
+
+});
diff --git a/app/assets/javascripts/admin/routes/admin_routes.js b/app/assets/javascripts/admin/routes/admin_routes.js
index 3b847a36dac..21b2b38b6a6 100644
--- a/app/assets/javascripts/admin/routes/admin_routes.js
+++ b/app/assets/javascripts/admin/routes/admin_routes.js
@@ -57,5 +57,7 @@ Discourse.Route.buildRoutes(function() {
});
});
+ this.route('badges');
+
});
});
diff --git a/app/assets/javascripts/admin/templates/admin.js.handlebars b/app/assets/javascripts/admin/templates/admin.js.handlebars
index f8044020fe4..43f18b5e2c1 100644
--- a/app/assets/javascripts/admin/templates/admin.js.handlebars
+++ b/app/assets/javascripts/admin/templates/admin.js.handlebars
@@ -24,6 +24,7 @@
{{#link-to 'admin.customize'}}{{i18n admin.customize.title}}{{/link-to}}
{{#link-to 'admin.api'}}{{i18n admin.api.title}}{{/link-to}}
{{#link-to 'admin.backups'}}{{i18n admin.backups.title}}{{/link-to}}
+ {{#link-to 'admin.badges'}}{{i18n admin.badges.title}}{{/link-to}}
{{/if}}
diff --git a/app/assets/javascripts/admin/templates/badges.js.handlebars b/app/assets/javascripts/admin/templates/badges.js.handlebars
new file mode 100644
index 00000000000..ff39e74181b
--- /dev/null
+++ b/app/assets/javascripts/admin/templates/badges.js.handlebars
@@ -0,0 +1,62 @@
+
+
+
+
{{i18n admin.badges.title}}
+
+
+
+
+ {{#if selectedItem}}
+ {{#with selectedItem}}
+
+ {{/with}}
+ {{/if}}
+
+
diff --git a/app/assets/javascripts/admin/templates/user_index.js.handlebars b/app/assets/javascripts/admin/templates/user_index.js.handlebars
index a99918adeeb..8af5cd2c5f3 100644
--- a/app/assets/javascripts/admin/templates/user_index.js.handlebars
+++ b/app/assets/javascripts/admin/templates/user_index.js.handlebars
@@ -336,6 +336,12 @@
+{{#if showBadges}}
+
+ {{i18n admin.badges.title}}
+
+{{/if}}
+