very simple api for contents (just create for now) + fix a lot of bugs in the custom fields plugin and some enhancements as well + add an ui for manage categories + fix bugs
This commit is contained in:
parent
7ccc3d4548
commit
d0ff08c9a1
29
app/controllers/admin/api_contents_controller.rb
Normal file
29
app/controllers/admin/api_contents_controller.rb
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
module Admin
|
||||||
|
class ApiContentsController < ActionController::Base
|
||||||
|
|
||||||
|
include Locomotive::Routing::SiteDispatcher
|
||||||
|
|
||||||
|
before_filter :require_site
|
||||||
|
|
||||||
|
before_filter :set_content_type
|
||||||
|
|
||||||
|
def create
|
||||||
|
@content = @content_type.contents.build(params[:content])
|
||||||
|
|
||||||
|
respond_to do |format|
|
||||||
|
if @content.save
|
||||||
|
format.json { render :json => { :content => @content } }
|
||||||
|
else
|
||||||
|
format.json { render :json => { :content => @content, :errors => @content.errors } }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
protected
|
||||||
|
|
||||||
|
def set_content_type
|
||||||
|
@content_type = current_site.content_types.where(:slug => params[:slug]).first
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
33
app/controllers/admin/custom_fields_controller.rb
Normal file
33
app/controllers/admin/custom_fields_controller.rb
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
module Admin
|
||||||
|
class CustomFieldsController < BaseController
|
||||||
|
|
||||||
|
layout false
|
||||||
|
|
||||||
|
before_filter :set_content_type
|
||||||
|
|
||||||
|
def edit
|
||||||
|
@field = @content_type.content_custom_fields.find(params[:id])
|
||||||
|
render :action => "edit_#{@field.kind.downcase}"
|
||||||
|
end
|
||||||
|
|
||||||
|
def update
|
||||||
|
@field = @content_type.content_custom_fields.find(params[:id])
|
||||||
|
@field.updated_at = Time.now # forces mongoid to save the object
|
||||||
|
|
||||||
|
params[:custom_field][:category_items_attributes].delete('-1')
|
||||||
|
|
||||||
|
if @field.update_attributes(params[:custom_field])
|
||||||
|
render :json => @field.attributes
|
||||||
|
else
|
||||||
|
render :json => { :error => translate_flash_msg(:successful) }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
protected
|
||||||
|
|
||||||
|
def set_content_type
|
||||||
|
@content_type = current_site.content_types.where(:slug => params[:slug]).first
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
43
app/views/admin/custom_fields/edit_category.html.haml
Normal file
43
app/views/admin/custom_fields/edit_category.html.haml
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
#edit-custom-field-category
|
||||||
|
.inner
|
||||||
|
%h2= t('.title')
|
||||||
|
|
||||||
|
%p= t('.help')
|
||||||
|
|
||||||
|
= semantic_form_for @field, :as => :custom_field, :url => admin_custom_field_url(@content_type.slug, @field) do |f|
|
||||||
|
= f.foldable_inputs :name => t('.collection_label'), :class => 'editable-list off' do
|
||||||
|
- @field.ordered_category_items.each do |item|
|
||||||
|
= f.fields_for :category_items, item, :child_index => item._index do |g|
|
||||||
|
%li{ :class => "item added #{'error' unless item.errors.empty?}"}
|
||||||
|
%span.handle
|
||||||
|
= image_tag 'admin/form/icons/drag.png'
|
||||||
|
|
||||||
|
= g.hidden_field :position, :class => 'position'
|
||||||
|
|
||||||
|
= g.text_field :name
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
%span.actions
|
||||||
|
= link_to image_tag('admin/form/icons/trash.png'), '#', :class => 'remove', :confirm => t('admin.messages.confirm')
|
||||||
|
|
||||||
|
= f.fields_for :category_items, @field.category_items.build, :child_index => '-1' do |g|
|
||||||
|
%li{ :class => 'item template' }
|
||||||
|
%span.handle
|
||||||
|
= image_tag 'admin/form/icons/drag.png'
|
||||||
|
|
||||||
|
= g.hidden_field :position, :class => 'position'
|
||||||
|
|
||||||
|
= g.text_field :name, :class => 'string name'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
%span.actions
|
||||||
|
= link_to image_tag('admin/form/icons/trash.png'), '#', :class => 'remove', :confirm => t('admin.messages.confirm')
|
||||||
|
%button{ :class => 'button light add', :type => 'button' }
|
||||||
|
%span= t('admin.buttons.new_item')
|
||||||
|
|
||||||
|
.popup-actions
|
||||||
|
%p
|
||||||
|
%button.button.light{ :type => 'button' }
|
||||||
|
%span= t('admin.shared.form_actions.update')
|
59
app/views/admin/shared/_custom_fields.html.haml.old
Normal file
59
app/views/admin/shared/_custom_fields.html.haml.old
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
- collection_name = "#{collection_name.singularize}_custom_fields"
|
||||||
|
- custom_fields = f.object.send(collection_name.to_sym)
|
||||||
|
- ordered_custom_fields = f.object.send(:"ordered_#{collection_name}")
|
||||||
|
|
||||||
|
= f.foldable_inputs :name => :custom_fields, :class => 'editable-list fields' do
|
||||||
|
- ordered_custom_fields.each do |field|
|
||||||
|
= f.fields_for collection_name.to_sym, field, :child_index => field._index do |g|
|
||||||
|
%li{ :class => "item added #{'error' unless field.errors.empty?}"}
|
||||||
|
%span.handle
|
||||||
|
= image_tag 'admin/form/icons/drag.png'
|
||||||
|
|
||||||
|
= g.hidden_field :position, :class => 'position'
|
||||||
|
|
||||||
|
= g.hidden_field :_alias, :class => 'alias'
|
||||||
|
|
||||||
|
= g.hidden_field :hint, :class => 'hint'
|
||||||
|
|
||||||
|
= g.text_field :label
|
||||||
|
|
||||||
|
—
|
||||||
|
|
||||||
|
%em= t("admin.custom_fields.kind.#{field.kind.downcase}")
|
||||||
|
|
||||||
|
= g.select :kind, options_for_field_kind
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
%span.actions
|
||||||
|
= link_to image_tag('admin/form/pen.png'), '#', :class => 'edit first'
|
||||||
|
= link_to image_tag('admin/form/icons/trash.png'), '#', :class => 'remove', :confirm => t('admin.messages.confirm')
|
||||||
|
|
||||||
|
= f.fields_for collection_name.to_sym, custom_fields.build(:label => 'field name'), :child_index => '-1' do |g|
|
||||||
|
%li{ :class => 'item template' }
|
||||||
|
%span.handle
|
||||||
|
= image_tag 'admin/form/icons/drag.png'
|
||||||
|
|
||||||
|
= g.hidden_field :position, :class => 'position'
|
||||||
|
|
||||||
|
= g.hidden_field :_alias, :class => 'alias'
|
||||||
|
|
||||||
|
= g.hidden_field :hint, :class => 'hint'
|
||||||
|
|
||||||
|
= g.text_field :label, :class => 'string label void'
|
||||||
|
|
||||||
|
—
|
||||||
|
|
||||||
|
%em
|
||||||
|
|
||||||
|
= g.select :kind, options_for_field_kind
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
%span.actions
|
||||||
|
= link_to image_tag('admin/form/pen.png'), '#', :class => 'edit first'
|
||||||
|
= link_to image_tag('admin/form/icons/trash.png'), '#', :class => 'remove', :confirm => t('admin.messages.confirm')
|
||||||
|
%button{ :class => 'button light add', :type => 'button' }
|
||||||
|
%span= t('admin.buttons.new_item')
|
||||||
|
|
||||||
|
|
BIN
public/images/admin/form/big_item-popup.png
Normal file
BIN
public/images/admin/form/big_item-popup.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.0 KiB |
BIN
public/images/admin/form/footer-popup.png
Normal file
BIN
public/images/admin/form/footer-popup.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.0 KiB |
BIN
public/images/admin/form/header-popup.png
Normal file
BIN
public/images/admin/form/header-popup.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 525 B |
BIN
public/images/admin/form/item-popup.png
Normal file
BIN
public/images/admin/form/item-popup.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 979 B |
91
public/javascripts/admin/custom_fields/category.js
Normal file
91
public/javascripts/admin/custom_fields/category.js
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
// edit category collection
|
||||||
|
var SetupCustomFieldCategoryEditor = function(target) {
|
||||||
|
|
||||||
|
var refreshPosition = function() {
|
||||||
|
jQuery.each($('#edit-custom-field-category .editable-list li.added input.position'), function(index) {
|
||||||
|
$(this).val(index);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
$('#edit-custom-field-category .editable-list li.template button').click(function() {
|
||||||
|
var lastRow = $(this).parents('li.template');
|
||||||
|
|
||||||
|
if (lastRow.find('input.name').val() == '') return ;
|
||||||
|
|
||||||
|
var newRow = lastRow.clone(true).removeClass('template').addClass('added new').insertBefore(lastRow);
|
||||||
|
|
||||||
|
var dateFragment = '[' + new Date().getTime() + ']';
|
||||||
|
newRow.find('input, select').each(function(index) {
|
||||||
|
$(this).attr('name', $(this).attr('name').replace('[-1]', dateFragment));
|
||||||
|
});
|
||||||
|
|
||||||
|
// then reset the form
|
||||||
|
lastRow.find('input').val('');
|
||||||
|
|
||||||
|
// warn the sortable widget about the new row
|
||||||
|
$("#edit-custom-field-category .editable-list ol").sortable('refresh');
|
||||||
|
refreshPosition();
|
||||||
|
|
||||||
|
// resize popup
|
||||||
|
$.fancybox.resize();
|
||||||
|
});
|
||||||
|
|
||||||
|
$('#edit-custom-field-category .editable-list li a.remove').click(function(e) {
|
||||||
|
if (confirm($(this).attr('data-confirm'))) {
|
||||||
|
var parent = $(this).parents('li');
|
||||||
|
if (parent.hasClass('new'))
|
||||||
|
parent.remove();
|
||||||
|
else {
|
||||||
|
var field = parent.find('input.position')
|
||||||
|
field.attr('name', field.attr('name').replace('[position]', '[_destroy]'));
|
||||||
|
parent.hide().removeClass('added');
|
||||||
|
}
|
||||||
|
refreshPosition();
|
||||||
|
}
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
});
|
||||||
|
|
||||||
|
$("#edit-custom-field-category .editable-list ol").sortable({
|
||||||
|
handle: 'span.handle',
|
||||||
|
items: 'li:not(.template)',
|
||||||
|
axis: 'y',
|
||||||
|
update: refreshPosition
|
||||||
|
});
|
||||||
|
|
||||||
|
/* ___ submit ___ */
|
||||||
|
|
||||||
|
var updateSelectOptions = function(list) {
|
||||||
|
console.log('updateSelectOptions [begin]');
|
||||||
|
var options = '';
|
||||||
|
var selectedValue = target.val();
|
||||||
|
for (var i = 0; i < list.length; i++) {
|
||||||
|
options += '<option value="' + list[i]._id + '" >' + list[i].name + '</option>';
|
||||||
|
}
|
||||||
|
target.html(options);
|
||||||
|
target.val(selectedValue);
|
||||||
|
console.log('updateSelectOptions [end]');
|
||||||
|
};
|
||||||
|
|
||||||
|
$('#edit-custom-field-category .popup-actions button').click(function(e) {
|
||||||
|
var form = $('#edit-custom-field-category form');
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
type: 'PUT',
|
||||||
|
dataType: 'json',
|
||||||
|
data: form.serialize(),
|
||||||
|
url: form.attr('action'),
|
||||||
|
success: function(data) {
|
||||||
|
console.log("success");
|
||||||
|
if (data.error == null) {
|
||||||
|
list = data.category_items.sort(function(a, b) { return (a.position - b.position); });
|
||||||
|
updateSelectOptions(list);
|
||||||
|
$.fancybox.close();
|
||||||
|
} else
|
||||||
|
$.growl("error", data.error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
});
|
||||||
|
}
|
9
public/javascripts/admin/utils.js
Normal file
9
public/javascripts/admin/utils.js
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
function makeSlug(val, sep) { // code largely inspired by http://www.thewebsitetailor.com/jquery-slug-plugin/
|
||||||
|
if (typeof sep == 'undefined') sep = '_';
|
||||||
|
var alphaNumRegexp = new RegExp('[^a-zA-Z0-9\\' + sep + ']', 'g');
|
||||||
|
var avoidDuplicateRegexp = new RegExp('[\\' + sep + ']{2,}', 'g');
|
||||||
|
val = val.replace(/\s/g, sep);
|
||||||
|
val = val.replace(alphaNumRegexp, '');
|
||||||
|
val = val.replace(avoidDuplicateRegexp, sep);
|
||||||
|
return val.toLowerCase();
|
||||||
|
}
|
28
vendor/plugins/custom_fields/spec/integration/custom_fields_for_spec.rb
vendored
Normal file
28
vendor/plugins/custom_fields/spec/integration/custom_fields_for_spec.rb
vendored
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
require 'spec_helper'
|
||||||
|
|
||||||
|
describe CustomFields::CustomFieldsFor do
|
||||||
|
|
||||||
|
describe 'Saving' do
|
||||||
|
|
||||||
|
before(:each) do
|
||||||
|
@project = Project.new(:name => 'Locomotive')
|
||||||
|
@project.person_custom_fields.build(:label => 'E-mail', :_alias => 'email', :kind => 'String')
|
||||||
|
@project.person_custom_fields.build(:label => 'Age', :_alias => 'age', :kind => 'String')
|
||||||
|
end
|
||||||
|
|
||||||
|
context '@create' do
|
||||||
|
|
||||||
|
it 'persists parent object' do
|
||||||
|
lambda { @project.save }.should change(Project, :count).by(1)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'persists custom fields' do
|
||||||
|
@project.save && @project.reload
|
||||||
|
@project.person_custom_fields.count.should == 2
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
26
vendor/plugins/custom_fields/spec/integration/types/category_spec.rb
vendored
Normal file
26
vendor/plugins/custom_fields/spec/integration/types/category_spec.rb
vendored
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
require 'spec_helper'
|
||||||
|
|
||||||
|
describe CustomFields::Types::Category do
|
||||||
|
|
||||||
|
before(:each) do
|
||||||
|
@project = Project.new(:name => 'Locomotive')
|
||||||
|
@field = @project.task_custom_fields.build(:label => 'Main category', :_alias => 'main_category', :kind => 'Category')
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'saving category items' do
|
||||||
|
|
||||||
|
before(:each) do
|
||||||
|
@field.category_items.build :name => 'Development'
|
||||||
|
@field.category_items.build :name => 'Design'
|
||||||
|
@field.updated_at = Time.now
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'persists items' do
|
||||||
|
@field.save.should be_true
|
||||||
|
@project.reload
|
||||||
|
@project.task_custom_fields.first.category_items.size.should == 2
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
Loading…
Reference in New Issue
Block a user