templatized page + fix bug with nav widget

This commit is contained in:
dinedine 2010-07-16 22:36:07 +02:00
parent 56d7fddcfb
commit fb148a31a4
20 changed files with 177 additions and 21 deletions

View File

@ -7,6 +7,7 @@ class ContentInstance
include CustomFields::ProxyClassEnabler
## fields (dynamic fields) ##
field :_slug
field :_position_in_list, :type => Integer, :default => 0
## validations ##
@ -16,6 +17,7 @@ class ContentInstance
embedded_in :content_type, :inverse_of => :contents
## callbacks ##
before_save :set_slug
before_create :add_to_list_bottom
## named scopes ##
@ -29,16 +31,29 @@ class ContentInstance
protected
def set_slug
_alias = self.highlighted_field_alias
self._slug = self.send(_alias).parameterize('_')
end
def add_to_list_bottom
Rails.logger.debug "add_to_list_bottom"
self._position_in_list = self.content_type.contents.size
end
def require_highlighted_field
_alias = self.content_type.highlighted_field._alias.to_sym
_alias = self.highlighted_field_alias
if self.send(_alias).blank?
self.errors.add(_alias, :blank)
end
end
def highlighted_field_value
self.send(self.content_type.highlighted_field._name)
end
def highlighted_field_alias
self.content_type.highlighted_field._alias.to_sym
end
end

View File

@ -0,0 +1,32 @@
module Models
module Extensions
module Page
module Templatized
extend ActiveSupport::Concern
included do
belongs_to_related :content_type
field :templatized, :type => Boolean, :default => false
field :content_type_visible_column
before_validate :set_slug_if_templatized
end
module InstanceMethods
def set_slug_if_templatized
self.slug = 'content_type_template' if self.templatized?
end
end
end
end
end
end

View File

@ -6,6 +6,7 @@ class Page
include Models::Extensions::Page::Tree
include Models::Extensions::Page::Parts
include Models::Extensions::Page::Render
include Models::Extensions::Page::Templatized
## fields ##
field :title
@ -31,8 +32,8 @@ class Page
## named scopes ##
named_scope :latest_updated, :order_by => [[:updated_at, :desc]], :limit => Locomotive.config.lastest_items_nb
named_scope :index, :where => { :slug => 'index', :depth => 0, :published => true }
named_scope :not_found, :where => { :slug => '404', :depth => 0, :published => true }
named_scope :index, :where => { :slug => 'index', :depth => 0 }
named_scope :not_found, :where => { :slug => '404', :depth => 0 }
named_scope :published, :where => { :published => true }
## behaviours ##

View File

@ -11,7 +11,12 @@
- 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? ? ' ' : @page.url, :input_html => { :data_url => get_path_admin_pages_url, :disabled => @page.index? || @page.not_found? }
= f.input :slug, :required => false, :hint => @page.slug.blank? ? ' ' : @page.url, :input_html => { :data_url => get_path_admin_pages_url, :disabled => @page.index? || @page.not_found? }, :wrapper_html => { :style => "#{'display: none' if @page.templatized?}" }
= f.custom_input :templatized, :css => 'toggle' do
= f.check_box :templatized
= f.input :content_type_id, :as => :select, :collection => current_site.content_types.all.to_a, :include_blank => false, :wrapper_html => { :style => "#{'display: none' unless @page.templatized?}" }
= f.custom_input :published, :css => 'toggle' do
= f.check_box :published

View File

@ -1,4 +1,4 @@
%li{ :id => "item-#{page.id}", :class => "#{'not-found' if page.not_found? }"}
%li{ :id => "item-#{page.id}", :class => "#{'not-found' if page.not_found? } #{'templatized' if page.templatized?}"}
- if not page.index? and not page.children.empty?
= image_tag 'admin/list/icons/node_closed.png', :class => 'toggler'
%em

View File

@ -268,6 +268,7 @@ en:
page:
published: "Only authenticated accounts can view unpublished pages."
cache_strategy: "Cache the page for better performance. The 'Simple' choice is a good compromise."
templatized: "Use the page as a template for a model you defined."
snippet:
slug: "You need to know it in order to insert the snippet inside a page or a layout"
site:

View File

@ -290,6 +290,7 @@ fr:
page:
published: "Seuls les administrateurs authentifiés peuvent voir une page non publiée."
cache_strategy: "Cache la page pour de meilleure performance. L'option 'Simple' est le meilleur compromis."
templatized: "Utilise la page comme un template pour un modèle défini."
snippet:
slug: "Utilisé pour insérer le snippet dans une page ou un gabarit."
site:

View File

@ -2,7 +2,7 @@ BOARD:
- refactor slugify method (use parameterize + create a module)
- send email when new content added thru api
- page templatized (bound to a model)
- shortcut for jquery include tag
BACKLOG:
@ -62,3 +62,4 @@ x flash messages in French
x save layout / snippet / page / stylesheet / javascript with CMD + S (ajax)
x change action icons according to the right action [Sacha]
x publish event when saving form in ajax (for instance, in order to update account name or site name)
x page templatized (bound to a model)

View File

@ -11,7 +11,9 @@ module Locomotive
end
end
def highlighted_field_value
@source.highlighted_field_value
end
end
end

View File

@ -3,7 +3,15 @@ module Locomotive
module Drops
class Page < Base
liquid_attributes << :title << :slug
# liquid_attributes << :title << :slug
def title
@source.templatized? ? @context['content_instance'].highlighted_field_value : @source.title
end
def slug
@source.templatized? ? @source.content_type.slug.singularize : @source.slug
end
def children
@children ||= liquify(*@source.children)

View File

@ -29,10 +29,12 @@ module Locomotive
source = context.registers[@site_or_page.to_sym]
puts "#{@site_or_page.to_sym} / source = #{source.inspect}"
if source.respond_to?(:name) # site ?
source = source.pages.first # start from home page
source = source.pages.index.first # start from home page
else
source = source.parent
source = source.parent || source
end
output = %{<ul id="nav">}

View File

@ -23,9 +23,24 @@ module Locomotive
path.gsub!(/^\//, '')
path = 'index' if path.blank?
if page = current_site.pages.where(:fullpath => path).first
if path != 'index'
dirname = File.dirname(path).gsub(/^\.$/, '') # also look for templatized page path
path = [path, File.join(dirname, 'content_type_template').gsub(/^\//, '')]
end
# TODO: path is not correctly built + find content instance in order to render a 404 page if not found
if page = current_site.pages.any_in(:fullpath => [*path]).first
if not page.published? and current_admin.nil?
page = nil
else
if page.templatized?
@content_instance = page.content_type.contents.where(:_slug => File.basename(path.first)).first
if @content_instance.nil? # content instance not found
page = nil
end
end
end
end
@ -43,6 +58,11 @@ module Locomotive
'current_page' => self.params[:page]
}
if @page.templatized? # add instance from content type
assigns['content_instance'] = @content_instance
assigns[@page.content_type.slug.singularize] = @content_instance # just here to help to write readable liquid code
end
registers = { :controller => self, :site => current_site, :page => @page }
::Liquid::Context.new(assigns, registers)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -31,6 +31,19 @@ $(document).ready(function() {
}
});
// templatized feature
$.subscribe('toggle.page_templatized.checked', function(event, data) {
$('#page_slug_input').hide();
$('#page_content_type_id_input').show();
}, []);
$.subscribe('toggle.page_templatized.unchecked', function(event, data) {
$('#page_slug_input').show();
$('#page_slug').val(makeSlug($('#page_title').val())).addClass('touched');
$('#page_content_type_id_input').hide();
}, []);
// automatic slug from page title
$('#page_title').keypress(function() {
var input = $(this);

View File

@ -64,6 +64,8 @@
$(element).parent().css("background-color", settings.off_bg_color);
$(element).parent().parent().prev().removeAttr("checked");
$(element).removeClass("left").addClass("right");
$.publish('toggle.' + $(element).parent().parent().prev().attr('id') + '.unchecked', []);
});
}else{
@ -78,6 +80,7 @@
$(element).parent().parent().prev().attr("checked","checked");
$(element).removeClass("right").addClass("left");
$.publish('toggle.' + $(element).parent().parent().prev().attr('id') + '.checked', []);
});
}

View File

@ -117,7 +117,7 @@ ul.assets li.asset.last {
margin-right: 0px;
}
ul.assets li.asset h4 { margin: 0px; height: 30px; border-bottom: 1px solid #C2C4D2; }
ul.assets li.asset h4 { margin: 0px; height: 30px; border-bottom: 1px solid #ccced7; }
ul.assets li.asset h4 a {
position: relative;
@ -205,6 +205,11 @@ div#uploadAssetsInputQueue { display: none; }
cursor: move;
}
#pages-list ul.folder li.templatized em {
background-position: left -62px;
cursor: pointer;
}
#pages-list li .toggler {
position: absolute;
top: 9px;

View File

@ -80,7 +80,7 @@ form.formtastic fieldset.inputs ol {
padding-top: 15px;
padding-bottom: 5px;
background: #ebedf4 url(/images/admin/form/footer.png) no-repeat 0 bottom;
border-top: 1px solid #C2C4D2;
border-top: 1px solid #ccced7;
}
@media screen and (-webkit-min-device-pixel-ratio:0) {

View File

@ -2,7 +2,7 @@
background: #ebedf4 url(/images/admin/form/footer.png) no-repeat 0 bottom;
width: 880px;
padding: 20px 20px;
border-top: 1px solid #C2C4D2;
border-top: 1px solid #ccced7;
}
#page-parts {

View File

@ -52,19 +52,19 @@ describe 'Locomotive rendering system' do
it 'should retrieve the index page /' do
@controller.request.fullpath = '/'
@controller.current_site.pages.expects(:where).with({ :fullpath => 'index' }).returns([@page])
@controller.current_site.pages.expects(:any_in).with({ :fullpath => %w{index} }).returns([@page])
@controller.send(:locomotive_page).should_not be_nil
end
it 'should also retrieve the index page (index.html)' do
@controller.request.fullpath = '/index.html'
@controller.current_site.pages.expects(:where).with({ :fullpath => 'index' }).returns([@page])
@controller.current_site.pages.expects(:any_in).with({ :fullpath => %w{index} }).returns([@page])
@controller.send(:locomotive_page).should_not be_nil
end
it 'should retrieve it based on the full path' do
@controller.request.fullpath = '/about_us/team.html'
@controller.current_site.pages.expects(:where).with({ :fullpath => 'about_us/team' }).returns([@page])
@controller.current_site.pages.expects(:any_in).with({ :fullpath => %w{about_us/team about_us/content_type_template} }).returns([@page])
@controller.send(:locomotive_page).should_not be_nil
end
@ -74,6 +74,31 @@ describe 'Locomotive rendering system' do
@controller.send(:locomotive_page).should be_true
end
context 'templatized page' do
before(:each) do
@content_type = Factory.build(:content_type, :site => nil)
@page.templatized = true
@page.content_type = @content_type
@controller.request.fullpath = '/projects/edeneo.html'
@controller.current_site.pages.expects(:any_in).with({ :fullpath => %w{projects/edeneo projects/content_type_template} }).returns([@page])
end
it 'sets the content_instance variable' do
@content_type.contents.stubs(:where).returns([42])
@controller.send(:locomotive_page).should_not be_nil
@controller.instance_variable_get(:@content_instance).should == 42
end
it 'returns the 404 page if the instance does not exist' do
@content_type.contents.stubs(:where).returns([])
@controller.current_site.pages.expects(:not_found).returns([true])
@controller.send(:locomotive_page).should be_true
@controller.instance_variable_get(:@content_instance).should be_nil
end
end
context 'non published page' do
before(:each) do
@ -83,7 +108,7 @@ describe 'Locomotive rendering system' do
it 'should return the 404 page if the page has not been published yet' do
@controller.request.fullpath = '/contact'
@controller.current_site.pages.expects(:where).with({ :fullpath => 'contact' }).returns([@page])
@controller.current_site.pages.expects(:any_in).with({ :fullpath => %w{contact content_type_template} }).returns([@page])
@controller.current_site.pages.expects(:not_found).returns([true])
@controller.send(:locomotive_page).should be_true
end
@ -91,7 +116,7 @@ describe 'Locomotive rendering system' do
it 'should not return the 404 page if the page has not been published yet and admin is logged in' do
@controller.current_admin = true
@controller.request.fullpath = '/contact'
@controller.current_site.pages.expects(:where).with({ :fullpath => 'contact' }).returns([@page])
@controller.current_site.pages.expects(:any_in).with({ :fullpath => %w{contact content_type_template} }).returns([@page])
@controller.send(:locomotive_page).should == @page
end

View File

@ -333,4 +333,26 @@ describe Page do
end
end
describe 'templatized extension' do
before(:each) do
@page = Factory.build(:page, :site => nil, :templatized => true, :content_type_id => 42)
ContentType.stubs(:find).returns(Factory.build(:content_type, :site => nil))
end
it 'is considered as a templatized page' do
@page.templatized?.should be_true
end
it 'fills in the slug field' do
@page.valid?
@page.slug.should == 'content_type_template'
end
it 'does forget to set the content type id' do
@page.content_type_id.should == '42'
end
end
end