Permalink
Browse files

move the responibility of rendering the page menu to a module, allow …

…for overriding modules
  • Loading branch information...
1 parent 7545e24 commit 785456609bf076e0c464d751bf5bee2df83c6806 @saturnflyer saturnflyer committed Nov 5, 2011
@@ -2,6 +2,11 @@ module Admin::NodeHelper
def render_node(page, locals = {})
@current_node = page
+ page.extend MenuRenderer
+ page.view = self
+ if page.additional_menu_features?
+ page.extend(*page.menu_renderer_modules)
+ end
locals.reverse_merge!(:level => 0, :simple => false).merge!(:page => page)
render :partial => 'admin/pages/node', :locals => locals
end
@@ -10,48 +15,6 @@ def homepage
@homepage ||= Page.find_by_parent_id(nil)
end
- def clean_page_description(page)
- page.description.to_s.strip.gsub(/\t/,'').gsub(/\s+/,' ')
- end
-
- def child_link_for(page)
- case children_for(page).size
- when 0
- content_tag :span, image('plus_disabled') + ' ' + t('add_child'), :class => 'action disabled'
- when 1
- link_to image('plus') + ' ' + t('add_child'), new_admin_page_child_path(page, :page_class => children_for(page).first), :class => "action"
- else
- link_to image('plus') + ' ' + t('add_child'), "#allowed_children_#{page.id}", :class => "action dropdown"
- end
- end
-
- def child_menu_for(page)
- children = children_for(page)
- return nil if children.size < 2
- children.unshift(children.delete(page.default_child), :separator) if children.include?(page.default_child)
- name_for = proc { |p| (name = p.name.to_name('Page')).blank? ? t('normal_page') : name }
- content_tag :ul, :class => 'menu', :id => "allowed_children_#{page.id}" do
- children.map do |child|
- if child == :separator
- content_tag :li, nil, :class => 'separator'
- else
- content_tag :li, link_to(name_for[child], new_admin_page_child_path(page, :page_class => child), :title => clean_page_description(child))
- end
- end.flatten.join('')
- end
- end
-
- def children_for(page)
- page.allowed_children
- end
-
- def children_for_with_roles(page)
- children = children_for_without_roles(page)
- children.reject! { |p| p.new.virtual? } unless admin?
- children
- end
- alias_method_chain :children_for, :roles
-
def show_all?
@controller.action_name == 'remove'
end
View
@@ -0,0 +1,133 @@
+module MenuRenderer
+
+ def exclude(*type_names)
+ @excluded_class_names ||= []
+ @excluded_class_names.concat(type_names).uniq!
+ end
+ module_function :exclude
+
+ def excluded_class_names
+ MenuRenderer.instance_variable_get(:@excluded_class_names)
+ end
+
+ module_function :excluded_class_names
+ public :excluded_class_names
+
+ def view=(val)
+ @view = val
+ end
+
+ def view
+ @view
+ end
+
+ def additional_menu_features?
+ @additional_menu_features ||= (menu_renderer_module_name != 'MenuRenderer' && Object.const_defined?(menu_renderer_module_name))
+ end
+
+ def menu_renderer_module_name
+ simple_name = self.class_name.to_s.sub('Page','')
+ "#{simple_name}MenuRenderer"
+ end
+
+ def menu_renderer_modules
+ [Object.const_get(menu_renderer_module_name)]
+ end
+
+ def allowed_child_classes
+ (allowed_children_cache.split(',') - Array(excluded_class_names)).map(&:constantize)
+ end
+
+ def default_child_item
+ menu_item(default_child)
+ end
+
+ def separator_item
+ view.content_tag :li, '', :class => 'separator'
+ end
+
+ def child_items
+ (allowed_child_classes - [self.class.default_child]).map do |child|
+ menu_item(child)
+ end
+ end
+
+ def menu_items
+ [default_child_item, separator_item] + child_items
+ end
+
+ def menu_list
+ view.content_tag :ul, menu_items.to_s, :class => 'menu', :id => "allowed_children_#{id}"
+ end
+
+ def remove_link
+ view.link_to view.image('minus') + ' ' + I18n.t('remove'), view.remove_admin_page_url(self), :class => "action"
+ end
+
+ def remove_option
+ remove_link
+ end
+
+ def add_child_disabled?
+ allowed_child_classes.size == 0
+ end
+
+ def disabled_add_child_link
+ view.content_tag :span, view.image('plus_disabled') + ' ' + I18n.t('add_child'), :class => 'action disabled'
+ end
+
+ def add_child_link
+ view.link_to view.image('plus') + ' ' + I18n.t('add_child'), view.new_admin_page_child_path(self, :page_class => default_child.name), :class => "action"
+ end
+
+ def add_child_link_with_menu_hook
+ view.link_to view.image('plus') + ' ' + I18n.t('add_child'), "#allowed_children_#{id}", :class => "action dropdown"
+ end
+
+ def add_child_menu
+ menu_list.to_s
+ end
+
+ def add_child_link_with_menu
+ add_child_link_with_menu_hook + add_child_menu
+ end
+
+ def add_child_option
+ if add_child_disabled?
+ disabled_add_child_link
+ else
+ if allowed_child_classes.size == 1
+ add_child_link
+ else
+ add_child_link_with_menu
+ end
+ end
+ end
+
+ private
+
+ def clean_page_description(page_class)
+ page_class.description.to_s.strip.gsub(/\t/,'').gsub(/\s+/,' ')
+ end
+
+ def menu_item(child_class)
+ view.content_tag :li, menu_link(child_class)
+ end
+
+ def menu_link(child_class)
+ title = clean_page_description(child_class)
+ path = view.new_admin_page_child_path(self, :page_class => child_class.name)
+ text = link_text_for_child_class(child_class.name)
+ view.link_to text, path, :title => title
+ end
+
+ def link_text_for_child_class(class_name)
+ translation_key = if class_name == 'Page' || class_name.blank?
+ 'normal_page'
+ else
+ class_name.sub('Page','').underscore
+ end
+ fallback = class_name == 'Page' ? 'Page' : class_name.sub('Page','').titleize
+ I18n.t(translation_key, :default => fallback)
+ end
+end
View
@@ -38,8 +38,6 @@ def initialize(message = 'Database missing root page'); super end
annotate :description
attr_accessor :request, :response, :pagination_parameters
- class_inheritable_accessor :in_menu
- self.in_menu = true
class_inheritable_accessor :default_child
self.default_child = self
@@ -209,23 +207,15 @@ def default_child
self.class.default_child
end
- def allowed_children
- return @allowed_children if @allowed_children
- set_allowed_children_cache if allowed_children_cache.blank?
- @allowed_children = allowed_children_cache.split(',').uniq.map(&:constantize)
- end
-
def allowed_children_lookup
- [default_child, *Page.descendants.sort_by(&:name)].select(&:in_menu?).uniq
+ [default_child, *Page.descendants.sort_by(&:name)].uniq
end
def set_allowed_children_cache
self.allowed_children_cache = allowed_children_lookup.collect(&:name).join(',')
end
class << self
- alias_method :in_menu?, :in_menu
- alias_method :in_menu, :in_menu=
def root
find_by_parent_id(nil)
@@ -17,10 +17,10 @@
- node.actions_column do
- unless simple
%td.actions
- = child_link_for(page)
- = link_to image('minus') + ' ' + t('remove'), remove_admin_page_url(page), :class => "action"
- = child_menu_for(page)
+ = page.add_child_option
+ = page.remove_option
- if expanded
- page.children.each do |child|
+ - child.becomes(child.class_name.constantize) if child.class_name.present?
= render_node child, :level => level + 1, :simple => simple
@@ -17,27 +17,17 @@ Feature: Managing pages
Scenario: Creating a homepage
Given I am logged in as "existing"
- Given there are no pages
- When I go to the "pages" admin page
- And I follow "New Homepage"
- Then I should see "New Page"
- And there should be a "body" part
- And there should be an "extended" part
- When I fill in "Page Title" with "My site"
- And I fill in "Slug" with "/"
- And I fill in "Breadcrumb" with "My site"
- And I fill in the "body" content with "Under Construction"
- And I fill in the "extended" content with "foobar"
- And I select "Published" from "Status"
- And I press "Create page"
+ And there are no pages
+ And I create a homepage
Then I should be on the sitemap
And I should see "My site"
When I go to the homepage
Then I should see "Under Construction"
Scenario: Creating child pages
- Given there is a homepage
+ Given there are no pages
And I am logged in as "existing"
+ And I create a homepage
When I go to the "pages" admin page
And I follow "Add Child"
And I follow "Normal Page"
@@ -26,3 +26,20 @@
page = pages(name.to_sym)
visit "/admin/pages/#{page.id}/edit"
end
+
+Given /^I create a homepage$/ do
+ steps %Q{
+ When I go to the "pages" admin page
+ And I follow "New Homepage"
+ Then I should see "New Page"
+ And there should be a "body" part
+ And there should be an "extended" part
+ When I fill in "Page Title" with "My site"
+ And I fill in "Slug" with "/"
+ And I fill in "Breadcrumb" with "My site"
+ And I fill in the "body" content with "Under Construction"
+ And I fill in the "extended" content with "foobar"
+ And I select "Published" from "Status"
+ And I press "Create page"
+ }
+end
@@ -8,7 +8,7 @@
@errors = mock("errors")
helper.stub!(:cookies).and_return(@cookies)
helper.stub!(:homepage).and_return(nil)
- @page = mock_model(Page)
+ @page = mock_model(Page, :class_name => 'Page')
@page.stub!(:sheet?).and_return(false) # core extension alters the behavior
helper.stub!(:image).and_return('')
helper.stub!(:admin?).and_return(true)
@@ -107,54 +107,5 @@
helper.spinner
end
- describe "#child_link_for" do
- it "should disable the menu when there are no allowable children" do
- @page.stub!(:allowed_children).and_return([])
- helper.child_link_for(@page).should match('<span class="action disabled">')
- end
-
- it "should link to Page#new when there is one allowable child" do
- @page.stub!(:allowed_children).and_return([Page])
- helper.child_link_for(@page).should match(Regexp.escape(new_admin_page_child_path(@page, :page_class => 'Page')))
- end
-
- it "should show the menu when there are multiple allowable children" do
- @page.stub!(:allowed_children).and_return([Page,FileNotFoundPage])
- helper.child_link_for(@page).should match("#allowed_children_#{@page.id}")
- end
- end
-
- describe "#children_for" do
- it "should not show virtual pages to designers" do
- helper.stub!(:admin?).and_return(false)
- @page.stub!(:allowed_children).and_return([Page, ArchivePage, FileNotFoundPage])
- helper.children_for(@page).flatten.should_not include(FileNotFoundPage)
- end
- end
-
- describe '#clean_page_description' do
- it "should remove all whitespace (except single spaces) from the given page's description" do
- @page.stub!(:description).and_return(%{
- This is the description for the
- current page!
- })
- helper.clean_page_description(@page).should == 'This is the description for the current page!'
- end
- end
-
- describe '#child_menu_for' do
- it "should be empty if there are no options" do
- helper.stub!(:children_for).and_return([])
- helper.child_menu_for(@page).should be_nil
- end
-
- it "should list options if there are any" do
- helper.stub!(:children_for).and_return([Page, FileNotFoundPage])
- @page.stub!(:default_child).and_return(Page)
- menu = helper.child_menu_for(@page)
- menu.should match(/Normal Page/)
- end
- end
-
end
Oops, something went wrong.

2 comments on commit 7854566

Owner

johnmuhl replied Nov 5, 2011

Owner

saturnflyer replied Nov 6, 2011

Sorry. Working on this now.

Please sign in to comment.