add missing files for the last commit about the control editable element + implement feature #326

This commit is contained in:
Didier Lafforgue 2012-03-22 02:13:24 +01:00
parent b3b0a5ac16
commit 6b8e3db8c3
12 changed files with 257 additions and 28 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

View File

@ -0,0 +1,24 @@
Locomotive.Views.EditableElements ||= {}
class Locomotive.Views.EditableElements.ControlView extends Backbone.View
tagName: 'li'
className: 'control input'
render: ->
$(@el).html(ich.editable_control_input(@model.toJSON()))
@bind_model()
return @
after_render: ->
# do nothing
refresh: ->
@bind_model()
bind_model: ->
Backbone.ModelBinding.bind @, { select: 'class' }

View File

@ -1,24 +0,0 @@
module Locomotive
class InlineEditorMiddleware
def initialize(app, opts = {})
@app = app
end
def call(env)
response = @app.call(env)
unless response[1]['Editable'].blank?
html = response.last.body.to_s.gsub '</body>', %(
<a href="_admin">Admin</a>
</body>
)
[response[0], response[1], [html]]
else
response
end
end
end
end

View File

@ -0,0 +1,56 @@
module Locomotive
class EditableControl < EditableElement
## fields ##
field :content
field :options, :type => Array, :default => []
## methods ##
def options=(value)
if value.respond_to?(:split)
value = value.split(/\s*\,\s*/).map do |option|
first, last = *option.split(/\s*=\s*/)
last ||= first
{ 'value' => first, 'text' => last }
end
end
super(value)
end
def default_content?
false
end
def copy_attributes_from(el)
super(el)
%w(content options).each do |meth|
self.attributes[meth] = el.attributes[meth]
end
end
def as_json(options = {})
Locomotive::EditableControlPresenter.new(self).as_json
end
protected
def propagate_content
if self.content_changed?
operations = {
'$set' => {
'editable_elements.$.content' => self.content,
'editable_elements.$.options' => self.options,
}
}
self.page.collection.update self._selector, operations, :multi => true
end
true
end
end
end

View File

@ -0,0 +1,18 @@
module Locomotive
class EditableControlPresenter < EditableElementPresenter
delegate :content, :to => :source
def options
self.source.options.map do |option|
option['selected'] = option['value'] == self.source.content
option
end
end
def included_methods
super + %w(content options)
end
end
end

View File

@ -111,10 +111,10 @@ x missing custom_fields
x many_to_many
x simplify cells integration when modifying a menu from the main app
x heroku module for locomotive
- refactoring
x refactoring
x remove the import / export scripts
x remove the cross domain authentication (use auth_token instead)
- where to put Locomotive::InlineEditorMiddleware ?
x where to put Locomotive::InlineEditorMiddleware ?
x global regions: keyword in editable element (http://www.mongodb.org/display/DOCS/Updating)
x override sort for contents

View File

@ -0,0 +1,22 @@
Feature: Manage Pages
In order to manage pages
As an administrator
I want to add/edit/delete editable elements of my pages
Background:
Given I have the site: "test site" set up
And I am an authenticated user
@javascript
Scenario: Insert a control element
Given a page named "hello-world" with the template:
"""
{% block menu %}{% editable_control 'Menu position', options: 'top=Top of the Page,bottom=Bottom of the Page' %}bottom{% endeditable_control %}{% endblock %}
"""
When I go to the "hello-world" edition page
Then "Bottom of the Page" should be selected for "page[editable_elements_attributes][0][content]"
When I select "Top of the Page" from "page[editable_elements_attributes][0][content]"
And I press "Save"
Then I should see "Page was successfully updated."
When I reload the page
Then "Top of the Page" should be selected for "page[editable_elements_attributes][0][content]"

View File

@ -77,7 +77,7 @@ module Locomotive
self.app_middleware.insert_before Rack::Lock, '::Locomotive::Middlewares::Fonts', :path => %r{^/fonts}
self.app_middleware.use '::Locomotive::Middlewares::SeoTrailingSlash'
self.app_middleware.use '::Locomotive::InlineEditorMiddleware' # TODO
self.app_middleware.use '::Locomotive::Middlewares::InlineEditor'
end
def self.configure_multi_sites

View File

@ -0,0 +1,31 @@
module Locomotive
module Liquid
module Tags
module Editable
class Control < Base
protected
def default_element_attributes
if @nodelist.first.is_a?(String)
super.merge(:content => @nodelist.first.try(:to_s), :options => @options[:options])
else
super
end
end
def render_element(context, element)
element.content
end
def document_type
EditableControl
end
end
::Liquid::Template.register_tag('editable_control', Control)
end
end
end
end

View File

@ -1,3 +1,4 @@
require 'locomotive/middlewares/fonts'
require 'locomotive/middlewares/seo_trailing_slash'
require 'locomotive/middlewares/cache'
require 'locomotive/middlewares/cache'
require 'locomotive/middlewares/inline_editor'

View File

@ -0,0 +1,31 @@
module Locomotive
module Middlewares
class InlineEditor
def initialize(app, opts = {})
@app = app
end
def call(env)
response = @app.call(env)
unless response[1]['Editable'].blank?
html = response.last.body.to_s.gsub '</body>', %(
<a href="_admin"
onmouseout="this.style.backgroundPosition='0px 0px'"
onmouseover="this.style.backgroundPosition='0px -45px'"
onmousedown="this.style.backgroundPosition='0px -90px'"
onmouseup="this.style.backgroundPosition='0px 0px'"
style="display: block;position:fixed;top: 10px; right: 10px;width: 48px; height: 45px;text-indent:-9999px;text-decoration:none;background: transparent url\('/assets/locomotive/icons/start.png'\) no-repeat 0 0;">
Admin</a>
</body>
)
[response[0], response[1], [html]]
else
response
end
end
end
end
end

View File

@ -0,0 +1,70 @@
require 'spec_helper'
describe Locomotive::EditableControl do
before(:each) do
@site = FactoryGirl.create(:site)
@home = @site.pages.root.first
end
describe '#simple' do
before(:each) do
@home.update_attributes :raw_template => "{% block body %}{% editable_control 'menu', options: 'true=Yes,false=No' %}false{% endeditable_control %}{% endblock %}"
@sub_page_1 = FactoryGirl.create(:page, :slug => 'sub_page_1', :parent => @home, :raw_template => "{% extends 'parent' %}")
end
it 'exists' do
@sub_page_1.editable_elements.size.should == 1
end
it 'has a non-nil slug' do
@sub_page_1.editable_elements.first.slug.should == 'menu'
end
it 'has a default value' do
@sub_page_1.editable_elements.first.content.should == 'false'
end
it 'has a list of options' do
@sub_page_1.editable_elements.first.options.should == [{ 'value' => 'true', 'text' => 'Yes' }, { 'value' => 'false', 'text' => 'No' }]
end
end
describe '"sticky" elements' do
before(:each) do
@home.update_attributes :raw_template => "{% block body %}{% editable_control 'menu', options: 'true=Yes,false=No', fixed: true %}false{% endeditable_control %}{% endblock %}"
@home_el = @home.editable_elements.first
@sub_page_1 = FactoryGirl.create(:page, :slug => 'sub_page_1', :parent => @home, :raw_template => "{% extends 'parent' %}")
@sub_page_2 = FactoryGirl.create(:page, :slug => 'sub_page_2', :parent => @home, :raw_template => "{% extends 'parent' %}")
@sub_page_1_el = @sub_page_1.editable_elements.first
@sub_page_2_el = @sub_page_2.editable_elements.first
end
it 'exists in sub pages' do
@sub_page_1.editable_elements.size.should == 1
@sub_page_2.editable_elements.size.should == 1
end
it 'is marked as fixed' do
@sub_page_1_el.fixed?.should be_true
@sub_page_2_el.fixed?.should be_true
end
it 'gets also updated when updating the very first element' do
@home_el.content = 'true'
@home.save
@sub_page_1.reload; @sub_page_1_el = @sub_page_1.editable_elements.first
@sub_page_2.reload; @sub_page_2_el = @sub_page_2.editable_elements.first
@sub_page_1_el.content.should == 'true'
@sub_page_2_el.content.should == 'true'
end
end
end