refactor the code (move some pieces of code into the custom_fields gem) + solve a ton of bugs: circular dependencies inside the content_entry presenter, fix Locomotive.mounted_on (broken in rails 3.2), js errors when creating a page, locale switcher broken if a page was not translated in the target locale
This commit is contained in:
parent
2a911d912c
commit
25e08596ef
@ -7,12 +7,12 @@ class Locomotive.Models.ContentEntry extends Backbone.Model
|
||||
initialize: ->
|
||||
@urlRoot = @urlRoot.replace(':slug', @get('content_type_slug'))
|
||||
|
||||
_.each @get('_has_many_fields'), (field) =>
|
||||
_.each @get('has_many_custom_fields'), (field) =>
|
||||
name = field[0]
|
||||
collection = new Locomotive.Models.ContentEntriesCollection(@get(name))
|
||||
@set_attribute name, collection
|
||||
|
||||
_.each @get('_many_to_many_fields'), (field) =>
|
||||
_.each @get('many_to_many_custom_fields'), (field) =>
|
||||
name = field[0]
|
||||
collection = new Locomotive.Models.ContentEntriesCollection(@get(name))
|
||||
collection.comparator = (entry) -> entry.get('__position') || 0
|
||||
@ -24,7 +24,7 @@ class Locomotive.Models.ContentEntry extends Backbone.Model
|
||||
@set data
|
||||
|
||||
update_attributes: (attributes) ->
|
||||
_.each attributes._file_fields, (field) => # special treatment for files
|
||||
_.each attributes.file_custom_fields, (field) => # special treatment for files
|
||||
attribute = "#{field}_url"
|
||||
@set_attribute attribute, attributes[attribute]
|
||||
@set_attribute "remove_#{field}", false
|
||||
@ -42,11 +42,11 @@ class Locomotive.Models.ContentEntry extends Backbone.Model
|
||||
unless _.include(@get('safe_attributes'), key)
|
||||
delete hash[key]
|
||||
|
||||
_.each @get('_has_many_fields'), (field) => # include the has_many relationships
|
||||
_.each @get('has_many_custom_fields'), (field) => # include the has_many relationships
|
||||
name = field[0]
|
||||
hash["#{name}_attributes"] = @get(name).toMinJSON()
|
||||
|
||||
_.each @get('_many_to_many_fields'), (field) => # include the many_to_many relationships
|
||||
_.each @get('many_to_many_custom_fields'), (field) => # include the many_to_many relationships
|
||||
name = field[0]; setter_name = field[1]
|
||||
hash[setter_name] = @get(name).sort().map (entry) => entry.id
|
||||
|
||||
|
@ -12,10 +12,13 @@ class Locomotive.Models.Page extends Backbone.Model
|
||||
|
||||
_normalize: ->
|
||||
@set
|
||||
editable_elements: new Locomotive.Models.EditableElementsCollection(@get('editable_elements'))
|
||||
editable_elements: new Locomotive.Models.EditableElementsCollection(@get('editable_elements') || [])
|
||||
|
||||
toJSON: ->
|
||||
_.tap super, (hash) =>
|
||||
hash.editable_elements = @get('editable_elements').toJSONForSave() if @get('editable_elements')
|
||||
_.each ['content_type_id_text', 'edit_url', 'parent_id_text'], (key) => delete hash[key]
|
||||
|
||||
delete hash['editable_elements']
|
||||
hash.editable_elements = @get('editable_elements').toJSONForSave() if @get('editable_elements')? && @get('editable_elements').length > 0
|
||||
|
||||
class Locomotive.Models.PagesCollection extends Backbone.Collection
|
@ -56,7 +56,7 @@ class Locomotive.Views.ContentEntries.FormView extends Locomotive.Views.Shared.F
|
||||
$(textarea).tinymce(settings)
|
||||
|
||||
enable_file_fields: ->
|
||||
_.each @model.get('_file_fields'), (name) =>
|
||||
_.each @model.get('file_custom_fields'), (name) =>
|
||||
view = new Locomotive.Views.Shared.Fields.FileView model: @model, name: name
|
||||
|
||||
@_file_field_views.push(view)
|
||||
@ -64,7 +64,7 @@ class Locomotive.Views.ContentEntries.FormView extends Locomotive.Views.Shared.F
|
||||
@$("##{@model.paramRoot}_#{name}_input").append(view.render().el)
|
||||
|
||||
enable_has_many_fields: ->
|
||||
_.each @model.get('_has_many_fields'), (field) =>
|
||||
_.each @model.get('has_many_custom_fields'), (field) =>
|
||||
name = field[0]; inverse_of = field[1]
|
||||
new_entry = new Locomotive.Models.ContentEntry(@options["#{name}_new_entry"])
|
||||
view = new Locomotive.Views.Shared.Fields.HasManyView model: @model, name: name, new_entry: new_entry, inverse_of: inverse_of
|
||||
@ -74,7 +74,7 @@ class Locomotive.Views.ContentEntries.FormView extends Locomotive.Views.Shared.F
|
||||
@$("##{@model.paramRoot}_#{name}_input label").after(view.render().el)
|
||||
|
||||
enable_many_to_many_fields: ->
|
||||
_.each @model.get('_many_to_many_fields'), (field) =>
|
||||
_.each @model.get('many_to_many_custom_fields'), (field) =>
|
||||
name = field[0]
|
||||
view = new Locomotive.Views.Shared.Fields.ManyToManyView model: @model, name: name, all_entries: @options["all_#{name}_entries"]
|
||||
|
||||
|
@ -52,7 +52,7 @@ module Locomotive
|
||||
|
||||
def get_path
|
||||
page = current_site.pages.build(:parent => current_site.pages.find(params[:parent_id]), :slug => params[:slug].permalink)
|
||||
|
||||
page.send(:build_fullpath)
|
||||
render :json => { :url => public_page_url(page), :slug => page.slug }
|
||||
end
|
||||
|
||||
|
@ -1,12 +1,13 @@
|
||||
module Locomotive::AccountsHelper
|
||||
module Locomotive
|
||||
module AccountsHelper
|
||||
|
||||
def admin_on?(site = current_site)
|
||||
site.memberships.detect { |m| m.admin? && m.account == current_locomotive_account }
|
||||
end
|
||||
|
||||
def options_for_account
|
||||
current_site.accounts.collect { |a| ["#{a.name} <#{a.email}>", a.id] }
|
||||
end
|
||||
|
||||
def admin_on?(site = current_site)
|
||||
site.memberships.detect { |m| m.admin? && m.account == current_locomotive_account }
|
||||
end
|
||||
|
||||
def options_for_account
|
||||
current_site.accounts.collect { |a| ["#{a.name} <#{a.email}>", a.id] }
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
@ -1,114 +1,116 @@
|
||||
module Locomotive::BaseHelper
|
||||
module Locomotive
|
||||
module BaseHelper
|
||||
|
||||
def title(title = nil)
|
||||
if title.nil?
|
||||
@content_for_title
|
||||
else
|
||||
@content_for_title = title
|
||||
''
|
||||
def title(title = nil)
|
||||
if title.nil?
|
||||
@content_for_title
|
||||
else
|
||||
@content_for_title = title
|
||||
''
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def inputs_folded?(resource)
|
||||
resource.persisted? && resource.errors.empty?
|
||||
end
|
||||
|
||||
def submenu_entry(name, url, options = {}, &block)
|
||||
default_options = { :i18n => true, :css => name.dasherize.downcase }
|
||||
default_options.merge!(options)
|
||||
|
||||
css = "#{'on' if name == sections(:sub)} #{options[:css]}"
|
||||
|
||||
label_link = default_options[:i18n] ? t("locomotive.shared.menu.#{name}") : name
|
||||
if block_given?
|
||||
popup = content_tag(:div, capture(&block), :class => 'popup', :style => 'display: none')
|
||||
link = link_to(content_tag(:span, preserve(label_link) + content_tag(:em)) + content_tag(:em), url, :class => css)
|
||||
content_tag(:li, link + popup, :class => 'hoverable')
|
||||
else
|
||||
content_tag(:li, link_to(content_tag(:span, label_link), url, :class => css))
|
||||
def inputs_folded?(resource)
|
||||
resource.persisted? && resource.errors.empty?
|
||||
end
|
||||
end
|
||||
|
||||
def local_action_button(text, url, options = {})
|
||||
text = text.is_a?(Symbol) ? t(".#{text}") : text
|
||||
link_to(url, options) do
|
||||
content_tag(:em, escape_once(' ')) + text
|
||||
def submenu_entry(name, url, options = {}, &block)
|
||||
default_options = { :i18n => true, :css => name.dasherize.downcase }
|
||||
default_options.merge!(options)
|
||||
|
||||
css = "#{'on' if name == sections(:sub)} #{options[:css]}"
|
||||
|
||||
label_link = default_options[:i18n] ? t("locomotive.shared.menu.#{name}") : name
|
||||
if block_given?
|
||||
popup = content_tag(:div, capture(&block), :class => 'popup', :style => 'display: none')
|
||||
link = link_to(content_tag(:span, preserve(label_link) + content_tag(:em)) + content_tag(:em), url, :class => css)
|
||||
content_tag(:li, link + popup, :class => 'hoverable')
|
||||
else
|
||||
content_tag(:li, link_to(content_tag(:span, label_link), url, :class => css))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def flash_message
|
||||
if not flash.empty?
|
||||
first_key = flash.keys.first
|
||||
content_tag :div, flash[first_key],
|
||||
:id => "flash-#{first_key}",
|
||||
:class => 'application-message'
|
||||
else
|
||||
''
|
||||
def local_action_button(text, url, options = {})
|
||||
text = text.is_a?(Symbol) ? t(".#{text}") : text
|
||||
link_to(url, options) do
|
||||
content_tag(:em, escape_once(' ')) + text
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def backbone_view_class_name
|
||||
action = case controller.action_name
|
||||
when 'create' then 'New'
|
||||
when 'update' then 'Edit'
|
||||
else
|
||||
controller.action_name
|
||||
end.camelize
|
||||
|
||||
"Locomotive.Views.#{controller.controller_name.camelize}.#{action}View"
|
||||
end
|
||||
|
||||
def backbone_view_data
|
||||
content_for?(:backbone_view_data) ? content_for(:backbone_view_data) : ''
|
||||
end
|
||||
|
||||
def nocoffee_tag
|
||||
link_to 'noCoffee', 'http://www.nocoffee.fr', :id => 'nocoffee'
|
||||
end
|
||||
|
||||
# sites
|
||||
|
||||
def application_domain
|
||||
domain = Locomotive.config.domain
|
||||
domain += ":#{request.port}" if request.port != 80
|
||||
domain
|
||||
end
|
||||
|
||||
def manage_subdomain_or_domains?
|
||||
Locomotive.config.manage_subdomain? || Locomotive.config.manage_domains?
|
||||
end
|
||||
|
||||
def manage_subdomain?
|
||||
Locomotive.config.manage_subdomain?
|
||||
end
|
||||
|
||||
def manage_domains?
|
||||
Locomotive.config.manage_domains?
|
||||
end
|
||||
|
||||
def multi_sites?
|
||||
Locomotive.config.multi_sites?
|
||||
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)
|
||||
def flash_message
|
||||
if not flash.empty?
|
||||
first_key = flash.keys.first
|
||||
content_tag :div, flash[first_key],
|
||||
:id => "flash-#{first_key}",
|
||||
:class => 'application-message'
|
||||
else
|
||||
''
|
||||
end
|
||||
end
|
||||
|
||||
def backbone_view_class_name
|
||||
action = case controller.action_name
|
||||
when 'create' then 'New'
|
||||
when 'update' then 'Edit'
|
||||
else
|
||||
controller.action_name
|
||||
end.camelize
|
||||
|
||||
"Locomotive.Views.#{controller.controller_name.camelize}.#{action}View"
|
||||
end
|
||||
|
||||
def backbone_view_data
|
||||
content_for?(:backbone_view_data) ? content_for(:backbone_view_data) : ''
|
||||
end
|
||||
|
||||
def nocoffee_tag
|
||||
link_to 'noCoffee', 'http://www.nocoffee.fr', :id => 'nocoffee'
|
||||
end
|
||||
|
||||
# sites
|
||||
|
||||
def application_domain
|
||||
domain = Locomotive.config.domain
|
||||
domain += ":#{request.port}" if request.port != 80
|
||||
domain
|
||||
end
|
||||
|
||||
def manage_subdomain_or_domains?
|
||||
Locomotive.config.manage_subdomain? || Locomotive.config.manage_domains?
|
||||
end
|
||||
|
||||
def manage_subdomain?
|
||||
Locomotive.config.manage_subdomain?
|
||||
end
|
||||
|
||||
def manage_domains?
|
||||
Locomotive.config.manage_domains?
|
||||
end
|
||||
|
||||
def multi_sites?
|
||||
Locomotive.config.multi_sites?
|
||||
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
|
||||
|
||||
# memberships
|
||||
|
||||
def options_for_membership_roles(options = {})
|
||||
list = (unless options[:skip_admin]
|
||||
Locomotive::Ability::ROLES.map { |r| [t("locomotive.memberships.roles.#{r}"), r] }
|
||||
else
|
||||
(Locomotive::Ability::ROLES - ['admin']).map { |r| [t("locomotive.memberships.roles.#{r}"), r] }
|
||||
end)
|
||||
|
||||
options_for_select(list)
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
# memberships
|
||||
|
||||
def options_for_membership_roles(options = {})
|
||||
list = (unless options[:skip_admin]
|
||||
Locomotive::Ability::ROLES.map { |r| [t("locomotive.memberships.roles.#{r}"), r] }
|
||||
else
|
||||
(Locomotive::Ability::ROLES - ['admin']).map { |r| [t("locomotive.memberships.roles.#{r}"), r] }
|
||||
end)
|
||||
|
||||
options_for_select(list)
|
||||
end
|
||||
|
||||
|
||||
end
|
@ -1,13 +1,15 @@
|
||||
module Locomotive::ContentEntriesHelper
|
||||
module Locomotive
|
||||
module ContentEntriesHelper
|
||||
|
||||
def options_for_belongs_to_custom_field(class_name)
|
||||
content_type = Locomotive::ContentType.class_name_to_content_type(class_name, current_site)
|
||||
def options_for_belongs_to_custom_field(class_name)
|
||||
content_type = Locomotive::ContentType.class_name_to_content_type(class_name, current_site)
|
||||
|
||||
if content_type
|
||||
content_type.ordered_entries.map { |entry| [entry._label, entry._id] }
|
||||
else
|
||||
[] # unknown content type
|
||||
if content_type
|
||||
content_type.ordered_entries.map { |entry| [entry._label, entry._id] }
|
||||
else
|
||||
[] # unknown content type
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
@ -1,66 +1,68 @@
|
||||
module Locomotive::ContentTypesHelper
|
||||
module Locomotive
|
||||
module ContentTypesHelper
|
||||
|
||||
# Iterates over the content types with the following rules
|
||||
# - content types are ordered by the updated_at date (DESC)
|
||||
# - each content type has its own submenu if saved recently
|
||||
# - if there are more than ui.max_content_types content types, the extra ones go under "..."
|
||||
# - if a content type is selected and it is part of the extra content types, then
|
||||
# it will be moved to the first position in the displayed list (with its own submenu)
|
||||
#
|
||||
# @param [ Block ] block The statements responsible to display the menu item from a content type or a list of content types
|
||||
#
|
||||
def each_content_type(&block)
|
||||
visible, others = [], []
|
||||
# Iterates over the content types with the following rules
|
||||
# - content types are ordered by the updated_at date (DESC)
|
||||
# - each content type has its own submenu if saved recently
|
||||
# - if there are more than ui.max_content_types content types, the extra ones go under "..."
|
||||
# - if a content type is selected and it is part of the extra content types, then
|
||||
# it will be moved to the first position in the displayed list (with its own submenu)
|
||||
#
|
||||
# @param [ Block ] block The statements responsible to display the menu item from a content type or a list of content types
|
||||
#
|
||||
def each_content_type(&block)
|
||||
visible, others = [], []
|
||||
|
||||
current_site.content_types.ordered.only(:site_id, :name, :slug, :label_field_name).each_with_index do |content_type, index|
|
||||
next if !content_type.persisted?
|
||||
current_site.content_types.ordered.only(:site_id, :name, :slug, :label_field_name).each_with_index do |content_type, index|
|
||||
next if !content_type.persisted?
|
||||
|
||||
if index >= Locomotive.config.ui.max_content_types
|
||||
if self.is_content_type_selected(content_type)
|
||||
others << visible.delete_at(Locomotive.config.ui.max_content_types - 1) # swap content types
|
||||
visible.insert(0, content_type)
|
||||
else
|
||||
others << content_type # fills the "..." menu
|
||||
if index >= Locomotive.config.ui.max_content_types
|
||||
if self.is_content_type_selected(content_type)
|
||||
others << visible.delete_at(Locomotive.config.ui.max_content_types - 1) # swap content types
|
||||
visible.insert(0, content_type)
|
||||
else
|
||||
others << content_type # fills the "..." menu
|
||||
end
|
||||
next
|
||||
end
|
||||
next
|
||||
|
||||
visible << content_type
|
||||
end
|
||||
|
||||
visible << content_type
|
||||
if visible.size > 0
|
||||
visible.map { |c| yield(c) }
|
||||
yield(others) if others.size > 0
|
||||
end
|
||||
end
|
||||
|
||||
if visible.size > 0
|
||||
visible.map { |c| yield(c) }
|
||||
yield(others) if others.size > 0
|
||||
def is_content_type_selected(content_type)
|
||||
@content_type && content_type.slug == @content_type.slug
|
||||
end
|
||||
end
|
||||
|
||||
def is_content_type_selected(content_type)
|
||||
@content_type && content_type.slug == @content_type.slug
|
||||
end
|
||||
# Renders the label of a content type entry. If no raw_item_template filled in the content type,
|
||||
# it just calls the _label method of the entry (based on the label_field_id). Otherwise, it
|
||||
# parses and renders the liquid template.
|
||||
#
|
||||
# @param [ ContentType ] content_type The content type for better performance
|
||||
# @param [ ContentEntry] entry The entry we want to display the label
|
||||
#
|
||||
# @return [ String ] The label of the content type entry
|
||||
#
|
||||
def entry_label(content_type, entry)
|
||||
if content_type.raw_item_template.blank?
|
||||
entry._label # default one
|
||||
else
|
||||
assigns = { 'site' => current_site, 'entry' => entry }
|
||||
|
||||
# Renders the label of a content type entry. If no raw_item_template filled in the content type,
|
||||
# it just calls the _label method of the entry (based on the label_field_id). Otherwise, it
|
||||
# parses and renders the liquid template.
|
||||
#
|
||||
# @param [ ContentType ] content_type The content type for better performance
|
||||
# @param [ ContentEntry] entry The entry we want to display the label
|
||||
#
|
||||
# @return [ String ] The label of the content type entry
|
||||
#
|
||||
def entry_label(content_type, entry)
|
||||
if content_type.raw_item_template.blank?
|
||||
entry._label # default one
|
||||
else
|
||||
assigns = { 'site' => current_site, 'entry' => entry }
|
||||
registers = {
|
||||
:controller => self,
|
||||
:site => current_site,
|
||||
:current_locomotive_account => current_locomotive_account
|
||||
}
|
||||
|
||||
registers = {
|
||||
:controller => self,
|
||||
:site => current_site,
|
||||
:current_locomotive_account => current_locomotive_account
|
||||
}
|
||||
|
||||
preserve(content_type.item_template.render(::Liquid::Context.new({}, assigns, registers)))
|
||||
preserve(content_type.item_template.render(::Liquid::Context.new({}, assigns, registers)))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
@ -1,166 +1,69 @@
|
||||
module Locomotive::CustomFieldsHelper
|
||||
module Locomotive
|
||||
module CustomFieldsHelper
|
||||
|
||||
def options_for_custom_field_type
|
||||
%w(string text select boolean date file belongs_to has_many many_to_many).map do |type|
|
||||
[t("custom_fields.types.#{type}"), type]
|
||||
def options_for_custom_field_type
|
||||
%w(string text select boolean date file belongs_to has_many many_to_many).map do |type|
|
||||
[t("custom_fields.types.#{type}"), type]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def options_for_label_field(content_type)
|
||||
content_type.ordered_entries_custom_fields.find_all do |field|
|
||||
%w(string date).include?(field.type)
|
||||
end.map do |field|
|
||||
[field.label, field._id]
|
||||
def options_for_label_field(content_type)
|
||||
content_type.ordered_entries_custom_fields.find_all do |field|
|
||||
%w(string date).include?(field.type)
|
||||
end.map do |field|
|
||||
[field.label, field._id]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def options_for_group_by_field(content_type)
|
||||
content_type.ordered_entries_custom_fields.find_all do |field|
|
||||
%w(select).include?(field.type)
|
||||
end.map do |field|
|
||||
[field.label, field._id]
|
||||
def options_for_group_by_field(content_type)
|
||||
content_type.ordered_entries_custom_fields.find_all do |field|
|
||||
%w(select).include?(field.type)
|
||||
end.map do |field|
|
||||
[field.label, field._id]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def options_for_order_by(content_type)
|
||||
options = %w{created_at updated_at _position}.map do |type|
|
||||
[t("locomotive.content_types.form.order_by.#{type.gsub(/^_/, '')}"), type]
|
||||
def options_for_order_by(content_type)
|
||||
options = %w{created_at updated_at _position}.map do |type|
|
||||
[t("locomotive.content_types.form.order_by.#{type.gsub(/^_/, '')}"), type]
|
||||
end
|
||||
options + options_for_label_field(content_type)
|
||||
end
|
||||
options + options_for_label_field(content_type)
|
||||
end
|
||||
|
||||
def options_for_order_direction
|
||||
%w(asc desc).map do |direction|
|
||||
[t("locomotive.content_types.form.order_direction.#{direction}"), direction]
|
||||
def options_for_order_direction
|
||||
%w(asc desc).map do |direction|
|
||||
[t("locomotive.content_types.form.order_direction.#{direction}"), direction]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def options_for_text_formatting
|
||||
%w(none html).map do |option|
|
||||
[t("locomotive.custom_fields.text_formatting.#{option}"), option]
|
||||
def options_for_text_formatting
|
||||
%w(none html).map do |option|
|
||||
[t("locomotive.custom_fields.text_formatting.#{option}"), option]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def options_for_content_type
|
||||
current_site.content_types.map do |c|
|
||||
c != @content_type ? [c.name, c.klass_with_custom_fields(:entries).to_s] : nil
|
||||
end.compact
|
||||
end
|
||||
def options_for_content_type
|
||||
current_site.content_types.map do |c|
|
||||
c != @content_type ? [c.name, c.klass_with_custom_fields(:entries).to_s] : nil
|
||||
end.compact
|
||||
end
|
||||
|
||||
def options_for_content_type_inverse_of
|
||||
{}.tap do |hash|
|
||||
current_site.content_types.where(:'entries_custom_fields.type'.in => %w(belongs_to many_to_many)).each do |content_type|
|
||||
content_type.entries_custom_fields.each do |field|
|
||||
if %w(belongs_to many_to_many).include?(field.type)
|
||||
hash[field.type] ||= []
|
||||
hash[field.type] << {
|
||||
:label => field.label,
|
||||
:name => field.name,
|
||||
:class_name => content_type.klass_with_custom_fields(:entries).to_s
|
||||
}
|
||||
def options_for_content_type_inverse_of
|
||||
{}.tap do |hash|
|
||||
current_site.content_types.where(:'entries_custom_fields.type'.in => %w(belongs_to many_to_many)).each do |content_type|
|
||||
content_type.entries_custom_fields.each do |field|
|
||||
if %w(belongs_to many_to_many).include?(field.type)
|
||||
hash[field.type] ||= []
|
||||
hash[field.type] << {
|
||||
:label => field.label,
|
||||
:name => field.name,
|
||||
:class_name => content_type.klass_with_custom_fields(:entries).to_s
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
# def options_for_association_target
|
||||
# current_site.reload.content_types.collect { |c| [c.name, c.content_klass.to_s] }
|
||||
# end
|
||||
#
|
||||
# def options_for_reverse_lookups(my_content_type)
|
||||
# klass_name = my_content_type.content_klass.to_s
|
||||
#
|
||||
# [].tap do |options|
|
||||
# ContentType.where(:'entries_custom_fields.kind' => 'has_one', :'entries_custom_fields.target' => klass_name).each do |content_type|
|
||||
# content_type.entries_custom_fields.find_all { |f| f.has_one? && f.target == klass_name }.each do |field|
|
||||
# options << {
|
||||
# :klass => content_type.content_klass.to_s,
|
||||
# :label => field.label,
|
||||
# :name => field._name
|
||||
# }
|
||||
# end
|
||||
# end
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# def filter_options_for_reverse_has_many(contents, reverse_lookup, object)
|
||||
# # Only display items which don't belong to a different object
|
||||
# contents.reject do |c|
|
||||
# owner = c.send(reverse_lookup.to_sym)
|
||||
# !(owner.nil? || owner == object._id)
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# def options_for_has_one(field, value)
|
||||
# self.options_for_has_one_or_has_many(field) do |groups|
|
||||
# grouped_options_for_select(groups.collect do |g|
|
||||
# if g[:items].empty?
|
||||
# nil
|
||||
# else
|
||||
# [g[:name], g[:items].collect { |c| [c._label, c._id] }]
|
||||
# end
|
||||
# end.compact, value)
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# def options_for_has_many(field, content = nil)
|
||||
# self.options_for_has_one_or_has_many(field, content)
|
||||
# end
|
||||
#
|
||||
# def options_for_has_one_or_has_many(field, content = nil, &block)
|
||||
# content_type = field.target.constantize._parent.reload
|
||||
#
|
||||
# if content_type.groupable?
|
||||
# grouped_contents = content_type.list_or_group_contents
|
||||
#
|
||||
# grouped_contents.each do |g|
|
||||
# g[:items] = filter_options_for_reverse_has_many(g[:items], field.reverse_lookup, content)
|
||||
# end if field.reverse_has_many?
|
||||
#
|
||||
# if block_given?
|
||||
# block.call(grouped_contents)
|
||||
# else
|
||||
# grouped_contents.collect do |g|
|
||||
# if g[:items].empty?
|
||||
# nil
|
||||
# else
|
||||
# { :name => g[:name], :items => g[:items].collect { |c| [c._label, c._id] } }
|
||||
# end
|
||||
# end.compact
|
||||
# end
|
||||
# else
|
||||
# contents = content_type.ordered_contents
|
||||
#
|
||||
# if field.reverse_has_many?
|
||||
# contents = filter_options_for_reverse_has_many(contents, field.reverse_lookup, content)
|
||||
# end
|
||||
#
|
||||
# contents.collect { |c| [c._label, c._id] }
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# def has_many_data_to_js(field, content)
|
||||
# options = {
|
||||
# :taken_ids => content.send(field._alias.to_sym).ids
|
||||
# }
|
||||
#
|
||||
# if !content.new_record? && field.reverse_has_many?
|
||||
# url_options = {
|
||||
# :breadcrumb_alias => field.reverse_lookup_alias,
|
||||
# "content[#{field.reverse_lookup_alias}]" => content._id
|
||||
# }
|
||||
#
|
||||
# options.merge!(
|
||||
# :new_item => {
|
||||
# :label => t('locomotive.contents.form.has_many.new_item'),
|
||||
# :url => new_content_url(field.target_klass._parent.slug, url_options)
|
||||
# },
|
||||
# :edit_item_url => edit_content_url(field.target_klass._parent.slug, 42, url_options)
|
||||
# )
|
||||
# end
|
||||
#
|
||||
# collection_to_js(options_for_has_many(field, content), options)
|
||||
# end
|
||||
|
||||
end
|
@ -1,7 +1,9 @@
|
||||
module Locomotive::InstallationHelper
|
||||
module Locomotive
|
||||
module InstallationHelper
|
||||
|
||||
def next_installation_step_link(step = 1, label = nil)
|
||||
link_to(content_tag(:span, label || t('admin.installation.common.next')), installation_step_url(step), :class => 'button')
|
||||
end
|
||||
|
||||
def next_installation_step_link(step = 1, label = nil)
|
||||
link_to(content_tag(:span, label || t('admin.installation.common.next')), installation_step_url(step), :class => 'button')
|
||||
end
|
||||
|
||||
end
|
@ -1,45 +1,47 @@
|
||||
module Locomotive::PagesHelper
|
||||
module Locomotive
|
||||
module PagesHelper
|
||||
|
||||
def css_for_page(page)
|
||||
%w(index not_found templatized redirect).inject([]) do |memo, state|
|
||||
memo << state.dasherize if page.send(:"#{state}?")
|
||||
memo
|
||||
end.join(' ')
|
||||
end
|
||||
def css_for_page(page)
|
||||
%w(index not_found templatized redirect).inject([]) do |memo, state|
|
||||
memo << state.dasherize if page.send(:"#{state}?")
|
||||
memo
|
||||
end.join(' ')
|
||||
end
|
||||
|
||||
def page_toggler(page)
|
||||
image_tag("locomotive/list/icons/node_#{(cookies["folder-#{page._id}"] != 'none') ? 'open' : 'closed'}.png", :class => 'toggler')
|
||||
end
|
||||
def page_toggler(page)
|
||||
image_tag("locomotive/list/icons/node_#{(cookies["folder-#{page._id}"] != 'none') ? 'open' : 'closed'}.png", :class => 'toggler')
|
||||
end
|
||||
|
||||
def parent_pages_options
|
||||
roots = current_site.pages.roots.where(:slug.ne => '404').and(:_id.ne => @page.id)
|
||||
def parent_pages_options
|
||||
roots = current_site.pages.roots.where(:slug.ne => '404').and(:_id.ne => @page.id)
|
||||
|
||||
[].tap do |list|
|
||||
roots.each do |page|
|
||||
list = add_children_to_options(page, list)
|
||||
[].tap do |list|
|
||||
roots.each do |page|
|
||||
list = add_children_to_options(page, list)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def add_children_to_options(page, list)
|
||||
return list if page.parent_ids.include?(@page.id) || page == @page
|
||||
|
||||
offset = '- ' * (page.depth || 0) * 2
|
||||
|
||||
list << ["#{offset}#{page.title}", page.id]
|
||||
page.children.each { |child| add_children_to_options(child, list) }
|
||||
list
|
||||
end
|
||||
|
||||
def options_for_page_cache_strategy
|
||||
[
|
||||
[t('.cache_strategy.none'), 'none'],
|
||||
[t('.cache_strategy.simple'), 'simple'],
|
||||
[t('.cache_strategy.hour'), 1.hour.to_s],
|
||||
[t('.cache_strategy.day'), 1.day.to_s],
|
||||
[t('.cache_strategy.week'), 1.week.to_s],
|
||||
[t('.cache_strategy.month'), 1.month.to_s]
|
||||
]
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
def add_children_to_options(page, list)
|
||||
return list if page.path.include?(@page.id) || page == @page
|
||||
|
||||
offset = '- ' * (page.depth || 0) * 2
|
||||
|
||||
list << ["#{offset}#{page.title}", page.id]
|
||||
page.children.each { |child| add_children_to_options(child, list) }
|
||||
list
|
||||
end
|
||||
|
||||
def options_for_page_cache_strategy
|
||||
[
|
||||
[t('.cache_strategy.none'), 'none'],
|
||||
[t('.cache_strategy.simple'), 'simple'],
|
||||
[t('.cache_strategy.hour'), 1.hour.to_s],
|
||||
[t('.cache_strategy.day'), 1.day.to_s],
|
||||
[t('.cache_strategy.week'), 1.week.to_s],
|
||||
[t('.cache_strategy.month'), 1.month.to_s]
|
||||
]
|
||||
end
|
||||
|
||||
end
|
@ -1,7 +1,9 @@
|
||||
module Locomotive::SitesHelper
|
||||
module Locomotive
|
||||
module SitesHelper
|
||||
|
||||
def ordered_current_site_locales
|
||||
current_site.locales + (Locomotive.config.site_locales - current_site.locales)
|
||||
end
|
||||
|
||||
def ordered_current_site_locales
|
||||
current_site.locales + (Locomotive.config.site_locales - current_site.locales)
|
||||
end
|
||||
|
||||
end
|
@ -1,24 +1,26 @@
|
||||
module Locomotive::ThemeAssetsHelper
|
||||
module Locomotive
|
||||
module ThemeAssetsHelper
|
||||
|
||||
def image_dimensions_and_size(asset)
|
||||
content_tag(:small, "#{asset.width}px x #{asset.height}px | #{number_to_human_size(asset.size)}")
|
||||
end
|
||||
|
||||
def plain_text_type(asset)
|
||||
asset.size && asset.size > 40000 ? 'nude' : (asset.content_type || 'stylesheet')
|
||||
end
|
||||
|
||||
def allow_plain_text_editing?(asset)
|
||||
asset.new_record? || asset.stylesheet_or_javascript?
|
||||
end
|
||||
|
||||
def display_plain_text?(asset)
|
||||
if asset.new_record?
|
||||
asset.performing_plain_text?
|
||||
else
|
||||
asset.stylesheet_or_javascript?
|
||||
def image_dimensions_and_size(asset)
|
||||
content_tag(:small, "#{asset.width}px x #{asset.height}px | #{number_to_human_size(asset.size)}")
|
||||
end
|
||||
|
||||
def plain_text_type(asset)
|
||||
asset.size && asset.size > 40000 ? 'nude' : (asset.content_type || 'stylesheet')
|
||||
end
|
||||
|
||||
def allow_plain_text_editing?(asset)
|
||||
asset.new_record? || asset.stylesheet_or_javascript?
|
||||
end
|
||||
|
||||
def display_plain_text?(asset)
|
||||
if asset.new_record?
|
||||
asset.performing_plain_text?
|
||||
else
|
||||
asset.stylesheet_or_javascript?
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
|
||||
end
|
@ -36,7 +36,7 @@ module Locomotive
|
||||
#
|
||||
def localized_page_fullpath(page, locale = nil)
|
||||
locale = (locale || I18n.locale).to_s
|
||||
fullpath = page.fullpath_translations[locale]
|
||||
fullpath = page.fullpath_translations[locale] || page.fullpath_translations[self.default_locale]
|
||||
|
||||
locale == self.default_locale ? fullpath : File.join(locale, fullpath)
|
||||
end
|
||||
|
@ -5,15 +5,16 @@ class Locomotive::BasePresenter
|
||||
include ActionView::Helpers::TextHelper
|
||||
include ActionView::Helpers::NumberHelper
|
||||
|
||||
attr_reader :source, :options, :ability
|
||||
attr_reader :source, :options, :ability, :depth
|
||||
|
||||
delegate :created_at, :updated_at, :to => :source
|
||||
|
||||
def initialize(object, options = {})
|
||||
@source = object
|
||||
@options = options
|
||||
@options = options || {}
|
||||
@depth = options[:depth] || 0
|
||||
|
||||
if @options && @options[:current_account] && @options[:current_site]
|
||||
if @options[:current_account] && @options[:current_site]
|
||||
@ability = Locomotive::Ability.new @options[:current_account], @options[:current_site]
|
||||
end
|
||||
end
|
||||
|
@ -1,44 +1,25 @@
|
||||
module Locomotive
|
||||
class ContentEntryPresenter < BasePresenter
|
||||
|
||||
delegate :_label, :_slug, :_position, :seo_title, :meta_keywords, :meta_description, :to => :source
|
||||
delegate :_label, :_slug, :_position, :seo_title, :meta_keywords, :meta_description, :file_custom_fields, :has_many_custom_fields, :many_to_many_custom_fields, :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
|
||||
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
|
||||
# Lists of all the attributes editable thru the html form for instance
|
||||
#
|
||||
# @returns [ List ] a list of attributes (string)
|
||||
#
|
||||
def safe_attributes
|
||||
self.source.custom_fields_recipe['rules'].map do |rule|
|
||||
case rule['type'].to_sym
|
||||
when :date then "formatted_#{rule['name']}"
|
||||
when :file then [rule['name'], "remove_#{rule['name']}"]
|
||||
when :select, :belongs_to then ["#{rule['name']}_id", "position_in_#{rule['name']}"]
|
||||
when :has_many, :many_to_many then nil
|
||||
self.source.custom_fields_safe_attributes + %w(_slug seo_title meta_keywords meta_description _destroy)
|
||||
end
|
||||
|
||||
def filtered_custom_fields_methods
|
||||
self.source.custom_fields_methods do |rule|
|
||||
if self.source.is_a_custom_field_many_relationship?(rule['name'])
|
||||
# avoid circular dependencies, it should accept only one deep level
|
||||
self.depth == 0
|
||||
else
|
||||
rule['name']
|
||||
true
|
||||
end
|
||||
end.compact.flatten + %w(_slug seo_title meta_keywords meta_description _destroy)
|
||||
end
|
||||
end
|
||||
|
||||
def errors
|
||||
@ -49,59 +30,24 @@ module Locomotive
|
||||
self.source.content_type.slug
|
||||
end
|
||||
|
||||
def _file_fields
|
||||
group_fields 'file'
|
||||
end
|
||||
|
||||
def _has_many_fields
|
||||
group_fields('has_many') { |rule| [rule['name'], rule['inverse_of']] }
|
||||
end
|
||||
|
||||
def _many_to_many_fields
|
||||
group_fields('many_to_many') { |rule| [rule['name'], "#{rule['name'].singularize}_ids"] }
|
||||
end
|
||||
|
||||
def included_methods
|
||||
default_list = %w(_label _slug _position content_type_slug _file_fields _has_many_fields _many_to_many_fields safe_attributes)
|
||||
default_list = %w(_label _slug _position content_type_slug file_custom_fields has_many_custom_fields many_to_many_custom_fields safe_attributes)
|
||||
default_list << 'errors' if !!self.options[:include_errors]
|
||||
super + self.custom_fields_methods + default_list
|
||||
super + self.filtered_custom_fields_methods + default_list
|
||||
end
|
||||
|
||||
def method_missing(meth, *arguments, &block)
|
||||
if self.custom_fields_methods.include?(meth.to_s)
|
||||
self.source.send(meth) rescue nil
|
||||
if self.source.custom_fields_methods.include?(meth.to_s)
|
||||
if self.source.is_a_custom_field_many_relationship?(meth.to_s)
|
||||
# go deeper
|
||||
self.source.send(meth).map { |entry| entry.to_presenter(:depth => self.depth + 1) }
|
||||
else
|
||||
self.source.send(meth) rescue nil
|
||||
end
|
||||
else
|
||||
super
|
||||
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.to_sym
|
||||
when :select then [name, "#{name}_id"]
|
||||
when :date then "formatted_#{name}"
|
||||
when :file then "#{name}_url"
|
||||
when :belongs_to then "#{name}_id"
|
||||
else
|
||||
name
|
||||
end
|
||||
end
|
||||
|
||||
def group_fields(type, &block)
|
||||
unless block_given?
|
||||
block = lambda { |rule| rule['name'] }
|
||||
end
|
||||
|
||||
self.source.custom_fields_recipe['rules'].find_all { |rule| rule['type'] == type }.map(&block)
|
||||
end
|
||||
|
||||
end
|
||||
end
|
@ -12,7 +12,7 @@ module Locomotive
|
||||
end
|
||||
|
||||
def included_methods
|
||||
super + %w(title slug fullpath raw_template published listed templatized redirect redirect_url cache_strategy template_changed editable_elements edit_url localized_fullpaths)
|
||||
super + %w(title slug fullpath raw_template published listed templatized redirect redirect_url cache_strategy template_changed editable_elements localized_fullpaths)
|
||||
end
|
||||
|
||||
def localized_fullpaths
|
||||
|
7
doc/TODO
7
doc/TODO
@ -104,11 +104,12 @@ x deployment
|
||||
x data ?
|
||||
x script to migrate existing site
|
||||
x i18n
|
||||
- upgrade to rails 3.2 (https://github.com/locomotivecms/engine/pull/281/files)
|
||||
- missing custom_fields
|
||||
x upgrade to rails 3.2 (https://github.com/locomotivecms/engine/pull/281/files)
|
||||
x missing custom_fields
|
||||
x belongs_to
|
||||
x has_many
|
||||
- many_to_many
|
||||
x many_to_many
|
||||
- simplify cells integration when modifying a menu from the main app
|
||||
- heroku module for locomotive
|
||||
- refactoring
|
||||
x remove the import / export scripts
|
||||
|
@ -122,7 +122,7 @@ module Locomotive
|
||||
end
|
||||
|
||||
def self.mounted_on
|
||||
Rails.application.routes.named_routes[:locomotive].path
|
||||
Rails.application.routes.named_routes[:locomotive].path.spec.to_s
|
||||
end
|
||||
|
||||
protected
|
||||
|
@ -61,7 +61,7 @@ module Locomotive
|
||||
case @options[:label]
|
||||
when :iso then locale
|
||||
when :locale then I18n.t("locomotive.locales.#{locale}", :locale => locale)
|
||||
when :title then @page.title
|
||||
when :title then @page.title # FIXME: this returns nil if the page has not been translated in the locale
|
||||
else
|
||||
locale
|
||||
end
|
||||
|
@ -91,7 +91,7 @@ module Locomotive
|
||||
:current_locomotive_account => current_locomotive_account
|
||||
}
|
||||
|
||||
::Liquid::Context.new({}, assigns, registers, false) # pass false to true to enable the re-thrown exception flag
|
||||
::Liquid::Context.new({}, assigns, registers, false) # switch from false to true to enable the re-thrown exception flag
|
||||
end
|
||||
|
||||
def prepare_and_set_response(output)
|
||||
|
Loading…
Reference in New Issue
Block a user