mirror of
https://github.com/codeninjasllc/discourse.git
synced 2024-11-27 17:46:05 -05:00
FEATURE: editable badge groups
This commit is contained in:
parent
0ab456b647
commit
1a6aa07611
12 changed files with 192 additions and 9 deletions
|
@ -7,6 +7,7 @@
|
|||
@module Discourse
|
||||
**/
|
||||
export default Ember.ArrayController.extend({
|
||||
needs: ['modal'],
|
||||
itemController: 'admin-badge',
|
||||
queryParams: ['badgeId'],
|
||||
badgeId: Em.computed.alias('selectedId'),
|
||||
|
|
|
@ -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");
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
|
|
@ -53,6 +53,7 @@
|
|||
content=controller.badgeGroupings
|
||||
optionValuePath="content.id"
|
||||
optionLabelPath="content.name"}}
|
||||
<button {{action editGroupings controller.badgeGroupings}}><i class="fa fa-pencil"></i></button>
|
||||
</div>
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
|
||||
<div class="modal-body">
|
||||
<div>
|
||||
<ul class='badge-groupings'>
|
||||
{{#each workingCopy}}
|
||||
<li>
|
||||
{{#if editing}}
|
||||
{{input value=this.name}}
|
||||
<button {{action save this}}><i class="fa fa-check"></i></button>
|
||||
{{else}}
|
||||
{{this.name}}
|
||||
{{/if}}
|
||||
<div class='actions'>
|
||||
<button {{action edit this}}><i class="fa fa-pencil"></i></button>
|
||||
<button {{action up this}}><i class="fa fa-toggle-up"></i></button>
|
||||
<button {{action down this}}><i class="fa fa-toggle-down"></i></button>
|
||||
<button {{action delete this}}><i class="fa fa-times"></i></button>
|
||||
</div>
|
||||
</li>
|
||||
{{/each}}
|
||||
</ul>
|
||||
</div>
|
||||
<button class='btn' {{action add}}>{{i18n admin.badges.new}}</button>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class='btn btn-primary' {{action saveAll}} {{bind-attr disabled="submitDisabled"}}>{{i18n admin.badges.save}}</button>
|
||||
<a {{action cancel}}>{{i18n cancel}}</a>
|
||||
</div>
|
|
@ -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')
|
||||
});
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -8,6 +8,10 @@ class BadgeGrouping < ActiveRecord::Base
|
|||
|
||||
has_many :badges
|
||||
|
||||
def system?
|
||||
id && id < 5
|
||||
end
|
||||
|
||||
def default_position=(pos)
|
||||
position ||= pos
|
||||
end
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue