From 210ce3d2d8e386ae07f1a8b551241916b960d372 Mon Sep 17 00:00:00 2001 From: dinedine Date: Sun, 2 Jan 2011 23:58:06 +0100 Subject: [PATCH] enhance the nav tag + some optimization in the back-office when rendering the pages tree --- app/controllers/admin/pages_controller.rb | 3 +- app/models/extensions/page/tree.rb | 60 +++++++++++++++++++ app/models/page.rb | 2 + app/models/site.rb | 4 ++ app/views/admin/pages/_page.html.haml | 6 +- .../admin/shared/menu/_contents.html.haml | 2 +- doc/TODO | 4 ++ lib/locomotive/liquid/drops/page.rb | 4 ++ lib/locomotive/liquid/tags/nav.rb | 38 ++++++++---- 9 files changed, 107 insertions(+), 16 deletions(-) diff --git a/app/controllers/admin/pages_controller.rb b/app/controllers/admin/pages_controller.rb index f1cb1339..3e0db0f8 100644 --- a/app/controllers/admin/pages_controller.rb +++ b/app/controllers/admin/pages_controller.rb @@ -6,7 +6,8 @@ module Admin respond_to :json, :only => [:update, :sort, :get_path] def index - @pages = current_site.pages.roots + # @pages = current_site.pages.roots.minimal_attributes + @pages = current_site.all_pages_in_once end def new diff --git a/app/models/extensions/page/tree.rb b/app/models/extensions/page/tree.rb index d4a934ad..c9da10bf 100644 --- a/app/models/extensions/page/tree.rb +++ b/app/models/extensions/page/tree.rb @@ -27,8 +27,68 @@ module Models alias :descendants :hacked_descendants end + module ClassMethods + + # Warning: used only in read-only + def quick_tree(site) + pages = site.pages.minimal_attributes.order_by([[:depth, :asc], [:position, :asc]]).to_a + + puts "pages size = #{pages.size}" + + tmp = [] + + while !pages.empty? + tmp << _quick_tree(pages.delete_at(0), pages) + end + + tmp + end + + def _quick_tree(current_page, pages) + puts "_build_tree [current_page = #{current_page.title}] / #{pages.size}" + i, children = 0, [] + + while !pages.empty? + puts "...#{i}" + page = pages[i] + + break if page.nil? + + if page.parent_id == current_page.id + page = pages.delete_at(i) + + children << _quick_tree(page, pages) + else + i += 1 + end + end + + current_page.instance_eval do + def children=(list); @children = list; end + def children; @children || []; end + end + + current_page.children = children + + puts "children size for #{current_page.title} = #{current_page.children.size}" + + current_page + end + + end + module InstanceMethods + def children? + self.class.where(self.parent_id_field => self.id).count + end + + def children_with_minimal_attributes + self.class.where(self.parent_id_field => self.id). + order_by(self.tree_order). + minimal_attributes + end + def sort_children!(ids) ids.each_with_index do |id, position| child = self.children.detect { |p| p._id == BSON::ObjectId(id) } diff --git a/app/models/page.rb b/app/models/page.rb index 19d03094..130a928b 100644 --- a/app/models/page.rb +++ b/app/models/page.rb @@ -40,6 +40,8 @@ class Page scope :index, :where => { :slug => 'index', :depth => 0 } scope :not_found, :where => { :slug => '404', :depth => 0 } scope :published, :where => { :published => true } + scope :fullpath, lambda { |fullpath| { :where => { :fullpath => fullpath } } } + scope :minimal_attributes, :only => %w(title slug fullpath position depth published templatized parent_id created_at updated_at) ## methods ## diff --git a/app/models/site.rb b/app/models/site.rb index d076d6c1..688a19a8 100644 --- a/app/models/site.rb +++ b/app/models/site.rb @@ -40,6 +40,10 @@ class Site ## methods ## + def all_pages_in_once + Page.quick_tree(self) + end + def domains=(array) array = [] if array.blank?; super(array) end diff --git a/app/views/admin/pages/_page.html.haml b/app/views/admin/pages/_page.html.haml index c90ad97d..7540a46a 100644 --- a/app/views/admin/pages/_page.html.haml +++ b/app/views/admin/pages/_page.html.haml @@ -1,5 +1,7 @@ %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? + - with_children = !page.children.empty? + + - if not page.index? and with_children = image_tag 'admin/list/icons/node_closed.png', :class => 'toggler' %em %strong= link_to truncate(page.title, :length => 80), edit_admin_page_url(page) @@ -11,6 +13,6 @@ - if not page.index? and not page.not_found? = link_to image_tag('admin/list/icons/trash.png'), admin_page_url(page), :class => 'remove', :confirm => t('admin.messages.confirm'), :method => :delete - - if not page.children.empty? + - if with_children %ul{ :id => "folder-#{page._id}", :class => "folder depth-#{(page.depth || 0) + 1}", :data_url => sort_admin_page_url(page), :style => "display: #{cookies["folder-#{page._id}"] || 'block'}" } = render page.children \ No newline at end of file diff --git a/app/views/admin/shared/menu/_contents.html.haml b/app/views/admin/shared/menu/_contents.html.haml index e9b1370e..81173748 100644 --- a/app/views/admin/shared/menu/_contents.html.haml +++ b/app/views/admin/shared/menu/_contents.html.haml @@ -5,7 +5,7 @@ .inner %h2!= t('admin.pages.index.lastest_items') %ul - - current_site.pages.latest_updated.each do |page| + - current_site.pages.latest_updated.minimal_attributes.each do |page| %li = link_to truncate(page.title, :length => 25), edit_admin_page_url(page) %span= time_ago_in_words(page.updated_at) diff --git a/doc/TODO b/doc/TODO index 87361836..09d295b5 100644 --- a/doc/TODO +++ b/doc/TODO @@ -8,6 +8,10 @@ x ruby 1.9.2: x DelayedJob not working x new version of Aloha-Editor x locomotive gem: test with staging +- nav tag: + - site | page | parent + - retrieve only important page information from mongodb +- published by default when importing pages BACKLOG: diff --git a/lib/locomotive/liquid/drops/page.rb b/lib/locomotive/liquid/drops/page.rb index f184bdc4..ea7e0e2c 100644 --- a/lib/locomotive/liquid/drops/page.rb +++ b/lib/locomotive/liquid/drops/page.rb @@ -19,6 +19,10 @@ module Locomotive @fullpath ||= @source.fullpath end + def depth + @source.depth + end + end end end diff --git a/lib/locomotive/liquid/tags/nav.rb b/lib/locomotive/liquid/tags/nav.rb index 957df4ad..aeb496d2 100644 --- a/lib/locomotive/liquid/tags/nav.rb +++ b/lib/locomotive/liquid/tags/nav.rb @@ -1,20 +1,22 @@ module Locomotive module Liquid module Tags - # Display the children pages of the site or the current page. If not precised, nav is applied on the current page. + # Display the children pages of the site, current page or the parent page. If not precised, nav is applied on the current page. # The html output is based on the ul/li tags. # # Usage: # # {% nav site %} => # + # {% nav site, no_wrapper: true, exclude: 'contact|about', id: 'main-nav' } + # class Nav < ::Liquid::Tag Syntax = /(#{::Liquid::Expression}+)?/ def initialize(tag_name, markup, tokens, context) if markup =~ Syntax - @site_or_page = $1 || 'page' + @source = ($1 || 'page').gsub(/"|'/, '') @options = {} markup.scan(::Liquid::TagAttributes) { |key, value| @options[key.to_sym] = value } @@ -29,15 +31,26 @@ module Locomotive def render(context) @current_page = context.registers[:page] - source = context.registers[@site_or_page.to_sym] - - if source.respond_to?(:name) # site ? - source = source.pages.index.first # start from home page + children = (case @source + when 'site' then context.registers[:site].pages.index.minimal_attributes.first # start from home page + when 'parent' then @current_page.parent || @current_page + when 'page' then @current_page else - source = source.parent || source + context.registers[:site].pages.fullpath(@source).minimal_attributes.first + end).children_with_minimal_attributes + + children_output = [] + + children.each_with_index do |p, index| + if include_page?(p) + css = '' + css = 'first' if index == 0 + css = 'last' if index == children.size - 1 + children_output << render_child_link(p, css) + end end - output = source.children.map { |p| include_page?(p) ? render_child_link(p) : '' }.join("\n") + output = children_output.join("\n") if @options[:no_wrapper] != 'true' output = %{} @@ -49,7 +62,7 @@ module Locomotive private def include_page?(page) - if page.templatized? + if page.templatized? || !page.published? false elsif @options[:exclude] (page.fullpath =~ @options[:exclude]).nil? @@ -58,14 +71,15 @@ module Locomotive end end - def render_child_link(page) - selected = @current_page._id == page._id ? ' on' : '' + def render_child_link(page, css) + # selected = @current_page._id == page._id ? ' on' : '' + selected = @current_page.fullpath =~ /^#{page.fullpath}/ ? ' on' : '' icon = @options[:icon] ? '' : '' label = %{#{icon if @options[:icon] != 'after' }#{page.title}#{icon if @options[:icon] == 'after' }} %{ -
  • +
  • #{label}
  • }.strip