diff --git a/app/assets/javascripts/admin/controllers/admin-badges.js.es6 b/app/assets/javascripts/admin/controllers/admin-badges.js.es6 index 5089a712c..199c7eab1 100644 --- a/app/assets/javascripts/admin/controllers/admin-badges.js.es6 +++ b/app/assets/javascripts/admin/controllers/admin-badges.js.es6 @@ -7,6 +7,7 @@ @module Discourse **/ export default Ember.ArrayController.extend({ + needs: ['modal'], itemController: 'admin-badge', queryParams: ['badgeId'], badgeId: Em.computed.alias('selectedId'), diff --git a/app/assets/javascripts/admin/controllers/admin-edit-badge-groupings.js.es6 b/app/assets/javascripts/admin/controllers/admin-edit-badge-groupings.js.es6 new file mode 100644 index 000000000..2034d1036 --- /dev/null +++ b/app/assets/javascripts/admin/controllers/admin-edit-badge-groupings.js.es6 @@ -0,0 +1,80 @@ +export default Ember.Controller.extend({ + needs: ['modal'], + + modelChanged: function(){ + + var grouping = Em.Object.extend({}); + + var model = this.get('model'); + var copy = Em.A(); + + if(model){ + model.forEach(function(o){ + copy.pushObject(grouping.create(o)); + }); + } + + this.set('workingCopy', copy); + }.observes('model'), + + moveItem: function(item, delta){ + var copy = this.get('workingCopy'); + var index = copy.indexOf(item); + if (index + delta < 0 || index + delta >= copy.length){ + return; + } + + copy.removeAt(index); + copy.insertAt(index+delta, item); + }, + + actions: { + up: function(item){ + this.moveItem(item, -1); + }, + down: function(item){ + this.moveItem(item, 1); + }, + "delete": function(item){ + this.get('workingCopy').removeObject(item); + }, + cancel: function(){ + this.set('model', null); + this.set('workingCopy', null); + this.send('closeModal'); + }, + edit: function(item){ + item.set("editing", true); + }, + save: function(item){ + item.set("editing", false); + }, + add: function(){ + var obj = Em.Object.create({editing: true, name: "Enter Name"}); + this.get('workingCopy').pushObject(obj); + }, + saveAll: function(){ + var self = this; + var items = this.get('workingCopy'); + var groupIds = items.map(function(i){return i.get("id") || -1}); + var names = items.map(function(i){return i.get("name")}); + + Discourse.ajax('/admin/badges/badge_groupings',{ + data: {ids: groupIds, names: names}, + method: 'POST' + }).then(function(data){ + items = self.get("model"); + items.clear(); + data.badge_groupings.forEach(function(g){ + items.pushObject(Em.Object.create(g)); + }); + self.set('model', null); + self.set('workingCopy', null); + self.send('closeModal'); + },function(){ + // TODO we can do better + bootbox.alert("Something went wrong"); + }); + } + } +}); diff --git a/app/assets/javascripts/admin/routes/admin_badges_route.js b/app/assets/javascripts/admin/routes/admin_badges_route.js index 6ac596b5c..ba8fb4f9c 100644 --- a/app/assets/javascripts/admin/routes/admin_badges_route.js +++ b/app/assets/javascripts/admin/routes/admin_badges_route.js @@ -1,7 +1,8 @@ Discourse.AdminBadgesRoute = Discourse.Route.extend({ setupController: function(controller) { Discourse.ajax('/admin/badges.json').then(function(json){ - controller.set('badgeGroupings', json.badge_groupings); + + controller.set('badgeGroupings', Em.A(json.badge_groupings)); controller.set('badgeTypes', json.badge_types); controller.set('protectedSystemFields', json.admin_badges.protected_system_fields); var triggers = []; @@ -11,6 +12,12 @@ Discourse.AdminBadgesRoute = Discourse.Route.extend({ controller.set('badgeTriggers', triggers); controller.set('model', Discourse.Badge.createFromJson(json)); }); + }, + + actions: { + editGroupings: function(model){ + Discourse.Route.showModal(this, 'admin_edit_badge_groupings', model); + } } }); diff --git a/app/assets/javascripts/admin/templates/badges.js.handlebars b/app/assets/javascripts/admin/templates/badges.js.handlebars index e5cf7e2f5..782fb6c9d 100644 --- a/app/assets/javascripts/admin/templates/badges.js.handlebars +++ b/app/assets/javascripts/admin/templates/badges.js.handlebars @@ -53,6 +53,7 @@ content=controller.badgeGroupings optionValuePath="content.id" optionLabelPath="content.name"}} +   diff --git a/app/assets/javascripts/admin/templates/modal/admin_edit_badge_groupings.js.handlebars b/app/assets/javascripts/admin/templates/modal/admin_edit_badge_groupings.js.handlebars new file mode 100644 index 000000000..5b636de1e --- /dev/null +++ b/app/assets/javascripts/admin/templates/modal/admin_edit_badge_groupings.js.handlebars @@ -0,0 +1,28 @@ + + + diff --git a/app/assets/javascripts/admin/views/modals/admin_edit_badge_groupings_view.js b/app/assets/javascripts/admin/views/modals/admin_edit_badge_groupings_view.js new file mode 100644 index 000000000..cf2227f35 --- /dev/null +++ b/app/assets/javascripts/admin/views/modals/admin_edit_badge_groupings_view.js @@ -0,0 +1,5 @@ + +Discourse.AdminEditBadgeGroupingsView = Discourse.ModalBodyView.extend({ + templateName: 'admin/templates/modal/admin_edit_badge_groupings', + title: I18n.t('admin.badges.badge_groupings.modal_title') +}); diff --git a/app/assets/stylesheets/common/admin/admin_base.scss b/app/assets/stylesheets/common/admin/admin_base.scss index f8f3eb15c..676a46810 100644 --- a/app/assets/stylesheets/common/admin/admin_base.scss +++ b/app/assets/stylesheets/common/admin/admin_base.scss @@ -1205,3 +1205,21 @@ and (max-width : 500px) { } } + +.badge-groupings { + list-style: none; + margin: 0; + padding: 10px 3px; + li { + padding: 6px 0; + width: 600px; + border-bottom: 1px solid #dfdfdf; + } + .actions { + font-size: 17px; + float: right; + a { + margin-left: 5px; + } + } +} diff --git a/app/controllers/admin/badges_controller.rb b/app/controllers/admin/badges_controller.rb index 186f4e44b..1bd7d3b0e 100644 --- a/app/controllers/admin/badges_controller.rb +++ b/app/controllers/admin/badges_controller.rb @@ -2,8 +2,8 @@ class Admin::BadgesController < Admin::AdminController def index data = { - badge_types: BadgeType.all.to_a, - badge_groupings: BadgeGrouping.all.to_a, + badge_types: BadgeType.all.order(:id).to_a, + badge_groupings: BadgeGrouping.all.order(:position).to_a, badges: Badge.all.to_a, protected_system_fields: Badge.protected_system_fields, triggers: Badge.trigger_hash @@ -20,8 +20,24 @@ class Admin::BadgesController < Admin::AdminController render_serialized(badge_types, BadgeTypeSerializer, root: "badge_types") end - def badge_groupings - badge_groupings = BadgeGrouping.all.to_a + def save_badge_groupings + + badge_groupings = BadgeGrouping.all.order(:position).to_a + ids = params[:ids].map(&:to_i) + + params[:names].each_with_index do |name,index| + id = ids[index].to_i + group = badge_groupings.find{|b| b.id == id} || BadgeGrouping.new() + group.name = name + group.position = index + group.save + end + + badge_groupings.each do |g| + g.destroy unless g.system? || ids.include?(g.id) + end + + badge_groupings = BadgeGrouping.all.order(:position).to_a render_serialized(badge_groupings, BadgeGroupingSerializer, root: "badge_groupings") end diff --git a/app/models/badge_grouping.rb b/app/models/badge_grouping.rb index 92d9dc65f..8bdfe2467 100644 --- a/app/models/badge_grouping.rb +++ b/app/models/badge_grouping.rb @@ -8,6 +8,10 @@ class BadgeGrouping < ActiveRecord::Base has_many :badges + def system? + id && id < 5 + end + def default_position=(pos) position ||= pos end diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml index 4f90e8ae5..4907c6e4e 100644 --- a/config/locales/client.en.yml +++ b/config/locales/client.en.yml @@ -1889,6 +1889,8 @@ en: description: Description badge_type: Badge Type badge_grouping: Group + badge_groupings: + modal_title: Badge Groupings granted_by: Granted By granted_at: Granted At save: Save diff --git a/config/routes.rb b/config/routes.rb index c38ca9892..f87dcf0d0 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -146,7 +146,7 @@ Discourse::Application.routes.draw do resources :badges, constraints: AdminConstraint.new do collection do get "types" => "badges#badge_types" - get "groupings" => "badges#badge_groupings" + post "badge_groupings" => "badges#save_badge_groupings" post "preview" => "badges#preview" end end diff --git a/spec/controllers/admin/badges_controller_spec.rb b/spec/controllers/admin/badges_controller_spec.rb index 5d418ba99..e36930e84 100644 --- a/spec/controllers/admin/badges_controller_spec.rb +++ b/spec/controllers/admin/badges_controller_spec.rb @@ -1,14 +1,35 @@ require 'spec_helper' describe Admin::BadgesController do - it "is a subclass of AdminController" do - (Admin::BadgesController < Admin::AdminController).should be_true - end context "while logged in as an admin" do let!(:user) { log_in(:admin) } let!(:badge) { Fabricate(:badge) } + context '.save_badge_groupings' do + + it 'can save badge groupings' do + groupings = BadgeGrouping.all.order(:position).to_a + groupings << BadgeGrouping.new(name: 'Test 1') + groupings << BadgeGrouping.new(name: 'Test 2') + + groupings.shuffle! + + names = groupings.map{|g| g.name} + ids = groupings.map{|g| g.id.to_s} + + + xhr :post, :save_badge_groupings, ids: ids, names: names + + groupings2 = BadgeGrouping.all.order(:position).to_a + + groupings2.map{|g| g.name}.should == names + (groupings.map(&:id) - groupings2.map{|g| g.id}).compact.should be_blank + + ::JSON.parse(response.body)["badge_groupings"].length.should == groupings2.length + end + end + context '.badge_types' do it 'returns success' do xhr :get, :badge_types