Commit 5660d7f484561f9dc8ebcbe7c3ece71eac559b79

Authored by AntonioTerceiro
1 parent 8ea19a9c

r236@sede: terceiro | 2007-07-28 18:50:13 -0300

ActionItem0: checkpoint: walking forward with design plugin
 


git-svn-id: https://svn.colivre.coop.br/svn/noosfero/trunk@240 3f533792-8f58-4932-b0fe-aaf55b0a4547
vendor/plugins/design/init.rb
... ... @@ -14,7 +14,12 @@ class ActionController::Base
14 14  
15 15 @design_plugin_config = config
16 16  
  17 + def self.design_plugin_config
  18 + @design_plugin_config
  19 + end
  20 +
17 21 include Design
  22 + helper Design::Helper
18 23 end
19 24  
20 25 # declares this controller as a design editor, including in it all the
... ... @@ -23,6 +28,7 @@ class ActionController::Base
23 28 def self.design_editor(config = {})
24 29 self.design(config)
25 30 include Design::Editor
  31 + helper Design::Editor::Helper
26 32 end
27 33  
28 34 end
... ...
vendor/plugins/design/lib/design.rb
... ... @@ -13,7 +13,7 @@ module Design
13 13  
14 14 return data[:design] if data.has_key?(:design)
15 15  
16   - config = self.class.instance_variable_get("@design_plugin_config")
  16 + config = self.class.design_plugin_config
17 17  
18 18 if config.has_key?(:holder)
19 19 holder_variable_name = config[:holder]
... ...
vendor/plugins/design/lib/design/editor/helper.rb 0 → 100644
... ... @@ -0,0 +1,44 @@
  1 +module Design
  2 +
  3 + module Editor
  4 +
  5 + # defines helper methods for controllers that use +design_editor+
  6 + module Helper
  7 +
  8 + # draws the user interface for the design editor.
  9 + def design_display_editor()
  10 + # TODO: check this
  11 + raise NotImplementedError
  12 +
  13 + content = [content_tag(
  14 + :ul,[
  15 + content_tag(
  16 + :li,
  17 + select_template,
  18 + :class => 'select_template'
  19 + ),
  20 + content_tag(
  21 + :li,
  22 + select_theme,
  23 + :class => 'select_template'
  24 + ),
  25 + content_tag(
  26 + :li,
  27 + select_icon_theme,
  28 + :class => 'select_template'
  29 + ),
  30 + ].join("\n"),
  31 + :class => 'select_options'
  32 + ),
  33 + @ft_config[:boxes].map{ |box|
  34 + content_tag(:div, edit_blocks(box, main_content) , :id=>"box_#{box.number}")
  35 + }].join("\n")
  36 +
  37 + content = content_tag(:div, content, :id => 'flexible_template_edit_mode')
  38 + end
  39 +
  40 + end # END OF module Helper
  41 +
  42 + end # END OF module Editor
  43 +
  44 +end # END OF module Design
... ...
vendor/plugins/design/lib/design/helper.rb
1 1 module Design
  2 +
2 3 module Helper
3   - end
4   -end
  4 +
  5 + # proxies calls to controller's design method
  6 + def design
  7 + @controller.send(:design)
  8 + end
  9 +
  10 + ########################################################
  11 + # Boxes and Blocks related
  12 + ########################################################
  13 +
  14 + # Displays +content+ inside the design used by the controller. Normally
  15 + # you'll want use this method in your layout view, like this:
  16 + #
  17 + # <%= design_display(yield) %>
  18 + #
  19 + # +content+ will be put inside all the blocks which return +true+ in the
  20 + # Block.main? method.
  21 + #
  22 + # The number of boxes generated will be no larger than the maximum number
  23 + # supported by the template, which is indicated in its YAML description
  24 + # file.
  25 + #
  26 + # If not blocks are present (e.g. the design holder has no blocks yet),
  27 + # +content+ is returned right away.
  28 + def design_display(content = "")
  29 +
  30 + # no blocks. nothing to be done
  31 + return content if design.boxes.empty?
  32 +
  33 + # Generate all boxes of the current profile and considering the defined
  34 + # on template.
  35 +
  36 + design.boxes.map do |box|
  37 + content_tag(:div, design_display_blocks(box, content) , :id=>"box_#{box.number}")
  38 + end.join("\n")
  39 + end
  40 +
  41 + # Displays all the blocks in a box.
  42 + # <ul id="sort#{number of the box}">
  43 + # <li class="block_item_box_#{number of the box}" id="block_#{id of block}">
  44 + # </li>
  45 + # </ul>
  46 + #
  47 + def design_display_blocks(box, content = "")
  48 + blocks = box.blocks_sort_by_position
  49 + content_tag(:div,
  50 + blocks.map { |b|
  51 + content_tag(:div, b.main? ? content : self.send('list_content', b.content), :class =>"block_item_box_#{box.number}" , :id => "block_#{b.id}" )
  52 + }.join("\n"), :id => "frame_#{box.number}"
  53 + )
  54 + end
  55 +
  56 +
  57 + ########################################################
  58 + # Template
  59 + ########################################################
  60 + # Load all the javascript files of a existing template with the template_name passed as argument.
  61 + #
  62 + # The files loaded are in the path:
  63 + #
  64 + # 'public/templates/#{template_name}/javascripts/*'
  65 + #
  66 + # If a invalid template it's passed the default template is applied
  67 + def javascript_include_tag_for_template
  68 + template_javascript_dir = Dir.glob("#{RAILS_ROOT}/public/templates/#{@ft_config[:template]}/javascripts/*.js")
  69 +
  70 + return if template_javascript_dir.blank?
  71 +
  72 + parse_path(template_javascript_dir).map do |filename|
  73 + javascript_include_tag(filename)
  74 + end
  75 + end
  76 +
  77 + # Load all the css files of a existing template with the template_name passed as argument.
  78 + #
  79 + # The files loaded are in the path:
  80 + #
  81 + # 'public/templates/#{template_name}/stylesheets/*'
  82 + # If a invalid template it's passed the default template is applied
  83 + def stylesheet_link_tag_for_template
  84 + template_stylesheet_dir = Dir.glob("#{RAILS_ROOT}/public/templates/#{@ft_config[:template]}/stylesheets/*.css")
  85 +
  86 + if template_stylesheet_dir.blank?
  87 + flash[:notice] = _("There is no stylesheets in directory %s of template %s.") % [ template_stylesheet_dir, @ft_config[:template]]
  88 + return
  89 + end
  90 +
  91 + parse_path(template_stylesheet_dir).map do |filename|
  92 + stylesheet_link_tag(filename)
  93 + end
  94 + end
  95 +
  96 +
  97 + #################################################
  98 + #THEMES
  99 + #################################################
  100 +
  101 + # Load all the css files of a existing theme with the @ft_config[:theme] passed as argument in owner object.
  102 + #
  103 + # The files loaded are in the path:
  104 + #
  105 + # 'public/themes/#{theme_name}/*'
  106 + # If a invalid theme it's passed the 'default' theme is applied
  107 + def stylesheet_link_tag_for_theme
  108 + path = "#{RAILS_ROOT}/public/themes/#{@ft_config[:theme]}/"
  109 + theme_dir = Dir.glob(path+"*")
  110 +
  111 + return if theme_dir.blank?
  112 +
  113 + parse_path(theme_dir).map do |filename|
  114 + stylesheet_link_tag(filename)
  115 + end
  116 +
  117 + end
  118 +
  119 +
  120 + #Display a given icon passed as argument
  121 + #The icon path should be '/icons/{icon_theme}/{icon_image}'
  122 + def display_icon(icon, options = {})
  123 + image_tag("/icons/#{@ft_config[:icon_theme]}/#{icon}.png", options)
  124 + end
  125 +
  126 + private
  127 +
  128 +
  129 + # Check if the current controller is the controller that allows layout editing
  130 + def edit_mode?
  131 + controller.flexible_template_edit_template?
  132 + end
  133 +
  134 + def parse_path(files_path = [], remove_until = 'public')
  135 + remove_until = remove_until.gsub(/\//, '\/')
  136 + files_path.map{|f| f.gsub(/.*#{remove_until}/, '')}
  137 + end
  138 +
  139 +
  140 + end # END SHOW TEMPLATE HELPER
  141 +
  142 + module EditTemplateHelper
  143 +
  144 +
  145 + # Symbol dictionary used on select when we add or edit a block.
  146 + # This method has the responsability of translate a Block class in a humam name
  147 + # By default the class "MainBlock" has the human name "Main Block". Other classes
  148 + # defined by user are not going to display in a human name format until de method
  149 + # flexible_template_block_dict be redefined in a controller by user
  150 +
  151 +#TODO define the method flexible_template_block_dict if not defined by helper
  152 +# if !self.public_instance_methods.include? "flexible_template_block_dict"
  153 +# define_method('flexible_template_block_dict') do |str|
  154 +# {
  155 +# 'MainBlock' => _("Main Block")
  156 +# }[str] || str
  157 +# end
  158 +# end
  159 +
  160 +
  161 + def flexible_template_block_helper_dict(str)
  162 + {
  163 + 'plain_content' => _('Plain Content') ,
  164 + 'list_content' => _('List Content')
  165 + }[str] || str
  166 + end
  167 +
  168 +
  169 + private
  170 +
  171 + #################################################
  172 + # TEMPLATES METHODS RELATED
  173 + #################################################
  174 +
  175 + # Shows the blocks as defined in <tt>show_blocks</tt> adding the sortable and draggable elements.
  176 + # In this case the layout can be manipulated
  177 + def edit_blocks(box, main_content = "")
  178 + blocks = box.blocks_sort_by_position
  179 + [
  180 + content_tag(
  181 + :ul,[
  182 + box.name,
  183 + link_to_active_sort(box),
  184 + link_to_add_block(box),
  185 + blocks.map {|b|
  186 + [content_tag(
  187 + :li,
  188 + b.name + link_to_destroy_block(b),
  189 + :class =>"block_item_box_#{box.number}" , :id => "block_#{b.id}"
  190 + ),
  191 + draggable("block_#{b.id}")].join("\n")
  192 + }.join("\n")].join("\n"), :id => "sort_#{box.number}"
  193 + ),
  194 + drag_drop_items(box)].join("\n")
  195 + end
  196 +
  197 + def link_to_active_sort(box)
  198 + link_to_remote(_('Sort'),
  199 + {:update => "sort_#{box.number}", :url => {:action => 'flexible_template_set_sort_mode', :box_id => box.id }},
  200 + :class => 'sort_button')
  201 + end
  202 +
  203 + def link_to_add_block(box)
  204 + link_to_remote(_('Add Block'),
  205 + {:update => "sort_#{box.number}", :url => {:action => 'flexible_template_new_block', :box_id => box.id }},
  206 + :class => 'add_block_button')
  207 + end
  208 +
  209 + def link_to_destroy_block(block)
  210 + link_to_remote(_('Remove'),
  211 + {:update => "sort_#{block.box.number}", :url => {:action => 'flexible_template_destroy_block', :block_id => block.id }},
  212 + :class => 'destroy_block_button')
  213 + end
  214 +
  215 +
  216 + # Allows the biven box to have sortable elements
  217 + def sortable_block(box_number)
  218 + sortable_element "sort_#{box_number}",
  219 + :url => {:action => 'flexible_template_sort_box', :box_number => box_number },
  220 + :complete => visual_effect(:highlight, "sort_#{box_number}")
  221 + end
  222 +
  223 + # Allows an element item to be draggable
  224 + def draggable(item)
  225 + draggable_element(item, :ghosting => true, :revert => true)
  226 + end
  227 +
  228 + # Allows an draggable element change between diferrents boxes
  229 + def drag_drop_items(box)
  230 + boxes = @ft_config[:boxes].reject{|b| b.id == box.id}
  231 +
  232 + boxes.map{ |b|
  233 + drop_receiving_element("box_#{box.number}",
  234 + :accept => "block_item_box_#{b.number}",
  235 + :complete => "$('spinner').hide();",
  236 + :before => "$('spinner').show();",
  237 + :hoverclass => 'hover',
  238 + :with => "'block=' + encodeURIComponent(element.id.split('_').last())",
  239 + :url => {:action=>:flexible_template_change_box, :box_id => box.id})
  240 + }.to_s
  241 + end
  242 +
  243 +
  244 + # Generate a select option to choose one of the available templates.
  245 + # The available templates are those in 'public/templates'
  246 + def select_template
  247 + available_templates = @ft_config[:available_templates]
  248 +
  249 + template_options = options_for_select(available_templates.map{|template| [template, template] }, @ft_config[:template])
  250 + [ select_tag('template_name', template_options ),
  251 + change_template].join("\n")
  252 + end
  253 +
  254 + # Generate a observer to reload a page when a template is selected
  255 + def change_template
  256 + observe_field( 'template_name',
  257 + :url => {:action => 'set_default_template'},
  258 + :with =>"'template_name=' + escape(value) + '&object_id=' + escape(#{@ft_config[:owner].id})",
  259 + :complete => "document.location.reload();"
  260 + )
  261 + end
  262 +
  263 + def available_blocks
  264 +#TODO check if are valids blocks
  265 + h = {
  266 + 'MainBlock' => _("Main Block"),
  267 + }
  268 + h.merge!(controller.class::FLEXIBLE_TEMPLATE_AVAILABLE_BLOCKS) if controller.class.constants.include? "FLEXIBLE_TEMPLATE_AVAILABLE_BLOCKS"
  269 + h
  270 + end
  271 +
  272 + def block_helpers
  273 +#TODO check if are valids helpers
  274 + h = {
  275 + 'plain_content' => _("Plain Content"),
  276 + 'list_content' => _("Simple List Content"),
  277 + }
  278 + h.merge!(controller.class::FLEXIBLE_TEMPLATE_BLOCK_HELPER) if controller.class.constants.include? "FLEXIBLE_TEMPLATE_BLOCK_HELPER"
  279 + h
  280 + end
  281 +
  282 + def new_block_form(box)
  283 + type_block_options = options_for_select(available_blocks.collect{|k,v| [v,k] })
  284 + type_block_helper_options = options_for_select(block_helpers.collect{|k,v| [v,k] })
  285 + @block = Block.new
  286 + @block.box = box
  287 +
  288 + _("Adding block on %s") % box.name +
  289 + [
  290 + form_remote_tag(:url => {:action => 'flexible_template_create_block'}, :update => "sort_#{box.number}"),
  291 + hidden_field('block', 'box_id'),
  292 + content_tag(
  293 + :p,
  294 + [
  295 + content_tag(
  296 + :label, _('Name:')
  297 + ),
  298 + text_field('block', 'name')
  299 + ].join("\n")
  300 + ),
  301 + content_tag(
  302 + :p,
  303 + [
  304 + content_tag(
  305 + :label, _('Title:')
  306 + ),
  307 + text_field('block', 'title')
  308 + ].join("\n")
  309 + ),
  310 + content_tag(
  311 + :p,
  312 + [
  313 + content_tag(
  314 + :label, _('Type:')
  315 + ),
  316 + select_tag('block[type]', type_block_options)
  317 + ].join("\n")
  318 + ),
  319 + content_tag(
  320 + :p,
  321 + [
  322 + content_tag(
  323 + :label, _('Visualization Mode:')
  324 + ),
  325 + select_tag('block[helper]', type_block_helper_options)
  326 + ].join("\n")
  327 + ),
  328 + submit_tag( _('Submit')),
  329 + end_form_tag
  330 + ].join("\n")
  331 +
  332 + end
  333 +
  334 + # Generate a select option to choose one of the available themes.
  335 + # The available themes are those in 'public/themes'
  336 + def select_theme
  337 + available_themes = @ft_config[:available_themes]
  338 + theme_options = options_for_select(available_themes.map{|theme| [theme, theme] }, @ft_config[:theme])
  339 + [ select_tag('theme_name', theme_options ),
  340 + change_theme].join("\n")
  341 + end
  342 +
  343 + # Generate a observer to reload a page when a theme is selected
  344 + def change_theme
  345 + observe_field( 'theme_name',
  346 + :url => {:action => 'set_default_theme'},
  347 + :with =>"'theme_name=' + escape(value) + '&object_id=' + escape(#{@ft_config[:owner].id})",
  348 + :complete => "document.location.reload();"
  349 + )
  350 + end
  351 +
  352 +
  353 + #################################################
  354 + #ICONS THEMES RELATED
  355 + #################################################
  356 +
  357 + # Generate a select option to choose one of the available icons themes.
  358 + # The available icons themes are those in 'public/icons'
  359 + def select_icon_theme
  360 + available_icon_themes = @ft_config[:available_icon_themes]
  361 + icon_theme_options = options_for_select(available_icon_themes.map{|icon_theme| [icon_theme, icon_theme] }, @ft_config[:icon_theme])
  362 + [ select_tag('icon_theme_name', icon_theme_options ),
  363 + change_icon_theme].join("\n")
  364 + end
  365 +
  366 + # Generate a observer to reload a page when a icons theme is selected
  367 + def change_icon_theme
  368 + observe_field( 'icon_theme_name',
  369 + :url => {:action => 'set_default_icon_theme'},
  370 + :with =>"'icon_theme_name=' + escape(value) + '&object_id=' + escape(#{@ft_config[:owner].id})",
  371 + :complete => "document.location.reload();"
  372 + )
  373 + end
  374 +
  375 +
  376 + end # END OF module HElper
  377 +
  378 +
  379 +end #END OF module Design
... ...
vendor/plugins/design/lib/design/main_block.rb
... ... @@ -5,8 +5,6 @@ module Design
5 5 # calling +yield+ inside a regular view.
6 6 class MainBlock < Block
7 7  
8   - set_table_name
9   -
10 8 # always returns true
11 9 def main?
12 10 true
... ...
vendor/plugins/design/test/design_helper_test.rb 0 → 100644
... ... @@ -0,0 +1,37 @@
  1 +require File.join(File.dirname(__FILE__), 'test_helper')
  2 +
  3 +class DesignHelperTestController < ActionController::Base
  4 +
  5 + box1 = Design::Box.new(:number => 1)
  6 + box2 = Design::Box.new(:number => 2)
  7 + box2.blocks << Design::MainBlock.new
  8 + box3 = Design::Box.new(:number => 3)
  9 +
  10 + design :fixed => {
  11 + :template => 'default',
  12 + :theme => 'default',
  13 + :icon_theme => 'default',
  14 + :boxes => [ box1, box2, box3 ],
  15 + }
  16 +
  17 + def index
  18 + render :inline => '<%= design_display("my content") %>'
  19 + end
  20 +end
  21 +
  22 +class DesignHelperTest < Test::Unit::TestCase
  23 +
  24 + def setup
  25 + @controller = DesignHelperTestController.new
  26 + @request = ActionController::TestRequest.new
  27 + @response = ActionController::TestResponse.new
  28 + end
  29 +
  30 + def test_should_generate_template
  31 + get :index
  32 + assert_tag :tag => 'div', :attributes => { :id => 'box_1' }
  33 + assert_tag :tag => 'div', :attributes => { :id => 'box_2' }
  34 + assert_tag :tag => 'div', :attributes => { :id => 'box_3' }
  35 + end
  36 +
  37 +end
... ...
vendor/plugins/design/test/design_test.rb
... ... @@ -27,4 +27,8 @@ class DesignTest &lt; Test::Unit::TestCase
27 27 end
28 28 end
29 29  
  30 + def test_should_expose_config_passed_to_design_class_method
  31 + assert_kind_of Hash, FixedDesignTestController.design_plugin_config
  32 + end
  33 +
30 34 end
... ...
vendor/plugins/design/test/test_helper.rb
... ... @@ -30,6 +30,7 @@ class FixedDesignTestController &lt; ActionController::Base
30 30  
31 31 BOX1 = Design::Box.new
32 32 BOX2 = Design::Box.new
  33 + BOX2.blocks << Design::MainBlock.new
33 34 BOX3 = Design::Box.new
34 35  
35 36 design :fixed => {
... ...