Commit e5160e47a2cecf07fdf331be8674ab1d33b81188
1 parent
ef14f486
Exists in
master
and in
22 other branches
ActionItem21: checkpoint, several small stuff
git-svn-id: https://svn.colivre.coop.br/svn/noosfero/trunk@962 3f533792-8f58-4932-b0fe-aaf55b0a4547
Showing
12 changed files
with
176 additions
and
8 deletions
Show diff stats
| @@ -0,0 +1,46 @@ | @@ -0,0 +1,46 @@ | ||
| 1 | +CMS editors for Noosfero | ||
| 2 | +======================== | ||
| 3 | + | ||
| 4 | +This directory contains code for custom content editors in Noosfero. | ||
| 5 | + | ||
| 6 | +Creating a new editor | ||
| 7 | +===================== | ||
| 8 | + | ||
| 9 | +:: File structure | ||
| 10 | + | ||
| 11 | +Let's say that you are implementingn and editor for type, say, "foo/bar". Then | ||
| 12 | +you have to create: | ||
| 13 | + | ||
| 14 | + * app/controllers/my_profile/cms/foo_bar.html | ||
| 15 | + * app/views/cms/foo_bar_*.rhtml (one view for each action you define in the | ||
| 16 | + controller class, if applicable). | ||
| 17 | + | ||
| 18 | +:: Coding conventions | ||
| 19 | + | ||
| 20 | +You file must add methods to CmsController class. They are going to be loaded | ||
| 21 | +after the cms_controller.rb file itself, to you don't need to care about | ||
| 22 | +declaring the superclass: | ||
| 23 | + | ||
| 24 | + class CmsController | ||
| 25 | + def foo_bar_edit | ||
| 26 | + # code for preparing the "edit" view | ||
| 27 | + end | ||
| 28 | + | ||
| 29 | + def foo_bar_new | ||
| 30 | + # code for preparing the "new" view | ||
| 31 | + end | ||
| 32 | + | ||
| 33 | + # etc ... | ||
| 34 | + end | ||
| 35 | + | ||
| 36 | +Note that *all* of your actions must be prefixed with the content type (e.g. | ||
| 37 | +"foor_bar_" for "foo/bar"), in order to avoid conflicts. | ||
| 38 | + | ||
| 39 | +The views for those actions can be thrown in app/views/cms/, just like other | ||
| 40 | +views for this controller. | ||
| 41 | + | ||
| 42 | +Limitations | ||
| 43 | +=========== | ||
| 44 | + | ||
| 45 | + | ||
| 46 | + |
| @@ -0,0 +1,23 @@ | @@ -0,0 +1,23 @@ | ||
| 1 | +class CmsController | ||
| 2 | + | ||
| 3 | + def text_html_new | ||
| 4 | + @article = Article.new(params[:article]) | ||
| 5 | + @article.parent = profile.articles.find(params[:parent_id]) | ||
| 6 | + @article.profile = profile | ||
| 7 | + if request.post? | ||
| 8 | + if @article.save | ||
| 9 | + redirect_to :action => 'view', :id => @article.id | ||
| 10 | + end | ||
| 11 | + end | ||
| 12 | + end | ||
| 13 | + | ||
| 14 | + def text_html_edit | ||
| 15 | + @article = Article.find(params[:id]) | ||
| 16 | + if request.post? | ||
| 17 | + if @article.update_attributes(params[:article]) | ||
| 18 | + redirect_to :action => 'view', :id => @article.id | ||
| 19 | + end | ||
| 20 | + end | ||
| 21 | + end | ||
| 22 | + | ||
| 23 | +end |
app/controllers/my_profile/cms_controller.rb
| @@ -3,6 +3,8 @@ class CmsController < MyProfileController | @@ -3,6 +3,8 @@ class CmsController < MyProfileController | ||
| 3 | # FIXME add the access control again | 3 | # FIXME add the access control again |
| 4 | # protect 'post_content', :profile, :only => [:edit, :new, :reorder, :delete] | 4 | # protect 'post_content', :profile, :only => [:edit, :new, :reorder, :delete] |
| 5 | 5 | ||
| 6 | + include CmsHelper | ||
| 7 | + | ||
| 6 | def view | 8 | def view |
| 7 | @article = profile.articles.find(params[:id]) | 9 | @article = profile.articles.find(params[:id]) |
| 8 | @subitems = @article.children | 10 | @subitems = @article.children |
| @@ -14,6 +16,11 @@ class CmsController < MyProfileController | @@ -14,6 +16,11 @@ class CmsController < MyProfileController | ||
| 14 | render :action => 'view' | 16 | render :action => 'view' |
| 15 | end | 17 | end |
| 16 | 18 | ||
| 19 | + def edit | ||
| 20 | + article = profile.articles.find(params[:id]) | ||
| 21 | + redirect_to(url_for_edit_article(article)) | ||
| 22 | + end | ||
| 23 | + | ||
| 17 | post_only :set_home_page | 24 | post_only :set_home_page |
| 18 | def set_home_page | 25 | def set_home_page |
| 19 | @article = profile.articles.find(params[:id]) | 26 | @article = profile.articles.find(params[:id]) |
| @@ -24,4 +31,18 @@ class CmsController < MyProfileController | @@ -24,4 +31,18 @@ class CmsController < MyProfileController | ||
| 24 | 31 | ||
| 25 | protected | 32 | protected |
| 26 | 33 | ||
| 34 | + class << self | ||
| 35 | + def available_editors | ||
| 36 | + Dir.glob(File.join(File.dirname(__FILE__), 'cms', '*.rb')) | ||
| 37 | + end | ||
| 38 | + | ||
| 39 | + def available_types | ||
| 40 | + available_editors.map {|item| File.basename(item).gsub(/\.rb$/, '').gsub('_', '/') } | ||
| 41 | + end | ||
| 42 | + end | ||
| 43 | + | ||
| 44 | +end | ||
| 45 | + | ||
| 46 | +CmsController.available_editors.each do |item| | ||
| 47 | + load item | ||
| 27 | end | 48 | end |
app/controllers/public/content_viewer_controller.rb
| @@ -7,6 +7,7 @@ class ContentViewerController < PublicController | @@ -7,6 +7,7 @@ class ContentViewerController < PublicController | ||
| 7 | 7 | ||
| 8 | if path.blank? | 8 | if path.blank? |
| 9 | @page = profile.home_page | 9 | @page = profile.home_page |
| 10 | + # FIXME need to do something when the user didn't set a homepage | ||
| 10 | else | 11 | else |
| 11 | @page = profile.articles.find_by_path(path) | 12 | @page = profile.articles.find_by_path(path) |
| 12 | end | 13 | end |
app/helpers/cms_helper.rb
| 1 | module CmsHelper | 1 | module CmsHelper |
| 2 | 2 | ||
| 3 | + def link_to_edit_article(article) | ||
| 4 | + link_to(_("Edit"), url_for_edit_article(article)) | ||
| 5 | + end | ||
| 6 | + | ||
| 7 | + def url_for_edit_article(article) | ||
| 8 | + action = article.mime_type.gsub('/', '_') + '_edit' | ||
| 9 | + url_for(:action => action, :id => article.id) | ||
| 10 | + end | ||
| 11 | + | ||
| 12 | + def link_to_new_article(mime_type) | ||
| 13 | + action = mime_type.gsub('/', '_') + '_new' | ||
| 14 | + link_to(_("New %s") % mime_type, :action => action, :parent_id => params[:parent_id]) | ||
| 15 | + end | ||
| 16 | + | ||
| 3 | end | 17 | end |
app/models/article.rb
| @@ -0,0 +1,13 @@ | @@ -0,0 +1,13 @@ | ||
| 1 | +<%= error_messages_for 'article' %> | ||
| 2 | + | ||
| 3 | +<% labelled_form_for 'article', @article do |f| %> | ||
| 4 | + | ||
| 5 | + <%= hidden_field_tag 'parent_id', params[:parent_id] %> | ||
| 6 | + | ||
| 7 | + <%= f.text_field 'name' %> | ||
| 8 | + | ||
| 9 | + <%= f.text_area('body') %> | ||
| 10 | + | ||
| 11 | + <%= submit_tag _('Save') %> | ||
| 12 | + | ||
| 13 | +<% end %> |
app/views/cms/view.rhtml
| @@ -30,6 +30,7 @@ | @@ -30,6 +30,7 @@ | ||
| 30 | <%# display the article content %> | 30 | <%# display the article content %> |
| 31 | 31 | ||
| 32 | <% if @article %> | 32 | <% if @article %> |
| 33 | + <%= link_to_edit_article(@article) %> | ||
| 33 | <h2><%= @article.name %></h2> | 34 | <h2><%= @article.name %></h2> |
| 34 | <%= @article.to_html %> | 35 | <%= @article.to_html %> |
| 35 | <% end %> | 36 | <% end %> |
test/functional/cms_controller_test.rb
| @@ -42,15 +42,42 @@ class CmsControllerTest < Test::Unit::TestCase | @@ -42,15 +42,42 @@ class CmsControllerTest < Test::Unit::TestCase | ||
| 42 | end | 42 | end |
| 43 | 43 | ||
| 44 | should 'be able to edit a document' do | 44 | should 'be able to edit a document' do |
| 45 | - flunk 'not yet' | 45 | + flunk 'pending' |
| 46 | end | 46 | end |
| 47 | 47 | ||
| 48 | should 'be able to save a save a document' do | 48 | should 'be able to save a save a document' do |
| 49 | - flunk 'not yet' | 49 | + flunk 'pending' |
| 50 | end | 50 | end |
| 51 | 51 | ||
| 52 | should 'be able to set home page' do | 52 | should 'be able to set home page' do |
| 53 | flunk 'pending' | 53 | flunk 'pending' |
| 54 | end | 54 | end |
| 55 | 55 | ||
| 56 | + should 'list available editors' do | ||
| 57 | + editors = [ "#{RAILS_ROOT}/app/controllers/my_profile/cms/bli.rb", "#{RAILS_ROOT}/app/controllers/my_profile/cms/blo.rb" ] | ||
| 58 | + Dir.expects(:glob).with("#{RAILS_ROOT}/app/controllers/my_profile/cms/*.rb").returns(editors) | ||
| 59 | + assert_equal editors, CmsController.available_editors | ||
| 60 | + end | ||
| 61 | + | ||
| 62 | + should 'list available types' do | ||
| 63 | + editors = [ "#{RAILS_ROOT}/app/controllers/my_profile/cms/text_html.rb", "#{RAILS_ROOT}/app/controllers/my_profile/cms/image.rb" ] | ||
| 64 | + CmsController.expects(:available_editors).returns(editors) | ||
| 65 | + assert_equal [ 'text/html', 'image' ], CmsController.available_types | ||
| 66 | + end | ||
| 67 | + | ||
| 68 | + should 'made the editor actions available' do | ||
| 69 | + # ASSUMING that 'text/html' is always available and has 'new' and 'edit' | ||
| 70 | + assert CmsController.instance_methods.include?('text_html_new') | ||
| 71 | + assert CmsController.instance_methods.include?('text_html_edit') | ||
| 72 | + end | ||
| 73 | + | ||
| 74 | + should 'edit by redirecting to the correct editor depending on the mime-type' do | ||
| 75 | + a = profile.articles.build(:name => 'test document') | ||
| 76 | + a.save! | ||
| 77 | + assert_equal 'text/html', a.mime_type | ||
| 78 | + | ||
| 79 | + get :edit, :profile => profile.identifier, :id => a.id | ||
| 80 | + assert_redirected_to :action => 'text_html_edit', :id => a.id | ||
| 81 | + end | ||
| 82 | + | ||
| 56 | end | 83 | end |
test/functional/content_viewer_controller_test.rb
| @@ -12,17 +12,27 @@ class ContentViewerControllerTest < Test::Unit::TestCase | @@ -12,17 +12,27 @@ class ContentViewerControllerTest < Test::Unit::TestCase | ||
| 12 | @controller = ContentViewerController.new | 12 | @controller = ContentViewerController.new |
| 13 | @request = ActionController::TestRequest.new | 13 | @request = ActionController::TestRequest.new |
| 14 | @response = ActionController::TestResponse.new | 14 | @response = ActionController::TestResponse.new |
| 15 | + | ||
| 16 | + @profile = create_user('testinguser').person | ||
| 15 | end | 17 | end |
| 18 | + attr_reader :profile | ||
| 19 | + | ||
| 20 | + def test_should_display_page | ||
| 21 | + page = profile.articles.build(:name => 'test') | ||
| 22 | + page.save! | ||
| 16 | 23 | ||
| 17 | - def test_should_display_homepage | ||
| 18 | uses_host 'anhetegua.net' | 24 | uses_host 'anhetegua.net' |
| 25 | + get :view_page, :profile => profile.identifier, :page => [ 'test' ] | ||
| 26 | + assert_response :success | ||
| 27 | + assert_equal page, assigns(:page) | ||
| 28 | + end | ||
| 19 | 29 | ||
| 20 | - a = Article.new | ||
| 21 | - Article.expects(:find_by_path).with('ze').returns(a) | 30 | + def test_should_display_homepage |
| 31 | + flunk 'pending' | ||
| 32 | + end | ||
| 22 | 33 | ||
| 23 | - get :view_page, :profile => 'ze', :page => [] | ||
| 24 | - assert_response :success | ||
| 25 | - assert_equal a, assigns(:page) | 34 | + def test_should_display_something_else_for_empty_homepage |
| 35 | + flunk 'pending' | ||
| 26 | end | 36 | end |
| 27 | 37 | ||
| 28 | def test_should_get_not_found_error_for_unexisting_page | 38 | def test_should_get_not_found_error_for_unexisting_page |