Commit b2833502d0184d05a577d9544379302412dc38f8
1 parent
7707a13c
Exists in
master
and in
23 other branches
ActionItem158: a better CMS
git-svn-id: https://svn.colivre.coop.br/svn/noosfero/trunk@1790 3f533792-8f58-4932-b0fe-aaf55b0a4547
Showing
8 changed files
with
170 additions
and
63 deletions
Show diff stats
app/controllers/my_profile/cms_controller.rb
| ... | ... | @@ -19,12 +19,14 @@ class CmsController < MyProfileController |
| 19 | 19 | |
| 20 | 20 | def view |
| 21 | 21 | @article = profile.articles.find(params[:id]) |
| 22 | - @subitems = @article.children | |
| 22 | + @subitems = @article.children.reject {|item| item.folder? } | |
| 23 | + @folders = @article.children.select {|item| item.folder? } | |
| 23 | 24 | end |
| 24 | 25 | |
| 25 | 26 | def index |
| 26 | 27 | @article = nil |
| 27 | - @subitems = profile.top_level_articles | |
| 28 | + @subitems = profile.top_level_articles.reject {|item| item.folder? } | |
| 29 | + @folders = profile.top_level_articles.select {|item| item.folder?} | |
| 28 | 30 | render :action => 'view' |
| 29 | 31 | end |
| 30 | 32 | |
| ... | ... | @@ -35,7 +37,7 @@ class CmsController < MyProfileController |
| 35 | 37 | if request.post? |
| 36 | 38 | @article.last_changed_by = user |
| 37 | 39 | if @article.update_attributes(params[:article]) |
| 38 | - redirect_to :action => 'view', :id => @article.id | |
| 40 | + redirect_back | |
| 39 | 41 | return |
| 40 | 42 | end |
| 41 | 43 | end |
| ... | ... | @@ -78,7 +80,7 @@ class CmsController < MyProfileController |
| 78 | 80 | @article.last_changed_by = user |
| 79 | 81 | if request.post? |
| 80 | 82 | if @article.save |
| 81 | - redirect_to :action => 'view', :id => @article.id | |
| 83 | + redirect_back | |
| 82 | 84 | return |
| 83 | 85 | end |
| 84 | 86 | end |
| ... | ... | @@ -102,5 +104,15 @@ class CmsController < MyProfileController |
| 102 | 104 | redirect_to :action => (@article.parent ? 'view' : 'index'), :id => @article.parent |
| 103 | 105 | end |
| 104 | 106 | |
| 107 | + protected | |
| 108 | + | |
| 109 | + def redirect_back | |
| 110 | + if @article.parent | |
| 111 | + redirect_to :action => 'view', :id => @article.parent | |
| 112 | + else | |
| 113 | + redirect_to :action => 'index' | |
| 114 | + end | |
| 115 | + end | |
| 116 | + | |
| 105 | 117 | end |
| 106 | 118 | ... | ... |
app/models/article.rb
| ... | ... | @@ -112,6 +112,10 @@ class Article < ActiveRecord::Base |
| 112 | 112 | true |
| 113 | 113 | end |
| 114 | 114 | |
| 115 | + def folder? | |
| 116 | + false | |
| 117 | + end | |
| 118 | + | |
| 115 | 119 | def self.find_by_initial(initial) |
| 116 | 120 | self.find(:all, :order => 'articles.name', :conditions => [ 'articles.name like (?) or articles.name like (?)', initial + '%', initial.upcase + '%']) |
| 117 | 121 | end | ... | ... |
app/models/folder.rb
app/views/cms/edit.rhtml
| ... | ... | @@ -16,6 +16,11 @@ |
| 16 | 16 | %> |
| 17 | 17 | |
| 18 | 18 | <% button_bar do %> |
| 19 | - <%= submit_button('save', _('Save'), :cancel => (@article.parent ? { :action => 'view', :id => @article.parent.id } : { :action => 'index' } )) %> | |
| 19 | + <%= submit_button :save, _('Save') %> | |
| 20 | + <% if @parent_id || @article.parent %> | |
| 21 | + <%= button :cancel, _('Cancel'), :action => 'view', :id => @parent_id || @article.parent %> | |
| 22 | + <% else %> | |
| 23 | + <%= button :cancel, _('Cancel'), :action => 'index' %> | |
| 24 | + <% end %> | |
| 20 | 25 | <% end %> |
| 21 | 26 | <% end %> | ... | ... |
app/views/cms/view.rhtml
| ... | ... | @@ -9,68 +9,59 @@ |
| 9 | 9 | <%= icon('cms') %> |
| 10 | 10 | <%= _('Content management') %> |
| 11 | 11 | </h2> |
| 12 | - | |
| 13 | - <% button_bar(:style => 'margin-bottom: 1em;') do %> | |
| 14 | - <%= lightbox_button('new', _('New article'), :action => 'new') %> | |
| 15 | - <% end %> | |
| 16 | - | |
| 17 | 12 | <% end %> |
| 18 | 13 | |
| 19 | -<%# subitem %> | |
| 20 | -<% if !@subitems.empty? && @article %> | |
| 21 | - <%= toggle_panel(_('Hide subitems'), _('Show subitems'), 'article-subitems') %> | |
| 14 | +<% button_bar(:style => 'margin-bottom: 1em;') do %> | |
| 15 | + <% parent_id = ((@article && @article.allow_children?) ? @article : nil) %> | |
| 16 | + <%= button :add, _('New folder'), :action => 'new', :type => 'Folder', :parent_id => parent_id %> | |
| 17 | + <%= lightbox_button('new', _('New article'), :action => 'new', :parent_id => parent_id) %> | |
| 22 | 18 | <% end %> |
| 23 | - | |
| 24 | -<div id='article-subitems'> | |
| 25 | - <div class='file-manager-title'><%= @article ? _('Subitems') : _('Articles') %></div> | |
| 26 | - <div class='file-manager-small'> | |
| 27 | - <% unless @subitems.empty? %> | |
| 28 | - <ul> | |
| 29 | - <% @subitems.each do |item| %> | |
| 30 | - <li> | |
| 31 | - <%= file_manager_button(item.name, icon_for_article(item), :action => 'view', :id => item.id) %> | |
| 32 | - </li> | |
| 33 | - <% end %> | |
| 34 | - </ul> | |
| 35 | - <% end %> | |
| 36 | 19 | |
| 37 | - <% if @article %> | |
| 38 | - <% button_bar(:class => 'file-manager-controls') do %> | |
| 39 | - <% if @article.allow_children? %> | |
| 40 | - <%= lightbox_button('new', _('New subitem'), :action => 'new', :parent_id => @article.id) %> | |
| 41 | - <% end %> | |
| 42 | - <%= button('up', _('Go up one level'), :action => (@article.parent ? 'view' : 'index'), :id => @article.parent) %> | |
| 43 | - <% end %> | |
| 44 | - <% end %> | |
| 45 | - </div> | |
| 46 | -</div> <!-- article-children --> | |
| 20 | +<table width='100%'> | |
| 47 | 21 | |
| 48 | -<%# display the article content %> | |
| 49 | -<div id='article-contents' style='clear: left;'> | |
| 50 | - <% if @article %> | |
| 51 | - <h2> | |
| 52 | - <%= @article.name %> | |
| 53 | - <%= image_tag(icon_for_article(@article)) %> | |
| 54 | - </h2> | |
| 55 | - <% button_bar(:id => 'article-controls') do %> | |
| 56 | - | |
| 57 | - <ul> | |
| 58 | - <li> | |
| 59 | - <%= _('"%{article}", last changed by %{author}') % { :article => @article.name, :author => (@article.last_changed_by ? @article.last_changed_by.name : _('Unknown User')) } %> | |
| 60 | - </li> | |
| 61 | - <li> | |
| 62 | - <%= _('Public address of this article: %s') % link_to(url_for(@article.url), @article.url) %> | |
| 63 | - </li> | |
| 64 | - <li> | |
| 65 | - <%= _('Tags:') %> <%= @article.tag_list %> | |
| 66 | - </li> | |
| 67 | - <%= _('Categories:') %> <%= @article.categories.map { |item| item.name }.join(', ') %> | |
| 68 | - </ul> | |
| 22 | + <%# folders %> | |
| 23 | + <tr> | |
| 24 | + <th colspan='2'> | |
| 25 | + <%= _('Folders') %> | |
| 26 | + </th> | |
| 27 | + </tr> | |
| 28 | + <% if @folders.empty? %> | |
| 29 | + <tr><td colspan='2' align='center'><em><%= _('None') %></em></td></tr> | |
| 30 | + <% end %> | |
| 31 | + <% for folder in @folders %> | |
| 32 | + <tr> | |
| 33 | + <td> | |
| 34 | + <%= image_tag(icon_for_article(folder)) %> | |
| 35 | + <%= link_to folder.name, :action => 'view', :id => folder.id %> | |
| 36 | + </td> | |
| 37 | + <td> | |
| 38 | + <%= link_to _('Properties'), :action => 'edit', :id => folder.id %> | |
| 39 | + <%= link_to _('View'), folder.url %> | |
| 40 | + </td> | |
| 41 | + </tr> | |
| 42 | + <% end %> | |
| 69 | 43 | |
| 70 | - <%= button('edit', _('Edit'), { :action => 'edit', :id => @article}) %> | |
| 71 | - <%= button('home', _('Use as homepage'), { :action => 'set_home_page', :id => @article }, { :method => :post }) %> | |
| 72 | - <%= button('delete', _('Delete'), { :action => 'destroy', :id => @article }, :method => :post, :confirm => _('Are you sure you wan to remove this article?')) %> | |
| 73 | - <% end %> | |
| 74 | - <%= @article.to_html %> | |
| 44 | + <%# non-folder subitems %> | |
| 45 | + <tr> | |
| 46 | + <th colspan='2'> | |
| 47 | + <%= _('Articles') %> | |
| 48 | + </th> | |
| 49 | + </tr> | |
| 50 | + <% if @subitems.empty? %> | |
| 51 | + <tr><td colspan='2' align='center'><em><%= _('None') %></em></td></tr> | |
| 52 | + <% end %> | |
| 53 | + <% for item in @subitems %> | |
| 54 | + <tr> | |
| 55 | + <td> | |
| 56 | + <%= image_tag(icon_for_article(item)) %> | |
| 57 | + <%= link_to item.name, :id => item.id %> | |
| 58 | + </td> | |
| 59 | + <td> | |
| 60 | + <%= link_to _('Edit'), :action => 'edit', :id => item.id %> | |
| 61 | + <%= link_to _('View'), item.url %> | |
| 62 | + </td> | |
| 63 | + </tr> | |
| 75 | 64 | <% end %> |
| 76 | -</div> | |
| 65 | + | |
| 66 | + | |
| 67 | +</table> | ... | ... |
test/functional/cms_controller_test.rb
| ... | ... | @@ -313,6 +313,89 @@ class CmsControllerTest < Test::Unit::TestCase |
| 313 | 313 | assert_tag :tag => 'input', :attributes => { :name => 'parent_id', :value => profile.home_page.id } |
| 314 | 314 | end |
| 315 | 315 | |
| 316 | + should 'list folders at top level' do | |
| 317 | + f1 = Folder.new(:name => 'f1'); profile.articles << f1; f1.save! | |
| 318 | + f2 = Folder.new(:name => 'f2'); profile.articles << f2; f2.save! | |
| 316 | 319 | |
| 320 | + get :index, :profile => profile.identifier | |
| 321 | + assert_equal [f1, f2], assigns(:folders) | |
| 322 | + assert_not_includes assigns(:subitems), f1 | |
| 323 | + assert_not_includes assigns(:subitems), f2 | |
| 324 | + end | |
| 325 | + | |
| 326 | + should 'list folders inside another folder' do | |
| 327 | + parent = Folder.new(:name => 'parent'); profile.articles << parent; parent.save! | |
| 328 | + f1 = Folder.new(:name => 'f1', :parent => parent); profile.articles << f1; f1.save! | |
| 329 | + f2 = Folder.new(:name => 'f2', :parent => parent); profile.articles << f2; f2.save! | |
| 330 | + | |
| 331 | + get :view, :profile => profile.identifier, :id => parent.id | |
| 332 | + assert_equal [f1, f2], assigns(:folders) | |
| 333 | + assert_not_includes assigns(:subitems), f1 | |
| 334 | + assert_not_includes assigns(:subitems), f2 | |
| 335 | + end | |
| 336 | + | |
| 337 | + should 'offer to create new top-level folder' do | |
| 338 | + get :index, :profile => profile.identifier | |
| 339 | + assert_tag :tag => 'a', :attributes => { :href => "/myprofile/#{profile.identifier}/cms/new?type=Folder"} | |
| 340 | + end | |
| 341 | + | |
| 342 | + should 'offer to create sub-folder' do | |
| 343 | + f = Folder.new(:name => 'f'); profile.articles << f; f.save! | |
| 344 | + get :view, :profile => profile.identifier, :id => f.id | |
| 345 | + | |
| 346 | + assert_tag :tag => 'a', :attributes => { :href => "/myprofile/#{profile.identifier}/cms/new?parent_id=#{f.id}&type=Folder" } | |
| 347 | + end | |
| 348 | + | |
| 349 | + should 'redirect back to index after creating top-level article' do | |
| 350 | + post :new, :profile => profile.identifier, :type => 'TextileArticle', :article => { :name => 'test' } | |
| 351 | + assert_redirected_to :action => 'index' | |
| 352 | + end | |
| 353 | + | |
| 354 | + should 'redirect back to folder after creating article inside it' do | |
| 355 | + f = Folder.new(:name => 'f'); profile.articles << f; f.save! | |
| 356 | + post :new, :profile => profile.identifier, :type => 'TextileArticle', :parent_id => f.id, :article => { :name => 'test' } | |
| 357 | + assert_redirected_to :action => 'view', :id => f.id | |
| 358 | + end | |
| 359 | + | |
| 360 | + should 'redirect back to index after editing top-level article' do | |
| 361 | + f = Folder.new(:name => 'f'); profile.articles << f; f.save! | |
| 362 | + post :edit, :profile => profile.identifier, :id => f.id | |
| 363 | + assert_redirected_to :action => 'index' | |
| 364 | + end | |
| 365 | + | |
| 366 | + should 'redirect back to folder after editing article inside it' do | |
| 367 | + f = Folder.new(:name => 'f'); profile.articles << f; f.save! | |
| 368 | + a = TextileArticle.create!(:parent => f, :name => 'test', :profile_id => profile.id) | |
| 369 | + | |
| 370 | + post :edit, :profile => profile.identifier, :id => a.id | |
| 371 | + assert_redirected_to :action => 'view', :id => f.id | |
| 372 | + end | |
| 373 | + | |
| 374 | + should 'point back to index when cancelling creation of top-level article' do | |
| 375 | + get :new, :profile => profile.identifier, :type => 'Folder' | |
| 376 | + assert_tag :tag => 'a', :attributes => { :href => "/myprofile/#{profile.identifier}/cms" }, :descendant => { :content => /Cancel/ } | |
| 377 | + end | |
| 378 | + | |
| 379 | + should 'point back to index when cancelling edition of top-level article' do | |
| 380 | + f = Folder.new(:name => 'f'); profile.articles << f; f.save! | |
| 381 | + get :edit, :profile => profile.identifier, :id => f.id | |
| 382 | + | |
| 383 | + assert_tag :tag => 'a', :attributes => { :href => "/myprofile/#{profile.identifier}/cms" }, :descendant => { :content => /Cancel/ } | |
| 384 | + end | |
| 385 | + | |
| 386 | + should 'point back to folder when cancelling creation of an article inside it' do | |
| 387 | + f = Folder.new(:name => 'f'); profile.articles << f; f.save! | |
| 388 | + get :new, :profile => profile.identifier, :type => 'Folder', :parent_id => f.id | |
| 389 | + | |
| 390 | + assert_tag :tag => 'a', :attributes => { :href => "/myprofile/#{profile.identifier}/cms/view/#{f.id}" }, :descendant => { :content => /Cancel/ } | |
| 391 | + end | |
| 392 | + | |
| 393 | + should 'point back to folder when cancelling edition of an article inside it' do | |
| 394 | + f = Folder.new(:name => 'f'); profile.articles << f; f.save! | |
| 395 | + a = TextileArticle.create!(:name => 'test', :parent => f, :profile_id => profile.id) | |
| 396 | + get :edit, :profile => profile.identifier, :id => a.id | |
| 397 | + | |
| 398 | + assert_tag :tag => 'a', :attributes => { :href => "/myprofile/#{profile.identifier}/cms/view/#{f.id}" }, :descendant => { :content => /Cancel/ } | |
| 399 | + end | |
| 317 | 400 | |
| 318 | 401 | end | ... | ... |
test/unit/article_test.rb
test/unit/folder_test.rb
| ... | ... | @@ -30,4 +30,8 @@ class FolderTest < ActiveSupport::TestCase |
| 30 | 30 | assert_match(/<li><a href=".*\/testuser\/f\/otherarticle">otherarticle<\/a><\/li>/, f.to_html) |
| 31 | 31 | end |
| 32 | 32 | |
| 33 | + should 'identify as folder' do | |
| 34 | + assert Folder.new.folder?, 'folder must identity itself as folder' | |
| 35 | + end | |
| 36 | + | |
| 33 | 37 | end | ... | ... |