editable_file tag is implemented + remove not used editable elements all in once for better performance + default content inherits from the content of the parent element
This commit is contained in:
parent
335d7a1aac
commit
35b4e5358c
4
Gemfile
4
Gemfile
@ -3,8 +3,8 @@ source 'http://rubygems.org'
|
|||||||
|
|
||||||
gem 'rails', '3.0.0.rc'
|
gem 'rails', '3.0.0.rc'
|
||||||
|
|
||||||
# gem 'liquid', :path => '../gems/liquid' # local
|
gem 'liquid', :path => '../gems/liquid' # local
|
||||||
gem 'liquid', :git => 'git://github.com/locomotivecms/liquid.git', :ref => '9ec570927f5281e1f397'
|
# gem 'liquid', :git => 'git://github.com/locomotivecms/liquid.git', :ref => '9ec570927f5281e1f397'
|
||||||
|
|
||||||
gem 'bson_ext', '1.0.4'
|
gem 'bson_ext', '1.0.4'
|
||||||
gem 'mongoid', '2.0.0.beta.16'
|
gem 'mongoid', '2.0.0.beta.16'
|
||||||
|
12
Gemfile.lock
12
Gemfile.lock
@ -11,13 +11,6 @@ GIT
|
|||||||
specs:
|
specs:
|
||||||
custom_fields (0.0.0.1)
|
custom_fields (0.0.0.1)
|
||||||
|
|
||||||
GIT
|
|
||||||
remote: git://github.com/locomotivecms/liquid.git
|
|
||||||
revision: 9ec5709
|
|
||||||
ref: 9ec570927f5281e1f397
|
|
||||||
specs:
|
|
||||||
liquid (2.1.3)
|
|
||||||
|
|
||||||
GIT
|
GIT
|
||||||
remote: http://github.com/ianwhite/pickle.git
|
remote: http://github.com/ianwhite/pickle.git
|
||||||
revision: 65ba8b7
|
revision: 65ba8b7
|
||||||
@ -28,6 +21,11 @@ GIT
|
|||||||
rspec (>= 1.3)
|
rspec (>= 1.3)
|
||||||
yard
|
yard
|
||||||
|
|
||||||
|
PATH
|
||||||
|
remote: /Users/didier/Desktop/NoCoffee/LocomotiveCMS/gems/liquid
|
||||||
|
specs:
|
||||||
|
liquid (2.1.3)
|
||||||
|
|
||||||
GEM
|
GEM
|
||||||
remote: http://rubygems.org/
|
remote: http://rubygems.org/
|
||||||
specs:
|
specs:
|
||||||
|
@ -3,10 +3,10 @@ class EditableElement
|
|||||||
include Mongoid::Document
|
include Mongoid::Document
|
||||||
|
|
||||||
## fields ##
|
## fields ##
|
||||||
field :kind
|
# field :kind
|
||||||
field :slug
|
field :slug
|
||||||
field :block
|
field :block
|
||||||
field :content
|
# field :content
|
||||||
field :default_content
|
field :default_content
|
||||||
field :hint
|
field :hint
|
||||||
field :disabled, :type => Boolean, :default => false
|
field :disabled, :type => Boolean, :default => false
|
||||||
@ -20,12 +20,12 @@ class EditableElement
|
|||||||
|
|
||||||
## methods ##
|
## methods ##
|
||||||
|
|
||||||
def content
|
# def content
|
||||||
self.read_attribute(:content).blank? ? self.default_content : self.read_attribute(:content)
|
# self.read_attribute(:content).blank? ? self.default_content : self.read_attribute(:content)
|
||||||
end
|
# end
|
||||||
|
#
|
||||||
def short_text?; self.kind == 'ShortText'; end
|
# def short_text?; self._type == 'EditableShortText'; end
|
||||||
|
#
|
||||||
def long_text?; self.kind == 'LongText'; end
|
# def long_text?; self._type == 'EditableLongText'; end
|
||||||
|
|
||||||
end
|
end
|
9
app/models/editable_file.rb
Normal file
9
app/models/editable_file.rb
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
class EditableFile < EditableElement
|
||||||
|
|
||||||
|
mount_uploader :source, EditableFileUploader
|
||||||
|
|
||||||
|
def content
|
||||||
|
self.source? ? self.source.url : self.default_content
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
3
app/models/editable_long_text.rb
Normal file
3
app/models/editable_long_text.rb
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
class EditableLongText < EditableShortText
|
||||||
|
|
||||||
|
end
|
12
app/models/editable_short_text.rb
Normal file
12
app/models/editable_short_text.rb
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
class EditableShortText < EditableElement
|
||||||
|
|
||||||
|
## fields ##
|
||||||
|
field :content
|
||||||
|
|
||||||
|
## methods ##
|
||||||
|
|
||||||
|
def content
|
||||||
|
self.read_attribute(:content).blank? ? self.default_content : self.read_attribute(:content)
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
@ -8,6 +8,13 @@ module Models
|
|||||||
included do
|
included do
|
||||||
embeds_many :editable_elements
|
embeds_many :editable_elements
|
||||||
|
|
||||||
|
after_save :remove_disabled_editable_elements
|
||||||
|
|
||||||
|
# editable file callbacks
|
||||||
|
after_save :store_file_sources!
|
||||||
|
before_save :write_file_source_identifiers
|
||||||
|
after_destroy :remove_file_sources!
|
||||||
|
|
||||||
accepts_nested_attributes_for :editable_elements
|
accepts_nested_attributes_for :editable_elements
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -26,21 +33,26 @@ module Models
|
|||||||
end
|
end
|
||||||
|
|
||||||
def editable_elements_grouped_by_blocks
|
def editable_elements_grouped_by_blocks
|
||||||
groups = self.editable_elements.group_by(&:block)
|
all_enabled = self.editable_elements.reject { |el| el.disabled? }
|
||||||
groups.delete_if { |block, elements| elements.all? { |el| el.disabled? } }
|
groups = all_enabled.group_by(&:block)
|
||||||
|
groups.delete_if { |block, elements| elements.empty? }
|
||||||
end
|
end
|
||||||
|
|
||||||
def find_editable_element(block, slug)
|
def find_editable_element(block, slug)
|
||||||
self.editable_elements.detect { |el| el.block == block && el.slug == slug }
|
self.editable_elements.detect { |el| el.block == block && el.slug == slug }
|
||||||
end
|
end
|
||||||
|
|
||||||
def add_or_update_editable_element(attributes)
|
def find_editable_files
|
||||||
|
self.editable_elements.find_all { |el| el.respond_to?(:source) }
|
||||||
|
end
|
||||||
|
|
||||||
|
def add_or_update_editable_element(attributes, type)
|
||||||
element = self.find_editable_element(attributes[:block], attributes[:slug])
|
element = self.find_editable_element(attributes[:block], attributes[:slug])
|
||||||
|
|
||||||
if element
|
if element
|
||||||
element.attributes = attributes
|
element.attributes = attributes
|
||||||
else
|
else
|
||||||
self.editable_elements.build(attributes)
|
self.editable_elements.build(attributes, type)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -50,18 +62,52 @@ module Models
|
|||||||
|
|
||||||
def merge_editable_elements_from_page(source)
|
def merge_editable_elements_from_page(source)
|
||||||
source.editable_elements.each do |el|
|
source.editable_elements.each do |el|
|
||||||
|
puts "\t*** merging #{el.class} / #{el.slug} / #{el.block} / #{el.disabled?} / #{el.from_parent?}"
|
||||||
|
|
||||||
next if el.disabled?
|
next if el.disabled?
|
||||||
|
|
||||||
existing_el = self.find_editable_element(el.block, el.slug)
|
existing_el = self.find_editable_element(el.block, el.slug)
|
||||||
|
|
||||||
if existing_el.nil? # new one from parents
|
if existing_el.nil? # new one from parents
|
||||||
self.editable_elements.build(el.attributes.merge(:from_parent => true))
|
new_attributes = el.attributes.merge(:from_parent => true)
|
||||||
|
new_attributes[:default_content] = el.content
|
||||||
|
|
||||||
|
foo = self.editable_elements.build(new_attributes, el.class)
|
||||||
|
puts "\t\t*** building #{foo.inspect} / #{foo.valid?} / #{foo.errors.full_messages.inspect}"
|
||||||
else
|
else
|
||||||
existing_el.disabled = false
|
existing_el.attributes = { :disabled => false, :default_content => el.content }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def remove_disabled_editable_elements
|
||||||
|
return unless self.editable_elements.any? { |el| el.disabled? }
|
||||||
|
|
||||||
|
puts "*** removing #{self.editable_elements.find_all { |el| el.disabled? }.size} elements"
|
||||||
|
|
||||||
|
# super fast way to remove useless elements all in once (TODO callbacks)
|
||||||
|
self.collection.update(self._selector, '$pull' => { 'editable_elements' => { 'disabled' => true } })
|
||||||
|
end
|
||||||
|
|
||||||
|
protected
|
||||||
|
|
||||||
|
## callbacks for editable files
|
||||||
|
|
||||||
|
# equivalent to "after_save :store_source!" in EditableFile
|
||||||
|
def store_file_sources!
|
||||||
|
self.find_editable_files.collect(&:store_source!)
|
||||||
|
end
|
||||||
|
|
||||||
|
# equivalent to "before_save :write_source_identifier" in EditableFile
|
||||||
|
def write_file_source_identifiers
|
||||||
|
self.find_editable_files.collect(&:write_source_identifier)
|
||||||
|
end
|
||||||
|
|
||||||
|
# equivalent to "after_destroy :remove_source!" in EditableFile
|
||||||
|
def remove_file_sources!
|
||||||
|
self.find_editable_files.collect(&:remove_source!)
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
@ -93,9 +93,11 @@ module Models
|
|||||||
end
|
end
|
||||||
|
|
||||||
direct_descendants.each do |page|
|
direct_descendants.each do |page|
|
||||||
|
puts "*** #{page.fullpath} descendant of #{self.fullpath}"
|
||||||
page.send(:_parse_and_serialize_template, { :cached_parent => self, :cached_pages => cached })
|
page.send(:_parse_and_serialize_template, { :cached_parent => self, :cached_pages => cached })
|
||||||
|
|
||||||
page.send(:_update_direct_template_descendants, template_descendants, cached)
|
page.send(:_update_direct_template_descendants, template_descendants, cached)
|
||||||
|
puts "-------- done -----------"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
11
app/uploaders/editable_file_uploader.rb
Normal file
11
app/uploaders/editable_file_uploader.rb
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
class EditableFileUploader < ::CarrierWave::Uploader::Base
|
||||||
|
|
||||||
|
def store_dir
|
||||||
|
"sites/#{model.page.site_id}/pages/#{model.page.id}/files"
|
||||||
|
end
|
||||||
|
|
||||||
|
def cache_dir
|
||||||
|
"#{Rails.root}/tmp/uploads"
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
@ -22,7 +22,7 @@
|
|||||||
= form.custom_input field._alias.to_sym, :label => field.label, :hint => field.hint, :css => 'file' do
|
= form.custom_input field._alias.to_sym, :label => field.label, :hint => field.hint, :css => 'file' do
|
||||||
= form.file_field field._name.to_sym
|
= form.file_field field._name.to_sym
|
||||||
- if form.object.send(:"#{field._name}?")
|
- if form.object.send(:"#{field._name}?")
|
||||||
%p
|
%p.remove
|
||||||
%strong
|
%strong
|
||||||
= link_to File.basename(form.object.send(field._name).url), form.object.send(field._name).url
|
= link_to File.basename(form.object.send(field._name).url), form.object.send(field._name).url
|
||||||
%span
|
%span
|
||||||
|
@ -17,7 +17,19 @@
|
|||||||
%ol
|
%ol
|
||||||
- elements.each_with_index do |el, index|
|
- elements.each_with_index do |el, index|
|
||||||
= f.fields_for 'editable_elements', el, :child_index => el._index do |g|
|
= f.fields_for 'editable_elements', el, :child_index => el._index do |g|
|
||||||
- if el.short_text?
|
- case el
|
||||||
= g.input :content, :label => el.slug.humanize, :hint => el.hint
|
- when EditableLongText
|
||||||
- elsif el.long_text?
|
= g.input :content, :label => el.slug.humanize, :hint => el.hint, :as => :text, :input_html => { :class => 'html' }
|
||||||
= g.input :content, :label => el.slug.humanize, :hint => el.hint, :as => :text, :input_html => { :class => 'html' }
|
- when EditableShortText
|
||||||
|
= g.input :content, :label => el.slug.humanize, :hint => el.hint
|
||||||
|
- when EditableFile
|
||||||
|
= g.custom_input :source, :label => el.slug.humanize, :hint => el.hint, :css => 'file' do
|
||||||
|
= g.file_field :source
|
||||||
|
- if el.source?
|
||||||
|
%p.remove
|
||||||
|
%strong
|
||||||
|
= link_to File.basename(el.source.url), el.source.url
|
||||||
|
%span
|
||||||
|
/
|
||||||
|
!= t('admin.pages.form.delete_file')
|
||||||
|
= g.check_box :remove_source
|
@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
%p!= t('.help')
|
%p!= t('.help')
|
||||||
|
|
||||||
= semantic_form_for @page, :url => admin_page_url(@page), :html => { :class => 'save-with-shortcut' } do |form|
|
= semantic_form_for @page, :url => admin_page_url(@page), :html => { :class => 'save-with-shortcut', :multipart => true } do |form|
|
||||||
|
|
||||||
= render 'form', :f => form
|
= render 'form', :f => form
|
||||||
|
|
||||||
|
@ -99,6 +99,7 @@ en:
|
|||||||
help: "The page title can be updated by clicking it."
|
help: "The page title can be updated by clicking it."
|
||||||
ask_for_title: "Please type the new page title"
|
ask_for_title: "Please type the new page title"
|
||||||
form:
|
form:
|
||||||
|
delete_file: Delete file
|
||||||
default_block: Default
|
default_block: Default
|
||||||
cache_strategy:
|
cache_strategy:
|
||||||
none: None
|
none: None
|
||||||
|
@ -99,6 +99,7 @@ fr:
|
|||||||
help: "Le titre de la page est modifiable en cliquant dessus."
|
help: "Le titre de la page est modifiable en cliquant dessus."
|
||||||
ask_for_title: "Veuillez entrer le nouveau titre"
|
ask_for_title: "Veuillez entrer le nouveau titre"
|
||||||
form:
|
form:
|
||||||
|
delete_file: Supprimer fichier
|
||||||
default_block: Défaut
|
default_block: Défaut
|
||||||
cache_strategy:
|
cache_strategy:
|
||||||
none: Aucun
|
none: Aucun
|
||||||
|
6
doc/TODO
6
doc/TODO
@ -8,7 +8,11 @@ x theme assets selector in page editor
|
|||||||
x saving page in ajax
|
x saving page in ajax
|
||||||
x editable_long_text tag
|
x editable_long_text tag
|
||||||
x blocking issue when modifying the parent of 2 templates => one of the 2 children has reference of the first child
|
x blocking issue when modifying the parent of 2 templates => one of the 2 children has reference of the first child
|
||||||
- editable_file tag
|
x editable_file tag
|
||||||
|
x stylish file field
|
||||||
|
x remove not used editable element all in once
|
||||||
|
x default content from parent editable element
|
||||||
|
x unable to upload/remove editable file
|
||||||
|
|
||||||
- refactor slugify method (use parameterize + create a module)
|
- refactor slugify method (use parameterize + create a module)
|
||||||
- [content types] the "display column" selector should not include file types
|
- [content types] the "display column" selector should not include file types
|
||||||
|
@ -114,3 +114,16 @@ Scenario: Combine inheritance and update
|
|||||||
Another Main
|
Another Main
|
||||||
Default sidebar title
|
Default sidebar title
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
Scenario: Insert editable files
|
||||||
|
Given a page named "hello-world" with the template:
|
||||||
|
"""
|
||||||
|
My application file is {% editable_file 'a_file', hint: 'please enter a new file' %}/default.pdf{% endeditable_file %}
|
||||||
|
"""
|
||||||
|
When I view the rendered page at "/hello-world"
|
||||||
|
Then the rendered output should look like:
|
||||||
|
"""
|
||||||
|
My application file is /default.pdf
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,2 +1,4 @@
|
|||||||
|
require 'locomotive/liquid/tags/editable/base'
|
||||||
require 'locomotive/liquid/tags/editable/short_text'
|
require 'locomotive/liquid/tags/editable/short_text'
|
||||||
require 'locomotive/liquid/tags/editable/long_text'
|
require 'locomotive/liquid/tags/editable/long_text'
|
||||||
|
require 'locomotive/liquid/tags/editable/file'
|
60
lib/locomotive/liquid/tags/editable/base.rb
Normal file
60
lib/locomotive/liquid/tags/editable/base.rb
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
module Locomotive
|
||||||
|
module Liquid
|
||||||
|
module Tags
|
||||||
|
module Editable
|
||||||
|
class Base < ::Liquid::Block
|
||||||
|
|
||||||
|
Syntax = /(#{::Liquid::QuotedFragment})(\s*,\s*#{::Liquid::Expression}+)?/
|
||||||
|
|
||||||
|
def initialize(tag_name, markup, tokens, context)
|
||||||
|
if markup =~ Syntax
|
||||||
|
@slug = $1.gsub('\'', '')
|
||||||
|
@options = {}
|
||||||
|
markup.scan(::Liquid::TagAttributes) { |key, value| @options[key.to_sym] = value.gsub(/^'/, '').gsub(/'$/, '') }
|
||||||
|
else
|
||||||
|
raise ::Liquid::SyntaxError.new("Syntax Error in 'editable_xxx' - Valid syntax: editable_xxx <slug>(, <options>)")
|
||||||
|
end
|
||||||
|
|
||||||
|
super
|
||||||
|
end
|
||||||
|
|
||||||
|
def end_tag
|
||||||
|
@context[:page].add_or_update_editable_element({
|
||||||
|
:block => @context[:current_block].try(:name),
|
||||||
|
:slug => @slug,
|
||||||
|
:hint => @options[:hint],
|
||||||
|
:default_content => @nodelist.first.to_s,
|
||||||
|
:disabled => false,
|
||||||
|
:from_parent => false
|
||||||
|
}, document_type)
|
||||||
|
end
|
||||||
|
|
||||||
|
def render(context)
|
||||||
|
current_page = context.registers[:page]
|
||||||
|
|
||||||
|
element = current_page.find_editable_element(context['block'].try(:name), @slug)
|
||||||
|
|
||||||
|
if element
|
||||||
|
render_element(element)
|
||||||
|
else
|
||||||
|
Locomotive.logger "[editable element] missing element #{context[:block].name} / #{@slug}"
|
||||||
|
''
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
protected
|
||||||
|
|
||||||
|
def render_element(element)
|
||||||
|
raise 'FIXME: has to be overidden'
|
||||||
|
end
|
||||||
|
|
||||||
|
def document_type
|
||||||
|
raise 'FIXME: has to be overidden'
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
23
lib/locomotive/liquid/tags/editable/file.rb
Normal file
23
lib/locomotive/liquid/tags/editable/file.rb
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
module Locomotive
|
||||||
|
module Liquid
|
||||||
|
module Tags
|
||||||
|
module Editable
|
||||||
|
class File < Base
|
||||||
|
|
||||||
|
protected
|
||||||
|
|
||||||
|
def render_element(element)
|
||||||
|
element.source? ? element.source.url : element.default_content
|
||||||
|
end
|
||||||
|
|
||||||
|
def document_type
|
||||||
|
EditableFile
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
::Liquid::Template.register_tag('editable_file', File)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
@ -3,6 +3,13 @@ module Locomotive
|
|||||||
module Tags
|
module Tags
|
||||||
module Editable
|
module Editable
|
||||||
class LongText < ShortText
|
class LongText < ShortText
|
||||||
|
|
||||||
|
protected
|
||||||
|
|
||||||
|
def document_type
|
||||||
|
EditableLongText
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
::Liquid::Template.register_tag('editable_long_text', LongText)
|
::Liquid::Template.register_tag('editable_long_text', LongText)
|
||||||
|
@ -2,51 +2,16 @@ module Locomotive
|
|||||||
module Liquid
|
module Liquid
|
||||||
module Tags
|
module Tags
|
||||||
module Editable
|
module Editable
|
||||||
class ShortText < ::Liquid::Block
|
class ShortText < Base
|
||||||
|
|
||||||
Syntax = /(#{::Liquid::QuotedFragment})(\s*,\s*#{::Liquid::Expression}+)?/
|
|
||||||
|
|
||||||
def initialize(tag_name, markup, tokens, context)
|
|
||||||
if markup =~ Syntax
|
|
||||||
@slug = $1.gsub('\'', '')
|
|
||||||
@options = {}
|
|
||||||
markup.scan(::Liquid::TagAttributes) { |key, value| @options[key.to_sym] = value.gsub(/^'/, '').gsub(/'$/, '') }
|
|
||||||
else
|
|
||||||
raise ::Liquid::SyntaxError.new("Syntax Error in 'editable_short_text' - Valid syntax: editable_short_text <slug>(, <options>)")
|
|
||||||
end
|
|
||||||
|
|
||||||
super
|
|
||||||
end
|
|
||||||
|
|
||||||
def end_tag
|
|
||||||
@context[:page].add_or_update_editable_element({
|
|
||||||
:kind => self.kind,
|
|
||||||
:block => @context[:current_block].try(:name),
|
|
||||||
:slug => @slug,
|
|
||||||
:hint => @options[:hint],
|
|
||||||
:default_content => @nodelist.first.to_s,
|
|
||||||
:disabled => false,
|
|
||||||
:from_parent => false
|
|
||||||
})
|
|
||||||
end
|
|
||||||
|
|
||||||
def render(context)
|
|
||||||
current_page = context.registers[:page]
|
|
||||||
|
|
||||||
element = current_page.find_editable_element(context['block'].try(:name), @slug)
|
|
||||||
|
|
||||||
if element
|
|
||||||
element.content
|
|
||||||
else
|
|
||||||
Locomotive.logger "[editable short text] missing editable short text #{context[:block].name} / #{@slug}"
|
|
||||||
''
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
protected
|
protected
|
||||||
|
|
||||||
def kind
|
def render_element(element)
|
||||||
self.class.name.demodulize
|
element.content
|
||||||
|
end
|
||||||
|
|
||||||
|
def document_type
|
||||||
|
EditableShortText
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
@ -8,6 +8,8 @@ module Locomotive
|
|||||||
|
|
||||||
parent_page = @context[:parent_page]
|
parent_page = @context[:parent_page]
|
||||||
|
|
||||||
|
@context[:page].merge_editable_elements_from_page(parent_page)
|
||||||
|
|
||||||
@context[:snippets] = parent_page.snippet_dependencies
|
@context[:snippets] = parent_page.snippet_dependencies
|
||||||
@context[:templates] = ([*parent_page.template_dependencies] + [parent_page.id]).compact
|
@context[:templates] = ([*parent_page.template_dependencies] + [parent_page.id]).compact
|
||||||
end
|
end
|
||||||
@ -29,8 +31,6 @@ module Locomotive
|
|||||||
|
|
||||||
raise PageNotFound.new("Page with fullpath '#{@template_name}' was not found") if @context[:parent_page].nil?
|
raise PageNotFound.new("Page with fullpath '#{@template_name}' was not found") if @context[:parent_page].nil?
|
||||||
|
|
||||||
@context[:page].merge_editable_elements_from_page(@context[:parent_page])
|
|
||||||
|
|
||||||
@context[:parent_page].template
|
@context[:parent_page].template
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -15,3 +15,58 @@ module Mongoid #:nodoc:
|
|||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# http://github.com/emk/mongoid/blob/503e346b1b7b250d682a12332ad9d5872f1575e6/lib/mongoid/atomicity.rb
|
||||||
|
module Mongoid #:nodoc:
|
||||||
|
module Atomicity #:nodoc:
|
||||||
|
extend ActiveSupport::Concern
|
||||||
|
|
||||||
|
def _updates
|
||||||
|
processed = {}
|
||||||
|
|
||||||
|
_children.inject({ "$set" => _sets, "$pushAll" => {}, :other => {} }) do |updates, child|
|
||||||
|
changes = child._sets
|
||||||
|
updates["$set"].update(changes)
|
||||||
|
unless changes.empty?
|
||||||
|
processed[child._conficting_modification_key] = true
|
||||||
|
end
|
||||||
|
|
||||||
|
# MongoDB does not allow "conflicting modifications" to be
|
||||||
|
# performed in a single operation. Conflicting modifications are
|
||||||
|
# detected by the 'haveConflictingMod' function in MongoDB.
|
||||||
|
# Examination of the code suggests that two modifications (a $set
|
||||||
|
# and a $pushAll, for example) conflict if (1) the key paths being
|
||||||
|
# modified are equal or (2) one key path is a prefix of the other.
|
||||||
|
# So a $set of 'addresses.0.street' will conflict with a $pushAll
|
||||||
|
# to 'addresses', and we will need to split our update into two
|
||||||
|
# pieces. We do not, however, attempt to match MongoDB's logic
|
||||||
|
# exactly. Instead, we assume that two updates conflict if the
|
||||||
|
# first component of the two key paths matches.
|
||||||
|
if processed.has_key?(child._conficting_modification_key)
|
||||||
|
target = :other
|
||||||
|
else
|
||||||
|
target = "$pushAll"
|
||||||
|
end
|
||||||
|
|
||||||
|
child._pushes.each do |attr, val|
|
||||||
|
if updates[target].has_key?(attr)
|
||||||
|
updates[target][attr] << val
|
||||||
|
else
|
||||||
|
updates[target].update({attr => [val]})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
updates
|
||||||
|
end.delete_if do |key, value|
|
||||||
|
value.empty?
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
protected
|
||||||
|
# Get the key used to check for conflicting modifications. For now, we
|
||||||
|
# just use the first component of _path, and discard the first period
|
||||||
|
# and everything that follows.
|
||||||
|
def _conficting_modification_key
|
||||||
|
_path.sub(/\..*/, '')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
@ -59,5 +59,6 @@
|
|||||||
|
|
||||||
#editable-elements .wrapper ul li fieldset ol { margin-top: 0px; border-top: 0px; background: #EBEDF4; }
|
#editable-elements .wrapper ul li fieldset ol { margin-top: 0px; border-top: 0px; background: #EBEDF4; }
|
||||||
#editable-elements .wrapper ul li fieldset ol li label { padding-left: 0px; padding-right: 3em; }
|
#editable-elements .wrapper ul li fieldset ol li label { padding-left: 0px; padding-right: 3em; }
|
||||||
|
#editable-elements .wrapper ul li fieldset ol li p.remove,
|
||||||
#editable-elements .wrapper ul li fieldset ol li p.inline-hints { margin-left: 13.3em; }
|
#editable-elements .wrapper ul li fieldset ol li p.inline-hints { margin-left: 13.3em; }
|
||||||
|
|
||||||
|
@ -380,22 +380,22 @@ form.formtastic fieldset.validations ol li.added em.key {
|
|||||||
width: 180px;
|
width: 180px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ___ content instance ___ */
|
/* ___ content instance / editable elements___ */
|
||||||
|
|
||||||
form.content_instance fieldset ol li.text textarea {
|
form.content_instance fieldset ol li.text textarea {
|
||||||
width: 75%;
|
width: 75%;
|
||||||
}
|
}
|
||||||
|
|
||||||
form.content_instance fieldset ol li.file p {
|
form.formtastic fieldset ol li.file p.remove {
|
||||||
margin: 5px 0 0 20%;
|
margin: 5px 0 0 20%;
|
||||||
}
|
}
|
||||||
|
|
||||||
form.content_instance fieldset ol li.file p a {
|
form.formtastic fieldset ol li.file p.remove a {
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
color: #333;
|
color: #333;
|
||||||
}
|
}
|
||||||
|
|
||||||
form.content_instance fieldset ol li.file p a:hover { text-decoration: underline; }
|
form.formtastic fieldset ol li.file p.remove a:hover { text-decoration: underline; }
|
||||||
|
|
||||||
/* ___ my account ___ */
|
/* ___ my account ___ */
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user