Commit b2833502d0184d05a577d9544379302412dc38f8
1 parent
7707a13c
Exists in
master
and in
29 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 | ... | ... |