From 11d92ab80e39f7e1bf2ea11b68acec0205ed0514 Mon Sep 17 00:00:00 2001 From: Didier Lafforgue Date: Wed, 28 Mar 2012 00:26:32 +0200 Subject: [PATCH] nested templatized pages finally done (+ specs) + upgrade gems + change the zindex value of the start button for the inline editor + change version (rc.3) for the next rc release --- Gemfile.lock | 2 +- .../views/pages/_form_view.js.coffee | 7 +++ .../locomotive/pages_controller.rb | 7 ++- .../locomotive/extensions/page/listed.rb | 1 + .../locomotive/extensions/page/parse.rb | 5 ++ .../locomotive/extensions/page/templatized.rb | 44 ++++++++++++- app/presenters/locomotive/page_presenter.rb | 4 +- app/views/locomotive/pages/_form.html.haml | 6 +- lib/locomotive/middlewares/inline_editor.rb | 2 +- lib/locomotive/version.rb | 2 +- spec/models/locomotive/page_spec.rb | 62 ++++++++++++++++++- 11 files changed, 125 insertions(+), 17 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index b7f2f6bf..c14da849 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -28,7 +28,7 @@ GIT PATH remote: . specs: - locomotive_cms (2.0.0.rc2) + locomotive_cms (2.0.0.rc3) RedCloth (~> 4.2.8) actionmailer-with-request (~> 0.3.0) bson_ext (~> 1.5.2) diff --git a/app/assets/javascripts/locomotive/views/pages/_form_view.js.coffee b/app/assets/javascripts/locomotive/views/pages/_form_view.js.coffee index 241250e4..3531ef1d 100644 --- a/app/assets/javascripts/locomotive/views/pages/_form_view.js.coffee +++ b/app/assets/javascripts/locomotive/views/pages/_form_view.js.coffee @@ -112,6 +112,11 @@ class Locomotive.Views.Pages.FormView extends Locomotive.Views.Shared.FormView data: { parent_id: @$('#page_parent_id').val(), slug: @$('#page_slug').val() } success: (data) => @$('#page_slug_input .inline-hints').html(data.url).effect('highlight') + if data.templatized_parent + @$('li#page_slug_input').show() + @$('li#page_templatized_input, li#page_target_klass_name_input').hide() + else + @$('li#page_templatized_input, li#page_target_klass_name_input').show() enable_response_type_select: -> @$('li#page_response_type_input').change (event) => @@ -129,6 +134,8 @@ class Locomotive.Views.Pages.FormView extends Locomotive.Views.Shared.FormView off_callback: => @$('li#page_target_klass_name_input').hide() + @$('li#page_templatized_input').hide() if @model.get('templatized_from_parent') == true + enable_redirect_checkbox: -> @_enable_checkbox 'redirect', features: ['templatized', 'cache_strategy'] diff --git a/app/controllers/locomotive/pages_controller.rb b/app/controllers/locomotive/pages_controller.rb index 4e3d79e5..d607b609 100644 --- a/app/controllers/locomotive/pages_controller.rb +++ b/app/controllers/locomotive/pages_controller.rb @@ -53,9 +53,10 @@ module Locomotive end 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 } + page = current_site.pages.build(:parent => current_site.pages.find(params[:parent_id]), :slug => params[:slug].permalink).tap do |p| + p.valid?; p.send(:build_fullpath) + end + render :json => { :url => public_page_url(page), :slug => page.slug, :templatized_parent => page.templatized_from_parent? } end end diff --git a/app/models/locomotive/extensions/page/listed.rb b/app/models/locomotive/extensions/page/listed.rb index 3503e24b..4edd25e2 100644 --- a/app/models/locomotive/extensions/page/listed.rb +++ b/app/models/locomotive/extensions/page/listed.rb @@ -7,6 +7,7 @@ module Locomotive included do + ## fields ## field :listed, :type => Boolean, :default => true end diff --git a/app/models/locomotive/extensions/page/parse.rb b/app/models/locomotive/extensions/page/parse.rb index fb1c9337..2280dd61 100644 --- a/app/models/locomotive/extensions/page/parse.rb +++ b/app/models/locomotive/extensions/page/parse.rb @@ -6,17 +6,22 @@ module Locomotive extend ActiveSupport::Concern included do + ## fields ## field :serialized_template, :type => Binary, :localize => true field :template_dependencies, :type => Array, :default => [], :localize => true field :snippet_dependencies, :type => Array, :default => [], :localize => true + ## virtual attributes attr_reader :template_changed + ## callbacks ## before_validation :serialize_template after_save :update_template_descendants + ## validations ## validate :template_must_be_valid + ## scopes ## scope :pages, lambda { |domain| { :any_in => { :domains => [*domain] } } } end diff --git a/app/models/locomotive/extensions/page/templatized.rb b/app/models/locomotive/extensions/page/templatized.rb index 66868163..9d6a64d3 100644 --- a/app/models/locomotive/extensions/page/templatized.rb +++ b/app/models/locomotive/extensions/page/templatized.rb @@ -7,7 +7,9 @@ module Locomotive included do - field :templatized, :type => Boolean, :default => false + ## fields ## + field :templatized, :type => Boolean, :default => false + field :templatized_from_parent, :type => Boolean, :default => false field :target_klass_name ## validations ## @@ -15,8 +17,10 @@ module Locomotive validate :ensure_target_klass_name_security ## callbacks ## + before_validation :get_templatized_from_parent before_validation :set_slug_if_templatized before_validation :ensure_target_klass_name_security + after_save :propagate_templatized ## scopes ## scope :templatized, :where => { :templatized => true } @@ -73,10 +77,26 @@ module Locomotive protected - def set_slug_if_templatized - self.slug = 'content_type_template' if self.templatized? + def get_templatized_from_parent + return if self.parent.nil? + + if self.parent.templatized? + self.templatized = self.templatized_from_parent = true + self.target_klass_name = self.parent.target_klass_name + elsif !self.templatized? + self.templatized = self.templatized_from_parent = false + self.target_klass_name = nil + end end + def set_slug_if_templatized + self.slug = 'content_type_template' if self.templatized? && !self.templatized_from_parent? + end + + # Makes sure the target_klass is owned by the site OR + # if it belongs to the models allowed by the application + # thanks to the models_for_templatization option. + # def ensure_target_klass_name_security return if !self.templatized? || self.target_klass_name.blank? @@ -89,7 +109,25 @@ module Locomotive elsif !Locomotive.config.models_for_templatization.include?(self.target_klass_name) self.errors.add :target_klass_name, :security end + end + # Sets the templatized, templatized_from_parent properties of + # the children of the current page ONLY IF the templatized + # attribute got changed. + # + def propagate_templatized + return unless self.templatized_changed? + + selector = { 'parent_ids' => { '$in' => [self._id] } } + operations = { + '$set' => { + 'templatized' => self.templatized, + 'templatized_from_parent' => self.templatized, + 'target_klass_name' => self.target_klass_name + } + } + + self.collection.update selector, operations, :multi => true end end diff --git a/app/presenters/locomotive/page_presenter.rb b/app/presenters/locomotive/page_presenter.rb index 62a7798b..c41fbba4 100644 --- a/app/presenters/locomotive/page_presenter.rb +++ b/app/presenters/locomotive/page_presenter.rb @@ -1,7 +1,7 @@ module Locomotive class PagePresenter < BasePresenter - delegate :title, :slug, :fullpath, :handle, :raw_template, :published, :listed, :templatized, :redirect, :redirect_url, :template_changed, :cache_strategy, :response_type, :to => :source + delegate :title, :slug, :fullpath, :handle, :raw_template, :published, :listed, :templatized, :templatized_from_parent, :redirect, :redirect_url, :template_changed, :cache_strategy, :response_type, :to => :source def escaped_raw_template h(self.source.raw_template) @@ -12,7 +12,7 @@ module Locomotive end def included_methods - super + %w(title slug fullpath handle raw_template published listed templatized redirect redirect_url cache_strategy response_type template_changed editable_elements localized_fullpaths) + super + %w(title slug fullpath handle raw_template published listed templatized templatized_from_parent redirect redirect_url cache_strategy response_type template_changed editable_elements localized_fullpaths) end def localized_fullpaths diff --git a/app/views/locomotive/pages/_form.html.haml b/app/views/locomotive/pages/_form.html.haml index 69800585..9e5290aa 100644 --- a/app/views/locomotive/pages/_form.html.haml +++ b/app/views/locomotive/pages/_form.html.haml @@ -16,7 +16,7 @@ - if not @page.index? and not @page.not_found? = f.input :parent_id, :as => :select, :collection => parent_pages_options, :include_blank => false - = f.input :slug, :required => false, :hint => @page.slug.blank? ? t('.empty_slug') : public_page_url(@page), :input_html => { :'data-url' => get_path_pages_url, :disabled => @page.index? || @page.not_found? }, :wrapper_html => { :style => "#{'display: none' if @page.templatized?};", :class => 'em-inline-hints' } + = f.input :slug, :required => false, :hint => @page.slug.blank? ? t('.empty_slug') : public_page_url(@page), :input_html => { :'data-url' => get_path_pages_url, :disabled => @page.index? || @page.not_found? }, :wrapper_html => { :style => "#{'display: none' if @page.templatized? && !@page.templatized_from_parent?};", :class => 'em-inline-hints' } = f.inputs :name => :seo, :class => "inputs foldable #{'folded' if inputs_folded?(@page)}" do @@ -34,9 +34,9 @@ = f.input :response_type, :as => :select, :collection => options_for_page_response_type, :include_blank => false - = f.input :templatized, :as => :'Locomotive::Toggle', :style => "#{'display: none' if @page.redirect?}" + = f.input :templatized, :as => :'Locomotive::Toggle', :style => "#{'display: none' if @page.redirect? || @page.templatized_from_parent?}" - = f.input :target_klass_name, :as => :select, :collection => options_for_target_klass_name, :include_blank => false, :wrapper_html => { :style => "#{'display: none' unless @page.templatized?}" } + = f.input :target_klass_name, :as => :select, :collection => options_for_target_klass_name, :include_blank => false, :wrapper_html => { :style => "#{'display: none' unless @page.templatized? && !@page.templatized_from_parent?}" } = f.input :published, :as => :'Locomotive::Toggle' diff --git a/lib/locomotive/middlewares/inline_editor.rb b/lib/locomotive/middlewares/inline_editor.rb index b1a812df..044e854f 100644 --- a/lib/locomotive/middlewares/inline_editor.rb +++ b/lib/locomotive/middlewares/inline_editor.rb @@ -16,7 +16,7 @@ module Locomotive 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;"> + style="display: block;z-index: 1031;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 ) diff --git a/lib/locomotive/version.rb b/lib/locomotive/version.rb index 34dd2ec2..69b7d30f 100644 --- a/lib/locomotive/version.rb +++ b/lib/locomotive/version.rb @@ -1,3 +1,3 @@ module Locomotive #:nodoc - VERSION = '2.0.0.rc2' + VERSION = '2.0.0.rc3' end diff --git a/spec/models/locomotive/page_spec.rb b/spec/models/locomotive/page_spec.rb index b62be49b..3f4faafd 100644 --- a/spec/models/locomotive/page_spec.rb +++ b/spec/models/locomotive/page_spec.rb @@ -203,12 +203,30 @@ describe Locomotive::Page do end + describe 'render module' do + + context '#path combinations' do + + it 'generates them for a path depth equals to 1' do + Locomotive::Page.path_combinations('foo').should == ['foo', 'content_type_template'] + end + + it 'generates them for a path depth equals to 2' do + Locomotive::Page.path_combinations('foo/bar').should == ['foo/bar', 'foo/content_type_template', 'content_type_template/bar'] + end + + it 'generates them for a path depth equals to 3' do + Locomotive::Page.path_combinations('foo/bar/baz').should == ['foo/bar/baz', 'foo/bar/content_type_template', 'foo/content_type_template/baz', 'content_type_template/bar/baz'] + end + + end + + end + describe 'templatized extension' do before(:each) do - @page = FactoryGirl.build(:page, :templatized => true, :target_klass_name => 'Foo') - # @page.stubs(:target_klass) - # Locomotive::ContentType.stubs(:find).returns(FactoryGirl.build(:content_type, :site => nil)) + @page = FactoryGirl.build(:page, :parent => Factory.build(:page, :templatized => false), :templatized => true, :target_klass_name => 'Foo') end it 'is considered as a templatized page' do @@ -233,6 +251,44 @@ describe Locomotive::Page do @page.fetch_target_entry('foo') end + context '#descendants' do + + before(:each) do + @home = FactoryGirl.create(:page) + @page.attributes = { :parent_id => @home._id, :site => @home.site }; @page.save! + @sub_page = FactoryGirl.build(:page, :title => 'Subpage', :slug => 'foo', :parent => @page, :site => @home.site, :templatized => false) + end + + it 'inherits the templatized property from its parent' do + @sub_page.valid? + @sub_page.templatized?.should be_true + @sub_page.templatized_from_parent?.should be_true + @sub_page.target_klass_name.should == 'Foo' + end + + it 'gets templatized if its parent is' do + @page.attributes = { :templatized => false, :target_klass_name => nil }; @page.save! + @sub_page.save.should be_true + @sub_page.templatized?.should be_false + + @page.attributes = { :templatized => true, :target_klass_name => 'Foo' }; @page.save! + @sub_page.reload + @sub_page.templatized?.should be_true + @sub_page.templatized_from_parent?.should be_true + @sub_page.target_klass_name.should == 'Foo' + end + + it 'is not templatized if its parent is no more a templatized page' do + @sub_page.save.should be_true + @page.templatized = false; @page.save! + @sub_page.reload + @sub_page.templatized.should be_false + @sub_page.templatized_from_parent.should be_false + @sub_page.target_klass_name.should be_nil + end + + end + context 'using a content type' do before(:each) do