clean and improve the ui concerning the editable elements of a page + fix bugs and refactor a bit

This commit is contained in:
dinedine 2010-08-28 02:00:05 +02:00
parent 0d72a9f932
commit af5fe62d89
24 changed files with 131 additions and 281 deletions

View File

@ -3,14 +3,14 @@ source 'http://rubygems.org'
gem 'rails', '3.0.0.rc'
gem 'liquid', :git => 'git://github.com/locomotivecms/liquid.git', :ref => 'f299f8b7ff6ea102bfb3'
gem 'liquid', :git => 'git://github.com/locomotivecms/liquid.git', :ref => '7ce591f38ab826875337'
gem 'bson_ext', '>= 1.0.1'
gem 'mongoid', '2.0.0.beta.16'
gem 'mongoid_acts_as_tree', '0.1.5'
gem 'mongo_session_store', '2.0.0.pre'
gem 'warden'
gem 'devise', :git => 'git://github.com/plataformatec/devise.git'
gem 'devise', '1.1.2' #:git => 'git://github.com/plataformatec/devise.git'
gem 'haml', '3.0.15'
gem 'rmagick', '2.12.2'
gem 'aws'

View File

@ -13,19 +13,11 @@ GIT
GIT
remote: git://github.com/locomotivecms/liquid.git
revision: f299f8b
ref: f299f8b7ff6ea102bfb3
revision: 7ce591f
ref: 7ce591f38ab826875337
specs:
liquid (2.1.3)
GIT
remote: git://github.com/plataformatec/devise.git
revision: c6002bb
specs:
devise (1.2.0)
bcrypt-ruby (~> 2.1.2)
warden (~> 0.10.7)
GIT
remote: http://github.com/codegram/pickle.git
revision: 2834204
@ -99,6 +91,9 @@ GEM
culerity (0.2.12)
daemons (1.1.0)
database_cleaner (0.5.2)
devise (1.1.2)
bcrypt-ruby (~> 2.1.2)
warden (~> 0.10.7)
diff-lcs (1.1.2)
erubis (2.6.6)
abstract (>= 1.0.0)
@ -248,7 +243,7 @@ DEPENDENCIES
cucumber-rails
custom_fields!
database_cleaner
devise!
devise (= 1.1.2)
factory_girl_rails
fastthread
formtastic-rails3 (= 1.0.0.beta3)

View File

@ -1,16 +0,0 @@
# @DEPRECATED
# module Admin
# class PagePartsController < BaseController
#
# layout nil
#
# respond_to :json
#
# def index
# parts = current_site.layouts.find(params[:layout_id]).parts
#
# respond_with parts.collect(&:attributes)
# end
#
# end
# end

View File

@ -11,7 +11,18 @@ module Admin
def new
@page = current_site.pages.build
# @page.parts << PagePart.build_body_part
end
def update
update! do |success, failure|
success.json do
render :json => {
:notice => t('flash.admin.pages.update.notice'),
:editable_elements => @page.template_changed ?
render_to_string(:partial => 'admin/pages/editable_elements.html.haml') : ''
}
end
end
end
def sort

View File

@ -17,6 +17,10 @@ module Models
self.editable_elements.each { |el| el.disabled = true if el.from_parent? && el.block == block }
end
def disable_all_editable_elements
self.editable_elements.each { |el| el.disabled = true }
end
def editable_element_blocks
self.editable_elements.collect(&:block)
end
@ -40,11 +44,6 @@ module Models
end
end
def disable_all_editable_elements
# TODO: only if block != blank
self.editable_elements.each { |el| el.disabled = true }
end
def enable_editable_elements(block)
self.editable_elements.each { |el| el.disabled = false if el.block == block }
end

View File

@ -10,6 +10,8 @@ module Models
field :template_dependencies, :type => Array, :default => []
field :snippet_dependencies, :type => Array, :default => []
attr_reader :template_changed
before_validation :serialize_template
after_save :update_template_descendants
@ -58,11 +60,11 @@ module Models
context = default_context.merge(context)
puts "*** [#{self.fullpath}] enter context = #{context.object_id} / #{context[:page].fullpath}"
# puts "*** [#{self.fullpath}] enter context = #{context.object_id} / #{context[:page].fullpath}"
@template = ::Liquid::Template.parse(self.raw_template, context)
puts "*** exit context = #{context.object_id}"
# puts "*** exit context = #{context.object_id}"
self.template_dependencies = context[:templates]
self.snippet_dependencies = context[:snippets]
@ -85,7 +87,7 @@ module Models
# group them by fullpath for better performance
cached = template_descendants.inject({}) { |memo, page| memo[page.fullpath] = page; memo }
puts "*** [#{self.fullpath}] #{template_descendants.collect(&:fullpath).inspect}"
# puts "*** [#{self.fullpath}] #{template_descendants.collect(&:fullpath).inspect}"
self._update_direct_template_descendants(template_descendants, cached)
@ -96,13 +98,13 @@ module Models
end
def _update_direct_template_descendants(template_descendants, cached)
puts "*** [#{self.fullpath}] _update_direct_template_descendants"
# puts "*** [#{self.fullpath}] _update_direct_template_descendants"
direct_descendants = template_descendants.select do |page|
puts "*** \t\t[#{self.fullpath}] _update_direct_template_descendants (#{page.template_dependencies.inspect})"
# puts "*** \t\t[#{self.fullpath}] _update_direct_template_descendants (#{page.template_dependencies.inspect})"
((page.template_dependencies || [])- (self.template_dependencies || [])).size == 1
end
puts "*** [#{self.fullpath}] direct = #{direct_descendants.inspect}"
# puts "*** [#{self.fullpath}] direct = #{direct_descendants.inspect}"
direct_descendants.each do |page|
page.send(:_parse_and_serialize_template, { :cached_parent => self, :cached_pages => cached })

View File

@ -1,59 +0,0 @@
# @DEPRECATED
# module Models
# module Extensions
# module Page
# module Parts
#
# extend ActiveSupport::Concern
#
# included do
# embeds_many :parts, :class_name => 'PagePart'
#
# before_validation do |p|
# if p.parts.empty?
# p.parts << PagePart.build_body_part(p.respond_to?(:body) ? p.body : nil)
# end
# end
# end
#
# module InstanceMethods
#
# def parts_attributes=(attributes)
# self.update_parts(attributes.values.map { |attrs| PagePart.new(attrs) })
# end
#
# def joined_parts
# self.parts.enabled.map(&:template).join('')
# end
#
# protected
#
# def update_parts(parts)
# performed = []
#
# # add / update
# parts.each do |part|
# if (existing = self.parts.detect { |p| p.id == part.id || p.slug == part.slug })
# existing.attributes = part.attributes.delete_if { |k, v| %w{_id slug}.include?(k) }
# else
# self.parts << (existing = part)
# end
# performed << existing unless existing.disabled?
# end
#
# # disable missing parts
# (self.parts.map(&:slug) - performed.map(&:slug)).each do |slug|
# self.parts.detect { |p| p.slug == slug }.disabled = true
# end
# end
#
# def update_parts!(new_parts)
# self.update_parts(new_parts)
# self.save
# end
#
# end
# end
# end
# end
# end

View File

@ -1,36 +0,0 @@
# @DEPRECATED
# class PagePart
#
# include Mongoid::Document
#
# ## fields ##
# field :name
# field :slug
# field :value
# field :disabled, :type => Boolean, :default => false
# field :value
#
# ## associations ##
# embedded_in :page, :inverse_of => :parts
#
# ## validations ##
# validates_presence_of :name, :slug
#
# ## named scopes ##
# scope :enabled, where(:disabled => false)
#
# ## methods ##
#
# def template
# "{% capture content_for_#{self.slug} %}#{self.value}{% endcapture %}"
# end
#
# def self.build_body_part(body_content = nil)
# self.new({
# :name => I18n.t('attributes.defaults.page_parts.name'),
# :value => body_content || I18n.t('attributes.defaults.pages.other.body'),
# :slug => 'layout'
# })
# end
#
# end

View File

@ -0,0 +1,20 @@
- grouped_editable_elements = @page.editable_elements_grouped_by_blocks
= semantic_fields_for(@page) do |f|
- unless grouped_editable_elements.empty?
#editable-elements
.nav
- grouped_editable_elements.keys.each_with_index do |name, index|
= link_to content_tag(:span, name.try(:humanize) || t('admin.pages.form.default_block')), "#block-#{index}", :id => "block-nav-#{index}", :class => "#{'on' if index == 0}"
.clear
.wrapper
%ul{ :id => "blocks" }
- grouped_editable_elements.keys.each_with_index do |name, index|
- elements = grouped_editable_elements[name]
%li{ :id => "block-#{index}", :class => 'block', :style => "display: #{index == 0 ? 'block' : 'none' }" }
%fieldset.inputs
%ol
- elements.each_with_index do |el, index|
= f.fields_for 'editable_elements', el, :child_index => el._index do |g|
= g.input :content, :label => el.slug.humanize, :hint => el.hint

View File

@ -1,6 +1,7 @@
- content_for :head do
= javascript_include_tag 'admin/plugins/codemirror/codemirror', 'admin/plugins/wslide', 'admin/pages', 'admin/editable_elements'
= javascript_include_tag 'admin/plugins/codemirror/codemirror', 'admin/pages', 'admin/editable_elements'
= stylesheet_link_tag 'admin/editable_elements'
= image_picker_include_tags
= f.foldable_inputs :name => :information do
@ -21,39 +22,13 @@
= f.input :cache_strategy, :as => :select, :collection => options_for_page_cache_strategy, :include_blank => false
#editable-elements
- grouped_editable_elements = @page.editable_elements_grouped_by_blocks
.nav
- grouped_editable_elements.keys.each_with_index do |name, index|
= link_to content_tag(:span, name.try(:humanize) || t('.default_block')), "#block-#{index}", :id => "block-nav-#{index}", :class => "#{'on' if index == 0}"
.clear
.wrapper
%ul{ :id => "blocks" }
- grouped_editable_elements.keys.each_with_index do |name, index|
- elements = grouped_editable_elements[name]
%li{ :id => "block-#{index}", :class => 'block', :style => "display: #{index == 0 ? 'block' : 'none' }" }
%fieldset.inputs
%ol
- elements.each_with_index do |el, index|
= f.fields_for 'editable_elements', el, :child_index => el._index do |g|
= g.input :content, :label => el.slug.humanize, :hint => el.hint
/
/
/ = f.fields_for :editable_elements do |g|
/ %li
/ = g.label :value, g.object.name, :style => "display:none"
/ %code= g.text_area :value
/ = g.hidden_field :name
/ = g.hidden_field :slug
/ = g.hidden_field :disabled, :class => 'disabled'
= render 'editable_elements', :page => @page
= f.foldable_inputs :name => :raw_template do
= f.custom_input :value, :css => 'code full', :with_label => false do
= f.label :raw_template
%code{ :class => 'html' }
= f.text_area :raw_template
/ .more
/ = link_to t('admin.image_picker.link'), admin_theme_assets_path, :id => 'image-picker-link'
= f.errors_on :template
.more
= link_to t('admin.image_picker.link'), admin_theme_assets_path, :id => 'image-picker-link'

View File

@ -25,8 +25,6 @@ en:
body: "Content of the 404 page"
other:
body: "Content goes here"
page_parts:
name: "Body"
pagination:
previous: "&laquo; Previous"

View File

@ -46,8 +46,6 @@ fr:
body: "Contenu de la page d'erreur 404"
other:
body: "Le contenu va ici"
page_parts:
name: "Corps"
activemodel:
attributes:

View File

@ -1,17 +1,18 @@
BOARD:
x liquid inheritance
x bug editable_xxx disabled for nil block
- duplicated block name
! duplicated block name
x display liquid errors
x theme assets selector in page editor
x saving page in ajax
- editable_long_text tag
- editable_file tag
- refactor slugify method (use parameterize + create a module)
- [content types] the "display column" selector should not include file types
- add dom_id and css_class fields in page (body structure ?)
- liquid inheritance:
BACKLOG:

View File

@ -17,41 +17,6 @@ Scenario: Simple Page
Hello World
"""
# Scenario: Page with Parts
# Given a layout named "layout_with_sidebar" with the source:
# """
# <div class="header"></div>
# <div class="content">
# <div class="sidebar">{{ content_for_sidebar }}</div>
# <div class="body">
# {{ content_for_layout }}
# </div>
# </div>
# <div class="footer"></div>
# """
# And a page named "hello-world-multipart" with the layout "layout_with_sidebar" and the body:
# """
# IM IN UR BODY OUTPUTTING SUM CODEZ!!
# """
#
# And the page named "hello-world-multipart" has the part "sidebar" with the content:
# """
# IM IN UR SIDEBAR PUTTING OUT LINKZ
# """
#
# When I view the rendered page at "/hello-world-multipart"
# Then the rendered output should look like:
# """
# <div class="header"></div>
# <div class="content">
# <div class="sidebar">IM IN UR SIDEBAR PUTTING OUT LINKZ</div>
# <div class="body">
# IM IN UR BODY OUTPUTTING SUM CODEZ!!
# </div>
# </div>
# <div class="footer"></div>
# """
#
# @wip
# Scenario: Simple Page with Admin Inline Editing
# Given a simple page named "hello-world-inline" with the body:
@ -64,8 +29,8 @@ Scenario: Simple Page
# """
# <div class="inline-editing" data-url="/admin/parts/XXXX" data-title="hello">Hello World</div>
# """
#
# {% block main %}Didier{% endblock %}
# {% block body %}{% block main %}{{ block.super }}Jacques{% endblock %}{% endblock %}
# {% block body %}Hello mister Jacques{% endblock %}
#
# {% block body %}{% block main %}{{ block.super }}Jacques{% endblock %}{% endblock %}
# {% block body %}Hello mister Jacques{% endblock %}

View File

@ -17,26 +17,6 @@ Given /^a page named "([^"]*)" with the template:$/ do |page_slug, template|
@page = create_content_page(page_slug, '', template)
end
# # creates a part within a page
# Given /^the page named "([^"]*)" has the part "([^"]*)" with the content:$/ do |page_slug, part_slug, part_contents|
# page = @site.pages.where(:slug => page_slug).first
# raise "Could not find page: #{page_slug}" unless page
#
# # find or crate page part
# part = page.parts.where(:slug => part_slug).first
# unless part
# part = page.parts.build(:name => part_slug.titleize, :slug => part_slug)
# end
#
# # set part value
# part.value = part_contents
# part.should be_valid
#
# # save page with embedded part
# page.save
# end
# update a page
When /^I update the "([^"]*)" page with the template:$/ do |page_slug, template|
page = @site.pages.where(:slug => page_slug).first

View File

@ -15,11 +15,11 @@ module Locomotive
end
super
# puts "context = #{context.object_id} / #{@context[:page]}"
end
# puts "@nodelist = #{@nodelist.inspect}"
puts "context = #{context.object_id} / #{@context[:page]}"
context[:page].add_or_update_editable_element({
def end_tag
@context[:page].add_or_update_editable_element({
:block => @context[:current_block].try(:name),
:slug => @slug,
:hint => @options[:hint],

View File

@ -9,10 +9,10 @@ module Locomotive
if markup =~ Syntax
@template_name = $1.gsub('\'', '').strip
else
raise SyntaxError.new("Error in tag 'extends' - Valid syntax: extends [template]")
raise ::Liquid::SyntaxError.new("Error in tag 'extends' - Valid syntax: extends [template]")
end
puts "** [Extends] #{context[:page].fullpath}"
# puts "** [Extends] #{context[:page].fullpath}"
@context = context
@ -37,7 +37,7 @@ module Locomotive
blocks = find_blocks(template.root.nodelist)
blocks.each_value do |block|
puts "*** [Extends] merging #{block.name} / #{@context.object_id}"
# puts "*** [Extends] merging #{block.name} / #{@context.object_id}"
block.send(:instance_variable_set, :"@context", @context)
block.send(:register_current_block)
end

View File

@ -7,51 +7,51 @@ module Locomotive
if markup =~ Syntax
@name = $1
else
raise SyntaxError.new("Error in tag 'block' - Valid syntax: block [name]")
raise ::Liquid::SyntaxError.new("Error in tag 'block' - Valid syntax: block [name]")
end
context[:current_block] = self # for now, no need to push it in a stack
puts "** InheritedBlock[begin] #{context.object_id} / #{@name} / #{context[:page].try(:fullpath)}"
# puts "** InheritedBlock[begin] #{context.object_id} / #{@name} / #{context[:page].try(:fullpath)}"
super if tokens
end
def end_tag
puts "** InheritedBlock[end_tag] before super #{@name} / #{@context.object_id}/ #{@context[:page].fullpath}"
# puts "** InheritedBlock[end_tag] before super #{@name} / #{@context.object_id}/ #{@context[:page].fullpath}"
self.register_current_block
if !self.contains_super?(@nodelist) # then disable all editable_elements coming from the parent block too and not used
puts "** InheritedBlock[end_tag] disabling_parent_editable_elements... #{@context.object_id}"
# puts "** InheritedBlock[end_tag] disabling_parent_editable_elements... #{@context.object_id}"
@context[:page].disable_parent_editable_elements(@name)
end
puts "** InheritedBlock[end_tag] after super #{@name} / #{@context.object_id}/ #{@context[:page].fullpath}"
# puts "** InheritedBlock[end_tag] after super #{@name} / #{@context.object_id}/ #{@context[:page].fullpath}"
end
protected
def register_current_block
@context[:blocks] ||= {}
block = @context[:blocks][@name]
if block
# needed for the block.super statement
# puts "[BLOCK #{@name}|end_tag] nodelist #{@nodelist.inspect}"
block.add_parent(@nodelist)
@parent = block.parent
@nodelist = block.nodelist
# puts "[BLOCK #{@name}|end_tag] direct parent #{block.parent.inspect}"
else
# register it
# puts "[BLOCK #{@name}|end_tag] register it"
@context[:blocks][@name] = self
end
end
# def register_current_block
# @context[:blocks] ||= {}
#
# block = @context[:blocks][@name]
#
# if block
# # needed for the block.super statement
# # puts "[BLOCK #{@name}|end_tag] nodelist #{@nodelist.inspect}"
# block.add_parent(@nodelist)
#
# @parent = block.parent
# @nodelist = block.nodelist
#
# # puts "[BLOCK #{@name}|end_tag] direct parent #{block.parent.inspect}"
# else
# # register it
# # puts "[BLOCK #{@name}|end_tag] register it"
# @context[:blocks][@name] = self
# end
# end
def contains_super?(nodelist)
nodelist.any? do |node|

View File

@ -1,15 +1,26 @@
$(document).ready(function() {
$('#editable-elements .nav a').click(function(e) {
var index = parseInt($(this).attr('href').match(/block-(.+)/)[1]);
var enableNav = function() {
$('#editable-elements .nav a').click(function(e) {
var index = parseInt($(this).attr('href').match(/block-(.+)/)[1]);
$('#editable-elements .wrapper ul li.block').hide();
$('#block-' + index).show();
$('#editable-elements .wrapper ul li.block').hide();
$('#block-' + index).show();
$(this).parent().find('.on').removeClass('on');
$(this).addClass('on');
$(this).parent().find('.on').removeClass('on');
$(this).addClass('on');
e.preventDefault();
});
e.preventDefault();
});
}
enableNav();
$.subscribe('form.saved.success', function(event, data) {
if (data.editable_elements != '') {
$('#editable-elements').replaceWith(data.editable_elements);
enableNav();
}
}, []);
});

View File

@ -77,4 +77,10 @@ $(document).ready(function() {
}
}, 2000);
$('a#image-picker-link').imagepicker({
insertFn: function(link) {
return "{{ theme_images." + link.attr('data-slug') + " }}";
}
});
});

View File

@ -59,5 +59,5 @@
#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 p.inline-hints { margin-left: 20%; }
#editable-elements .wrapper ul li fieldset ol li p.inline-hints { margin-left: 13.3em; }

View File

@ -141,10 +141,10 @@ form.formtastic fieldset ol li.code label { display: none; }
form.formtastic fieldset ol li.code p.inline-errors {
display: block;
float: right;
float: left;
margin: 4px 16px 0 0;
position: relative;
left: 0px;
left: 20px;
background-image: none;
}

View File

@ -4,6 +4,7 @@ describe Locomotive::Liquid::Tags::EditableShortText do
it 'should have a valid syntax' do
markup = "'title', hint: 'Simple short text'"
Locomotive::Liquid::Tags::EditableShortText.any_instance.stubs(:end_tag).returns(true)
lambda do
Locomotive::Liquid::Tags::EditableShortText.new('editable_short_text', markup, ["{% endeditable_short_text %}"], {})
end.should_not raise_error

View File

@ -115,8 +115,7 @@ describe Site do
it 'should create index and 404 pages' do
@site.pages.size.should == 2
@site.pages.first.slug.should == 'index'
@site.pages.last.slug.should == '404'
@site.pages.map(&:fullpath).sort.should == %w{404 index}
end
end