diff --git a/Gemfile b/Gemfile index 720459f0..159b799f 100644 --- a/Gemfile +++ b/Gemfile @@ -6,22 +6,22 @@ gem 'rake', '0.9.2' gem 'rails', '~> 3.1.3' -gem 'devise', :git => 'git://github.com/plataformatec/devise.git'# FIXME: waiting for the new devise gem coming soon +gem 'devise', '~> 1.5.3' gem 'cancan', '~> 1.6.7' -gem 'bson_ext', '~> 1.4.0' -gem 'mongoid', '~> 2.3.3' +gem 'mongo', '~> 1.5.2' +gem 'bson_ext', '~> 1.5.2' +gem 'mongoid', '~> 2.4.0' gem 'locomotive_mongoid_acts_as_tree', :git => 'git@github.com:locomotivecms/mongoid_acts_as_tree.git' -# gem 'custom_fields', :git => 'git://github.com/locomotivecms/custom_fields.git' gem 'custom_fields', :path => '../gems/custom_fields' # DEV # gem 'custom_fields', :git => 'git://github.com/locomotivecms/custom_fields.git', :branch => 'experimental' gem 'kaminari' gem 'haml', '~> 3.1.3' gem 'sass-rails', '~> 3.1.4' -gem "compass", :git => 'git://github.com/chriseppstein/compass.git' gem 'coffee-script', '~> 2.2.0' gem 'uglifier', '~> 1.0.4' +gem 'compass', '~> 0.12.alpha.4' gem 'jquery-rails', '~> 1.0.16' gem 'rails-backbone', '0.5.4' gem 'codemirror-rails' diff --git a/Gemfile.lock b/Gemfile.lock index e36053b2..d67fec61 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,22 +1,3 @@ -GIT - remote: git://github.com/chriseppstein/compass.git - revision: bffba483754cb9381fa51efd8e2a1f0482a21ac6 - specs: - compass (0.12.alpha.4.bffba48) - chunky_png (~> 1.2) - fssm (>= 0.2.7) - sass (~> 3.1) - -GIT - remote: git://github.com/plataformatec/devise.git - revision: a949f9eca24f9d43f516363fbf2f5d004623355e - specs: - devise (2.0.0.rc) - bcrypt-ruby (~> 3.0) - orm_adapter (~> 0.0.3) - railties (~> 3.1) - warden (~> 1.1) - GIT remote: git@github.com:locomotivecms/mongoid_acts_as_tree.git revision: ca494d22c3d7946385aba1153c017d9c30e9f9d3 @@ -29,7 +10,7 @@ PATH custom_fields (2.0.0.rc1) activesupport (~> 3.1.3) carrierwave-mongoid (~> 0.1.3) - mongoid (~> 2.3.4) + mongoid (~> 2.4.0) GEM remote: http://rubygems.org/ @@ -73,7 +54,8 @@ GEM ZenTest (>= 4.4.1) bcrypt-ruby (3.0.1) bson (1.5.2) - bson_ext (1.4.0) + bson_ext (1.5.2) + bson (= 1.5.2) builder (3.0.0) bushido (0.0.35) highline (>= 1.6.1) @@ -105,6 +87,10 @@ GEM coffee-script-source execjs coffee-script-source (1.2.0) + compass (0.12.alpha.4) + chunky_png (~> 1.2) + fssm (>= 0.2.7) + sass (~> 3.1) cucumber (1.1.4) builder (>= 2.1.2) diff-lcs (>= 1.1.2) @@ -121,6 +107,10 @@ GEM delayed_job_mongoid (1.0.8) delayed_job (~> 3.0.0) mongoid (>= 2.0) + devise (1.5.3) + bcrypt-ruby (~> 3.0) + orm_adapter (~> 0.0.3) + warden (~> 1.1) diff-lcs (1.1.3) dragonfly (0.9.9) rack @@ -182,7 +172,7 @@ GEM mocha (0.9.12) mongo (1.5.2) bson (= 1.5.2) - mongoid (2.3.4) + mongoid (2.4.0) activemodel (~> 3.1) mongo (~> 1.3) tzinfo (~> 0.3.22) @@ -298,7 +288,7 @@ DEPENDENCIES ZenTest actionmailer-with-request (~> 0.3.0) autotest - bson_ext (~> 1.4.0) + bson_ext (~> 1.5.2) bushido (= 0.0.35) cancan (~> 1.6.7) capybara @@ -306,12 +296,12 @@ DEPENDENCIES cells (~> 3.7.0) codemirror-rails coffee-script (~> 2.2.0) - compass! + compass (~> 0.12.alpha.4) cucumber-rails custom_fields! database_cleaner delayed_job_mongoid (~> 1.0.8) - devise! + devise (~> 1.5.3) dragonfly (~> 0.9.8) factory_girl_rails (~> 1.1) flash_cookie_session (~> 1.1.1) @@ -328,7 +318,8 @@ DEPENDENCIES locomotive_mongoid_acts_as_tree! mimetype-fu (~> 0.1.2) mocha (= 0.9.12) - mongoid (~> 2.3.3) + mongo (~> 1.5.2) + mongoid (~> 2.4.0) pickle rack-cache (~> 1.1) rails (~> 3.1.3) diff --git a/README.textile b/README.textile index 17e0dda5..26afbd32 100644 --- a/README.textile +++ b/README.textile @@ -48,7 +48,7 @@ h2. Community h2. Team * Developers: "Didier Lafforgue":http://www.nocoffee.fr, "Jacques Crocker":http://www.railsjedi.com, "Mario Visic":http://www.mariovisic.com -* Contributors: "Dirk Kelly":http://www.dirkkelly.com, "Raphael Costa":http://raphaelcosta.net (Brazilian Portuguese translation), "Bernd Hauser":http://www.designhunger.de (German translation), "Andrea Frigido":http://www.frisoft.it (Italian translation), "Enrique García":https://github.com/kikito (Spanish translation), "Lars Smit":https://github.com/larssmit (Dutch translation), "PitOn":https://github.com/GarPit (Russian translation) +* Contributors: "Dirk Kelly":http://www.dirkkelly.com, "Raphael Costa":http://raphaelcosta.net (Brazilian Portuguese translation), "Bernd Hauser":http://www.designhunger.de (German translation), "Andrea Frigido":http://www.frisoft.it (Italian translation), "Enrique García":https://github.com/kikito (Spanish translation), "Lars Smit":https://github.com/larssmit (Dutch translation), "PitOn":https://github.com/GarPit (Russian translation), "paulsponagl":https://github.com/paulsponagl * UI Designer: "Sacha Greif":http://www.sachagreif.com * IE maintainer: "Alex Sanford":https://github.com/alexsanford diff --git a/app/assets/javascripts/locomotive/application.js.coffee b/app/assets/javascripts/locomotive/application.js.coffee index 2c53832a..57bdc3fd 100644 --- a/app/assets/javascripts/locomotive/application.js.coffee +++ b/app/assets/javascripts/locomotive/application.js.coffee @@ -3,13 +3,11 @@ #= require_tree ./utils #= require_tree ./models #= require_tree ./views -#= require_tree ./routers window.Locomotive = mount_on: '/locomotive' Models: {} Collections: {} - Routers: {} Views: {} window.Locomotive.Views.Memberships = {} \ No newline at end of file diff --git a/app/assets/javascripts/locomotive/models/custom_field.js.coffee b/app/assets/javascripts/locomotive/models/custom_field.js.coffee index ffa8f96c..d0a6031e 100644 --- a/app/assets/javascripts/locomotive/models/custom_field.js.coffee +++ b/app/assets/javascripts/locomotive/models/custom_field.js.coffee @@ -13,7 +13,7 @@ class Locomotive.Models.CustomField extends Backbone.Model toJSONForSave: -> _.tap {}, (hash) => for key, value of @.toJSON() - hash[key] = value unless _.include(['select_options', 'type_text', 'created_at', 'updated_at'], key) + hash[key] = value unless _.include(['select_options', 'type_text', 'text_formatting_text', 'created_at', 'updated_at'], key) hash.select_options_attributes = @get('select_options').toJSONForSave() if @get('select_options') class Locomotive.Models.CustomFieldsCollection extends Backbone.Collection diff --git a/app/assets/javascripts/locomotive/routers/.gitkeep b/app/assets/javascripts/locomotive/routers/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/app/assets/javascripts/locomotive/views/content_types/_form_view.js.coffee b/app/assets/javascripts/locomotive/views/content_types/_form_view.js.coffee index 3f2f481a..9ec68e18 100644 --- a/app/assets/javascripts/locomotive/views/content_types/_form_view.js.coffee +++ b/app/assets/javascripts/locomotive/views/content_types/_form_view.js.coffee @@ -23,7 +23,7 @@ class Locomotive.Views.ContentTypes.FormView extends Locomotive.Views.Shared.For @enable_liquid_editing() # turn textarea into editable liquid code zone - @enable_public_form_checkbox() + @enable_public_submission_checkbox() @enable_order_by_toggler() @@ -48,10 +48,10 @@ class Locomotive.Views.ContentTypes.FormView extends Locomotive.Views.Shared.For theme: 'default medium' onChange: (editor) => @model.set(raw_item_template: editor.getValue()) - enable_public_form_checkbox: -> - @_enable_checkbox 'public_form_enabled', - on_callback: => @$('#content_type_public_form_accounts_input').show() - off_callback: => @$('#content_type_public_form_accounts_input').hide() + enable_public_submission_checkbox: -> + @_enable_checkbox 'public_submission_enabled', + on_callback: => @$('#content_type_public_submission_accounts_input').show() + off_callback: => @$('#content_type_public_submission_accounts_input').hide() enable_order_by_toggler: -> @$('#content_type_order_by_input').bind 'change', (event) => diff --git a/app/controllers/locomotive/api_contents_controller.rb b/app/controllers/locomotive/api_contents_controller.rb deleted file mode 100644 index d5a06833..00000000 --- a/app/controllers/locomotive/api_contents_controller.rb +++ /dev/null @@ -1,61 +0,0 @@ -module Locomotive - class ApiContentsController < ActionController::Base - - # FIXME: NEED REFACTORING - - include Locomotive::Routing::SiteDispatcher - - before_filter :require_site - - before_filter :set_content_type - - before_filter :block_content_type_with_disabled_api - - before_filter :sanitize_content_params, :only => :create - - def create - @entry = @content_type.entries.build(params[:entry]) - - respond_to do |format| - if @entry.save - format.json { render :json => { :entry => @entry } } - format.html do - flash[@content_type.slug.singularize] = @entry.aliased_attributes - redirect_to params[:success_callback] - end - else - format.json { render :json => { :entry => @content, :errors => @content.errors } } - format.html do - flash[@content_type.slug.singularize] = @content.aliased_attributes - flash['errors'] = @content.errors_to_hash - redirect_to params[:error_callback] - end - end - end - end - - protected - - def set_content_type - @content_type = current_site.content_types.where(:slug => params[:slug]).first - end - - def block_content_type_with_disabled_api - unless @content_type.api_enabled? - respond_to do |format| - format.json { render :json => { :error => 'Api not enabled' }, :status => :forbidden } - format.html { render :text => 'Api not enabled', :status => :forbidden } - end - return false - end - end - - def sanitize_content_params - (params[:content] || {}).each do |key, value| - next unless value.is_a?(String) - params[:content][key] = Sanitize.clean(value, Sanitize::Config::BASIC) - end - end - - end -end diff --git a/app/controllers/locomotive/base_controller.rb b/app/controllers/locomotive/base_controller.rb index e62f9ff5..17e1aeab 100644 --- a/app/controllers/locomotive/base_controller.rb +++ b/app/controllers/locomotive/base_controller.rb @@ -3,6 +3,8 @@ module Locomotive include Locomotive::Routing::SiteDispatcher + include Locomotive::ActionController::Helpers + layout '/locomotive/layouts/application' before_filter :require_account @@ -17,15 +19,11 @@ module Locomotive before_filter :set_current_thread_variables - helper_method :sections, :current_site_public_url, :switch_to_site_url, :public_page_url, :current_ability + helper_method :sections, :current_ability - # https://rails.lighthouseapp.com/projects/8994/tickets/1905-apphelpers-within-plugin-not-being-mixed-in - helper Locomotive::BaseHelper, Locomotive::ContentTypesHelper #, Locomotive::BoxHelper - # Dir[File.dirname(__FILE__) + "/../../helpers/**/*_helper.rb"].each do |file| - # helper "locomotive/#{File.basename(file, '.rb').gsub(/_helper$/, '')}" - # end + helper Locomotive::BaseHelper, Locomotive::ContentTypesHelper - self.responder = Locomotive::Responder # custom responder + self.responder = Locomotive::ActionController::Responder # custom responder respond_to :html @@ -44,8 +42,8 @@ module Locomotive protected def set_current_thread_variables - Thread.current[:account] = current_locomotive_account - Thread.current[:site] = current_site + Thread.current[:account] = current_locomotive_account + Thread.current[:site] = current_site end def current_ability @@ -56,51 +54,5 @@ module Locomotive authenticate_locomotive_account! end - def self.sections(main, sub = nil) - before_filter do |c| - sub = sub.call(c) if sub.respond_to?(:call) - sections = { :main => main, :sub => sub } - c.instance_variable_set(:@locomotive_sections, sections) - end - end - - def sections(key = nil) - if !key.nil? && key.to_sym == :sub - @locomotive_sections[:sub] || self.controller_name.dasherize - else - @locomotive_sections[:main] - end - end - - def set_locale - I18n.locale = current_locomotive_account.locale rescue Locomotive.config.default_locale - end - - # ___ site/page urls builder ___ - - def current_site_public_url - request.protocol + request.host_with_port - end - - def switch_to_site_url(site, options = {}) - options = { :fullpath => true, :protocol => true }.merge(options) - - url = "#{site.subdomain}.#{Locomotive.config.domain}" - url += ":#{request.port}" if request.port != 80 - - url = File.join(url, request.fullpath) if options[:fullpath] - url = "http://#{url}" if options[:protocol] - url - end - - def public_page_url(page, options = {}) - if content = options.delete(:content) - File.join(current_site_public_url, page.fullpath.gsub('content_type_template', ''), content._slug) - else - File.join(current_site_public_url, page.fullpath) - end - end - - end end diff --git a/app/controllers/locomotive/public/base_controller.rb b/app/controllers/locomotive/public/base_controller.rb new file mode 100644 index 00000000..8539cab1 --- /dev/null +++ b/app/controllers/locomotive/public/base_controller.rb @@ -0,0 +1,19 @@ +module Locomotive + module Public + class BaseController < ApplicationController + + include Locomotive::Routing::SiteDispatcher + + include Locomotive::ActionController::Helpers + + before_filter :require_site + + protected + + def set_locale + logger.info "[public/set_locale] TODO" + end + + end + end +end \ No newline at end of file diff --git a/app/controllers/locomotive/public/content_entries_controller.rb b/app/controllers/locomotive/public/content_entries_controller.rb new file mode 100644 index 00000000..e4a0c418 --- /dev/null +++ b/app/controllers/locomotive/public/content_entries_controller.rb @@ -0,0 +1,50 @@ +module Locomotive + module Public + class ContentEntriesController < BaseController + + before_filter :set_content_type + + before_filter :sanitize_entry_params, :only => :create + + skip_before_filter :verify_authenticity_token + + self.responder = Locomotive::ActionController::PublicResponder # custom responder + + respond_to :html, :json + + def create + @entry = @content_type.entries.create(params[:entry]) + flash[@content_type.slug.singularize] = @entry.to_presenter(:include_errors => true).as_json + respond_with @entry, :location => self.callback_url + end + + protected + + def set_content_type + @content_type = current_site.content_types.where(:slug => params[:slug]).first + + # check if ability to receive public submissions + unless @content_type.public_submission_enabled? + respond_to do |format| + format.json { render :json => { :error => 'Public submissions not accepted' }, :status => :forbidden } + format.html { render :text => 'Public submissions not accepted', :status => :forbidden } + end + return false + end + end + + def callback_url + @entry.errors.empty? ? params[:success_callback] : params[:error_callback] + end + + def sanitize_entry_params + entry_params = params[:entry] || params[:content] || {} + entry_params.each do |key, value| + next unless value.is_a?(String) + entry_params[key] = Sanitize.clean(value, Sanitize::Config::BASIC) + end + end + + end + end +end diff --git a/app/controllers/locomotive/public/rendering_controller.rb b/app/controllers/locomotive/public/rendering_controller.rb new file mode 100644 index 00000000..705355ff --- /dev/null +++ b/app/controllers/locomotive/public/rendering_controller.rb @@ -0,0 +1,26 @@ +module Locomotive + module Public + class RenderingController < ApplicationController + + include Locomotive::Routing::SiteDispatcher + + include Locomotive::Render + + before_filter :require_site + + before_filter :authenticate_admin!, :only => [:edit] + + before_filter :validate_site_membership, :only => [:edit] + + def show + render_locomotive_page + end + + def edit + @editing = true + render_locomotive_page + end + + end + end +end \ No newline at end of file diff --git a/app/controllers/locomotive/public/robots_controller.rb b/app/controllers/locomotive/public/robots_controller.rb new file mode 100644 index 00000000..71e65106 --- /dev/null +++ b/app/controllers/locomotive/public/robots_controller.rb @@ -0,0 +1,16 @@ +module Locomotive + module Public + class RobotsController < BaseController + + include Locomotive::Render + + respond_to :txt + + def show + template = ::Liquid::Template.parse(current_site.robots_txt) + render :text => template.render('request_host' => self.request.host.downcase) + end + + end + end +end \ No newline at end of file diff --git a/app/controllers/locomotive/public/sitemaps_controller.rb b/app/controllers/locomotive/public/sitemaps_controller.rb new file mode 100644 index 00000000..717aff61 --- /dev/null +++ b/app/controllers/locomotive/public/sitemaps_controller.rb @@ -0,0 +1,14 @@ +module Locomotive + module Public + class SitemapsController < BaseController + + respond_to :xml + + def show + @pages = current_site.pages.published + respond_with @pages + end + + end + end +end \ No newline at end of file diff --git a/app/controllers/locomotive/rendering_controller.rb b/app/controllers/locomotive/rendering_controller.rb deleted file mode 100644 index cfd7bc00..00000000 --- a/app/controllers/locomotive/rendering_controller.rb +++ /dev/null @@ -1,22 +0,0 @@ -module Locomotive - class RenderingController < ActionController::Base - - include Locomotive::Routing::SiteDispatcher - - include Locomotive::Render - - before_filter :require_site - before_filter :authenticate_admin!, :only => [:edit] - before_filter :validate_site_membership, :only => [:edit] - - def show - render_locomotive_page - end - - def edit - @editing = true - render_locomotive_page - end - - end -end diff --git a/app/controllers/locomotive/robots_controller.rb b/app/controllers/locomotive/robots_controller.rb deleted file mode 100644 index 741693aa..00000000 --- a/app/controllers/locomotive/robots_controller.rb +++ /dev/null @@ -1,18 +0,0 @@ -module Locomotive - class RobotsController < ActionController::Base - - include Locomotive::Routing::SiteDispatcher - - include Locomotive::Render - - before_filter :require_site - - respond_to :txt - - def show - template = ::Liquid::Template.parse(current_site.robots_txt) - render :text => template.render('request_host' => self.request.host.downcase) - end - - end -end \ No newline at end of file diff --git a/app/controllers/locomotive/sitemaps_controller.rb b/app/controllers/locomotive/sitemaps_controller.rb deleted file mode 100644 index 79ffc48f..00000000 --- a/app/controllers/locomotive/sitemaps_controller.rb +++ /dev/null @@ -1,18 +0,0 @@ -module Locomotive - class SitemapsController < BaseController - - skip_before_filter :require_account, :validate_site_membership, :set_locale - - before_filter :require_site - - respond_to :xml - - skip_load_and_authorize_resource - - def show - @pages = current_site.pages.published - respond_with @pages - end - - end -end diff --git a/app/mailers/locomotive/notifications.rb b/app/mailers/locomotive/notifications.rb index c7b24ae0..b59e1364 100644 --- a/app/mailers/locomotive/notifications.rb +++ b/app/mailers/locomotive/notifications.rb @@ -4,9 +4,9 @@ module Locomotive default :from => Locomotive.config.mailer_sender def new_content_entry(account, entry) - @account, @entry = account, entry + @account, @entry, @type = account, entry.to_presenter, entry.content_type - subject = t('locomotive.notifications.new_content_entry.subject', :type => entry.content_type.name, :locale => account.locale) + subject = t('locomotive.notifications.new_content_entry.subject', :type => @type.name, :locale => account.locale) mail :subject => subject, :to => account.email end diff --git a/app/models/locomotive/content_entry.rb b/app/models/locomotive/content_entry.rb index c5f710d3..8fa6aaed 100644 --- a/app/models/locomotive/content_entry.rb +++ b/app/models/locomotive/content_entry.rb @@ -64,8 +64,8 @@ module Locomotive Locomotive::Liquid::Drops::ContentEntry.new(self) end - def to_presenter - Locomotive::ContentEntryPresenter.new(self) + def to_presenter(options = {}) + Locomotive::ContentEntryPresenter.new(self, options) end def as_json(options = {}) @@ -119,10 +119,10 @@ module Locomotive end def send_notifications - return if !self.content_type.public_form_enabled? || self.content_type.public_form_accounts.blank? + return if !self.content_type.public_submission_enabled? || self.content_type.public_submission_accounts.blank? self.content_type.site.accounts.each do |account| - next unless self.content_type.public_form_accounts.include?(account._id.to_s) + next unless self.content_type.public_submission_accounts.include?(account._id.to_s) Locomotive::Notifications.new_content_entry(account, self).deliver end diff --git a/app/models/locomotive/content_type.rb b/app/models/locomotive/content_type.rb index 35436344..43f7c756 100644 --- a/app/models/locomotive/content_type.rb +++ b/app/models/locomotive/content_type.rb @@ -11,13 +11,13 @@ module Locomotive field :name field :description field :slug - field :label_field_id, :type => BSON::ObjectId + field :label_field_id, :type => BSON::ObjectId field :label_field_name - field :group_by_field_id, :type => BSON::ObjectId + field :group_by_field_id, :type => BSON::ObjectId field :order_by - field :order_direction, :default => 'asc' - field :public_form_enabled, :type => Boolean, :default => false - field :public_form_accounts, :type => Array + field :order_direction, :default => 'asc' + field :public_submission_enabled, :type => Boolean, :default => false + field :public_submission_accounts, :type => Array ## associations ## belongs_to :site, :class_name => 'Locomotive::Site' @@ -53,8 +53,8 @@ module Locomotive [order_by_attribute, direction] end - def ordered_entries - self.entries.order_by([order_by_definition]) + def ordered_entries(conditions = {}) + self.entries.order_by([order_by_definition]).where(conditions) end def groupable? @@ -81,71 +81,6 @@ module Locomotive self.to_presenter.as_json end - # def list_or_group_contents - # if self.groupable? - # groups = self.contents.klass.send(:"group_by_#{self.group_by_field._alias}", :ordered_contents) - # - # # look for items with no category or unknown ones - # items_without_category = self.contents.find_all { |c| !self.group_by_field.category_ids.include?(c.send(self.group_by_field_name)) } - # if not items_without_category.empty? - # groups << { :name => nil, :items => items_without_category } - # else - # groups - # end - # else - # self.ordered_contents - # end - # end - # - # def latest_updated_contents - # self.contents.latest_updated.reject { |c| !c.persisted? } - # end - # - # def ordered_contents(conditions = {}) - # column = self.order_by.to_sym - # - # list = (if conditions.nil? || conditions.empty? - # self.contents - # else - # conditions_with_names = {} - # - # conditions.each do |key, value| - # # convert alias (key) to name - # field = self.entries_custom_fields.detect { |f| f._alias == key } - # - # case field.kind.to_sym - # when :category - # if (category_item = field.category_items.where(:name => value).first).present? - # conditions_with_names[field._name.to_sym] = category_item._id - # end - # else - # conditions_with_names[field._name.to_sym] = value - # end - # end - # - # self.contents.where(conditions_with_names) - # end).sort { |a, b| (a.send(column) && b.send(column)) ? (a.send(column) || 0) <=> (b.send(column) || 0) : 0 } - # - # return list if self.order_manually? - # - # self.asc_order? ? list : list.reverse - # end - # - # def sort_contents!(ids) - # ids.each_with_index do |id, position| - # self.contents.find(BSON::ObjectId(id))._position_in_list = position - # end - # self.save - # end - # - # def highlighted_field - # self.entries_custom_fields.detect { |f| f._name == self.highlighted_field_name } - # end - # - # def group_by_field - # @group_by_field ||= self.entries_custom_fields.detect { |f| f._name == self.group_by_field_name } - # end - protected def order_by_attribute @@ -155,7 +90,8 @@ module Locomotive def set_default_values self.order_by ||= 'created_at' - field = self.entries_custom_fields.find(self.label_field_id) rescue self.entries_custom_fields.first + self.label_field_id = self.entries_custom_fields.first._id if self.label_field_id.blank? + field = self.entries_custom_fields.find(self.label_field_id) self.label_field_name = field.name end @@ -177,3 +113,64 @@ module Locomotive end end + +# def list_or_group_contents +# if self.groupable? +# groups = self.contents.klass.send(:"group_by_#{self.group_by_field._alias}", :ordered_contents) +# +# # look for items with no category or unknown ones +# items_without_category = self.contents.find_all { |c| !self.group_by_field.category_ids.include?(c.send(self.group_by_field_name)) } +# if not items_without_category.empty? +# groups << { :name => nil, :items => items_without_category } +# else +# groups +# end +# else +# self.ordered_contents +# end +# end +# +# def latest_updated_contents +# self.contents.latest_updated.reject { |c| !c.persisted? } +# end +# +# def ordered_contents(conditions = {}) +# column = self.order_by.to_sym +# +# list = (if conditions.nil? || conditions.empty? +# self.contents +# else +# conditions_with_names = {} +# +# conditions.each do |key, value| +# # convert alias (key) to name +# field = self.entries_custom_fields.detect { |f| f._alias == key } +# +# case field.kind.to_sym +# when :category +# if (category_item = field.category_items.where(:name => value).first).present? +# conditions_with_names[field._name.to_sym] = category_item._id +# end +# else +# conditions_with_names[field._name.to_sym] = value +# end +# end +# +# self.contents.where(conditions_with_names) +# end).sort { |a, b| (a.send(column) && b.send(column)) ? (a.send(column) || 0) <=> (b.send(column) || 0) : 0 } +# +# return list if self.order_manually? +# +# self.asc_order? ? list : list.reverse +# end +# +# def sort_contents!(ids) +# ids.each_with_index do |id, position| +# self.contents.find(BSON::ObjectId(id))._position_in_list = position +# end +# self.save +# end +# +# def group_by_field +# @group_by_field ||= self.entries_custom_fields.detect { |f| f._name == self.group_by_field_name } +# end \ No newline at end of file diff --git a/app/presenters/locomotive/base_presenter.rb b/app/presenters/locomotive/base_presenter.rb index b6003297..f298cc88 100644 --- a/app/presenters/locomotive/base_presenter.rb +++ b/app/presenters/locomotive/base_presenter.rb @@ -1,7 +1,7 @@ class Locomotive::BasePresenter include ActionView::Helpers::SanitizeHelper - extend ActionView::Helpers::SanitizeHelper::ClassMethods + extend ActionView::Helpers::SanitizeHelper::ClassMethods include ActionView::Helpers::TextHelper include ActionView::Helpers::NumberHelper @@ -20,8 +20,6 @@ class Locomotive::BasePresenter def id self.source.persisted? || self.source.embedded? ? self.source._id.to_s : nil - # self.persisted? ? self.source._id.to_s : nil - # self.source._id.to_s end def ability? @@ -35,8 +33,8 @@ class Locomotive::BasePresenter def as_json(methods = nil) methods ||= self.included_methods {}.tap do |hash| - methods.map(&:to_sym).each do |meth| - hash[meth] = self.send(meth) rescue nil + methods.each do |meth| + hash[meth] = self.send(meth.to_sym) rescue nil end end end diff --git a/app/presenters/locomotive/content_entry_presenter.rb b/app/presenters/locomotive/content_entry_presenter.rb index 7a9d0c91..ad9baebe 100644 --- a/app/presenters/locomotive/content_entry_presenter.rb +++ b/app/presenters/locomotive/content_entry_presenter.rb @@ -3,20 +3,33 @@ module Locomotive delegate :_slug, :_position, :seo_title, :meta_keywords, :meta_description, :to => :source + # Returns the value of a field in the context of the current entry. + # + # @params [ CustomFields::Field ] field The field + # + # @returns [ Object ] The value of the field for the entry + # + def value_for(field) + getter = [*self.getters_for(field.name, field.type)].first.to_sym + self.source.send(getter) + end + + # Returns the list of getters for an entry + # + # @returns [ List ] a list of method names (string) + # def custom_fields_methods - source.custom_fields_recipe['rules'].map do |rule| - case rule['type'] - when 'select' then [rule['name'], "#{rule['name']}_id"] - when 'date' then "formatted_#{rule['name']}" - when 'file' then "#{rule['name']}_url" - else - rule['name'] - end + self.source.custom_fields_recipe['rules'].map do |rule| + self.getters_for rule['name'], rule['type'] end.flatten end + # Lists of all the attributes editable by a html form + # + # @returns [ List ] a list of attributes (string) + # def safe_attributes - source.custom_fields_recipe['rules'].map do |rule| + self.source.custom_fields_recipe['rules'].map do |rule| case rule['type'] when 'select' then "#{rule['name']}_id" when 'date' then "formatted_#{rule['name']}" @@ -27,6 +40,10 @@ module Locomotive end.flatten + %w(_slug seo_title meta_keywords meta_description) end + def errors + self.source.errors.to_hash.stringify_keys + end + def content_type_slug self.source.content_type.slug end @@ -36,7 +53,9 @@ module Locomotive end def included_methods - super + self.custom_fields_methods + %w(_slug _position content_type_slug _file_fields safe_attributes persisted) + default_list = %w(_slug _position content_type_slug _file_fields safe_attributes) + default_list << 'errors' if !!self.options[:include_errors] + super + self.custom_fields_methods + default_list end def method_missing(meth, *arguments, &block) @@ -47,5 +66,24 @@ module Locomotive end end + protected + + # Gets the names of the getter methods for a field. + # The names depend on the field type. + # + # @params [ String ] name Name of the field + # @params [ String ] type Type of the field + # + # @returns [ Object ] A string or an array of names + def getters_for(name, type) + case type + when 'select' then [name, "#{name}_id"] + when 'date' then "formatted_#{name}" + when 'file' then "#{name}_url" + else + name + end + end + end end \ No newline at end of file diff --git a/app/views/locomotive/content_types/_form.html.haml b/app/views/locomotive/content_types/_form.html.haml index cb253ec6..d3ff847c 100644 --- a/app/views/locomotive/content_types/_form.html.haml +++ b/app/views/locomotive/content_types/_form.html.haml @@ -33,6 +33,6 @@ = f.input :order_direction, :as => :select, :collection => options_for_order_direction, :include_blank => false, :wrapper_html => { :style => "#{'display: none' if @content_type.order_manually?}" } - = f.input :public_form_enabled, :as => :'Locomotive::Toggle' + = f.input :public_submission_enabled, :as => :'Locomotive::Toggle' - = f.input :public_form_accounts, :as => :select, :collection => options_for_account, :include_blank => false, :multiple => true, :wrapper_html => { :class => 'multiple', :style => (@content_type.public_form_enabled? ? '' : 'display: none') } + = f.input :public_submission_accounts, :as => :select, :collection => options_for_account, :include_blank => false, :multiple => true, :wrapper_html => { :class => 'multiple', :style => (@content_type.public_submission_enabled? ? '' : 'display: none') } diff --git a/app/views/locomotive/content_types/edit.html.haml b/app/views/locomotive/content_types/edit.html.haml index 1ce43ac3..52729ced 100644 --- a/app/views/locomotive/content_types/edit.html.haml +++ b/app/views/locomotive/content_types/edit.html.haml @@ -7,8 +7,8 @@ = render 'locomotive/shared/actions/contents' - content_for :buttons do - = local_action_button :show_items, content_entries_url(@content_type.slug_was), :class => 'show' - = local_action_button :new_item, new_content_entry_url(@content_type.slug_was), :class => 'new' + = local_action_button :show_entries, content_entries_url(@content_type.slug_was), :class => 'show' + = local_action_button :new_entry, new_content_entry_url(@content_type.slug_was), :class => 'new' %p!= t('.help') diff --git a/app/views/locomotive/custom_fields/_custom_form.html.haml b/app/views/locomotive/custom_fields/_custom_form.html.haml deleted file mode 100644 index ae427aa7..00000000 --- a/app/views/locomotive/custom_fields/_custom_form.html.haml +++ /dev/null @@ -1,10 +0,0 @@ -- highlighted_field_name = parent.highlighted_field_name rescue '' - -= form.inputs :name => title || :attributes do - - form.object.custom_fields.each do |field| - - highlighted = highlighted_field_name == field._name - - required = highlighted || field.required - - = render "/admin/custom_fields/types/#{field.kind}", :form => form, :parent => parent, :field => field, :required => required, :highlighted => highlighted - -= render '/admin/custom_fields/category_tmpl' \ No newline at end of file diff --git a/app/views/locomotive/custom_fields/_form.html.haml b/app/views/locomotive/custom_fields/_form.html.haml index 31c551dc..2629f783 100644 --- a/app/views/locomotive/custom_fields/_form.html.haml +++ b/app/views/locomotive/custom_fields/_form.html.haml @@ -42,7 +42,7 @@ = g.input :select_options, :as => :'Locomotive::Empty', :wrapper_html => { :class => 'extra select-options', :style => 'display: none' } - = g.input :text_formatting, :as => :select, :collection => options_for_text_formatting, :include_blank => false, :wrapper_html => { :class => 'extra text-formatting', :style => 'display: none' } + = g.input :text_formatting, :as => :select, :collection => options_for_text_formatting, :include_blank => false, :wrapper_html => { :class => 'extra text-formatting' }, :input_html => { :class => 'text_formatting' } %span.actions = link_to 'toggle', '#', :class => 'toggle' diff --git a/app/views/locomotive/custom_fields/types/_boolean.html.haml b/app/views/locomotive/custom_fields/types/_boolean.html.haml index d4e1d585..11159f00 100644 --- a/app/views/locomotive/custom_fields/types/_boolean.html.haml +++ b/app/views/locomotive/custom_fields/types/_boolean.html.haml @@ -1 +1,4 @@ -= f.input name, :label => field.label, :as => :'Locomotive::Toggle', :hint => field.hint \ No newline at end of file += f.input name, + :label => field.label, + :hint => field.hint, + :as => :'Locomotive::Toggle' \ No newline at end of file diff --git a/app/views/locomotive/custom_fields/types/_category.html.haml b/app/views/locomotive/custom_fields/types/_category.html.haml deleted file mode 100644 index e12b067e..00000000 --- a/app/views/locomotive/custom_fields/types/_category.html.haml +++ /dev/null @@ -1,4 +0,0 @@ -= form.custom_input field._alias.to_sym, :label => field.label, :hint => field.hint, :css => 'toggle', :required => required do - = form.select field._name.to_sym, field.ordered_category_items.collect { |item| [item.name, item.id] } - %button.button.light.edit-categories-link{ :type => 'button', :'data-url' => edit_admin_custom_field_path(parent.class.model_name.underscore, parent.slug, field) } - %span!= t('.edit_categories') diff --git a/app/views/locomotive/custom_fields/types/_date.html.haml b/app/views/locomotive/custom_fields/types/_date.html.haml index 9f5aee72..890005ba 100644 --- a/app/views/locomotive/custom_fields/types/_date.html.haml +++ b/app/views/locomotive/custom_fields/types/_date.html.haml @@ -1 +1,5 @@ -= f.input :"formatted_#{name}", :label => field.label, :hint => field.hint, :input_html => { :maxlength => 10 }, :wrapper_html => { :class => 'date' } \ No newline at end of file += f.input :"formatted_#{name}", + :label => field.label, + :hint => field.hint, + :wrapper_html => { :class => 'date' }, + :input_html => { :maxlength => 10 } diff --git a/app/views/locomotive/custom_fields/types/_file.html.haml b/app/views/locomotive/custom_fields/types/_file.html.haml index 344c6abe..fd2e1b45 100644 --- a/app/views/locomotive/custom_fields/types/_file.html.haml +++ b/app/views/locomotive/custom_fields/types/_file.html.haml @@ -1 +1,4 @@ -= f.input name, :label => field.label, :hint => field.hint, :as => :'Locomotive::File' \ No newline at end of file += f.input name, + :label => field.label, + :hint => field.hint, + :as => :'Locomotive::File' \ No newline at end of file diff --git a/app/views/locomotive/custom_fields/types/_select.html.haml b/app/views/locomotive/custom_fields/types/_select.html.haml index 3d61bd3e..89f4f9ba 100644 --- a/app/views/locomotive/custom_fields/types/_select.html.haml +++ b/app/views/locomotive/custom_fields/types/_select.html.haml @@ -1 +1,5 @@ -= f.input :"#{name}_id", :as => 'select', :collection => field.ordered_select_options.map { |option| [option.name, option.id] }, :label => field.label, :hint => field.hint \ No newline at end of file += f.input :"#{name}_id", + :label => field.label, + :hint => field.hint, + :as => 'select', + :collection => field.ordered_select_options.map { |option| [option.name, option.id] } \ No newline at end of file diff --git a/app/views/locomotive/custom_fields/types/_string.html.haml b/app/views/locomotive/custom_fields/types/_string.html.haml index d4ab6b70..0fc160a9 100644 --- a/app/views/locomotive/custom_fields/types/_string.html.haml +++ b/app/views/locomotive/custom_fields/types/_string.html.haml @@ -1 +1,4 @@ -= f.input name, :label => field.label, :hint => field.hint, :wrapper_html => { :class => "#{'highlighted' if highlighted}" } \ No newline at end of file += f.input name, + :label => field.label, + :hint => field.hint, + :wrapper_html => { :class => "#{'highlighted' if highlighted}" } \ No newline at end of file diff --git a/app/views/locomotive/custom_fields/types/_text.html.haml b/app/views/locomotive/custom_fields/types/_text.html.haml index 9d568b10..2258ed21 100644 --- a/app/views/locomotive/custom_fields/types/_text.html.haml +++ b/app/views/locomotive/custom_fields/types/_text.html.haml @@ -1 +1,5 @@ -= f.input field.name.to_sym, :label => field.label, :hint => field.hint, :as => :'Locomotive::Rte', :input_html => { :class => field.text_formatting } \ No newline at end of file += f.input field.name.to_sym, + :label => field.label, + :hint => field.hint, + :as => field.text_formatting == 'html' ? :'Locomotive::Rte' : 'text', + :input_html => { :class => field.text_formatting } \ No newline at end of file diff --git a/app/views/locomotive/notifications/new_content_entry.html.haml b/app/views/locomotive/notifications/new_content_entry.html.haml index cfc4f674..05844631 100644 --- a/app/views/locomotive/notifications/new_content_entry.html.haml +++ b/app/views/locomotive/notifications/new_content_entry.html.haml @@ -3,19 +3,20 @@ %hr %p - %b= t('.type', :type => @content_entry.content_type.name, :locale => @account.locale) + %b= t('.type', :type => @type.name, :locale => @account.locale) %br - %i= @content_entry.content_type.description + %i= @type.description %hr %ul - - @content_entry.custom_fields.each do |field| + - @type.entries_custom_fields.each do |field| + - value = @entry.value_for(field) %li %strong= field.label  -  %i - - if field.file? - = link_to File.basename(@content_entry.send(field.name).url), @content_entry.send(field.name).url + - if field.type == 'file' + = link_to File.basename(value), value - else - = @content_entry.send(field.name) + = value diff --git a/app/views/locomotive/sitemaps/show.xml.builder b/app/views/locomotive/public/sitemaps/show.xml.builder similarity index 100% rename from app/views/locomotive/sitemaps/show.xml.builder rename to app/views/locomotive/public/sitemaps/show.xml.builder diff --git a/config/locales/admin_ui.en.yml b/config/locales/admin_ui.en.yml index 06c6974b..e6a27bfb 100644 --- a/config/locales/admin_ui.en.yml +++ b/config/locales/admin_ui.en.yml @@ -222,14 +222,15 @@ en: content_types: index: new: new model + edit: edit model new: title: New model help: "Create your own data model (Projects, People, ...etc). Your model should have one field at least. The items created from this content type would have their first field mandatory." edit: title: Editing model help: "Your model should have one field at least. The items created from this content type would have their first field mandatory." - show_items: show items - new_item: new item + show_entries: show entries + new_entry: new entry form: order_by: created_at: 'By creation date' diff --git a/config/locales/formtastic.en.yml b/config/locales/formtastic.en.yml index e81c9a95..191825f7 100644 --- a/config/locales/formtastic.en.yml +++ b/config/locales/formtastic.en.yml @@ -41,7 +41,8 @@ en: default_site_template: "Use the default site template. Click here to upload a site template as a zip file instead." content_type: raw_item_template: Item template - public_form_accounts: Notified Accounts + public_submission_enabled: Public submission + public_submission_accounts: Notified Accounts "custom_fields/field": select_options: "Options" content_entry: @@ -95,8 +96,8 @@ en: name: "We suggest you to type the plural form of the model. Ex: Projects, Recipes, Posts, Articles, ...etc" slug: "It will be used as the name of the collection in the liquid templates. Ex: {{ contents.my_projects }}" raw_item_template: "You can customize the text displayed for each item in the list. Simply use Liquid. Ex: {{ entry.name }})" - public_form_enabled: "It is used to let people from outside to create new instances (example: messages in a contact form)" - public_form_accounts: "A notification email will be sent to each of the accounts listed above when a new instance is created" + public_submission_enabled: "It is used to let people from outside to create new entries (example: messages in a contact form)" + public_submission_accounts: "If the public submission option is enabled and for each entry created, sends a notification email tothe accounts listed above." "custom_fields/field": name: "Name of the property for liquid templates. Ex: {{ your_object.<name_of_your_field> }}" hint: "Text displayed in the model form just below the field" diff --git a/config/routes.rb b/config/routes.rb index dad86759..976cc3b9 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -41,8 +41,6 @@ Locomotive::Engine.routes.draw do put :sort, :on => :collection end - resources :api_contents, :path => 'api/:slug/contents', :controller => 'api_contents', :only => [:create] - resources :custom_fields, :path => 'custom/:parent/:slug/fields' resources :cross_domain_sessions, :only => [:new, :create] @@ -58,13 +56,16 @@ end Rails.application.routes.draw do # sitemap - match '/sitemap.xml' => 'locomotive/sitemaps#show', :format => 'xml' + match '/sitemap.xml' => 'locomotive/public/sitemaps#show', :format => 'xml' # robots.txt - match '/robots.txt' => 'locomotive/robots#show', :format => 'txt' + match '/robots.txt' => 'locomotive/public/robots#show', :format => 'txt' + + # public content entry submissions + resources :locomotive_entry_submissions, :controller => 'locomotive/public/content_entries', :path => 'entry_submissions/:slug' # magic urls - match '/' => 'locomotive/rendering#show' - match '*path/edit' => 'locomotive/rendering#edit' - match '*path' => 'locomotive/rendering#show' + match '/' => 'locomotive/public/rendering#show' + match '*path/edit' => 'locomotive/public/rendering#edit' + match '*path' => 'locomotive/public/rendering#show' end \ No newline at end of file diff --git a/doc/TODO b/doc/TODO index 754e9c0b..5fd224ec 100644 --- a/doc/TODO +++ b/doc/TODO @@ -8,9 +8,9 @@ x bugs: x undefined method `_selector' for # x editable_elements => view + handlebar template x editable_short_text => tinymce -- editable_file => +x editable_file => x backbone / handlebar - - new formtastic inputs + x new formtastic inputs x menu / submenu in full css3 (no images) x fix css in firefox x update page in ajax @@ -61,7 +61,11 @@ x edit my site x file x edit x destroy - - public_form (previously api something) + x public_form (previously api something) + x bug text formatting + - use list_or_group_entries instead of ordered_entries + - bug ui with contents popup + - custom_fields: use the appropriate icon to drag select options - disallow to click twice on the submit form button (spinner ?) - message to notify people if their browser is too old diff --git a/doc/changelogs/version_2.txt b/doc/changelogs/version_2.txt index 436e9d38..a875fb39 100644 --- a/doc/changelogs/version_2.txt +++ b/doc/changelogs/version_2.txt @@ -8,10 +8,13 @@ - content_types: - category => select - highlighted_field_name => highlighted_field_id (label_field_id) - - api_enabled => public_form_enabled - - api_accounts => public_form_accounts + - api_enabled => public_submission_enabled + - api_accounts => public_submission_accounts - contents (content_entries now) - _position_in_list => _position + - api_contents: + - url => entry_submissions + - params[:content] => params[:entries] collection, selector = Locomotive::ContentType.collection, Locomotive::ContentType.criteria.selector diff --git a/lib/locomotive.rb b/lib/locomotive.rb index e0e6c3ac..7cad1332 100644 --- a/lib/locomotive.rb +++ b/lib/locomotive.rb @@ -6,7 +6,6 @@ require 'locomotive/version' require 'locomotive/core_ext' require 'locomotive/configuration' require 'locomotive/logger' - require 'locomotive/formtastic' require 'locomotive/dragonfly' require 'locomotive/kaminari' @@ -15,7 +14,7 @@ require 'locomotive/mongoid' require 'locomotive/carrierwave' require 'locomotive/custom_fields' require 'locomotive/httparty' -require 'locomotive/responder' +require 'locomotive/action_controller' require 'locomotive/routing' require 'locomotive/regexps' require 'locomotive/render' @@ -76,11 +75,11 @@ module Locomotive self.add_middlewares # Load all the dynamic classes (custom fields) - # begin - # ContentType.all.collect(&:fetch_content_klass) - # rescue ::Mongoid::Errors::InvalidDatabase => e - # # let assume it's because of the first install (meaning no config.yml file) - # end + begin + ContentType.all.collect { |content_type| content_type.klass_with_custom_fields(:entries) } + rescue ::Mongoid::Errors::InvalidDatabase => e + # let assume it's because of the first install (meaning no config.yml file) + end end def self.add_middlewares diff --git a/lib/locomotive/action_controller.rb b/lib/locomotive/action_controller.rb new file mode 100644 index 00000000..4ba1eb57 --- /dev/null +++ b/lib/locomotive/action_controller.rb @@ -0,0 +1,3 @@ +require 'locomotive/action_controller/helpers' +require 'locomotive/action_controller/responder' +require 'locomotive/action_controller/public_responder' \ No newline at end of file diff --git a/lib/locomotive/action_controller/helpers.rb b/lib/locomotive/action_controller/helpers.rb new file mode 100644 index 00000000..251b170a --- /dev/null +++ b/lib/locomotive/action_controller/helpers.rb @@ -0,0 +1,66 @@ +module Locomotive + module ActionController + module Helpers + + extend ActiveSupport::Concern + + included do + helper_method :current_site_public_url, :switch_to_site_url, :public_page_url + end + + module InstanceMethods + + def set_locale + I18n.locale = current_locomotive_account.locale rescue Locomotive.config.default_locale + end + + def sections(key = nil) + if !key.nil? && key.to_sym == :sub + @locomotive_sections[:sub] || self.controller_name.dasherize + else + @locomotive_sections[:main] + end + end + + # ___ site/page urls builder ___ + + def current_site_public_url + request.protocol + request.host_with_port + end + + def switch_to_site_url(site, options = {}) + options = { :fullpath => true, :protocol => true }.merge(options) + + url = "#{site.subdomain}.#{Locomotive.config.domain}" + url += ":#{request.port}" if request.port != 80 + + url = File.join(url, request.fullpath) if options[:fullpath] + url = "http://#{url}" if options[:protocol] + url + end + + def public_page_url(page, options = {}) + if content = options.delete(:content) + File.join(current_site_public_url, page.fullpath.gsub('content_type_template', ''), content._slug) + else + File.join(current_site_public_url, page.fullpath) + end + end + + end + + module ClassMethods + + def sections(main, sub = nil) + before_filter do |c| + sub = sub.call(c) if sub.respond_to?(:call) + sections = { :main => main, :sub => sub } + c.instance_variable_set(:@locomotive_sections, sections) + end + end + + end + + end + end +end \ No newline at end of file diff --git a/lib/locomotive/action_controller/public_responder.rb b/lib/locomotive/action_controller/public_responder.rb new file mode 100644 index 00000000..261e9ccb --- /dev/null +++ b/lib/locomotive/action_controller/public_responder.rb @@ -0,0 +1,17 @@ +module Locomotive + module ActionController + class PublicResponder < ::ActionController::Responder + + def navigation_behavior(error) + if get? + raise error + elsif has_errors? && default_action + redirect_to navigation_location + else + redirect_to navigation_location + end + end + + end + end +end \ No newline at end of file diff --git a/lib/locomotive/action_controller/responder.rb b/lib/locomotive/action_controller/responder.rb new file mode 100644 index 00000000..38b0dd10 --- /dev/null +++ b/lib/locomotive/action_controller/responder.rb @@ -0,0 +1,63 @@ +module Locomotive + module ActionController + class Responder < ::ActionController::Responder + + include ::Responders::FlashResponder + + # by default flash_now messages if the resource has errors + def set_flash_now? + super || has_errors? + end + + def to_json + if get? + display resource + elsif has_errors? + with_flash_message(:alert) do + display resource.errors, :status => :unprocessable_entity + end + elsif post? + in_header = controller.request.headers['X-Flash'] == 'true' + with_flash_message(:notice, in_header) do + display resource, :location => api_location + end + elsif put? + with_flash_message do |message| + display resource, :status => :ok, :location => api_location + end + elsif delete? + with_flash_message do |message| + display resource, :status => :ok, :location => api_location + end + elsif has_empty_resource_definition? + display empty_resource, :status => :ok + else + with_flash_message do + head :ok + end + end + end + + protected + + def with_flash_message(type = :notice, in_header = true) + if in_header + set_flash_message! + message = controller.flash[type] + + controller.headers['X-Message'] = message + controller.headers['X-Message-Type'] = type + + yield if block_given? + + controller.flash.discard # reset flash messages ! + else + set_flash_message! + + yield if block_given? + end + end + + end + end +end \ No newline at end of file diff --git a/lib/locomotive/engine.rb b/lib/locomotive/engine.rb index edb5315d..b11ca83c 100644 --- a/lib/locomotive/engine.rb +++ b/lib/locomotive/engine.rb @@ -24,7 +24,7 @@ module Locomotive end initializer 'locomotive.action_controller' do |app| - ActionController::Base.wrap_parameters :format => [:json] + ::ActionController::Base.wrap_parameters :format => [:json] end end diff --git a/lib/locomotive/liquid/drops/content_types.rb b/lib/locomotive/liquid/drops/content_types.rb new file mode 100644 index 00000000..32ab5edb --- /dev/null +++ b/lib/locomotive/liquid/drops/content_types.rb @@ -0,0 +1,79 @@ +module Locomotive + module Liquid + module Drops + class ContentTypes < ::Liquid::Drop + + def before_method(meth) + type = @context.registers[:site].content_types.where(:slug => meth.to_s).first + ProxyCollection.new(type) + end + + end + + class ProxyCollection < ::Liquid::Drop + + def initialize(content_type) + @content_type = content_type + @collection = nil + end + + def first + self.collection.first + end + + def last + self.collection.last + end + + def each(&block) + self.collection.each(&block) + end + + def each_with_index(&block) + self.collection.each_with_index(&block) + end + + def count + @count ||= self.collection.count + end + + alias :size :count + alias :length :count + + def empty? + self.collection.empty? + end + + def any? + self.collection.any? + end + + def public_submission_url + @context.registers[:controller].main_app.locomotive_entry_submissions_url(@content_type.slug) + end + + def before_method(meth) + klass = @content_type.entries.klass # delegate to the proxy class + + if (meth.to_s =~ /^group_by_.+$/) == 0 + klass.send(meth, :ordered_entries) + else + Rails.logger.warn "[Liquid template] trying to call #{meth} on a content_type object" + # klass.send(meth) + end + end + + protected + + def paginate(options = {}) + @collection.page(options[:page]).per(options[:per_page]) + end + + def collection + @collection ||= @content_type.ordered_entries(@context['with_scope']) + end + end + + end + end +end diff --git a/lib/locomotive/liquid/drops/contents.rb b/lib/locomotive/liquid/drops/contents.rb index 65e27e51..3ba6841e 100644 --- a/lib/locomotive/liquid/drops/contents.rb +++ b/lib/locomotive/liquid/drops/contents.rb @@ -1,79 +1,81 @@ -module Locomotive - module Liquid - module Drops - class Contents < ::Liquid::Drop +# DEPRECATED - # TODO: refactoring - - def before_method(meth) - type = @context.registers[:site].content_types.where(:slug => meth.to_s).first - ProxyCollection.new(type) - end - - end - - class ProxyCollection < ::Liquid::Drop - - def initialize(content_type) - @content_type = content_type - @collection = nil - end - - def first - self.collection.first - end - - def last - self.collection.last - end - - def each(&block) - self.collection.each(&block) - end - - def each_with_index(&block) - self.collection.each_with_index(&block) - end - - def size - self.collection.size - end - - alias :length :size - - def empty? - self.collection.empty? - end - - def any? - self.collection.any? - end - - def api - { 'create' => @context.registers[:controller].send('api_contents_url', @content_type.slug) } - end - - def before_method(meth) - klass = @content_type.entries.klass # delegate to the proxy class - - if (meth.to_s =~ /^group_by_.+$/) == 0 - klass.send(meth, :ordered_contents) - else - klass.send(meth) - end - end - - protected - - def paginate(options = {}) - @collection = Kaminari.paginate_array(self.collection).page(options[:page]).per(options[:per_page]) - end - - def collection - @collection ||= @content_type.ordered_contents(@context['with_scope']) - end - end - - end - end -end +# module Locomotive +# module Liquid +# module Drops +# class Contents < ::Liquid::Drop +# +# # TODO: refactoring +# +# def before_method(meth) +# type = @context.registers[:site].content_types.where(:slug => meth.to_s).first +# ProxyCollection.new(type) +# end +# +# end +# +# class ProxyCollection < ::Liquid::Drop +# +# def initialize(content_type) +# @content_type = content_type +# @collection = nil +# end +# +# def first +# self.collection.first +# end +# +# def last +# self.collection.last +# end +# +# def each(&block) +# self.collection.each(&block) +# end +# +# def each_with_index(&block) +# self.collection.each_with_index(&block) +# end +# +# def size +# self.collection.size +# end +# +# alias :length :size +# +# def empty? +# self.collection.empty? +# end +# +# def any? +# self.collection.any? +# end +# +# def api +# { 'create' => @context.registers[:controller].send('api_contents_url', @content_type.slug) } +# end +# +# def before_method(meth) +# klass = @content_type.entries.klass # delegate to the proxy class +# +# if (meth.to_s =~ /^group_by_.+$/) == 0 +# klass.send(meth, :ordered_contents) +# else +# klass.send(meth) +# end +# end +# +# protected +# +# def paginate(options = {}) +# @collection = Kaminari.paginate_array(self.collection).page(options[:page]).per(options[:per_page]) +# end +# +# def collection +# @collection ||= @content_type.ordered_contents(@context['with_scope']) +# end +# end +# +# end +# end +# end diff --git a/lib/locomotive/render.rb b/lib/locomotive/render.rb index 3f925f19..0967a94a 100644 --- a/lib/locomotive/render.rb +++ b/lib/locomotive/render.rb @@ -61,7 +61,8 @@ module Locomotive assigns = { 'site' => current_site, 'page' => @page, - 'contents' => Locomotive::Liquid::Drops::Contents.new, + 'models' => Locomotive::Liquid::Drops::ContentTypes.new, + 'contents' => Locomotive::Liquid::Drops::ContentTypes.new, # DEPRECATED 'current_page' => self.params[:page], 'params' => self.params, 'path' => request.path, @@ -72,10 +73,12 @@ module Locomotive assigns.merge!(Locomotive.config.context_assign_extensions) - assigns.merge!(flash.to_hash.stringify_keys) # data from api + Rails.logger.debug flash.to_hash.stringify_keys.inspect + + assigns.merge!(flash.to_hash.stringify_keys) # data from public submissions if @page.templatized? # add instance from content type - assigns['content_entry'] = @content_entry + assigns['entry'] = @content_entry assigns[@page.content_type.slug.singularize] = @content_entry # just here to help to write readable liquid code end @@ -111,7 +114,7 @@ module Locomotive end def editing_page? - @editing + !!@editing end def page_status diff --git a/lib/locomotive/responder.rb b/lib/locomotive/responder.rb deleted file mode 100644 index e5ff427d..00000000 --- a/lib/locomotive/responder.rb +++ /dev/null @@ -1,61 +0,0 @@ -module Locomotive - class Responder < ::ActionController::Responder - - include ::Responders::FlashResponder - - # by default flash_now messages if the resource has errors - def set_flash_now? - super || has_errors? - end - - def to_json - if get? - display resource - elsif has_errors? - with_flash_message(:alert) do - display resource.errors, :status => :unprocessable_entity - end - elsif post? - in_header = controller.request.headers['X-Flash'] == 'true' - with_flash_message(:notice, in_header) do - display resource, :location => api_location - end - elsif put? - with_flash_message do |message| - display resource, :status => :ok, :location => api_location - end - elsif delete? - with_flash_message do |message| - display resource, :status => :ok, :location => api_location - end - elsif has_empty_resource_definition? - display empty_resource, :status => :ok - else - with_flash_message do - head :ok - end - end - end - - protected - - def with_flash_message(type = :notice, in_header = true) - if in_header - set_flash_message! - message = controller.flash[type] - - controller.headers['X-Message'] = message - controller.headers['X-Message-Type'] = type - - yield if block_given? - - controller.flash.discard # reset flash messages ! - else - set_flash_message! - - yield if block_given? - end - end - - end -end \ No newline at end of file diff --git a/locomotive_cms.gemspec b/locomotive_cms.gemspec index 57ded121..457c569e 100644 --- a/locomotive_cms.gemspec +++ b/locomotive_cms.gemspec @@ -17,7 +17,7 @@ Gem::Specification.new do |s| s.required_rubygems_version = '>= 1.3.6' s.rubyforge_project = 'nowarning' - s.add_dependency 'rails', '~> 3.0.10' + s.add_dependency 'rails', '~> 3.1.3' s.add_dependency 'warden' s.add_dependency 'devise', '1.3.4' s.add_dependency 'devise_bushido_authenticatable', '1.0.0.alpha10'