add missing files for the last commit about the control editable element + implement feature #326
This commit is contained in:
parent
b3b0a5ac16
commit
6b8e3db8c3
BIN
app/assets/images/locomotive/icons/start.png
Normal file
BIN
app/assets/images/locomotive/icons/start.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.3 KiB |
@ -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' }
|
||||||
|
|
@ -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
|
|
56
app/models/locomotive/editable_control.rb
Normal file
56
app/models/locomotive/editable_control.rb
Normal 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
|
||||||
|
|
18
app/presenters/locomotive/editable_control_presenter.rb
Normal file
18
app/presenters/locomotive/editable_control_presenter.rb
Normal 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
|
4
doc/TODO
4
doc/TODO
@ -111,10 +111,10 @@ x missing custom_fields
|
|||||||
x many_to_many
|
x many_to_many
|
||||||
x simplify cells integration when modifying a menu from the main app
|
x simplify cells integration when modifying a menu from the main app
|
||||||
x heroku module for locomotive
|
x heroku module for locomotive
|
||||||
- refactoring
|
x refactoring
|
||||||
x remove the import / export scripts
|
x remove the import / export scripts
|
||||||
x remove the cross domain authentication (use auth_token instead)
|
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 global regions: keyword in editable element (http://www.mongodb.org/display/DOCS/Updating)
|
||||||
x override sort for contents
|
x override sort for contents
|
||||||
|
|
||||||
|
22
features/backoffice/editable_elements.feature
Normal file
22
features/backoffice/editable_elements.feature
Normal 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]"
|
@ -77,7 +77,7 @@ module Locomotive
|
|||||||
self.app_middleware.insert_before Rack::Lock, '::Locomotive::Middlewares::Fonts', :path => %r{^/fonts}
|
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::Middlewares::SeoTrailingSlash'
|
||||||
|
|
||||||
self.app_middleware.use '::Locomotive::InlineEditorMiddleware' # TODO
|
self.app_middleware.use '::Locomotive::Middlewares::InlineEditor'
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.configure_multi_sites
|
def self.configure_multi_sites
|
||||||
|
31
lib/locomotive/liquid/tags/editable/control.rb
Normal file
31
lib/locomotive/liquid/tags/editable/control.rb
Normal 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
|
@ -1,3 +1,4 @@
|
|||||||
require 'locomotive/middlewares/fonts'
|
require 'locomotive/middlewares/fonts'
|
||||||
require 'locomotive/middlewares/seo_trailing_slash'
|
require 'locomotive/middlewares/seo_trailing_slash'
|
||||||
require 'locomotive/middlewares/cache'
|
require 'locomotive/middlewares/cache'
|
||||||
|
require 'locomotive/middlewares/inline_editor'
|
31
lib/locomotive/middlewares/inline_editor.rb
Normal file
31
lib/locomotive/middlewares/inline_editor.rb
Normal 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
|
70
spec/models/locomotive/editable_control_spec.rb
Normal file
70
spec/models/locomotive/editable_control_spec.rb
Normal 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
|
Loading…
Reference in New Issue
Block a user