Commit 3f754a9b794b73c642c0f2cc4924f49f9de47685

Authored by Antonio Terceiro
2 parents ecccea23 96a2e91e

Merge branch 'master' into rails3

Conflicts:
	Gemfile
	Gemfile.lock
	Rakefile
	app/controllers/admin/users_controller.rb
	app/helpers/application_helper.rb
	app/models/article.rb
	app/models/enterprise.rb
	app/models/license.rb
	app/models/product.rb
	app/models/profile.rb
	app/models/user.rb
	app/views/account/_signup_form.html.erb
	app/views/admin_panel/site_info.html.erb
	app/views/box_organizer/_block_types.html.erb
	app/views/layouts/application-ng.html.erb
	app/views/search/_article.html.erb
	app/views/search/_article.rhtml
	app/views/search/_blog.html.erb
	app/views/search/_blog.rhtml
	app/views/search/_content.html.erb
	app/views/search/_event.html.erb
	app/views/search/_event.rhtml
	app/views/search/_facets_menu.html.erb
	app/views/search/_facets_menu.rhtml
	app/views/search/_facets_unselect_menu.html.erb
	app/views/search/_facets_unselect_menu.rhtml
	app/views/search/_folder.html.erb
	app/views/search/_folder.rhtml
	app/views/search/_forum.html.erb
	app/views/search/_forum.rhtml
	app/views/search/_full_article.html.erb
	app/views/search/_full_blog.html.erb
	app/views/search/_full_enterprise.html.erb
	app/views/search/_full_event.html.erb
	app/views/search/_full_folder.html.erb
	app/views/search/_full_forum.html.erb
	app/views/search/_full_gallery.html.erb
	app/views/search/_full_product.rhtml
	app/views/search/_full_text_article.html.erb
	app/views/search/_full_uploaded_file.html.erb
	app/views/search/_gallery.html.erb
	app/views/search/_gallery.rhtml
	app/views/search/_product.html.erb
	app/views/search/_product.rhtml
	app/views/search/_profile.html.erb
	app/views/search/_profile.rhtml
	app/views/search/_text_article.html.erb
	app/views/search/_text_article.rhtml
	app/views/search/_uploaded_file.html.erb
	app/views/search/_uploaded_file.rhtml
	app/views/search/articles.html.erb
	app/views/search/category_index.html.erb
	app/views/search/communities.html.erb
	app/views/search/contents.html.erb
	app/views/search/enterprises.html.erb
	app/views/search/events.html.erb
	app/views/search/facets_browse.html.erb
	app/views/search/facets_browse.rhtml
	app/views/search/people.html.erb
	app/views/search/products.html.erb
	app/views/users/_user_csv.html.erb
	app/views/users/index_csv.html.erb
	app/views/users/send_mail.html.erb
	config/environment.rb
	features/support/fixtures.rb
	features/support/selenium.rb
	lib/noosfero.rb
	lib/noosfero/plugin.rb
	lib/tasks/cucumber.rake
	plugins/mezuro/lib/kalibro/model.rb
	plugins/mezuro/lib/mezuro_plugin/helpers/content_viewer_helper.rb
	plugins/mezuro/test/features/echo_port_test.rb
	plugins/mezuro/test/functional/mezuro_plugin_myprofile_controller_test.rb
	plugins/mezuro/test/functional/mezuro_plugin_profile_controller_test.rb
	plugins/mezuro/test/unit/kalibro/base_tool_test.rb
	plugins/mezuro/test/unit/kalibro/compound_metric_test.rb
	plugins/mezuro/test/unit/kalibro/compound_metric_with_error_test.rb
	plugins/mezuro/test/unit/kalibro/error_test.rb
	plugins/mezuro/test/unit/kalibro/metric_configuration_test.rb
	plugins/mezuro/test/unit/kalibro/metric_result_test.rb
	plugins/mezuro/test/unit/kalibro/module_node_test.rb
	plugins/mezuro/test/unit/kalibro/module_result_test.rb
	plugins/mezuro/test/unit/kalibro/native_metric_test.rb
	plugins/mezuro/test/unit/kalibro/project_result_test.rb
	plugins/mezuro/test/unit/mezuro_plugin/configuration_content_test.rb
	plugins/mezuro/test/unit/mezuro_plugin/helpers/content_viewer_helper_test.rb
	plugins/mezuro/test/unit/mezuro_plugin/project_content_test.rb
	plugins/mezuro/views/mezuro_plugin_myprofile/_edit_range.html.erb
	plugins/mezuro/views/mezuro_plugin_myprofile/_new_range.html.erb
	plugins/mezuro/views/mezuro_plugin_myprofile/edit_compound_metric_configuration.html.erb
	plugins/mezuro/views/mezuro_plugin_myprofile/edit_metric_configuration.html.erb
	plugins/mezuro/views/mezuro_plugin_myprofile/new_compound_metric_configuration.html.erb
	plugins/mezuro/views/mezuro_plugin_myprofile/new_metric_configuration.html.erb
	plugins/shopping_cart/views/shopping_cart_plugin_myprofile/edit.html.erb
	plugins/shopping_cart/views/shopping_cart_plugin_profile/buy.html.erb
	plugins/solr/lib/acts_as_faceted.rb
	plugins/solr/lib/acts_as_searchable.rb
	plugins/solr/test/test_helper.rb
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/.gitignore
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/.travis.yml
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/Gemfile
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/LICENSE
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/README.markdown
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/Rakefile
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/TESTING_THE_PLUGIN
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/VERSION
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/acts_as_solr_reloaded.gemspec
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/config/solr_environment.rb
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/generators/dynamic_attributes_migration/dynamic_attributes_migration_generator.rb
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/generators/dynamic_attributes_migration/templates/migration.rb
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/generators/local_migration/local_migration_generator.rb
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/generators/local_migration/templates/migration.rb
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/init.rb
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/install.rb
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/lib/acts_as_solr.rb
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/lib/acts_as_solr/acts_methods.rb
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/lib/acts_as_solr/class_methods.rb
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/lib/acts_as_solr/common_methods.rb
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/lib/acts_as_solr/deprecation.rb
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/lib/acts_as_solr/dynamic_attribute.rb
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/lib/acts_as_solr/instance_methods.rb
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/lib/acts_as_solr/lazy_document.rb
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/lib/acts_as_solr/local.rb
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/lib/acts_as_solr/mongo_mapper.rb
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/lib/acts_as_solr/parser_methods.rb
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/lib/acts_as_solr/post.rb
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/lib/acts_as_solr/search_results.rb
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/lib/acts_as_solr/solr_fixtures.rb
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/lib/acts_as_solr/tasks.rb
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/lib/acts_as_solr_reloaded.rb
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/lib/solr.rb
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/lib/solr/connection.rb
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/lib/solr/document.rb
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/lib/solr/exception.rb
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/lib/solr/field.rb
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/lib/solr/importer.rb
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/lib/solr/importer/array_mapper.rb
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/lib/solr/importer/delimited_file_source.rb
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/lib/solr/importer/hpricot_mapper.rb
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/lib/solr/importer/mapper.rb
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/lib/solr/importer/solr_source.rb
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/lib/solr/importer/xpath_mapper.rb
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/lib/solr/indexer.rb
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/lib/solr/request.rb
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/lib/solr/request/add_document.rb
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/lib/solr/request/base.rb
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/lib/solr/request/commit.rb
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/lib/solr/request/delete.rb
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/lib/solr/request/dismax.rb
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/lib/solr/request/index_info.rb
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/lib/solr/request/json_update.rb
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/lib/solr/request/modify_document.rb
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/lib/solr/request/optimize.rb
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/lib/solr/request/ping.rb
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/lib/solr/request/select.rb
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/lib/solr/request/spellcheck.rb
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/lib/solr/request/standard.rb
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/lib/solr/request/update.rb
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/lib/solr/response.rb
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/lib/solr/response/add_document.rb
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/lib/solr/response/base.rb
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/lib/solr/response/commit.rb
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/lib/solr/response/delete.rb
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/lib/solr/response/dismax.rb
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/lib/solr/response/index_info.rb
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/lib/solr/response/modify_document.rb
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/lib/solr/response/optimize.rb
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/lib/solr/response/ping.rb
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/lib/solr/response/ruby.rb
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/lib/solr/response/select.rb
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/lib/solr/response/spellcheck.rb
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/lib/solr/response/standard.rb
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/lib/solr/response/xml.rb
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/lib/solr/util.rb
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/lib/solr/xml.rb
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/lib/tasks/database.rake
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/lib/tasks/solr.rake
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/lib/tasks/test.rake
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/rails/init.rb
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/solr/solr/conf/admin-extra.html
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/solr/solr/conf/elevate.xml
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/solr/solr/conf/en_US.aff
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/solr/solr/conf/en_US.dic
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/solr/solr/conf/mapping-ISOLatin1Accent.txt
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/solr/solr/conf/protwords.en.txt
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/solr/solr/conf/protwords.pt.txt
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/solr/solr/conf/pt_PT.aff
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/solr/solr/conf/pt_PT.dic
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/solr/solr/conf/schema.xml
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/solr/solr/conf/scripts.conf
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/solr/solr/conf/solrconfig.xml
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/solr/solr/conf/spellings.en.txt
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/solr/solr/conf/stopwords.en.txt
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/solr/solr/conf/stopwords.pt.txt
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/solr/solr/conf/synonyms.en.txt
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/solr/solr/conf/xslt/example.xsl
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/solr/solr/conf/xslt/example_atom.xsl
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/solr/solr/conf/xslt/example_rss.xsl
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/solr/solr/conf/xslt/luke.xsl
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/solr_test_rakefile.rb
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/test/config/solr.yml
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/test/db/connections/mysql/connection.rb
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/test/db/connections/sqlite/connection.rb
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/test/db/migrate/001_create_books.rb
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/test/db/migrate/002_create_movies.rb
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/test/db/migrate/003_create_categories.rb
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/test/db/migrate/004_create_electronics.rb
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/test/db/migrate/005_create_authors.rb
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/test/db/migrate/006_create_postings.rb
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/test/db/migrate/007_create_posts.rb
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/test/db/migrate/008_create_gadgets.rb
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/test/db/migrate/009_create_dynamic_attributes.rb
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/test/db/migrate/010_create_advertises.rb
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/test/db/migrate/011_create_locals.rb
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/test/fixtures/advertises.yml
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/test/fixtures/authors.yml
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/test/fixtures/books.yml
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/test/fixtures/categories.yml
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/test/fixtures/db_definitions/mysql.sql
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/test/fixtures/dynamic_attributes.yml
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/test/fixtures/electronics.yml
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/test/fixtures/movies.yml
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/test/fixtures/postings.yml
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/test/functional/acts_as_solr_test.rb
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/test/functional/association_indexing_test.rb
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/test/functional/faceted_search_test.rb
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/test/functional/multi_solr_search_test.rb
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/test/models/advertise.rb
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/test/models/author.rb
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/test/models/book.rb
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/test/models/category.rb
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/test/models/document.rb
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/test/models/dynamic_attribute.rb
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/test/models/electronic.rb
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/test/models/gadget.rb
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/test/models/local.rb
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/test/models/movie.rb
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/test/models/novel.rb
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/test/models/post.rb
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/test/models/posting.rb
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/test/test_helper.rb
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/test/unit/acts_methods_shoulda.rb
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/test/unit/class_methods_shoulda.rb
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/test/unit/common_methods_shoulda.rb
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/test/unit/instance_methods_shoulda.rb
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/test/unit/lazy_document_shoulda.rb
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/test/unit/parser_instance.rb
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/test/unit/parser_methods_shoulda.rb
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/test/unit/solr_add_document_shoulda.rb
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/test/unit/solr_instance.rb
	plugins/solr/vendor/plugins/acts_as_solr_reloaded/test/unit/test_helper.rb
	plugins/solr/views/facets_browse.html.erb
	plugins/solr/views/search/_facets_menu.html.erb
	plugins/solr/views/search/_facets_unselect_menu.rhtml
Showing 892 changed files with 213553 additions and 73745 deletions   Show diff stats

Too many changes.

To preserve performance only 100 of 892 files displayed.

AUTHORS
... ... @@ -6,22 +6,37 @@ noosfero, that's not a problem).
6 6 Developers
7 7 ==========
8 8  
  9 +Alan Freihof Tygel <alantygel@gmail.com>
9 10 Alessandro Palmeira <alessandro.palmeira@gmail.com>
10 11 Alessandro Palmeira + Caio C. Salgado <alessandro.palmeira@gmail.com>
11 12 Alessandro Palmeira + Caio Salgado <alessandro.palmeira@gmail.com>
12 13 Alessandro Palmeira + Caio Salgado <caio.csalgado@gmail.com>
13 14 Alessandro Palmeira + Caio Salgado + Diego Araújo + João M. M. da Silva <diegoamc90@gmail.com>
14 15 Alessandro Palmeira + Carlos Morais <alessandro.palmeira@gmail.com>
  16 +Alessandro Palmeira + Daniel Alves <alessandro.palmeira@gmail.com>
  17 +Alessandro Palmeira + Daniel Alves + Diego Araújo <diegoamc90@gmail.com>
  18 +Alessandro Palmeira + Daniel Alves + Diego Araújo + Guilherme Rojas <danpaulalves@gmail.com>
  19 +Alessandro Palmeira + Diego Araujo <alessandro.palmeira@gmail.com>
15 20 Alessandro Palmeira + Diego Araújo <alessandro.palmeira@gmail.com>
  21 +Alessandro Palmeira + Diego Araujo + Daniela Feitosa <alessandro.palmeira@gmail.com>
  22 +Alessandro Palmeira + Diego Araujo <diegoamc90@gmail.com>
16 23 Alessandro Palmeira + Diego Araújo <diegoamc90@gmail.com>
  24 +Alessandro Palmeira + Diego Araujo + Eduardo Morais <alessandro.palmeira@gmail.com>
  25 +Alessandro Palmeira + Diego Araújo + João M. M. da Silva <alessandro.palmeira@gmail.com>
  26 +Alessandro Palmeira + Diego Araújo + João M. M. da Silva <diegoamc90@gmail.com>
  27 +Alessandro Palmeira + Diego Araujo + João M. M. da Silva + Paulo Meirelles <alessandro.palmeira@gmail.com>
17 28 Alessandro Palmeira + Diego Araújo + Pedro Leal <diegoamc90@gmail.com>
18 29 Alessandro Palmeira + Diego Araújo + Pedro Leal + João M. M. da Silva <diegoamc90@gmail.com>
19 30 Alessandro Palmeira + Diego Araujo + Rafael Manzo <alessandro.palmeira@gmail.com>
  31 +Alessandro Palmeira + Eduardo Morais <alessandro.palmeira@gmail.com>
  32 +Alessandro Palmeira + Guilherme Rojas <alessandro.palmeira@gmail.com>
20 33 Alessandro Palmeira + Jefferson Fernandes <alessandro.palmeira@gmail.com>
21 34 Alessandro Palmeira + João M. M. da Silva <alessandro.palmeira@gmail.com>
  35 +Alessandro Palmeira + Joao M. M. da Silva + Diego Araujo <alessandro.palmeira@gmail.com>
22 36 Alessandro Palmeira + João M. M. da Silva + Renan Teruo <alessandro.palmeira@gmail.com>
23 37 Alessandro Palmeira + João M. M. Silva <alessandro.palmeira@gmail.com>
24 38 Alessandro Palmeira + Paulo Meirelles <alessandro.palmeira@gmail.com>
  39 +Alessandro Palmeira + Paulo Meirelles + João M. M. da Silva <alessandro.palmeira@gmail.com>
25 40 Alessandro Palmeira + Rafael Manzo <alessandro.palmeira@gmail.com>
26 41 Antonio Terceiro + Carlos Morais <terceiro@colivre.coop.br>
27 42 Antonio Terceiro + Paulo Meirelles <terceiro@colivre.coop.br>
... ... @@ -31,6 +46,7 @@ Braulio Bhavamitra &lt;brauliobo@gmail.com&gt;
31 46 Bráulio Bhavamitra <brauliobo@gmail.com>
32 47 Caio <caio.csalgado@gmail.com>
33 48 Caio + Diego + Pedro + João <caio.csalgado@gmail.com>
  49 +Caio Formiga <caio.formiga@gmail.com>
34 50 Caio, Pedro <caio.csalgado@gmail.com>
35 51 Caio Salgado + Alessandro Palmeira <caio.csalgado@gmail.com>
36 52 Caio Salgado <caio.csalgado@gmail.com>
... ... @@ -56,26 +72,42 @@ Carlos Morais + Diego Araújo &lt;diegoamc90@gmail.com&gt;
56 72 Carlos Morais + Eduardo Morais <carlos88morais@gmail.com>
57 73 Carlos Morais + Paulo Meirelles <carlos88morais@gmail.com>
58 74 Carlos Morais + Pedro Leal <carlos88morais@gmail.com>
  75 +Daniel Alves + Diego Araújo <danpaulalves@gmail.com>
  76 +Daniel Alves + Diego Araújo <diegoamc90@gmail.com>
  77 +Daniel Alves + Diego Araújo + Guilherme Rojas <danpaulalves@gmail.com>
  78 +Daniel Alves + Diego Araújo + Guilherme Rojas <diegoamc90@gmail.com>
  79 +Daniel Alves + Diego Araújo + Guilherme Rojas <guilhermehrojas@gmail.com>
  80 +Daniel Alves + Guilherme Rojas <danpaulalves@gmail.com>
  81 +Daniel Alves + Rafael Manzo <rr.manzo@gmail.com>
59 82 Daniela Soares Feitosa <danielafeitosa@colivre.coop.br>
60 83 Daniel Cunha <daniel@colivre.coop.br>
61 84 diegoamc <diegoamc90@gmail.com>
62 85 Diego Araújo + Alessandro Palmeira <diegoamc90@gmail.com>
  86 +Diego Araújo + Alessandro Palmeira + João M. M. da Silva <diegoamc90@gmail.com>
  87 +Diego Araújo + Alessandro Palmeira + Rafael Manzo <rr.manzo@gmail.com>
63 88 Diego Araujo + Caio Salgado <diegoamc90@gmail.com>
  89 +Diego Araújo + Daniel Alves + Rafael Manzo <rr.manzo@gmail.com>
64 90 Diego Araújo <diegoamc90@gmail.com>
  91 +Diego Araújo + Eduardo Morais + Paulo Meirelles <diegoamc90@gmail.com>
  92 +Diego Araújo + Guilherme Rojas <diegoamc90@gmail.com>
65 93 Diego Araújo + Jefferson Fernandes <diegoamc90@gmail.com>
66 94 Diego Araujo + Jefferson Fernandes <jeffs.fernandes@gmail.com>
67 95 Diego Araújo + João Machini <diegoamc90@gmail.com>
68 96 Diego Araújo + João Machini <digoamc90@gmail.com>
  97 +Diego Araújo + João M. M. da Silva + Alessandro Palmeira <jaodsilv@linux.ime.usp.br>
69 98 Diego Araújo + João M. M. da Silva <diegoamc90@gmail.com>
70 99 Diego Araújo + João M. M. da Silva + João Machini <diegoamc90@gmail.com>
71 100 Diego Araújo + João M. M. da Silva + Pedro Leal <diegoamc90@gmail.com>
72 101 Diego Araújo + Paulo Meirelles <diegoamc90@gmail.com>
73 102 Diego Araújo + Pedro Leal <diegoamc90@gmail.com>
  103 +Diego Araujo + Rafael Manzo <diegoamc90@gmail.com>
74 104 Diego Araújo + Rafael Manzo <diegoamc90@gmail.com>
75 105 Diego Araújo + Renan Teruo + Alessandro Palmeira <diegoamc90@gmail.com>
76 106 Diego Araújo + Renan Teruo <diegoamc90@gmail.com>
  107 +Diego Araujo + Rodrigo Souto + Rafael Manzo <rr.manzo@gmail.com>
77 108 Diego + Jefferson <diegoamc90@gmail.com>
78 109 Diego Martinez <diegoamc90@gmail.com>
  110 +Diego Martinez <diego@diego-K55A.(none)>
79 111 Diego + Renan <renanteruoc@gmail.com>
80 112 Fernanda Lopes <nanda.listas+psl@gmail.com>
81 113 Grazieno Pellegrino <grazieno@gmail.com>
... ... @@ -88,6 +120,7 @@ João da Silva &lt;jaodsilv@linux.ime.usp.br&gt;
88 120 João Marco Maciel da Silva + Rafael Manzo + Renan Teruo <jaodsilv@linux.ime.usp.br>
89 121 João M. M. da Silva + Alessandro Palmeira + Diego Araújo + Caio Salgado <jaodsilv@linux.ime.usp.br>
90 122 João M. M. da Silva + Alessandro Palmeira + Diego Araújo <jaodsilv@linux.ime.usp.br>
  123 +Joao M. M. da Silva + Alessandro Palmeira <jaodsilv@linux.ime.usp.br>
91 124 João M. M. da Silva + Alessandro Palmeira <jaodsilv@linux.ime.usp.br>
92 125 João M. M. da Silva + Alessandro Palmeira + João Machini <jaodsilv@linux.ime.usp.br>
93 126 João M. M. da Silva + Caio Salgado + Alessandro Palmeira <jaodsilv@linux.ime.usp.br>
... ... @@ -119,20 +152,30 @@ Larissa Reis &lt;reiss.larissa@gmail.com&gt;
119 152 Leandro Nunes dos Santos <leandronunes@gmail.com>
120 153 Leandro Nunes dos Santos <leandro.santos@serpro.gov.br>
121 154 LinguÁgil 2010 <linguagil.bahia@gmail.com>
  155 +Lucas Melo <lucas@colivre.coop.br>
  156 +Luis David Aguilar Carlos <ludwig9003@gmail.com>
122 157 Martín Olivera <molivera@solar.org.ar>
123 158 Moises Machado <moises@colivre.coop.br>
124 159 Nanda Lopes <nanda.listas+psl@gmail.com>
  160 +Paulo Meirelles + Alessandro Palmeira + João M. M. da Silva <paulo@softwarelivre.org>
125 161 Paulo Meirelles + Alessandro Palmeira <paulo@softwarelivre.org>
126 162 Paulo Meirelles + Carlos Morais <paulo@softwarelivre.org>
127 163 Paulo Meirelles + Diego Araújo <paulo@softwarelivre.org>
128 164 Paulo Meirelles + João M. M. da Silva <paulo@softwarelivre.org>
129 165 Paulo Meirelles <paulo@softwarelivre.org>
  166 +Paulo Meirelles + Rafael Manzo <paulo@softwarelivre.org>
130 167 Rafael Gomes <rafaelgomes@techfree.com.br>
  168 +Rafael Manzo + Alessandro Palmeira <rr.manzo@gmail.com>
  169 +Rafael Manzo + Daniel Alves <danpaulalves@gmail.com>
  170 +Rafael Manzo + Diego Araújo <rr.manzo@gmail.com>
131 171 Rafael Manzo + João M. M. Silva <rr.manzo@gmail.com>
  172 +Rafael Manzo + Paulo Meirelles <rr.manzo@gmail.com>
132 173 Rafael Martins <rmmartins@gmail.com>
133 174 Rafael Reggiani Manzo + Caio Salgado + Jefferson Fernandes <rr.manzo@gmail.com>
134 175 Rafael Reggiani Manzo + Diego Araujo <diegoamc90@gmail.com>
135 176 Rafael Reggiani Manzo + Diego Araujo <rr.manzo@gmail.com>
  177 +Rafael Reggiani Manzo + Diego Araújo <rr.manzo@gmail.com>
  178 +Rafael Reggiani Manzo + João M. M. da Silva <rr.manzo@gmail.com>
136 179 Rafael Reggiani Manzo <rr.manzo@gmail.com>
137 180 Raphaël Rousseau <raph@r4f.org>
138 181 Raquel Lira <raquel.lira@gmail.com>
... ... @@ -144,8 +187,11 @@ Renan Teruo + Paulo Meirelles &lt;renanteruoc@gmail.com&gt;
144 187 Renan Teruo + Rafael Manzo <renanteruoc@gmail.com>
145 188 Rodrigo Souto <rodrigo@colivre.coop.br>
146 189 Ronny Kursawe <kursawe.ronny@googlemail.com>
  190 +root <root@debian.sdr.serpro>
147 191 Samuel R. C. Vale <srcvale@holoscopio.com>
148 192 Valessio Brito <valessio@gmail.com>
  193 +vfcosta <vfcosta@gmail.com>
  194 +Visita <visita@debian.(none)>
149 195 Yann Lugrin <yann.lugrin@liquid-concept.ch>
150 196  
151 197 Ideas, specifications and incentive
... ...
Gemfile
1   -source :rubygems
2   -gem 'cucumber'
3   -# TODO needs a rebuild diff-lcs wrt wheezy
  1 +source "https://rubygems.org"
  2 +gem 'rails'
4 3  
5   -gem 'rspec'
6   -# gem 'rspec-rails', '1.2.9' # FIXME package this
  4 +# TODO needs a rebuild diff-lcs wrt wheezy
7 5  
8 6 # FIXME list here all actual dependencies (i.e. the ones in debian/control),
9 7 # with their GEM names (not the Debian package names)
10 8  
11   -gem 'rails'
  9 +group :test do
  10 + #gem 'rspec'
  11 + #gem 'rspec-rails'
  12 +end
  13 +
  14 +group :cucumber do
  15 + gem 'rake'
  16 + # TODO gem 'cucumber-rails'
  17 + # TODO gem 'capybara'
  18 + # gem 'cucumber'
  19 + # TODO gem 'database_cleaner'
  20 +end
12 21  
13 22 def program(name)
14 23 unless system("which #{name} > /dev/null")
... ...
Gemfile.lock
1 1 GEM
2   - remote: http://rubygems.org/
  2 + remote: https://rubygems.org/
3 3 specs:
4 4 actionmailer (3.2.6)
5 5 actionpack (= 3.2.6)
... ... @@ -30,19 +30,10 @@ GEM
30 30 multi_json (~> 1.0)
31 31 arel (3.0.2)
32 32 builder (3.0.0)
33   - cucumber (1.2.1)
34   - builder (>= 2.1.2)
35   - diff-lcs (>= 1.1.3)
36   - gherkin (~> 2.11.0)
37   - json (>= 1.4.6)
38   - diff-lcs (1.1.3)
39 33 erubis (2.7.0)
40   - gherkin (2.11.1)
41   - json (>= 1.4.6)
42 34 hike (1.2.1)
43 35 i18n (0.6.0)
44 36 journey (1.0.3)
45   - json (1.7.3)
46 37 mail (2.4.4)
47 38 i18n (>= 0.4.0)
48 39 mime-types (~> 1.16)
... ... @@ -55,7 +46,7 @@ GEM
55 46 rack (>= 0.4)
56 47 rack-ssl (1.3.2)
57 48 rack
58   - rack-test (0.6.2)
  49 + rack-test (0.6.1)
59 50 rack (>= 1.0)
60 51 rails (3.2.6)
61 52 actionmailer (= 3.2.6)
... ... @@ -74,14 +65,6 @@ GEM
74 65 thor (>= 0.14.6, < 2.0)
75 66 rake (0.9.2.2)
76 67 rdoc (3.9.4)
77   - rspec (2.10.0)
78   - rspec-core (~> 2.10.0)
79   - rspec-expectations (~> 2.10.0)
80   - rspec-mocks (~> 2.10.0)
81   - rspec-core (2.10.1)
82   - rspec-expectations (2.10.0)
83   - diff-lcs (~> 1.1.3)
84   - rspec-mocks (2.10.1)
85 68 sprockets (2.1.3)
86 69 hike (~> 1.2)
87 70 multi_json (~> 1.0)
... ... @@ -98,6 +81,5 @@ PLATFORMS
98 81 ruby
99 82  
100 83 DEPENDENCIES
101   - cucumber
102 84 rails
103   - rspec
  85 + rake
... ...
INSTALL
... ... @@ -33,7 +33,7 @@ You need to install some packages Noosfero depends on. On Debian GNU/Linux or
33 33 Debian-based systems, all of these packages are available through the Debian
34 34 archive. You can install them with the following command:
35 35  
36   - # apt-get install ruby rake po4a libgettext-ruby-util libgettext-ruby1.8 libsqlite3-ruby rcov librmagick-ruby libredcloth-ruby libwill-paginate-ruby iso-codes libfeedparser-ruby openjdk-6-jre libdaemons-ruby thin tango-icon-theme libhpricot-ruby
  36 + # apt-get install ruby rake po4a libgettext-ruby-util libgettext-ruby1.8 libsqlite3-ruby rcov librmagick-ruby libredcloth-ruby libwill-paginate-ruby iso-codes libfeedparser-ruby libdaemons-ruby thin tango-icon-theme libhpricot-ruby
37 37  
38 38 On other systems, they may or may not be available through your regular package
39 39 management system. Below are the links to their homepages.
... ... @@ -43,7 +43,6 @@ management system. Below are the links to their homepages.
43 43 * po4a: http://po4a.alioth.debian.org/
44 44 * Ruby-sqlite3: http://rubyforge.org/projects/sqlite-ruby
45 45 * rcov: http://eigenclass.org/hiki/rcov
46   -* Solr: http://lucene.apache.org/solr
47 46 * RMagick: http://rmagick.rubyforge.org/
48 47 * RedCloth: http://redcloth.org/
49 48 * will_paginate: http://github.com/mislav/will_paginate/wikis
... ... @@ -104,16 +103,13 @@ $ git checkout -b stable origin/stable
104 103 downloading tarball
105 104 -------------------
106 105  
107   -Note: replace 0.35.0 below from the latest stable version.
  106 +Note: replace 0.39.0 below from the latest stable version.
108 107  
109   -$ wget http://noosfero.org/pub/Development/NoosferoVersion00x35x00/noosfero-0.35.0.tar.gz
110   -$ tar -zxvf noosfero-0.35.0.tar.gz
111   -$ ln -s noosfero-0.35.0 current
  108 +$ wget http://noosfero.org/pub/Development/NoosferoVersion00x39x00/noosfero-0.39.0.tar.gz
  109 +$ tar -zxvf noosfero-0.39.0.tar.gz
  110 +$ ln -s noosfero-0.39.0 current
112 111 $ cd current
113 112  
114   -Copy config/solr.yml.dist to config/solr.yml. You will
115   -probably not need to customize this configuration, but have a look at it.
116   -
117 113 Create the thin configuration file:
118 114  
119 115 $ thin -C config/thin.yml -e production config
... ... @@ -187,19 +183,6 @@ $ ./script/dbconsole production
187 183 If it connects to your database, then everything is fine. If you got an error
188 184 message, then you have to check your database configuration.
189 185  
190   -Installing gem rack
191   -===================
192   -
193   -This gem is required if you want to run Mezuro plugin.
194   -
195   -Install RubyGem Rack 1.0.1.
196   -Others versions may not be compatible with Noosfero:
197   -
198   -# gem install rack -v 1.0.1
199   -
200   -As noosfero user
201   -================
202   -
203 186 Create the database structure:
204 187  
205 188 $ RAILS_ENV=production rake db:schema:load
... ... @@ -208,10 +191,6 @@ Compile the translations:
208 191  
209 192 $ RAILS_ENV=production rake noosfero:translations:compile
210 193  
211   -Run Solr:
212   -
213   -$ rake solr:start
214   -
215 194 Now we must create some initial data. To create your default environment
216 195 (the first one), run the command below:
217 196  
... ... @@ -228,10 +207,10 @@ $ RAILS_ENV=production ./script/runner &quot;Environment.default.domains &lt;&lt; Domain.ne
228 207  
229 208 Add at least one user as admin of environment:
230 209  
231   -$ RAILS_ENV=production ./script/runner "User.create(:login => 'adminuser', :email => 'admin@example.com', :password => 'admin', :password_confirmation => 'admin', :environment => Environment.default)"
  210 +$ RAILS_ENV=production ./script/runner "User.create(:login => 'adminuser', :email => 'admin@example.com', :password => 'admin', :password_confirmation => 'admin', :environment => Environment.default, :activated_at => Time.new)"
232 211  
233 212 (replace "adminuser", "admin@example.com", "admin" with the login, email
234   -and password of your environment admin)
  213 +and password of your environment administrator)
235 214  
236 215 To start the Noosfero application servers:
237 216  
... ... @@ -241,23 +220,6 @@ At this point you have a functional Noosfero installation running, the only
241 220 thing left is to configure your webserver as a reverse proxy to pass requests
242 221 to them.
243 222  
244   -Enabling exception notifications
245   -================================
246   -
247   -This is an optional step. You will need it only if you want to receive e-mail
248   -notifications when some exception occurs on Noosfero.
249   -
250   -First, install this version of the gem.
251   -Others versions may not be compatible with Noosfero:
252   -
253   -# gem install exception_notification -v 1.0.20090728
254   -
255   -You can configure the e-mails that will receive the notifications.
256   -Change the file config/noosfero.yml as the following example, replacing the
257   -e-mails by real ones:
258   -
259   - production:
260   - exception_recipients: [admin@example.com, you@example.com]
261 223  
262 224 ==================
263 225 Apache instalation
... ... @@ -351,6 +313,26 @@ Now restart your apache server (as root):
351 313  
352 314 # invoke-rc.d apache2 restart
353 315  
  316 +
  317 +Enabling exception notifications
  318 +================================
  319 +
  320 +This is an optional step. You will need it only if you want to receive e-mail
  321 +notifications when some exception occurs on Noosfero.
  322 +
  323 +First, install this version of the gem.
  324 +Others versions may not be compatible with Noosfero:
  325 +
  326 +# gem install exception_notification -v 1.0.20090728
  327 +
  328 +You can configure the e-mails that will receive the notifications.
  329 +Change the file config/noosfero.yml as the following example, replacing the
  330 +e-mails by real ones:
  331 +
  332 + production:
  333 + exception_recipients: [admin@example.com, you@example.com]
  334 +
  335 +
354 336 ============
355 337 Maintainance
356 338 ============
... ...
INSTALL.varnish
... ... @@ -45,6 +45,10 @@ Install the RPAF apache module (or skip this step if not using apache):
45 45 On manual installations, change "/etc/noosfero/*" to
46 46 "{Rails.root}/etc/noosfero/*"
47 47  
  48 +NOTE: it is very important that the *.vcl files are included in that order,
  49 +i.e. *first* include "varnish-noosfero.vcl", and *after*
  50 +"noosfero-accept-language.cvl".
  51 +
48 52 4c) Restart Varnish
49 53  
50 54 # invoke-rc.d varnish restart
... ...
RELEASING
... ... @@ -31,6 +31,7 @@ To prepare a release of noosfero, you must follow the steps below:
31 31 sha1 of the package (with sha1sum and paste the SHA1 hash as comment in the
32 32 attachment form)
33 33 * Download the attached and verify the MD5 hash
  34 +* Push the new version tag (with git push --tags)
34 35 * Update an eventual demonstration version that you run.
35 36 * Write an announcement e-mail to the relevant mailing lists pointing to the
36 37 release notes, and maybe to the demonstration version.
... ...
Rakefile
... ... @@ -5,4 +5,3 @@
5 5 require File.expand_path('../config/application', __FILE__)
6 6  
7 7 Noosfero::Application.load_tasks
8   -
... ...
app/controllers/admin/environment_design_controller.rb
... ... @@ -3,7 +3,8 @@ class EnvironmentDesignController &lt; BoxOrganizerController
3 3 protect 'edit_environment_design', :environment
4 4  
5 5 def available_blocks
6   - @available_blocks ||= [ ArticleBlock, LoginBlock, EnvironmentStatisticsBlock, RecentDocumentsBlock, EnterprisesBlock, CommunitiesBlock, PeopleBlock, SellersSearchBlock, LinkListBlock, FeedReaderBlock, SlideshowBlock, HighlightsBlock, FeaturedProductsBlock, CategoriesBlock, RawHTMLBlock ]
  6 + @available_blocks ||= [ ArticleBlock, LoginBlock, EnvironmentStatisticsBlock, RecentDocumentsBlock, EnterprisesBlock, CommunitiesBlock, PeopleBlock, SellersSearchBlock, LinkListBlock, FeedReaderBlock, SlideshowBlock, HighlightsBlock, FeaturedProductsBlock, CategoriesBlock, RawHTMLBlock, TagsBlock ]
  7 + @available_blocks += plugins.dispatch(:extra_blocks, :type => Environment)
7 8 end
8 9  
9 10 end
... ...
app/controllers/admin/region_validators_controller.rb
... ... @@ -33,7 +33,7 @@ class RegionValidatorsController &lt; AdminController
33 33 def load_region_and_search
34 34 @region = environment.regions.find(params[:id])
35 35 if params[:search]
36   - @search = @region.search_possible_validators(params[:search])
  36 + @search = find_by_contents(:organizations, Organization, params[:search])[:results].reject {|item| @region.validator_ids.include?(item.id) }
37 37 end
38 38 end
39 39  
... ...
app/controllers/admin/users_controller.rb
  1 +require 'csv'
  2 +
1 3 class UsersController < AdminController
2 4  
3 5 protect 'manage_environment_users', :environment
... ... @@ -15,8 +17,16 @@ class UsersController &lt; AdminController
15 17 :disposition => "attachment; filename=users.xml"
16 18 end
17 19 format.csv do
18   - @users = User.find(:all, :conditions => {:environment_id => environment.id}, :include => [:person])
19   - render :template => "users/index_csv.html.erb", :content_type => 'text/csv', :layout => false
  20 + # using a direct connection with the dbms to optimize
  21 + command = User.send(:sanitize_sql, ["SELECT profiles.name, users.email FROM profiles
  22 + INNER JOIN users ON profiles.user_id=users.id
  23 + WHERE profiles.environment_id = ?", environment.id])
  24 + users = User.connection.execute(command)
  25 + csv_content = "name;email\n"
  26 + users.each { |u|
  27 + CSV.generate_row([u['name'], u['email']], 2, csv_content, fs=';')
  28 + }
  29 + render :text => csv_content, :content_type => 'text/csv', :layout => false
20 30 end
21 31 end
22 32 end
... ...
app/controllers/application_controller.rb
... ... @@ -153,4 +153,18 @@ class ApplicationController &lt; ActionController::Base
153 153 end
154 154 end
155 155  
  156 + def find_by_contents(asset, scope, query, paginate_options={:page => 1}, options={})
  157 + scope = scope.send(options[:filter]) if options[:filter]
  158 +
  159 + @plugins.first(:find_by_contents, asset, scope, query, paginate_options, options) ||
  160 + fallback_find_by_contents(asset, scope, query, paginate_options, options)
  161 + end
  162 +
  163 + private
  164 +
  165 + def fallback_find_by_contents(asset, scope, query, paginate_options, options)
  166 + return {:results => scope.paginate(paginate_options)} if query.blank?
  167 + {:results => scope.like_search(query).paginate(paginate_options)}
  168 + end
  169 +
156 170 end
... ...
app/controllers/box_organizer_controller.rb
... ... @@ -68,8 +68,8 @@ class BoxOrganizerController &lt; ApplicationController
68 68 raise ArgumentError.new("Type %s is not allowed. Go away." % type)
69 69 end
70 70 else
71   - @center_block_types = Box.acceptable_center_blocks & available_blocks
72   - @side_block_types = Box.acceptable_side_blocks & available_blocks
  71 + @center_block_types = (Box.acceptable_center_blocks & available_blocks) + plugins.dispatch(:extra_blocks, :type => boxes_holder.class, :position => 1)
  72 + @side_block_types = (Box.acceptable_side_blocks & available_blocks) + plugins.dispatch(:extra_blocks, :type => boxes_holder.class, :position => [2,3])
73 73 @boxes = boxes_holder.boxes
74 74 render :action => 'add_block', :layout => false
75 75 end
... ...
app/controllers/my_profile/cms_controller.rb
... ... @@ -18,7 +18,7 @@ class CmsController &lt; MyProfileController
18 18  
19 19 protect_if :only => :upload_files do |c, user, profile|
20 20 article_id = c.params[:parent_id]
21   - (article_id && profile.articles.find(article_id).allow_create?(user)) ||
  21 + (!article_id.blank? && profile.articles.find(article_id).allow_create?(user)) ||
22 22 (user && (user.has_permission?('post_content', profile) || user.has_permission?('publish_content', profile)))
23 23 end
24 24  
... ... @@ -270,7 +270,7 @@ class CmsController &lt; MyProfileController
270 270  
271 271 def search
272 272 query = params[:q]
273   - results = profile.files.published.find_by_contents(query)[:results]
  273 + results = find_by_contents(:uploaded_files, profile.files.published, query)[:results]
274 274 render :text => article_list_to_json(results), :content_type => 'application/json'
275 275 end
276 276  
... ...
app/controllers/my_profile/profile_design_controller.rb
... ... @@ -7,17 +7,25 @@ class ProfileDesignController &lt; BoxOrganizerController
7 7 def available_blocks
8 8 blocks = [ ArticleBlock, TagsBlock, RecentDocumentsBlock, ProfileInfoBlock, LinkListBlock, MyNetworkBlock, FeedReaderBlock, ProfileImageBlock, LocationBlock, SlideshowBlock, ProfileSearchBlock, HighlightsBlock ]
9 9  
  10 + blocks += plugins.dispatch(:extra_blocks)
  11 +
10 12 # blocks exclusive for organizations
11 13 if profile.has_members?
12 14 blocks << MembersBlock
13 15 end
14 16  
15   - # blocks exclusive to person
  17 + # blocks exclusive to people
16 18 if profile.person?
17 19 blocks << FriendsBlock
18 20 blocks << FavoriteEnterprisesBlock
19 21 blocks << CommunitiesBlock
20 22 blocks << EnterprisesBlock
  23 + blocks += plugins.dispatch(:extra_blocks, :type => Person)
  24 + end
  25 +
  26 + # blocks exclusive to communities
  27 + if profile.community?
  28 + blocks += plugins.dispatch(:extra_blocks, :type => Community)
21 29 end
22 30  
23 31 # blocks exclusive for enterprises
... ... @@ -26,6 +34,7 @@ class ProfileDesignController &lt; BoxOrganizerController
26 34 blocks << HighlightsBlock
27 35 blocks << FeaturedProductsBlock
28 36 blocks << FansBlock
  37 + blocks += plugins.dispatch(:extra_blocks, :type => Enterprise)
29 38 end
30 39  
31 40 # product block exclusive for enterprises in environments that permits it
... ... @@ -33,7 +42,7 @@ class ProfileDesignController &lt; BoxOrganizerController
33 42 blocks << ProductsBlock
34 43 end
35 44  
36   - # block exclusive to profile has blog
  45 + # block exclusive to profiles that have blog
37 46 if profile.has_blog?
38 47 blocks << BlogArchivesBlock
39 48 end
... ...
app/controllers/my_profile/profile_members_controller.rb
... ... @@ -32,7 +32,6 @@ class ProfileMembersController &lt; MyProfileController
32 32  
33 33 def last_admin
34 34 @roles = [Profile::Roles.admin(environment.id)]
35   - @pre_population = [].to_json
36 35 end
37 36  
38 37 def add_role
... ...
app/controllers/public/account_controller.rb
... ... @@ -4,6 +4,7 @@ class AccountController &lt; ApplicationController
4 4  
5 5 before_filter :login_required, :only => [:activation_question, :accept_terms, :activate_enterprise]
6 6 before_filter :redirect_if_logged_in, :only => [:login, :signup]
  7 + before_filter :protect_from_bots, :only => :signup
7 8  
8 9 # say something nice, you goof! something sweet.
9 10 def index
... ... @@ -55,6 +56,11 @@ class AccountController &lt; ApplicationController
55 56 render :action => 'login', :layout => false
56 57 end
57 58  
  59 + def signup_time
  60 + key = set_signup_start_time_for_now
  61 + render :text => { :ok=>true, :key=>key }.to_json
  62 + end
  63 +
58 64 # action to register an user to the application
59 65 def signup
60 66 if @plugins.dispatch(:allow_user_registration).include?(false)
... ... @@ -62,12 +68,9 @@ class AccountController &lt; ApplicationController
62 68 session[:notice] = _("This environment doesn't allow user registration.")
63 69 end
64 70  
  71 + @block_bot = !!session[:may_be_a_bot]
65 72 @invitation_code = params[:invitation_code]
66 73 begin
67   - if params[:user]
68   - params[:user].delete(:password_confirmation_clear)
69   - params[:user].delete(:password_clear)
70   - end
71 74 @user = User.new(params[:user])
72 75 @user.terms_of_use = environment.terms_of_use
73 76 @user.environment = environment
... ... @@ -76,19 +79,28 @@ class AccountController &lt; ApplicationController
76 79 @person = Person.new(params[:profile_data])
77 80 @person.environment = @user.environment
78 81 if request.post?
79   - @user.signup!
80   - owner_role = Role.find_by_name('owner')
81   - @user.person.affiliate(@user.person, [owner_role]) if owner_role
82   - invitation = Task.find_by_code(@invitation_code)
83   - if invitation
84   - invitation.update_attributes!({:friend => @user.person})
85   - invitation.finish
86   - end
87   - if @user.activated?
88   - self.current_user = @user
89   - redirect_to '/'
  82 + if may_be_a_bot
  83 + set_signup_start_time_for_now
  84 + @block_bot = true
  85 + session[:may_be_a_bot] = true
90 86 else
91   - @register_pending = true
  87 + if session[:may_be_a_bot]
  88 + return false unless verify_recaptcha :model=>@user, :message=>_('Captcha (the human test)')
  89 + end
  90 + @user.signup!
  91 + owner_role = Role.find_by_name('owner')
  92 + @user.person.affiliate(@user.person, [owner_role]) if owner_role
  93 + invitation = Task.find_by_code(@invitation_code)
  94 + if invitation
  95 + invitation.update_attributes!({:friend => @user.person})
  96 + invitation.finish
  97 + end
  98 + if @user.activated?
  99 + self.current_user = @user
  100 + redirect_to '/'
  101 + else
  102 + @register_pending = true
  103 + end
92 104 end
93 105 end
94 106 rescue ActiveRecord::RecordInvalid
... ... @@ -97,6 +109,7 @@ class AccountController &lt; ApplicationController
97 109 @person.errors.delete(:user_id)
98 110 render :action => 'signup'
99 111 end
  112 + clear_signup_start_time
100 113 end
101 114  
102 115 # action to perform logout from the application
... ... @@ -271,7 +284,36 @@ class AccountController &lt; ApplicationController
271 284 def no_redirect
272 285 @cannot_redirect = true
273 286 end
274   -
  287 +
  288 + def set_signup_start_time_for_now
  289 + key = 'signup_start_time_' + rand.to_s.split('.')[1]
  290 + Rails.cache.write key, Time.now
  291 + key
  292 + end
  293 +
  294 + def get_signup_start_time
  295 + Rails.cache.read params[:signup_time_key]
  296 + end
  297 +
  298 + def clear_signup_start_time
  299 + Rails.cache.delete params[:signup_time_key] if params[:signup_time_key]
  300 + end
  301 +
  302 + def may_be_a_bot
  303 + # No minimum signup delay, no bot test.
  304 + return false if environment.min_signup_delay == 0
  305 +
  306 + # answering captcha, may be human!
  307 + return false if params[:recaptcha_response_field]
  308 +
  309 + # never set signup_time, hi wget!
  310 + signup_start_time = get_signup_start_time
  311 + return true if signup_start_time.nil?
  312 +
  313 + # so fast, so bot.
  314 + signup_start_time > ( Time.now - environment.min_signup_delay.seconds )
  315 + end
  316 +
275 317 def check_answer
276 318 unless answer_correct
277 319 @enterprise.block
... ...
app/controllers/public/catalog_controller.rb
1 1 class CatalogController < PublicController
2 2 needs_profile
  3 + no_design_blocks
3 4  
4 5 before_filter :check_enterprise_and_environment
5 6  
6 7 def index
7   - @products = @profile.products.paginate(:order => 'name asc', :per_page => 9, :page => params[:page])
  8 + @category = params[:level] ? ProductCategory.find(params[:level]) : nil
  9 + @products = @profile.products.from_category(@category).paginate(:order => 'available desc, highlighted desc, name asc', :per_page => 9, :page => params[:page])
  10 + @categories = ProductCategory.on_level(params[:level]).order(:name)
8 11 end
9 12  
10 13 protected
... ...
app/controllers/public/content_viewer_controller.rb
... ... @@ -25,24 +25,26 @@ class ContentViewerController &lt; ApplicationController
25 25 return
26 26 end
27 27 end
28   -
29   - # page not found, give error
30   - if @page.nil?
31   - render_not_found(@path)
32   - return
33   - end
34 28 end
35 29  
36   - if !@page.display_to?(user)
37   - if profile.display_info_to?(user) || !profile.visible?
38   - message = _('You are not allowed to view this content. You can contact the owner of this profile to request access then.')
  30 + if !@page.nil? && !@page.display_to?(user)
  31 + if !profile.public?
  32 + private_profile_partial_parameters
  33 + render :template => 'profile/_private_profile.rhtml', :status => 403
  34 + else #if !profile.visible?
  35 + message = _('You are not allowed to view this content.')
  36 + message += ' ' + _('You can contact the owner of this profile to request access then.')
39 37 render_access_denied(message)
40   - elsif !profile.public?
41   - redirect_to :controller => 'profile', :action => 'index', :profile => profile.identifier
42 38 end
43 39 return
44 40 end
45 41  
  42 + # page not found, give error
  43 + if @page.nil?
  44 + render_not_found(@path)
  45 + return
  46 + end
  47 +
46 48 if request.xhr? && params[:toolbar]
47 49 render :partial => 'article_toolbar'
48 50 return
... ...
app/controllers/public/profile_controller.rb
... ... @@ -368,14 +368,7 @@ class ProfileController &lt; PublicController
368 368 end
369 369  
370 370 def private_profile
371   - if profile.person?
372   - @action = :add_friend
373   - @message = _("The content here is available to %s's friends only.") % profile.short_name
374   - else
375   - @action = :join
376   - @message = _('The contents in this community is available to members only.')
377   - end
378   - @no_design_blocks = true
  371 + private_profile_partial_parameters
379 372 end
380 373  
381 374 def invisible_profile
... ...
app/controllers/public/profile_search_controller.rb
... ... @@ -11,7 +11,7 @@ class ProfileSearchController &lt; PublicController
11 11 if params[:where] == 'environment'
12 12 redirect_to :controller => 'search', :query => @q
13 13 else
14   - @results = profile.articles.published.find_by_contents(@q, {:per_page => 10, :page => params[:page]})[:results]
  14 + @results = find_by_contents(:articles, profile.articles.published, @q, {:per_page => 10, :page => params[:page]})[:results]
15 15 end
16 16 end
17 17 end
... ...
app/controllers/public/search_controller.rb
... ... @@ -4,10 +4,11 @@ class SearchController &lt; PublicController
4 4 include SearchHelper
5 5 include ActionView::Helpers::NumberHelper
6 6  
7   - before_filter :redirect_asset_param, :except => [:facets_browse, :assets]
  7 + before_filter :redirect_asset_param, :except => :assets
8 8 before_filter :load_category
9 9 before_filter :load_search_assets
10 10 before_filter :load_query
  11 + before_filter :load_filter
11 12  
12 13 # Backwards compatibility with old URLs
13 14 def redirect_asset_param
... ... @@ -17,25 +18,51 @@ class SearchController &lt; PublicController
17 18  
18 19 no_design_blocks
19 20  
20   - def facets_browse
21   - @asset = params[:asset]
22   - @asset_class = asset_class(@asset)
  21 + def index
  22 + @searches = {}
  23 + @order = []
  24 + @names = {}
  25 + @results_only = true
23 26  
24   - @facets_only = true
25   - send(@asset)
  27 + @enabled_searches.select { |key,description| @searching[key] }.each do |key, description|
  28 + load_query
  29 + @asset = key
  30 + send(key)
  31 + @order << key
  32 + @names[key] = getterm(description)
  33 + end
  34 + @asset = nil
26 35  
27   - @facet = @asset_class.map_facets_for(environment).find { |facet| facet[:id] == params[:facet_id] }
28   - raise 'Facet not found' if @facet.nil?
  36 + if @searches.keys.size == 1
  37 + @asset = @searches.keys.first
  38 + render :action => @asset
  39 + end
  40 + end
29 41  
30   - render :layout => false
  42 + # view the summary of one category
  43 + def category_index
  44 + @searches = {}
  45 + @order = []
  46 + @names = {}
  47 + limit = MULTIPLE_SEARCH_LIMIT
  48 + [
  49 + [ :people, _('People'), :recent_people ],
  50 + [ :enterprises, _('Enterprises'), :recent_enterprises ],
  51 + [ :products, _('Products'), :recent_products ],
  52 + [ :events, _('Upcoming events'), :upcoming_events ],
  53 + [ :communities, _('Communities'), :recent_communities ],
  54 + [ :articles, _('Contents'), :recent_articles ]
  55 + ].each do |asset, name, filter|
  56 + @order << asset
  57 + @searches[asset]= {:results => @category.send(filter, limit)}
  58 + raise "No total_entries for: #{asset}" unless @searches[asset][:results].respond_to?(:total_entries)
  59 + @names[asset] = name
  60 + end
31 61 end
32 62  
33 63 def articles
34   - if !@empty_query
35   - full_text_search ['public:true']
36   - else
37   - @results[@asset] = @environment.articles.public.send(@filter).paginate(paginate_options)
38   - end
  64 + @scope = @environment.articles.public
  65 + full_text_search
39 66 end
40 67  
41 68 def contents
... ... @@ -43,49 +70,23 @@ class SearchController &lt; PublicController
43 70 end
44 71  
45 72 def people
46   - if !@empty_query
47   - full_text_search ['public:true']
48   - else
49   - @results[@asset] = visible_profiles(Person).send(@filter).paginate(paginate_options)
50   - end
  73 + @scope = visible_profiles(Person)
  74 + full_text_search
51 75 end
52 76  
53 77 def products
54   - public_filters = ['public:true', 'enabled:true']
55   - if !@empty_query
56   - full_text_search public_filters
57   - else
58   - @one_page = true
59   - @geosearch = logged_in? && current_user.person.lat && current_user.person.lng
60   -
61   - extra_limit = LIST_SEARCH_LIMIT*5
62   - sql_options = {:limit => LIST_SEARCH_LIMIT, :order => 'random()'}
63   - if @geosearch
64   - full_text_search public_filters, :sql_options => sql_options, :extra_limit => extra_limit,
65   - :alternate_query => "{!boost b=recip(geodist(),#{"%e" % (1.to_f/DistBoost)},1,1)}",
66   - :radius => DistFilt, :latitude => current_user.person.lat, :longitude => current_user.person.lng
67   - else
68   - full_text_search public_filters, :sql_options => sql_options, :extra_limit => extra_limit,
69   - :boost_functions => ['recip(ms(NOW/HOUR,updated_at),1.3e-10,1,1)']
70   - end
71   - end
  78 + @scope = @environment.products
  79 + full_text_search
72 80 end
73 81  
74 82 def enterprises
75   - if !@empty_query
76   - full_text_search ['public:true']
77   - else
78   - @filter_title = _('Enterprises from network')
79   - @results[@asset] = visible_profiles(Enterprise, [{:products => :product_category}]).paginate(paginate_options)
80   - end
  83 + @scope = visible_profiles(Enterprise, [{:products => :product_category}])
  84 + full_text_search
81 85 end
82 86  
83 87 def communities
84   - if !@empty_query
85   - full_text_search ['public:true']
86   - else
87   - @results[@asset] = visible_profiles(Community).send(@filter).paginate(paginate_options)
88   - end
  88 + @scope = visible_profiles(Community)
  89 + full_text_search
89 90 end
90 91  
91 92 def events
... ... @@ -93,7 +94,7 @@ class SearchController &lt; PublicController
93 94 month = (params[:month] ? params[:month].to_i : Date.today.month)
94 95 day = (params[:day] ? params[:day].to_i : Date.today.day)
95 96 date = build_date(params[:year], params[:month], params[:day])
96   - date_range = (date - 1.month)..(date + 1.month).at_end_of_month
  97 + date_range = (date - 1.month).at_beginning_of_month..(date + 1.month).at_end_of_month
97 98  
98 99 @selected_day = nil
99 100 @events_of_the_day = []
... ... @@ -104,64 +105,21 @@ class SearchController &lt; PublicController
104 105 environment.events.by_day(@selected_day)
105 106 end
106 107  
107   - if !@empty_query
108   - full_text_search
109   - else
110   - @results[@asset] = date_range ? environment.events.by_range(date_range) : environment.events
111   - end
  108 + @scope = date_range && params[:action] == 'events' ? environment.events.by_range(date_range) : environment.events
  109 + full_text_search
112 110  
113   - events = @results[@asset]
  111 + events = @searches[@asset][:results]
114 112 @calendar = populate_calendar(date, events)
115 113 @previous_calendar = populate_calendar(date - 1.month, events)
116 114 @next_calendar = populate_calendar(date + 1.month, events)
117 115 end
118 116  
119   - def index
120   - @results = {}
121   - @order = []
122   - @names = {}
123   - @results_only = true
124   -
125   - @enabled_searches.select { |key,description| @searching[key] }.each do |key, description|
126   - load_query
127   - @asset = key
128   - send(key)
129   - @order << key
130   - @names[key] = getterm(description)
131   - end
132   - @asset = nil
133   - @facets = {}
134   -
135   - render :action => @results.keys.first if @results.keys.size == 1
136   - end
137   -
138 117 # keep old URLs workings
139 118 def assets
140 119 params[:action] = params[:asset].is_a?(Array) ? :index : params.delete(:asset)
141 120 redirect_to params
142 121 end
143 122  
144   - # view the summary of one category
145   - def category_index
146   - @results = {}
147   - @order = []
148   - @names = {}
149   - limit = MULTIPLE_SEARCH_LIMIT
150   - [
151   - [ :people, _('People'), :recent_people ],
152   - [ :enterprises, _('Enterprises'), :recent_enterprises ],
153   - [ :products, _('Products'), :recent_products ],
154   - [ :events, _('Upcoming events'), :upcoming_events ],
155   - [ :communities, _('Communities'), :recent_communities ],
156   - [ :articles, _('Contents'), :recent_articles ]
157   - ].each do |asset, name, filter|
158   - @order << asset
159   - @results[asset] = @category.send(filter, limit)
160   - raise "No total_entries for: #{asset}" unless @results[asset].respond_to?(:total_entries)
161   - @names[asset] = name
162   - end
163   - end
164   -
165 123 def tags
166 124 @tags_cache_key = "tags_env_#{environment.id.to_s}"
167 125 if is_cache_expired?(@tags_cache_key)
... ... @@ -173,7 +131,7 @@ class SearchController &lt; PublicController
173 131 @tag = params[:tag]
174 132 @tag_cache_key = "tag_#{CGI.escape(@tag.to_s)}_env_#{environment.id.to_s}_page_#{params[:npage]}"
175 133 if is_cache_expired?(@tag_cache_key)
176   - @results[@asset] = environment.articles.find_tagged_with(@tag).paginate(paginate_options)
  134 + @searches[@asset] = {:results => environment.articles.find_tagged_with(@tag).paginate(paginate_options)}
177 135 end
178 136 end
179 137  
... ... @@ -187,11 +145,9 @@ class SearchController &lt; PublicController
187 145 protected
188 146  
189 147 def load_query
190   - @asset = params[:action].to_sym
  148 + @asset = (params[:asset] || params[:action]).to_sym
191 149 @order ||= [@asset]
192   - @results ||= {}
193   - @filter = filter
194   - @filter_title = filter_description(@asset, @filter)
  150 + @searches ||= {}
195 151  
196 152 @query = params[:query] || ''
197 153 @empty_query = @category.nil? && @query.blank?
... ... @@ -211,42 +167,13 @@ class SearchController &lt; PublicController
211 167 end
212 168 end
213 169  
214   - FILTERS = %w(
215   - more_recent
216   - more_active
217   - more_popular
218   - more_comments
219   - )
220   - def filter
221   - if FILTERS.include?(params[:filter])
222   - params[:filter]
223   - else
224   - 'more_recent'
225   - end
226   - end
227   -
228   - def filter_description(asset, filter)
229   - {
230   - 'articles_more_recent' => _('More recent contents from network'),
231   - 'articles_more_popular' => _('More viewed contents from network'),
232   - 'articles_more_comments' => _('Most commented contents from network'),
233   - 'people_more_recent' => _('More recent people from network'),
234   - 'people_more_active' => _('More active people from network'),
235   - 'people_more_popular' => _('More popular people from network'),
236   - 'communities_more_recent' => _('More recent communities from network'),
237   - 'communities_more_active' => _('More active communities from network'),
238   - 'communities_more_popular' => _('More popular communities from network'),
239   - 'products_more_recent' => _('Highlights'),
240   - }[asset.to_s + '_' + filter]
241   - end
242   -
243 170 def load_search_assets
244   - if Searches.keys.include?(params[:action].to_sym) and environment.enabled?("disable_asset_#{params[:action]}")
  171 + if SEARCHES.keys.include?(params[:action].to_sym) && environment.enabled?("disable_asset_#{params[:action]}")
245 172 render_not_found
246 173 return
247 174 end
248 175  
249   - @enabled_searches = Searches.select {|key, name| environment.disabled?("disable_asset_#{params[:action]}") }
  176 + @enabled_searches = SEARCHES.select {|key, name| environment.disabled?("disable_asset_#{key}") }
250 177 @searching = {}
251 178 @titles = {}
252 179 @enabled_searches.each do |key, name|
... ... @@ -256,13 +183,19 @@ class SearchController &lt; PublicController
256 183 @names = @titles if @names.nil?
257 184 end
258 185  
  186 + def load_filter
  187 + @filter = 'more_recent'
  188 + if SEARCHES.keys.include?(@asset.to_sym)
  189 + available_filters = asset_class(@asset)::SEARCH_FILTERS
  190 + @filter = params[:filter] if available_filters.include?(params[:filter])
  191 + end
  192 + end
  193 +
259 194 def limit
260   - if map_search?
  195 + if map_search?(@searches)
261 196 MAP_SEARCH_LIMIT
262 197 elsif !multiple_search?
263   - if [:people, :communities].include? @asset
264   - BLOCKS_SEARCH_LIMIT
265   - elsif @asset == :enterprises and @empty_query
  198 + if [:people, :communities, :enterprises].include? @asset
266 199 BLOCKS_SEARCH_LIMIT
267 200 else
268 201 LIST_SEARCH_LIMIT
... ... @@ -273,41 +206,12 @@ class SearchController &lt; PublicController
273 206 end
274 207  
275 208 def paginate_options(page = params[:page])
276   - page = 1 if multiple_search? or params[:display] == 'map'
  209 + page = 1 if multiple_search?(@searches) || params[:display] == 'map'
277 210 { :per_page => limit, :page => page }
278 211 end
279 212  
280   - def full_text_search(filters = [], options = {})
281   - paginate_options = paginate_options(params[:page])
282   - asset_class = asset_class(@asset)
283   - solr_options = options
284   - pg_options = paginate_options(params[:page])
285   -
286   - if !multiple_search?
287   - if !@results_only and asset_class.respond_to? :facets
288   - solr_options.merge! asset_class.facets_find_options(params[:facet])
289   - solr_options[:all_facets] = true
290   - end
291   - solr_options[:filter_queries] ||= []
292   - solr_options[:filter_queries] += filters
293   - solr_options[:filter_queries] << "environment_id:#{environment.id}"
294   - solr_options[:filter_queries] << asset_class.facet_category_query.call(@category) if @category
295   -
296   - solr_options[:boost_functions] ||= []
297   - params[:order_by] = nil if params[:order_by] == 'none'
298   - if params[:order_by]
299   - order = SortOptions[@asset][params[:order_by].to_sym]
300   - raise "Unknown order by" if order.nil?
301   - order[:solr_opts].each do |opt, value|
302   - solr_options[opt] = value.is_a?(Proc) ? instance_eval(&value) : value
303   - end
304   - end
305   - end
306   -
307   - ret = asset_class.find_by_contents(@query, paginate_options, solr_options)
308   - @results[@asset] = ret[:results]
309   - @facets = ret[:facets]
310   - @all_facets = ret[:all_facets]
  213 + def full_text_search
  214 + @searches[@asset] = find_by_contents(@asset, @scope, @query, paginate_options, {:category => @category, :filter => @filter})
311 215 end
312 216  
313 217 private
... ...
app/helpers/application_helper.rb
... ... @@ -32,6 +32,12 @@ module ApplicationHelper
32 32  
33 33 include AccountHelper
34 34  
  35 + include BlogHelper
  36 +
  37 + include ContentViewerHelper
  38 +
  39 + include LayoutHelper
  40 +
35 41 def locale
36 42 (@page && !@page.language.blank?) ? @page.language : FastGettext.locale
37 43 end
... ... @@ -262,12 +268,16 @@ module ApplicationHelper
262 268 end
263 269  
264 270 def button_bar(options = {}, &block)
265   - concat(content_tag('div', capture(&block) + tag('br', :style => 'clear: left;'), { :class => 'button-bar' }.merge(options)))
  271 + options[:class].nil? ?
  272 + options[:class]='button-bar' :
  273 + options[:class]+=' button-bar'
  274 + concat(content_tag('div', capture(&block) + tag('br', :style => 'clear: left;'), options))
266 275 end
267 276  
268   - def partial_for_class_in_view_path(klass, view_path, suffix = nil)
  277 +
  278 + def partial_for_class_in_view_path(klass, view_path, prefix = nil, suffix = nil)
269 279 return nil if klass.nil?
270   - name = [klass.name.underscore, suffix].compact.map(&:to_s).join('_')
  280 + name = [prefix, klass.name.underscore, suffix].compact.map(&:to_s).join('_')
271 281  
272 282 search_name = String.new(name)
273 283 if search_name.include?("/")
... ... @@ -280,14 +290,14 @@ module ApplicationHelper
280 290 path = defined?(params) && params[:controller] ? File.join(view_path, params[:controller], search_name + '.html.erb') : File.join(view_path, search_name + '.html.erb')
281 291 return name if File.exists?(File.join(path))
282 292  
283   - partial_for_class_in_view_path(klass.superclass, view_path, suffix)
  293 + partial_for_class_in_view_path(klass.superclass, view_path, prefix, suffix)
284 294 end
285 295  
286   - def partial_for_class(klass, suffix=nil)
  296 + def partial_for_class(klass, prefix=nil, suffix=nil)
287 297 raise ArgumentError, 'No partial for object. Is there a partial for any class in the inheritance hierarchy?' if klass.nil?
288 298 name = klass.name.underscore
289   - controller.view_paths.each do |view_path|
290   - partial = partial_for_class_in_view_path(klass, view_path, suffix)
  299 + @controller.view_paths.each do |view_path|
  300 + partial = partial_for_class_in_view_path(klass, view_path, prefix, suffix)
291 301 return partial if partial
292 302 end
293 303  
... ... @@ -348,10 +358,6 @@ module ApplicationHelper
348 358 end
349 359 end
350 360  
351   - def theme_stylesheet_path
352   - theme_path + '/style.css'
353   - end
354   -
355 361 def current_theme
356 362 @current_theme ||=
357 363 begin
... ... @@ -491,23 +497,24 @@ module ApplicationHelper
491 497  
492 498 def profile_cat_icons( profile )
493 499 if profile.class == Enterprise
494   - icons =
495   - profile.product_categories.map{ |c| c.size > 1 ? c[1] : nil }.
496   - compact.uniq.map{ |c|
497   - cat_name = c.gsub( /[-_\s,.;'"]+/, '_' )
498   - cat_icon = "/images/icons-cat/#{cat_name}.png"
499   - if ! File.exists? Rails.root.to_s() + '/public/' + cat_icon
500   - cat_icon = '/images/icons-cat/undefined.png'
501   - end
502   - content_tag 'span',
503   - content_tag( 'span', c ),
504   - :title => c,
505   - :class => 'product-cat-icon cat_icon_' + cat_name,
506   - :style => "background-image:url(#{cat_icon})"
507   - }.join "\n"
508   - content_tag 'div',
509   - content_tag( 'span', _('Principal Product Categories'), :class => 'header' ) +"\n"+ icons,
510   - :class => 'product-category-icons'
  500 + icons = profile.product_categories.map{ |c| c.size > 1 ? c[1] : nil }.
  501 + compact.uniq.map do |c|
  502 + cat_name = c.gsub( /[-_\s,.;'"]+/, '_' )
  503 + cat_icon = "/images/icons-cat/#{cat_name}.png"
  504 + if ! File.exists? RAILS_ROOT.to_s() + '/public/' + cat_icon
  505 + cat_icon = '/images/icons-cat/undefined.png'
  506 + end
  507 + content_tag('span',
  508 + content_tag( 'span', c ),
  509 + :title => c,
  510 + :class => 'product-cat-icon cat_icon_' + cat_name,
  511 + :style => "background-image:url(#{cat_icon})"
  512 + )
  513 + end.join("\n").html_safe
  514 + content_tag('div',
  515 + content_tag( 'span', _('Principal Product Categories'), :class => 'header' ) +"\n"+ icons,
  516 + :class => 'product-category-icons'
  517 + )
511 518 else
512 519 ''
513 520 end
... ... @@ -631,10 +638,10 @@ module ApplicationHelper
631 638 # FIXME
632 639 ([toplevel] + toplevel.children_for_menu).each do |cat|
633 640 if cat.top_level?
634   - result << '<div class="categorie_box">'
  641 + result << '<div class="categorie_box">'.html_safe
635 642 result << icon_button( :down, _('open'), '#', :onclick => 'open_close_cat(this); return false' )
636 643 result << content_tag('h5', toplevel.name)
637   - result << '<div style="display:none"><ul class="categories">'
  644 + result << '<div style="display:none"><ul class="categories">'.html_safe
638 645 else
639 646 checkbox_id = "#{object_name}_#{cat.full_name.downcase.gsub(/\s+|\//, '_')}"
640 647 result << content_tag('li', labelled_check_box(
... ... @@ -645,7 +652,7 @@ module ApplicationHelper
645 652 :class => ( object.category_ids.include?(cat.id) ? 'cat_checked' : '' ) ) + "\n"
646 653 end
647 654 end
648   - result << '</ul></div></div>'
  655 + result << '</ul></div></div>'.html_safe
649 656 end
650 657  
651 658 content_tag('div', result)
... ... @@ -785,10 +792,10 @@ module ApplicationHelper
785 792 :class => 'lineitem' + (line_item+=1).to_s() ) +"\n"
786 793 if line_item == line_size
787 794 line_item = 0
788   - html += "<br />\n"
  795 + html += "<br />\n".html_safe
789 796 end
790 797 }
791   - html += "<br />\n" if line_size == 0 || ( values.size % line_size ) > 0
  798 + html += "<br />\n".html_safe if line_size == 0 || ( values.size % line_size ) > 0
792 799 column = object.class.columns_hash[method.to_s]
793 800 text =
794 801 ( column ?
... ... @@ -871,14 +878,6 @@ module ApplicationHelper
871 878 content_tag('div', labelled_check_box(_('Public'), 'profile_data[fields_privacy]['+name+']', 'public', profile.public_fields.include?(name)), :class => 'field-privacy-selector')
872 879 end
873 880  
874   - def template_stylesheet_path
875   - if profile.nil?
876   - "/designs/templates/#{environment.layout_template}/stylesheets/style.css"
877   - else
878   - "/designs/templates/#{profile.layout_template}/stylesheets/style.css"
879   - end
880   - end
881   -
882 881 def login_url
883 882 options = Noosfero.url_options.merge({ :controller => 'account', :action => 'login' })
884 883 url_for(options)
... ... @@ -940,42 +939,13 @@ module ApplicationHelper
940 939 (@category ? " - #{@category.full_name}" : '')
941 940 end
942 941  
943   - def noosfero_javascript
944   - render :file => 'layouts/_javascript'
945   - end
946   -
947   - def noosfero_stylesheets
948   - [
949   - 'application',
950   - 'search',
951   - 'thickbox',
952   - 'lightbox',
953   - 'colorpicker',
954   - 'colorbox',
955   - pngfix_stylesheet_path,
956   - ] +
957   - tokeninput_stylesheets
958   - end
959   -
960 942 # DEPRECATED. Do not use this·
961 943 def import_controller_stylesheets(options = {})
962 944 stylesheet_import( "controller_"+ controller.controller_name(), options )
963 945 end
964 946  
965   - def pngfix_stylesheet_path
966   - 'iepngfix/iepngfix.css'
967   - end
968   -
969   - def tokeninput_stylesheets
970   - ['token-input', 'token-input-facebook', 'token-input-mac', 'token-input-facet']
971   - end
972   -
973   - def noosfero_layout_features
974   - render :file => 'shared/noosfero_layout_features'
975   - end
976   -
977 947 def link_to_email(email)
978   - javascript_tag('var array = ' + email.split('@').to_json + '; document.write("<a href=\'mailto:" + array.join("@") + "\'>" + array.join("@") + "</a>")')
  948 + javascript_tag('var array = ' + email.split('@').to_json + '; document.write("<a href=\'mailto:" + array.join("@") + "\'>" + array.join("@") + "</a>")'.html_safe)
979 949 end
980 950  
981 951 def stylesheet(*args)
... ... @@ -985,13 +955,43 @@ module ApplicationHelper
985 955 def article_to_html(article, options = {})
986 956 options.merge!(:page => params[:npage])
987 957 content = article.to_html(options)
988   - content = content.kind_of?(Proc) ? self.instance_eval(&content) : content
  958 + content = content.kind_of?(Proc) ? self.instance_eval(&content).html_safe : content.html_safe
989 959 @plugins && @plugins.each do |plugin|
990 960 content = plugin.parse_content(content)
991 961 end
992 962 content
993 963 end
994 964  
  965 + # Please, use link_to by default!
  966 + # This method was created to work around to inexplicable
  967 + # chain of problems when display_short_format was called
  968 + # from Article model for an ArticleBlock.
  969 + def reference_to_article(text, article, anchor=nil)
  970 + if article.profile.domains.empty?
  971 + href = "/#{article.url[:profile]}/"
  972 + else
  973 + href = "http://#{article.profile.domains.first.name}/"
  974 + end
  975 + href += article.url[:page].join('/')
  976 + href += '#' + anchor if anchor
  977 + content_tag('a', text, :href => href)
  978 + end
  979 +
  980 + def display_short_format(article, options={})
  981 + options[:comments_link] ||= true
  982 + options[:read_more_link] ||= true
  983 + html = content_tag('div',
  984 + article.lead +
  985 + content_tag('div',
  986 + (options[:comments_link] ? link_to_comments(article) : '') +
  987 + (options[:read_more_link] ? reference_to_article( _('Read more'), article) : ''),
  988 + :class => 'read-more'
  989 + ),
  990 + :class => 'short-post'
  991 + )
  992 + html
  993 + end
  994 +
995 995 def colorpicker_field(object_name, method, options = {})
996 996 text_field(object_name, method, options.merge(:class => 'colorpicker_field'))
997 997 end
... ... @@ -1001,7 +1001,7 @@ module ApplicationHelper
1001 1001 end
1002 1002  
1003 1003 def ui_icon(icon_class, extra_class = '')
1004   - "<span class='ui-icon #{icon_class} #{extra_class}' style='float:left; margin-right:7px;'></span>"
  1004 + "<span class='ui-icon #{icon_class} #{extra_class}' style='float:left; margin-right:7px;'></span>".html_safe
1005 1005 end
1006 1006  
1007 1007 def ui_button(label, url, html_options = {})
... ... @@ -1016,10 +1016,6 @@ module ApplicationHelper
1016 1016 theme_option(:jquery_theme) || 'smoothness_mod'
1017 1017 end
1018 1018  
1019   - def jquery_ui_theme_stylesheet_path
1020   - 'jquery.ui/' + jquery_theme + '/jquery-ui-1.8.2.custom'
1021   - end
1022   -
1023 1019 def ui_error(message)
1024 1020 content_tag('div', ui_icon('ui-icon-alert') + message, :class => 'alert fg-state-error ui-state-error')
1025 1021 end
... ... @@ -1033,13 +1029,13 @@ module ApplicationHelper
1033 1029 end
1034 1030  
1035 1031 def collapsed_item_icon
1036   - "<span class='ui-icon ui-icon-circlesmall-plus' style='float:left;'></span>"
  1032 + "<span class='ui-icon ui-icon-circlesmall-plus' style='float:left;'></span>".html_safe
1037 1033 end
1038 1034 def expanded_item_icon
1039   - "<span class='ui-icon ui-icon-circlesmall-minus' style='float:left;'></span>"
  1035 + "<span class='ui-icon ui-icon-circlesmall-minus' style='float:left;'></span>".html_safe
1040 1036 end
1041 1037 def leaf_item_icon
1042   - "<span class='ui-icon ui-icon-arrow-1-e' style='float:left;'></span>"
  1038 + "<span class='ui-icon ui-icon-arrow-1-e' style='float:left;'></span>".html_safe
1043 1039 end
1044 1040  
1045 1041 def display_category_menu(block, categories, root = true)
... ... @@ -1282,7 +1278,7 @@ module ApplicationHelper
1282 1278 (user.already_reported?(profile) ?
1283 1279 content_tag('a', text, :class => klass + ' disabled comment-footer comment-footer-link', :title => already_reported_message) :
1284 1280 link_to(text, url, :class => klass + ' comment-footer comment-footer-link', :title => report_profile_message)
1285   - ) + content_tag('span', ' | ', :class => 'comment-footer comment-footer-hide')
  1281 + ) + content_tag('span', ' ', :class => 'comment-footer comment-footer-hide')
1286 1282 end
1287 1283 end
1288 1284  
... ... @@ -1298,9 +1294,7 @@ module ApplicationHelper
1298 1294 titles = tabs.inject(''){ |result, tab| result << content_tag(:li, link_to(tab[:title], '#'+tab[:id]), :class => 'tab') }
1299 1295 contents = tabs.inject(''){ |result, tab| result << content_tag(:div, tab[:content], :id => tab[:id]) }
1300 1296  
1301   - content_tag :div, :class => 'ui-tabs' do
1302   - content_tag(:ul, titles) + contents
1303   - end
  1297 + content_tag(:div, content_tag(:ul, titles) + raw(contents), :class => 'ui-tabs')
1304 1298 end
1305 1299  
1306 1300 def jquery_token_input_messages_json(hintText = _('Type in an keyword'), noResultsText = _('No results'), searchingText = _('Searching...'))
... ... @@ -1329,11 +1323,12 @@ module ApplicationHelper
1329 1323 end
1330 1324  
1331 1325 def template_options(klass, field_name)
1332   - return '' if klass.templates.count == 0
1333   - return hidden_field_tag("#{field_name}[template_id]", klass.templates.first.id) if klass.templates.count == 1
  1326 + templates = klass.templates(environment)
  1327 + return '' if templates.count == 0
  1328 + return hidden_field_tag("#{field_name}[template_id]", templates.first.id) if templates.count == 1
1334 1329  
1335 1330 counter = 0
1336   - radios = klass.templates.map do |template|
  1331 + radios = templates.map do |template|
1337 1332 counter += 1
1338 1333 content_tag('li', labelled_radio_button(link_to(template.name, template.url, :target => '_blank'), "#{field_name}[template_id]", template.id, counter==1))
1339 1334 end.join("\n")
... ... @@ -1433,4 +1428,26 @@ module ApplicationHelper
1433 1428 def observe_field(*args)
1434 1429 ''
1435 1430 end
  1431 +
  1432 + def private_profile_partial_parameters
  1433 + if profile.person?
  1434 + @action = :add_friend
  1435 + @message = _("The content here is available to %s's friends only.") % profile.short_name
  1436 + else
  1437 + @action = :join
  1438 + @message = _('The contents in this community is available to members only.')
  1439 + end
  1440 + @no_design_blocks = true
  1441 + end
  1442 +
  1443 + def default_folder_for_image_upload(profile)
  1444 + default_folder = profile.folders.find_by_type('Gallery')
  1445 + default_folder = profile.folders.find_by_type('Folder') if default_folder.nil?
  1446 + default_folder
  1447 + end
  1448 +
  1449 + def content_id_to_str(content)
  1450 + content.nil? ? '' : content.id.to_s
  1451 + end
  1452 +
1436 1453 end
... ...
app/helpers/block_helper.rb
... ... @@ -3,7 +3,24 @@ module BlockHelper
3 3 def block_title(title)
4 4 tag_class = 'block-title'
5 5 tag_class += ' empty' if title.empty?
6   - content_tag 'h3', content_tag('span', title), :class => tag_class
  6 + content_tag 'h3', content_tag('span', h(title)), :class => tag_class
  7 + end
  8 +
  9 + def highlights_block_config_image_fields(block, image={})
  10 + "
  11 + <tr class=\"image-data-line\">
  12 + <td>
  13 + #{select_tag 'block[images][][image_id]', content_tag(:option) + option_groups_from_collection_for_select(block.folder_choices, :images, :name, :id, :name, image[:image_id].to_i).html_safe}
  14 + </td>
  15 + <td>#{text_field_tag 'block[images][][address]', image[:address], :class => 'highlight-address', :size => 20}</td>
  16 + <td>#{text_field_tag 'block[images][][position]', image[:position], :class => 'highlight-position', :size => 1}</td>
  17 + </tr><tr class=\"image-title\">
  18 + <td colspan=\"3\"><label>#{
  19 + content_tag('span', _('Title')) +
  20 + text_field_tag('block[images][][title]', image[:title], :class => 'highlight-title', :size => 45)
  21 + }</label></td>
  22 + </tr>
  23 + "
7 24 end
8 25  
9 26 end
... ...
app/helpers/blog_helper.rb
... ... @@ -18,8 +18,9 @@ module BlogHelper
18 18 pagination = will_paginate(articles, {
19 19 :param_name => 'npage',
20 20 :previous_label => _('&laquo; Newer posts'),
21   - :next_label => _('Older posts &raquo;')
22   - })
  21 + :next_label => _('Older posts &raquo;'),
  22 + :params => {:action=>"view_page", :page=>articles.first.parent.path.split('/'), :controller=>"content_viewer"}
  23 + }) if articles.present?
23 24 content = []
24 25 artic_len = articles.length
25 26 articles.each_with_index{ |art,i|
... ... @@ -31,7 +32,7 @@ module BlogHelper
31 32 css_add << position + '-inner'
32 33 content << content_tag('div',
33 34 content_tag('div',
34   - display_post(art, format) + '<br style="clear:both"/>',
  35 + display_post(art, format).html_safe + '<br style="clear:both"/>'.html_safe,
35 36 :class => 'blog-post ' + css_add.join(' '),
36 37 :id => "post-#{art.id}"), :class => position
37 38 )
... ... @@ -46,18 +47,6 @@ module BlogHelper
46 47 article_title(article, :no_comments => no_comments) + html
47 48 end
48 49  
49   - def display_short_format(article)
50   - html = content_tag('div',
51   - article.lead +
52   - content_tag('div',
53   - link_to_comments(article) +
54   - link_to( _('Read more'), article.url),
55   - :class => 'read-more'),
56   - :class => 'short-post'
57   - )
58   - html
59   - end
60   -
61 50 def display_full_format(article)
62 51 html = article_to_html(article)
63 52 html = content_tag('p', html) if ! html.include?('</p>')
... ...
app/helpers/catalog_helper.rb
... ... @@ -3,4 +3,28 @@ module CatalogHelper
3 3 include DisplayHelper
4 4 include ManageProductsHelper
5 5  
  6 + def breadcrumb(category)
  7 + start = link_to(_('Start'), {:action => 'index'})
  8 + ancestors = category.ancestors.map { |c| link_to(c.name, {:action => 'index', :level => c.id}) }.reverse
  9 + current_level = content_tag('strong', category.name)
  10 + all_items = [start] + ancestors + [current_level]
  11 + content_tag('div', all_items.join(' &rarr; '), :id => 'breadcrumb')
  12 + end
  13 +
  14 + def category_link(category, sub = false)
  15 + count = profile.products.from_category(category).count
  16 + name = truncate(category.name, :length => 22 - count.to_s.size)
  17 + link_name = sub ? name : content_tag('strong', name)
  18 + link = link_to(link_name, {:action => 'index', :level => category.id}, :title => category.name)
  19 + content_tag('li', "#{link} (#{count})") if count > 0
  20 + end
  21 +
  22 + def category_sub_links(category)
  23 + sub_categories = []
  24 + category.children.order(:name).each do |sub_category|
  25 + sub_categories << category_link(sub_category, true)
  26 + end
  27 + content_tag('ul', sub_categories) if sub_categories.size > 1
  28 + end
  29 +
6 30 end
... ...
app/helpers/content_viewer_helper.rb
... ... @@ -36,7 +36,7 @@ module ContentViewerHelper
36 36  
37 37 def link_to_comments(article, args = {})
38 38 return '' unless article.accept_comments?
39   - link_to(number_of_comments(article), article.url.merge(:anchor => 'comments_list') )
  39 + reference_to_article number_of_comments(article), article, 'comments_list'
40 40 end
41 41  
42 42 def article_translations(article)
... ... @@ -45,7 +45,7 @@ module ContentViewerHelper
45 45 { article.environment.locales[translation.language] => { :href => url_for(translation.url) } }
46 46 end
47 47 content_tag(:div, link_to(_('Translations'), '#',
48   - :onclick => "toggleSubmenu(this, '#{_('Translations')}', #{links.to_json}); return false",
  48 + :onmouseover => "toggleSubmenu(this, '#{_('Translations')}', #{links.to_json}); return false",
49 49 :class => 'article-translations-menu simplemenu-trigger up'),
50 50 :class => 'article-translations')
51 51 end
... ...
app/helpers/dates_helper.rb
... ... @@ -23,11 +23,13 @@ module DatesHelper
23 23 end
24 24  
25 25 # formats a date for displaying.
26   - def show_date(date, use_numbers = false)
  26 + def show_date(date, use_numbers = false, year=true)
27 27 if date && use_numbers
28   - _('%{month}/%{day}/%{year}') % { :day => date.day, :month => date.month, :year => date.year }
  28 + date_format = year ? _('%{month}/%{day}/%{year}') : _('%{month}/%{day}')
  29 + date_format % { :day => date.day, :month => date.month, :year => date.year }
29 30 elsif date
30   - _('%{month} %{day}, %{year}') % { :day => date.day, :month => month_name(date.month), :year => date.year }
  31 + date_format = year ? _('%{month_name} %{day}, %{year}') : _('%{month_name} %{day}')
  32 + date_format % { :day => date.day, :month_name => month_name(date.month), :year => date.year }
31 33 else
32 34 ''
33 35 end
... ... @@ -46,7 +48,27 @@ module DatesHelper
46 48 if (date1 == date2) || (date2.nil?)
47 49 show_date(date1, use_numbers)
48 50 else
49   - _('from %{date1} to %{date2}') % {:date1 => show_date(date1, use_numbers), :date2 => show_date(date2, use_numbers)}
  51 + if date1.year == date2.year
  52 + if date1.month == date2.month
  53 + _('from %{month} %{day1} to %{day2}, %{year}') % {
  54 + :day1 => date1.day,
  55 + :day2 => date2.day,
  56 + :month => use_numbers ? date1.month : month_name(date1.month),
  57 + :year => date1.year
  58 + }
  59 + else
  60 + _('from %{date1} to %{date2}, %{year}') % {
  61 + :date1 => show_date(date1, use_numbers, false),
  62 + :date2 => show_date(date2, use_numbers, false),
  63 + :year => date1.year
  64 + }
  65 + end
  66 + else
  67 + _('from %{date1} to %{date2}') % {
  68 + :date1 => show_date(date1, use_numbers),
  69 + :date2 => show_date(date2, use_numbers)
  70 + }
  71 + end
50 72 end
51 73 end
52 74  
... ...
app/helpers/display_helper.rb
... ... @@ -8,6 +8,14 @@ module DisplayHelper
8 8 opts
9 9 end
10 10  
  11 + def themed_path(file)
  12 + if File.exists?(File.join(Rails.root, 'public', theme_path, file))
  13 + File.join(theme_path, file)
  14 + else
  15 + file
  16 + end
  17 + end
  18 +
11 19 def image_link_to_product(product, opts={})
12 20 return _('No product') unless product
13 21 target = product_path(product)
... ...
app/helpers/forms_helper.rb
... ... @@ -142,38 +142,6 @@ module FormsHelper
142 142 content_tag('table',rows.join("\n"))
143 143 end
144 144  
145   - def select_folder(label_text, field_id, collection, default_value=nil, html_options = {}, js_options = {})
146   - root = profile ? profile.identifier : _("root")
147   - labelled_form_field(
148   - label_text,
149   - select_tag(
150   - field_id,
151   - options_for_select(
152   - [[root, '']] +
153   - collection.collect {|f| [ root + '/' + f.full_name, f.id ] },
154   - default_value
155   - ),
156   - html_options.merge(js_options)
157   - )
158   - )
159   - end
160   -
161   - def select_profile_folder(label_text, field_id, profile, default_value='', html_options = {}, js_options = {})
162   - result = labelled_form_field(
163   - label_text,
164   - select_tag(
165   - field_id,
166   - options_for_select(
167   - [[profile.identifier, '']] +
168   - profile.folders.collect {|f| [ profile.identifier + '/' + f.full_name, f.id ] },
169   - default_value
170   - ),
171   - html_options.merge(js_options)
172   - )
173   - )
174   - return result
175   - end
176   -
177 145 def date_field(name, value, format = '%Y-%m-%d', datepicker_options = {}, html_options = {})
178 146 datepicker_options[:disabled] ||= false
179 147 datepicker_options[:alt_field] ||= ''
... ... @@ -295,23 +263,28 @@ module FormsHelper
295 263 field_id,
296 264 options_for_select(
297 265 [[root, '']] +
298   - collection.collect {|f| [ root + '/' + f.full_name, f.id ] },
299   - default_value
  266 + collection.collect {|f| [ root + '/' + f.full_name, f.id.to_s ] },
  267 + default_value.to_s
300 268 ),
301 269 html_options.merge(js_options)
302 270 )
303 271 )
304 272 end
305 273  
306   - def select_profile_folder(label_text, field_id, profile, default_value='', html_options = {}, js_options = {})
  274 + def select_profile_folder(label_text, field_id, profile, default_value='', html_options = {}, js_options = {}, find_options = {})
  275 + if find_options.empty?
  276 + folders = profile.folders
  277 + else
  278 + folders = profile.folders.where(find_options)
  279 + end
307 280 result = labelled_form_field(
308 281 label_text,
309 282 select_tag(
310 283 field_id,
311 284 options_for_select(
312 285 [[profile.identifier, '']] +
313   - profile.folders.collect {|f| [ profile.identifier + '/' + f.full_name, f.id ] },
314   - default_value
  286 + folders.collect {|f| [ profile.identifier + '/' + f.full_name, f.id.to_s ] },
  287 + default_value.to_s
315 288 ),
316 289 html_options.merge(js_options)
317 290 )
... ...
app/helpers/layout_helper.rb 0 → 100644
... ... @@ -0,0 +1,88 @@
  1 +module LayoutHelper
  2 +
  3 + def body_classes
  4 + # Identify the current controller and action for the CSS:
  5 + " controller-#{@controller.controller_name}" +
  6 + " action-#{@controller.controller_name}-#{@controller.action_name}" +
  7 + " template-#{profile.nil? ? "default" : profile.layout_template}" +
  8 + (!profile.nil? && profile.is_on_homepage?(request.path,@page) ? " profile-homepage" : "")
  9 + end
  10 +
  11 + def noosfero_javascript
  12 + plugins_javascripts = @plugins.map { |plugin| plugin.js_files.map { |js| plugin.class.public_path(js) } }.flatten
  13 +
  14 + output = ''
  15 + output += render :file => 'layouts/_javascript'
  16 + output += javascript_tag 'render_all_jquery_ui_widgets()'
  17 + unless plugins_javascripts.empty?
  18 + output += javascript_include_tag plugins_javascripts, :cache => "cache/plugins-#{Digest::MD5.hexdigest plugins_javascripts.to_s}"
  19 + end
  20 + output
  21 + end
  22 +
  23 + def noosfero_stylesheets
  24 + standard_stylesheets = [
  25 + 'application',
  26 + 'search',
  27 + 'thickbox',
  28 + 'lightbox',
  29 + 'colorpicker',
  30 + 'colorbox',
  31 + pngfix_stylesheet_path,
  32 + ] + tokeninput_stylesheets
  33 + plugins_stylesheets = @plugins.select(&:stylesheet?).map { |plugin| plugin.class.public_path('style.css') }
  34 +
  35 + output = ''
  36 + output += stylesheet_link_tag standard_stylesheets, :cache => 'cache'
  37 + output += stylesheet_link_tag template_stylesheet_path
  38 + output += stylesheet_link_tag icon_theme_stylesheet_path
  39 + output += stylesheet_link_tag jquery_ui_theme_stylesheet_path
  40 + unless plugins_stylesheets.empty?
  41 + output += stylesheet_link_tag plugins_stylesheets, :cache => "cache/plugins-#{Digest::MD5.hexdigest plugins_stylesheets.to_s}"
  42 + end
  43 + output += stylesheet_link_tag theme_stylesheet_path
  44 + output
  45 + end
  46 +
  47 + def pngfix_stylesheet_path
  48 + 'iepngfix/iepngfix.css'
  49 + end
  50 +
  51 + def tokeninput_stylesheets
  52 + ['token-input', 'token-input-facebook', 'token-input-mac', 'token-input-facet']
  53 + end
  54 +
  55 + def noosfero_layout_features
  56 + render :file => 'shared/noosfero_layout_features'
  57 + end
  58 +
  59 + def template_stylesheet_path
  60 + if profile.nil?
  61 + "/designs/templates/#{environment.layout_template}/stylesheets/style.css"
  62 + else
  63 + "/designs/templates/#{profile.layout_template}/stylesheets/style.css"
  64 + end
  65 + end
  66 +
  67 + def icon_theme_stylesheet_path
  68 + icon_themes = []
  69 + theme_icon_themes = theme_option(:icon_theme) || []
  70 + for icon_theme in theme_icon_themes do
  71 + theme_path = "/designs/icons/#{icon_theme}/style.css"
  72 + if File.exists?(File.join(RAILS_ROOT, 'public', theme_path))
  73 + icon_themes << theme_path
  74 + end
  75 + end
  76 + icon_themes
  77 + end
  78 +
  79 + def jquery_ui_theme_stylesheet_path
  80 + 'jquery.ui/' + jquery_theme + '/jquery-ui-1.8.2.custom'
  81 + end
  82 +
  83 + def theme_stylesheet_path
  84 + theme_path + '/style.css'
  85 + end
  86 +
  87 +end
  88 +
... ...
app/helpers/profile_editor_helper.rb
... ... @@ -136,7 +136,7 @@ module ProfileEditorHelper
136 136 concat(
137 137 content_tag(
138 138 'div',
139   - capture(&block) + '<br style="clear:left;"/>&nbsp;',
  139 + capture(&block) + content_tag('br', '', :style => 'clear: left'),
140 140 :class => 'control-panel')
141 141 )
142 142 end
... ...
app/helpers/search_helper.rb
... ... @@ -2,12 +2,10 @@ module SearchHelper
2 2  
3 3 MAP_SEARCH_LIMIT = 2000
4 4 LIST_SEARCH_LIMIT = 20
5   - BLOCKS_SEARCH_LIMIT = 18
  5 + BLOCKS_SEARCH_LIMIT = 24
6 6 MULTIPLE_SEARCH_LIMIT = 8
7   - DistFilt = 200
8   - DistBoost = 50
9 7  
10   - Searches = ActiveSupport::OrderedHash[
  8 + SEARCHES = ActiveSupport::OrderedHash[
11 9 :articles, _('Contents'),
12 10 :enterprises, _('Enterprises'),
13 11 :people, _('People'),
... ... @@ -16,46 +14,31 @@ module SearchHelper
16 14 :events, _('Events'),
17 15 ]
18 16  
19   - SortOptions = {
20   - :products => ActiveSupport::OrderedHash[ :none, {:label => _('Relevance')},
21   - :more_recent, {:label => _('More recent'), :solr_opts => {:sort => 'updated_at desc, score desc'}},
22   - :name, {:label => _('Name'), :solr_opts => {:sort => 'name_sortable asc'}},
23   - :closest, {:label => _('Closest to me'), :if => proc{ logged_in? && (profile=current_user.person).lat && profile.lng },
24   - :solr_opts => {:sort => "geodist() asc",
25   - :latitude => proc{ current_user.person.lat }, :longitude => proc{ current_user.person.lng }}},
26   - ],
27   - :events => ActiveSupport::OrderedHash[ :none, {:label => _('Relevance')},
28   - :name, {:label => _('Name'), :solr_opts => {:sort => 'name_sortable asc'}},
29   - ],
30   - :articles => ActiveSupport::OrderedHash[ :none, {:label => _('Relevance')},
31   - :name, {:label => _('Name'), :solr_opts => {:sort => 'name_sortable asc'}},
32   - :more_recent, {:label => _('More recent'), :solr_opts => {:sort => 'updated_at desc, score desc'}},
33   - ],
34   - :enterprises => ActiveSupport::OrderedHash[ :none, {:label => _('Relevance')},
35   - :name, {:label => _('Name'), :solr_opts => {:sort => 'name_sortable asc'}},
36   - ],
37   - :people => ActiveSupport::OrderedHash[ :none, {:label => _('Relevance')},
38   - :name, {:label => _('Name'), :solr_opts => {:sort => 'name_sortable asc'}},
39   - ],
40   - :communities => ActiveSupport::OrderedHash[ :none, {:label => _('Relevance')},
41   - :name, {:label => _('Name'), :solr_opts => {:sort => 'name_sortable asc'}},
42   - ],
  17 + FILTER_TRANSLATION = {
  18 + 'more_popular' => _('More popular'),
  19 + 'more_active' => _('More active'),
  20 + 'more_recent' => _('More recent'),
  21 + 'more_comments' => _('More comments')
43 22 }
44 23  
45 24 # FIXME remove it after search_controler refactored
46 25 include EventsHelper
47 26  
48   - def multiple_search?
49   - ['index', 'category_index'].include?(params[:action]) or @results.size > 1
  27 + def multiple_search?(searches=nil)
  28 + ['index', 'category_index'].include?(params[:action]) || (searches && searches.size > 1)
50 29 end
51 30  
52   - def map_search?
53   - !@empty_query and !multiple_search? and params[:display] == 'map'
  31 + def map_search?(searches=nil)
  32 + !multiple_search?(searches) && params[:display] == 'map'
  33 + end
  34 +
  35 + def asset_class(asset)
  36 + asset.to_s.singularize.camelize.constantize
54 37 end
55 38  
56 39 def search_page_title(title, category = nil)
57 40 title = "<h1>" + title
58   - title += '<small>' + category.name + '</small>' if category
  41 + title += ' - <small>' + category.name + '</small>' if category
59 42 title + "</h1>"
60 43 end
61 44  
... ... @@ -66,8 +49,12 @@ module SearchHelper
66 49 :align => 'center', :class => 'search-category-context') if category
67 50 end
68 51  
69   - def display_results(map_capable = false)
70   - if map_capable and map_search?
  52 + def display?(asset, mode)
  53 + defined?(asset_class(asset)::SEARCH_DISPLAYS) && asset_class(asset)::SEARCH_DISPLAYS.include?(mode.to_s)
  54 + end
  55 +
  56 + def display_results(searches=nil, asset=nil)
  57 + if display?(asset, :map) && map_search?(searches)
71 58 partial = 'google_maps'
72 59 klass = 'map'
73 60 else
... ... @@ -78,10 +65,13 @@ module SearchHelper
78 65 content_tag('div', render(:partial => partial), :class => "map-or-list-search-results #{klass}")
79 66 end
80 67  
81   - def display_map_list_button
82   - button(:search, params[:display] == 'map' ? _('Display in list') : _('Display in map'),
83   - params.merge(:display => (params[:display] == 'map' ? 'list' : 'map')),
84   - :class => "map-toggle-button" )
  68 + def display_filter(asset, display)
  69 + asset = :articles if asset == :tag
  70 + if display?(asset, display)
  71 + display
  72 + else
  73 + asset_class(asset).default_search_display
  74 + end
85 75 end
86 76  
87 77 def city_with_state(city)
... ... @@ -97,120 +87,50 @@ module SearchHelper
97 87 end
98 88 end
99 89  
100   - def facets_menu(asset, _facets)
101   - @asset_class = asset_class(asset)
102   - @facets = _facets
103   - render(:partial => 'facets_menu')
104   - end
105   -
106   - def facets_unselect_menu(asset)
107   - @asset_class = asset_class(asset)
108   - render(:partial => 'facets_unselect_menu')
109   - end
110   -
111   - def facet_javascript(input_id, facet, array)
112   - array = [] if array.nil?
113   - hintText = _('Type in an option')
114   - text_field_tag('facet['+input_id+']', '', :id => input_id) +
115   - javascript_tag("jQuery.TokenList(jQuery('##{input_id}'), #{array.to_json},
116   - {searchDelay: 0, permanentDropdown: true, theme: 'facet', dontAdd: true, preventDuplicates: true,
117   - #{jquery_token_input_messages_json(hintText)}});")
118   - end
119   -
120   - def facet_link_html(facet, params, value, label, count)
121   - params = params ? params.dup : {}
122   - has_extra = label.kind_of?(Array)
123   - link_label = has_extra ? label[0] : label
124   - id = facet[:solr_field].to_s
125   - params[:facet] ||= {}
126   - params[:facet][id] ||= {}
127   - params[:page] = {} if params[:page]
128   -
129   - selected = facet[:label_id].nil? ? params[:facet][id] == value : params[:facet][id][facet[:label_id]].to_a.include?(value)
130   -
131   - if count > 0
132   - url = params.merge(:facet => params[:facet].merge(
133   - id => facet[:label_id].nil? ? value : params[:facet][id].merge( facet[:label_id] => params[:facet][id][facet[:label_id]].to_a | [value] )
134   - ))
135   - else
136   - # preserve others filters and change this filter
137   - url = params.merge(:facet => params[:facet].merge(
138   - id => facet[:label_id].nil? ? value : { facet[:label_id] => value }
139   - ))
  90 + def display_selector(asset, display, float = 'right')
  91 + display = nil if display.blank?
  92 + display ||= asset_class(asset).default_search_display
  93 + if [display?(asset, :map), display?(asset, :compact), display?(asset, :full)].select {|option| option}.count > 1
  94 + compact_link = display?(asset, :compact) ? (display == 'compact' ? _('Compact') : link_to(_('Compact'), params.merge(:display => 'compact'))) : nil
  95 + map_link = display?(asset, :map) ? (display == 'map' ? _('Map') : link_to(_('Map'), params.merge(:display => 'map'))) : nil
  96 + full_link = display?(asset, :full) ? (display == 'full' ? _('Full') : link_to(_('Full'), params.merge(:display => 'full'))) : nil
  97 + content_tag('div',
  98 + content_tag('strong', _('Display')) + ': ' + [compact_link, map_link, full_link].compact.join(' | ').html_safe,
  99 + :class => 'search-customize-options'
  100 + )
140 101 end
141   -
142   - content_tag 'div', link_to(link_label, url, :class => 'facet-result-link-label') +
143   - content_tag('span', (has_extra ? label[1] : ''), :class => 'facet-result-extra-label') +
144   - (count > 0 ? content_tag('span', " (#{count})", :class => 'facet-result-count') : ''),
145   - :class => 'facet-menu-item' + (selected ? ' facet-result-link-selected' : '')
146 102 end
147 103  
148   - def facet_selecteds_html_for(environment, klass, params)
149   - def name_with_extra(klass, facet, value)
150   - name = klass.facet_result_name(facet, value)
151   - name = name[0] + name[1] if name.kind_of?(Array)
152   - name
153   - end
154   -
155   - ret = []
156   - params = params.dup
157   - params[:facet].each do |id, value|
158   - facet = klass.facet_by_id(id.to_sym)
159   - next unless facet
160   - if value.kind_of?(Hash)
161   - label_hash = facet[:label].call(environment)
162   - value.each do |label_id, value|
163   - facet[:label_id] = label_id
164   - facet[:label] = label_hash[label_id]
165   - value.to_a.each do |value|
166   - ret << [facet[:label], name_with_extra(klass, facet, value),
167   - params.merge(:facet => params[:facet].merge(id => params[:facet][id].merge(label_id => params[:facet][id][label_id].to_a.reject{ |v| v == value })))]
168   - end
169   - end
170   - else
171   - ret << [klass.facet_label(facet), name_with_extra(klass, facet, value),
172   - params.merge(:facet => params[:facet].reject{ |k,v| k == id })]
173   - end
  104 + def filter_selector(asset, filter, float = 'right')
  105 + klass = asset_class(asset)
  106 + if klass::SEARCH_FILTERS.count > 1
  107 + options = options_for_select(klass::SEARCH_FILTERS.map {|f| [FILTER_TRANSLATION[f], f]}, filter)
  108 + url_params = url_for(params.merge(:filter => 'FILTER'))
  109 + onchange = "document.location.href = '#{url_params}'.replace('FILTER', this.value)"
  110 + select_field = select_tag(:filter, options, :onchange => onchange)
  111 + content_tag('div',
  112 + content_tag('strong', _('Filter')) + ': ' + select_field,
  113 + :class => "search-customize-options"
  114 + )
174 115 end
175   -
176   - ret.map do |label, name, url|
177   - content_tag('div', content_tag('span', label, :class => 'facet-selected-label') +
178   - content_tag('span', name, :class => 'facet-selected-name') +
179   - link_to('', url, :class => 'facet-selected-remove', :title => 'remove facet'), :class => 'facet-selected')
180   - end.join
181   - end
182   -
183   - def order_by(asset)
184   - options = SortOptions[asset].map do |name, options|
185   - next if options[:if] and ! instance_eval(&options[:if])
186   - [_(options[:label]), name.to_s]
187   - end.compact
188   -
189   - content_tag('div', _('Sort results by ') +
190   - select_tag(asset.to_s + '[order]', options_for_select(options, params[:order_by] || 'none'),
191   - {:onchange => "window.location = jQuery.param.querystring(window.location.href, { 'order_by' : this.options[this.selectedIndex].value})"}),
192   - :class => "search-ordering")
193   - end
194   -
195   - def label_total_found(asset, total_found)
196   - labels = {
197   - :products => _("%s products offers found"),
198   - :articles => _("%s articles found"),
199   - :events => _("%s events found"),
200   - :people => _("%s people found"),
201   - :enterprises => _("%s enterprises found"),
202   - :communities => _("%s communities found"),
203   - }
204   - content_tag('span', labels[asset] % total_found,
205   - :class => "total-pages-found") if labels[asset]
206   - end
207   -
208   - def asset_class(asset)
209   - asset.to_s.singularize.camelize.constantize
210 116 end
211 117  
212   - def asset_table(asset)
213   - asset_class(asset).table_name
  118 + def filter_title(asset, filter)
  119 + {
  120 + 'articles_more_recent' => _('More recent contents from network'),
  121 + 'articles_more_popular' => _('More viewed contents from network'),
  122 + 'articles_more_comments' => _('Most commented contents from network'),
  123 + 'people_more_recent' => _('More recent people from network'),
  124 + 'people_more_active' => _('More active people from network'),
  125 + 'people_more_popular' => _('More popular people from network'),
  126 + 'communities_more_recent' => _('More recent communities from network'),
  127 + 'communities_more_active' => _('More active communities from network'),
  128 + 'communities_more_popular' => _('More popular communities from network'),
  129 + 'enterprises_more_recent' => _('More recent enterprises from network'),
  130 + 'enterprises_more_active' => _('More active enterprises from network'),
  131 + 'enterprises_more_popular' => _('More popular enterprises from network'),
  132 + 'products_more_recent' => _('Highlights'),
  133 + }[asset.to_s + '_' + filter].to_s
214 134 end
215 135  
216 136 end
... ...
app/helpers/tags_helper.rb
... ... @@ -31,10 +31,8 @@ module TagsHelper
31 31 # (pt_BR only).
32 32 def tag_cloud(tags, tagname_option, url, options = {})
33 33  
34   - return content_tag('em', _('No tags yet.')) +
35   - ' <a href="' + _('http://en.wikipedia.org/wiki/Tag_%28metadata%29') +
36   - '" target="wptags"><span>(' +
37   - _('What are tags?') + ')</span></a>' if tags.empty?
  34 + return content_tag('em', _('No tags yet.') + ' ') +
  35 + link_to(content_tag(:span, _('What are tags?')),_('http://en.wikipedia.org/wiki/Tag_%28metadata%29')) if tags.empty?
38 36  
39 37 max_size = options[:max_size] || Cloud::MAX_SIZE
40 38 min_size = options[:min_size] || Cloud::MIN_SIZE
... ... @@ -70,7 +68,7 @@ module TagsHelper
70 68 :title => n_( 'one item', '%d items', count ) % count
71 69 end
72 70  
73   - end.join("\n")
  71 + end.join("\n").html_safe
74 72 end
75 73  
76 74 end
... ...
app/models/approve_article.rb
... ... @@ -48,7 +48,7 @@ class ApproveArticle &lt; Task
48 48 end
49 49  
50 50 def perform
51   - article.copy!(:name => name, :abstract => abstract, :body => body, :profile => target, :reference_article => article, :parent => article_parent, :highlighted => highlighted, :source => article.source, :last_changed_by_id => article.author)
  51 + article.copy!(:name => name, :abstract => abstract, :body => body, :profile => target, :reference_article => article, :parent => article_parent, :highlighted => highlighted, :source => article.source, :last_changed_by_id => article.author_id)
52 52 end
53 53  
54 54 def title
... ...
app/models/article.rb
... ... @@ -4,6 +4,29 @@ class Article &lt; ActiveRecord::Base
4 4  
5 5 attr_accessible :name, :body, :abstract, :profile
6 6  
  7 + SEARCHABLE_FIELDS = {
  8 + :name => 10,
  9 + :abstract => 3,
  10 + :body => 2,
  11 + :slug => 1,
  12 + :filename => 1,
  13 + }
  14 +
  15 + SEARCH_FILTERS = %w[
  16 + more_recent
  17 + more_popular
  18 + more_comments
  19 + ]
  20 +
  21 + SEARCH_DISPLAYS = %w[full]
  22 +
  23 + def self.default_search_display
  24 + 'full'
  25 + end
  26 +
  27 + #FIXME This is necessary because html is being generated on the model...
  28 + include ActionView::Helpers::TagHelper
  29 +
7 30 # use for internationalizable human type names in search facets
8 31 # reimplement on subclasses
9 32 def self.type_name
... ... @@ -25,6 +48,8 @@ class Article &lt; ActiveRecord::Base
25 48 validates_presence_of :profile_id, :name
26 49 validates_presence_of :slug, :path, :if => lambda { |article| !article.name.blank? }
27 50  
  51 + validates_length_of :name, :maximum => 150
  52 +
28 53 validates_uniqueness_of :slug, :scope => ['profile_id', 'parent_id'], :message => N_('The title (article name) is already being used by another article, please use another title.'), :if => lambda { |article| !article.slug.blank? }
29 54  
30 55 belongs_to :last_changed_by, :class_name => 'Person', :foreign_key => 'last_changed_by_id'
... ... @@ -227,8 +252,13 @@ class Article &lt; ActiveRecord::Base
227 252 # The implementation in this class just provides the +body+ attribute as the
228 253 # HTML. Other article types can override this method to provide customized
229 254 # views of themselves.
  255 + # (To override short format representation, override the lead method)
230 256 def to_html(options = {})
231   - body || ''
  257 + if options[:format] == 'short'
  258 + display_short_format(self)
  259 + else
  260 + body || ''
  261 + end
232 262 end
233 263  
234 264 def reported_version(options = {})
... ... @@ -408,8 +438,8 @@ class Article &lt; ActiveRecord::Base
408 438 scope :images, :conditions => { :is_image => true }
409 439 scope :text_articles, :conditions => [ 'articles.type IN (?)', text_article_types ]
410 440  
  441 + scope :more_popular, :order => 'hits DESC'
411 442 scope :more_comments, :order => "comments_count DESC"
412   - scope :more_views, :order => "hits DESC"
413 443 scope :more_recent, :order => "created_at DESC"
414 444  
415 445 def self.display_filter(user, profile)
... ... @@ -548,6 +578,10 @@ class Article &lt; ActiveRecord::Base
548 578 author ? author.url : nil
549 579 end
550 580  
  581 + def author_id
  582 + author ? author.id : nil
  583 + end
  584 +
551 585 alias :active_record_cache_key :cache_key
552 586 def cache_key(params = {}, the_profile = nil, language = 'en')
553 587 active_record_cache_key+'-'+language +
... ... @@ -594,7 +628,7 @@ class Article &lt; ActiveRecord::Base
594 628  
595 629 end
596 630  
597   - def more_views_label
  631 + def more_popular_label
598 632 amount = self.hits
599 633 {
600 634 0 => _('no views'),
... ... @@ -664,6 +698,8 @@ class Article &lt; ActiveRecord::Base
664 698 categories_including_virtual_ids
665 699 end
666 700  
  701 + delegate :region, :region_id, :environment, :environment_id, :to => :profile, :allow_nil => true
  702 +
667 703 private
668 704  
669 705 def sanitize_tag_list
... ...
app/models/article_block.rb
... ... @@ -12,7 +12,11 @@ class ArticleBlock &lt; Block
12 12 block = self
13 13 lambda do
14 14 block_title(block.title) +
15   - (block.article ? article_to_html(block.article, :gallery_view => false) : _('Article not selected yet.'))
  15 + (block.article ? article_to_html(block.article,
  16 + :gallery_view => false,
  17 + :inside_block => block, # For Blogs and folders
  18 + :format => block.visualization_format # For Articles and contents
  19 + ).html_safe : _('Article not selected yet.'))
16 20 end
17 21 end
18 22  
... ... @@ -49,4 +53,14 @@ class ArticleBlock &lt; Block
49 53 self.box.owner.kind_of?(Environment) ? self.box.owner.portal_community.articles : self.box.owner.articles
50 54 end
51 55  
  56 + def posts_per_page
  57 + self.settings[:posts_per_page] or 1
  58 + end
  59 +
  60 + def posts_per_page= value
  61 + value = value.to_i
  62 + self.settings[:posts_per_page] = value if value > 0
  63 + end
  64 +
  65 + settings_items :visualization_format, :type => :string, :default => 'short'
52 66 end
... ...
app/models/blog.rb
... ... @@ -24,8 +24,9 @@ class Blog &lt; Folder
24 24 # FIXME isn't this too much including just to be able to generate some HTML?
25 25 include ActionView::Helpers::TagHelper
26 26 def to_html(options = {})
  27 + me = self
27 28 lambda do
28   - render :file => 'content_viewer/blog_page'
  29 + render :file => 'content_viewer/blog_page', :locals => { :blog=>me, :inside_block=>options[:inside_block] }
29 30 end
30 31 end
31 32  
... ...
app/models/category.rb
1 1 class Category < ActiveRecord::Base
2 2  
  3 + SEARCHABLE_FIELDS = {
  4 + :name => 10,
  5 + :acronym => 5,
  6 + :abbreviation => 5,
  7 + :slug => 1,
  8 + }
  9 +
3 10 validates_exclusion_of :slug, :in => [ 'index' ], :message => N_('%{fn} cannot be like that.').fix_i18n
4 11 validates_presence_of :name, :environment_id
5 12 validates_uniqueness_of :slug,:scope => [ :environment_id, :parent_id ], :message => N_('%{fn} is already being used by another category.').fix_i18n
... ... @@ -13,6 +20,16 @@ class Category &lt; ActiveRecord::Base
13 20 {:conditions => ['parent_id is null and environment_id = ?', environment.id ]}
14 21 }
15 22  
  23 + named_scope :on_level, lambda { |parent| {:conditions => {:parent_id => parent}} }
  24 +
  25 + named_scope :sub_categories, lambda { |category|
  26 + {:conditions => ['categories.path LIKE ? AND categories.id != ?', "%#{category.slug}%", category.id]}
  27 + }
  28 +
  29 + named_scope :sub_tree, lambda { |category|
  30 + {:conditions => ['categories.path LIKE ?', "%#{category.slug}%"]}
  31 + }
  32 +
16 33 acts_as_filesystem
17 34  
18 35 has_many :article_categorizations, :dependent => :destroy
... ...
app/models/certifier.rb
1 1 class Certifier < ActiveRecord::Base
2 2  
  3 + SEARCHABLE_FIELDS = {
  4 + :name => 10,
  5 + :description => 3,
  6 + :link => 1,
  7 + }
  8 +
3 9 belongs_to :environment
4 10  
5 11 has_many :qualifier_certifiers, :dependent => :destroy
... ...
app/models/comment.rb
1 1 class Comment < ActiveRecord::Base
2 2  
  3 + SEARCHABLE_FIELDS = {
  4 + :title => 10,
  5 + :name => 4,
  6 + :body => 2,
  7 + }
  8 +
3 9 validates_presence_of :body
4 10  
5 11 belongs_to :source, :counter_cache => true, :polymorphic => true
... ... @@ -74,10 +80,8 @@ class Comment &lt; ActiveRecord::Base
74 80 self.find(:all, :order => 'created_at desc, id desc', :limit => limit)
75 81 end
76 82  
77   - after_save :notify_article
78   - after_destroy :notify_article
79   - def notify_article
80   - article.comments_updated if article.kind_of?(Article)
  83 + def notification_emails
  84 + self.article.profile.notification_emails - [self.author_email || self.email]
81 85 end
82 86  
83 87 after_create :new_follower
... ... @@ -114,7 +118,7 @@ class Comment &lt; ActiveRecord::Base
114 118  
115 119 def notify_by_mail
116 120 if source.kind_of?(Article) && article.notify_comments?
117   - if !article.profile.notification_emails.empty?
  121 + if !notification_emails.empty?
118 122 Comment::Notifier.deliver_mail(self)
119 123 end
120 124 emails = article.followers - [author_email]
... ... @@ -174,7 +178,7 @@ class Comment &lt; ActiveRecord::Base
174 178 class Notifier < ActionMailer::Base
175 179 def mail(comment)
176 180 profile = comment.article.profile
177   - recipients profile.notification_emails
  181 + recipients comment.notification_emails
178 182 from "#{profile.environment.name} <#{profile.environment.contact_email}>"
179 183 subject _("[%s] you got a new comment!") % [profile.environment.name]
180 184 body :recipient => profile.nickname || profile.name,
... ... @@ -224,6 +228,7 @@ class Comment &lt; ActiveRecord::Base
224 228 def spam!
225 229 self.spam = true
226 230 self.save!
  231 + SpammerLogger.log(ip_address, self)
227 232 Delayed::Job.enqueue(CommentHandler.new(self.id, :marked_as_spam))
228 233 self
229 234 end
... ...
app/models/enterprise.rb
... ... @@ -2,6 +2,8 @@
2 2 # only enterprises can offer products and services.
3 3 class Enterprise < Organization
4 4  
  5 + SEARCH_DISPLAYS += %w[map full]
  6 +
5 7 def self.type_name
6 8 _('Enterprise')
7 9 end
... ... @@ -14,7 +16,6 @@ class Enterprise &lt; Organization
14 16  
15 17 has_and_belongs_to_many :fans, :class_name => 'Person', :join_table => 'favorite_enteprises_people'
16 18  
17   - extra_data_for_index :product_categories
18 19 def product_categories
19 20 products.includes(:product_category).map{|p| p.category_full_name}.compact
20 21 end
... ... @@ -181,7 +182,15 @@ class Enterprise &lt; Organization
181 182 end
182 183  
183 184 def activities
184   - Scrap.find_by_sql("SELECT id, updated_at, 'Scrap' AS klass FROM scraps WHERE scraps.receiver_id = #{self.id} AND scraps.scrap_id IS NULL UNION SELECT id, updated_at, 'ActionTracker::Record' AS klass FROM action_tracker WHERE action_tracker.target_id = #{self.id} UNION SELECT action_tracker.id, action_tracker.updated_at, 'ActionTracker::Record' AS klass FROM action_tracker INNER JOIN articles ON action_tracker.target_id = articles.id WHERE articles.profile_id = #{self.id} AND action_tracker.target_type = 'Article' ORDER BY action_tracker.updated_at DESC")
  185 + Scrap.find_by_sql("SELECT id, updated_at, 'Scrap' AS klass FROM scraps WHERE scraps.receiver_id = #{self.id} AND scraps.scrap_id IS NULL UNION SELECT id, updated_at, 'ActionTracker::Record' AS klass FROM action_tracker WHERE action_tracker.target_id = #{self.id} UNION SELECT action_tracker.id, action_tracker.updated_at, 'ActionTracker::Record' AS klass FROM action_tracker INNER JOIN articles ON action_tracker.target_id = articles.id WHERE articles.profile_id = #{self.id} AND action_tracker.target_type = 'Article' ORDER BY updated_at DESC")
  186 + end
  187 +
  188 + def catalog_url
  189 + { :profile => identifier, :controller => 'catalog'}
  190 + end
  191 +
  192 + def more_recent_label
  193 + ''
185 194 end
186 195  
187 196 end
... ...
app/models/environment.rb
... ... @@ -235,8 +235,10 @@ class Environment &lt; ActiveRecord::Base
235 235 settings[:message_for_member_invitation] || InviteMember.mail_template
236 236 end
237 237  
  238 + settings_items :min_signup_delay, :type => Integer, :default => 3 #seconds
238 239 settings_items :activation_blocked_text, :type => String
239   - settings_items :message_for_disabled_enterprise, :type => String
  240 + settings_items :message_for_disabled_enterprise, :type => String,
  241 + :default => _('This enterprise needs to be enabled.')
240 242 settings_items :location, :type => String
241 243 settings_items :layout_template, :type => String, :default => 'default'
242 244 settings_items :homepage, :type => String
... ... @@ -268,8 +270,6 @@ class Environment &lt; ActiveRecord::Base
268 270  
269 271 settings_items :search_hints, :type => Hash, :default => {}
270 272  
271   - settings_items :top_level_category_as_facet_ids, :type => Array, :default => []
272   -
273 273 def news_amount_by_folder=(amount)
274 274 settings[:news_amount_by_folder] = amount.to_i
275 275 end
... ... @@ -605,12 +605,10 @@ class Environment &lt; ActiveRecord::Base
605 605 end
606 606  
607 607 def top_url
608   - protocol = 'http'
609   - result = "#{protocol}://#{default_hostname}"
610   - if Noosfero.url_options.has_key?(:port)
611   - result << ':' << Noosfero.url_options[:port].to_s
612   - end
613   - result
  608 + url = 'http://'
  609 + url << (Noosfero.url_options.key?(:host) ? Noosfero.url_options[:host] : default_hostname)
  610 + url << ':' << Noosfero.url_options[:port].to_s if Noosfero.url_options.key?(:port)
  611 + url
614 612 end
615 613  
616 614 def to_s
... ...
app/models/event.rb
... ... @@ -108,18 +108,30 @@ class Event &lt; Article
108 108 }
109 109 }
110 110  
  111 + # TODO: some good soul, please clean this ugly hack:
111 112 if self.body
112 113 html.div('_____XXXX_DESCRIPTION_GOES_HERE_XXXX_____', :class => 'event-description')
113 114 end
114 115 }
115 116  
116 117 if self.body
117   - result.sub!('_____XXXX_DESCRIPTION_GOES_HERE_XXXX_____', self.body)
  118 + if options[:format] == 'short'
  119 + result.sub!('_____XXXX_DESCRIPTION_GOES_HERE_XXXX_____', display_short_format(self))
  120 + else
  121 + result.sub!('_____XXXX_DESCRIPTION_GOES_HERE_XXXX_____', self.body)
  122 + end
118 123 end
119 124  
120 125 result
121 126 end
122 127  
  128 + def lead
  129 + content_tag('div',
  130 + show_period(start_date, end_date),
  131 + :class => 'event-dates'
  132 + ) + super
  133 + end
  134 +
123 135 def event?
124 136 true
125 137 end
... ...
app/models/external_feed.rb
... ... @@ -11,6 +11,15 @@ class ExternalFeed &lt; ActiveRecord::Base
11 11 }
12 12  
13 13 def add_item(title, link, date, content)
  14 + doc = Hpricot(content)
  15 + doc.search('*').each do |p|
  16 + if p.instance_of? Hpricot::Elem
  17 + p.remove_attribute 'style'
  18 + p.remove_attribute 'class'
  19 + end
  20 + end
  21 + content = doc.to_s
  22 +
14 23 article = TinyMceArticle.new(:name => title, :profile => blog.profile, :body => content, :published_at => date, :source => link, :profile => blog.profile, :parent => blog)
15 24 unless blog.children.exists?(:slug => article.slug)
16 25 article.save!
... ...
app/models/feed_reader_block.rb
... ... @@ -47,11 +47,11 @@ class FeedReaderBlock &lt; Block
47 47  
48 48 def formatted_feed_content
49 49 if error_message.blank?
50   - "<ul>\n" +
51   - self.feed_items[0..(limit-1)].map{ |item| "<li><a href='#{item[:link]}'>#{item[:title]}</a></li>" }.join("\n") +
52   - "</ul>"
  50 + "<ul>\n".html_safe +
  51 + self.feed_items[0..(limit-1)].map{ |item| "<li><a href='#{item[:link]}'>#{item[:title]}</a></li>" }.join("\n").html_safe +
  52 + "</ul>".html_safe
53 53 else
54   - '<p>' + error_message + '</p>'
  54 + "<p>#{error_message}</p>".html_safe
55 55 end
56 56 end
57 57  
... ...
app/models/license.rb
... ... @@ -2,6 +2,11 @@ class License &lt; ActiveRecord::Base
2 2  
3 3 attr_accessible :name, :url
4 4  
  5 + SEARCHABLE_FIELDS = {
  6 + :name => 10,
  7 + :url => 5,
  8 + }
  9 +
5 10 belongs_to :environment
6 11 has_many :content, :class_name => 'Article', :foreign_key => 'license_id'
7 12  
... ...
app/models/link_list_block.rb
... ... @@ -82,7 +82,7 @@ class LinkListBlock &lt; Block
82 82  
83 83 def icons_options
84 84 ICONS.map do |i|
85   - "<span title=\"#{i[1]}\" class=\"icon-#{i[0]}\" onclick=\"changeIcon(this, '#{i[0]}')\"></span>"
  85 + "<span title=\"#{i[1]}\" class=\"icon-#{i[0]}\" onclick=\"changeIcon(this, '#{i[0]}')\"></span>".html_safe
86 86 end
87 87 end
88 88  
... ...
app/models/national_region.rb
1 1 class NationalRegion < ActiveRecord::Base
2 2  
  3 + SEARCHABLE_FIELDS = {
  4 + :name => 1,
  5 + :national_region_code => 1,
  6 + }
  7 +
3 8 def self.search_city(city_name, like = false, state = nil)
4 9  
5 10 operator = "="
... ...
app/models/organization.rb
1 1 # Represents any organization of the system
2 2 class Organization < Profile
3 3  
  4 + SEARCH_FILTERS += %w[
  5 + more_popular
  6 + more_active
  7 + ]
  8 +
4 9 settings_items :closed, :type => :boolean, :default => false
5 10 def closed?
6 11 closed
... ... @@ -78,6 +83,8 @@ class Organization &lt; Profile
78 83 country
79 84 tag_list
80 85 template_id
  86 + district
  87 + address_reference
81 88 ]
82 89  
83 90 def self.fields
... ... @@ -96,8 +103,8 @@ class Organization &lt; Profile
96 103 []
97 104 end
98 105  
99   - N_('Display name'); N_('Description'); N_('Contact person'); N_('Contact email'); N_('Acronym'); N_('Foundation year'); N_('Legal form'); N_('Economic activity'); N_('Management information'); N_('Tag list')
100   - settings_items :display_name, :description, :contact_person, :contact_email, :acronym, :foundation_year, :legal_form, :economic_activity, :management_information
  106 + N_('Display name'); N_('Description'); N_('Contact person'); N_('Contact email'); N_('Acronym'); N_('Foundation year'); N_('Legal form'); N_('Economic activity'); N_('Management information'); N_('Tag list'); N_('District'); N_('Address reference')
  107 + settings_items :display_name, :description, :contact_person, :contact_email, :acronym, :foundation_year, :legal_form, :economic_activity, :management_information, :district, :address_reference
101 108  
102 109 validates_format_of :foundation_year, :with => Noosfero::Constants::INTEGER_FORMAT
103 110 validates_format_of :contact_email, :with => Noosfero::Constants::EMAIL_FORMAT, :if => (lambda { |org| !org.contact_email.blank? })
... ...
app/models/organization_mailing.rb
... ... @@ -5,7 +5,7 @@ class OrganizationMailing &lt; Mailing
5 5 end
6 6  
7 7 def recipients(offset=0, limit=100)
8   - source.members.all(:order => self.id, :offset => offset, :limit => limit, :joins => "LEFT OUTER JOIN mailing_sents m ON (m.mailing_id = #{id} AND m.person_id = profiles.id)", :conditions => { "m.person_id" => nil })
  8 + source.members.all(:order => :id, :offset => offset, :limit => limit, :joins => "LEFT OUTER JOIN mailing_sents m ON (m.mailing_id = #{id} AND m.person_id = profiles.id)", :conditions => { "m.person_id" => nil })
9 9 end
10 10  
11 11 def each_recipient
... ...
app/models/person.rb
1 1 # A person is the profile of an user holding all relationships with the rest of the system
2 2 class Person < Profile
3 3  
  4 + SEARCH_FILTERS += %w[
  5 + more_popular
  6 + more_active
  7 + ]
  8 +
4 9 def self.type_name
5 10 _('Person')
6 11 end
... ... @@ -133,6 +138,9 @@ class Person &lt; Profile
133 138 contact_phone
134 139 contact_information
135 140 description
  141 + image
  142 + district
  143 + address_reference
136 144 ]
137 145  
138 146 validates_multiparameter_assignments
... ... @@ -187,8 +195,8 @@ class Person &lt; Profile
187 195 N_('Education'); N_('Custom education'); N_('Custom area of study');
188 196 settings_items :formation, :custom_formation, :custom_area_of_study
189 197  
190   - N_('Contact information'); N_('City'); N_('State'); N_('Country'); N_('Sex'); N_('Zip code')
191   - settings_items :photo, :contact_information, :sex, :city, :state, :country, :zip_code
  198 + N_('Contact information'); N_('City'); N_('State'); N_('Country'); N_('Sex'); N_('Zip code'); N_('District'); N_('Address reference')
  199 + settings_items :photo, :contact_information, :sex, :city, :state, :country, :zip_code, :district, :address_reference
192 200  
193 201 extend SetProfileRegionFromCityState::ClassMethods
194 202 set_profile_region_from_city_state
... ...
app/models/product.rb
1 1 class Product < ActiveRecord::Base
2 2  
  3 + SEARCHABLE_FIELDS = {
  4 + :name => 10,
  5 + :description => 1,
  6 + }
  7 +
  8 + SEARCH_FILTERS = %w[
  9 + more_recent
  10 + ]
  11 +
  12 + SEARCH_DISPLAYS = %w[map full]
  13 +
  14 + def self.default_search_display
  15 + 'full'
  16 + end
  17 +
3 18 belongs_to :enterprise
4 19 has_one :region, :through => :enterprise
5 20 validates_presence_of :enterprise
... ... @@ -23,6 +38,10 @@ class Product &lt; ActiveRecord::Base
23 38  
24 39 scope :more_recent, :order => "created_at DESC"
25 40  
  41 + named_scope :from_category, lambda { |category|
  42 + {:joins => :product_category, :conditions => ['categories.path LIKE ?', "%#{category.slug}%"]} if category
  43 + }
  44 +
26 45 after_update :save_image
27 46  
28 47 def lat
... ... @@ -173,7 +192,7 @@ class Product &lt; ActiveRecord::Base
173 192  
174 193 def price_described?
175 194 return false if price.blank? or price == 0
176   - (price - total_production_cost).zero?
  195 + (price - total_production_cost.to_f).zero?
177 196 end
178 197  
179 198 def update_price_details(price_details)
... ... @@ -215,45 +234,6 @@ class Product &lt; ActiveRecord::Base
215 234 end
216 235 end
217 236  
218   - private
219   - def f_category
220   - self.product_category.name
221   - end
222   - def f_region
223   - self.enterprise.region.id if self.enterprise.region
224   - end
225   - def self.f_region_proc(id)
226   - c = Region.find(id)
227   - s = c.parent
228   - if c and c.kind_of?(City) and s and s.kind_of?(State) and s.acronym
229   - [c.name, ', ' + s.acronym]
230   - else
231   - c.name
232   - end
233   - end
234   - def self.f_qualifier_proc(ids)
235   - array = ids.split
236   - qualifier = Qualifier.find_by_id array[0]
237   - certifier = Certifier.find_by_id array[1]
238   - certifier ? [qualifier.name, _(' cert. ') + certifier.name] : qualifier.name
239   - end
240   - def f_qualifier
241   - product_qualifiers.map do |pq|
242   - "#{pq.qualifier_id} #{pq.certifier_id}"
243   - end
244   - end
245   -
246   - alias_method :name_sortable, :name
247 237 delegate :enabled, :region, :region_id, :environment, :environment_id, :to => :enterprise
248 238  
249   - def public
250   - self.public?
251   - end
252   - def price_sortable
253   - (price.nil? or price.zero?) ? nil : price
254   - end
255   - def category_filter
256   - enterprise.categories_including_virtual_ids << product_category_id
257   - end
258   -
259 239 end
... ...
app/models/profile.rb
... ... @@ -11,6 +11,22 @@ class Profile &lt; ActiveRecord::Base
11 11 _('Profile')
12 12 end
13 13  
  14 + SEARCHABLE_FIELDS = {
  15 + :name => 10,
  16 + :identifier => 5,
  17 + :nickname => 2,
  18 + }
  19 +
  20 + SEARCH_FILTERS = %w[
  21 + more_recent
  22 + ]
  23 +
  24 + SEARCH_DISPLAYS = %w[compact]
  25 +
  26 + def self.default_search_display
  27 + 'compact'
  28 + end
  29 +
14 30 module Roles
15 31 def self.admin(env_id)
16 32 find_role('admin', env_id)
... ... @@ -70,7 +86,7 @@ class Profile &lt; ActiveRecord::Base
70 86 #FIXME: these will work only if the subclass is already loaded
71 87 scope :enterprises, lambda { {:conditions => (Enterprise.send(:subclasses).map(&:name) << 'Enterprise').map { |klass| "profiles.type = '#{klass}'"}.join(" OR ")} }
72 88 scope :communities, lambda { {:conditions => (Community.send(:subclasses).map(&:name) << 'Community').map { |klass| "profiles.type = '#{klass}'"}.join(" OR ")} }
73   - scope :templates, :conditions => {:is_template => true}
  89 + scope :templates, lambda { |environment| { :conditions => {:is_template => true, :environment_id => environment.id} } }
74 90  
75 91 def members
76 92 scopes = plugins.dispatch_scopes(:organization_members, self)
... ... @@ -124,20 +140,12 @@ class Profile &lt; ActiveRecord::Base
124 140 scrap.nil? ? Scrap.all_scraps(self) : Scrap.all_scraps(self).find(scrap)
125 141 end
126 142  
127   - class_attribute :extra_index_methods
128   - self.extra_index_methods = []
129   -
130   - def extra_data_for_index
131   - self.class.extra_index_methods.map { |meth| meth.to_proc.call(self) }.flatten
132   - end
  143 + acts_as_having_settings :field => :data
133 144  
134   - def self.extra_data_for_index(sym = nil, &block)
135   - self.extra_index_methods.push(sym) if sym
136   - self.extra_index_methods.push(block) if block_given?
  145 + def settings
  146 + data
137 147 end
138 148  
139   - acts_as_having_settings :field => :data
140   -
141 149 settings_items :redirect_l10n, :type => :boolean, :default => false
142 150 settings_items :public_content, :type => :boolean, :default => true
143 151 settings_items :description
... ... @@ -204,7 +212,7 @@ class Profile &lt; ActiveRecord::Base
204 212 has_many :profile_categorizations_including_virtual, :class_name => 'ProfileCategorization'
205 213 has_many :categories_including_virtual, :through => :profile_categorizations_including_virtual, :source => :category
206 214  
207   - has_many :abuse_complaints, :foreign_key => 'requestor_id'
  215 + has_many :abuse_complaints, :foreign_key => 'requestor_id', :dependent => :destroy
208 216  
209 217 def top_level_categorization
210 218 ret = {}
... ... @@ -226,7 +234,7 @@ class Profile &lt; ActiveRecord::Base
226 234 if myregion
227 235 myregion.hierarchy.reverse.first(2).map(&:name).join(separator)
228 236 else
229   - %w[address city state country_name zip_code ].map {|item| (self.respond_to?(item) && !self.send(item).blank?) ? self.send(item) : nil }.compact.join(separator)
  237 + %w[address district city state country_name zip_code ].map {|item| (self.respond_to?(item) && !self.send(item).blank?) ? self.send(item) : nil }.compact.join(separator)
230 238 end
231 239 end
232 240  
... ... @@ -461,6 +469,10 @@ class Profile &lt; ActiveRecord::Base
461 469 { :profile => identifier, :controller => 'profile_editor', :action => 'index' }
462 470 end
463 471  
  472 + def tasks_url
  473 + { :profile => identifier, :controller => 'tasks', :action => 'index', :host => default_hostname }
  474 + end
  475 +
464 476 def leave_url(reload = false)
465 477 { :profile => identifier, :controller => 'profile', :action => 'leave', :reload => reload }
466 478 end
... ... @@ -692,7 +704,7 @@ private :generate_url, :url_options
692 704 def custom_footer_expanded
693 705 footer = custom_footer
694 706 if footer
695   - %w[contact_person contact_email contact_phone location address economic_activity city state country zip_code].each do |att|
  707 + %w[contact_person contact_email contact_phone location address district address_reference economic_activity city state country zip_code].each do |att|
696 708 if self.respond_to?(att) && footer.match(/\{[^{]*#{att}\}/)
697 709 if !self.send(att).nil? && !self.send(att).blank?
698 710 footer = footer.gsub(/\{([^{]*)#{att}\}/, '\1' + self.send(att))
... ... @@ -884,54 +896,6 @@ private :generate_url, :url_options
884 896 self.active_fields
885 897 end
886 898  
887   - private
888   - def self.f_categories_label_proc(environment)
889   - ids = environment.top_level_category_as_facet_ids
890   - r = Category.find(ids)
891   - map = {}
892   - ids.map{ |id| map[id.to_s] = r.detect{|c| c.id == id}.name }
893   - map
894   - end
895   - def self.f_categories_proc(facet, id)
896   - id = id.to_i
897   - return if id.zero?
898   - c = Category.find(id)
899   - c.name if c.top_ancestor.id == facet[:label_id].to_i or facet[:label_id] == 0
900   - end
901   - def f_categories
902   - category_ids - [region_id]
903   - end
904   -
905   - def f_region
906   - self.region_id
907   - end
908   - def self.f_region_proc(id)
909   - c = Region.find(id)
910   - s = c.parent
911   - if c and c.kind_of?(City) and s and s.kind_of?(State) and s.acronym
912   - [c.name, ', ' + s.acronym]
913   - else
914   - c.name
915   - end
916   - end
917   -
918   - def self.f_enabled_proc(enabled)
919   - enabled = enabled == "true" ? true : false
920   - enabled ? s_('facets|Enabled') : s_('facets|Not enabled')
921   - end
922   - def f_enabled
923   - self.enabled
924   - end
925   -
926   - def public
927   - self.public?
928   - end
929   - def category_filter
930   - categories_including_virtual_ids
931   - end
932   -
933   - public
934   -
935 899 def control_panel_settings_button
936 900 {:title => _('Profile Info and settings'), :icon => 'edit-profile'}
937 901 end
... ...
app/models/profile_list_block.rb
... ... @@ -51,13 +51,12 @@ class ProfileListBlock &lt; Block
51 51 send(:profile_image_link, item, :minor )
52 52 }.join("\n ")
53 53 if list.empty?
54   - list = '<div class="common-profile-list-block-none">'+ _('None') +'</div>'
  54 + list = content_tag 'div', _('None'), :class => 'common-profile-list-block-none'
55 55 else
56 56 list = content_tag 'ul', nl +' '+ list + nl
57 57 end
58 58 block_title(title) + nl +
59   - '<div class="common-profile-list-block">' +
60   - nl + list + nl + '<br style="clear:both" /></div>'
  59 + content_tag('div', nl + list + nl + content_tag('br', '', :style => 'clear:both'))
61 60 end
62 61 end
63 62  
... ...
app/models/qualifier.rb
1 1 class Qualifier < ActiveRecord::Base
2 2  
  3 + SEARCHABLE_FIELDS = {
  4 + :name => 1,
  5 + }
  6 +
3 7 belongs_to :environment
4 8  
5 9 has_many :qualifier_certifiers, :dependent => :destroy
... ...
app/models/raw_html_block.rb
... ... @@ -7,7 +7,7 @@ class RawHTMLBlock &lt; Block
7 7 settings_items :html, :type => :text
8 8  
9 9 def content(args={})
10   - (title.blank? ? '' : block_title(title)) + html.to_s
  10 + (title.blank? ? '' : block_title(title)).html_safe + html.to_s.html_safe
11 11 end
12 12  
13 13 end
... ...
app/models/region.rb
... ... @@ -4,12 +4,6 @@ class Region &lt; Category
4 4  
5 5 require_dependency 'enterprise' # enterprises can also be validators
6 6  
7   - # searches for organizations that could become validators for this region.
8   - # <tt>search</tt> is passed as is to find_by_contents on Organization.
9   - def search_possible_validators(search)
10   - Organization.find_by_contents(search)[:results].docs.reject {|item| self.validator_ids.include?(item.id) }
11   - end
12   -
13 7 def has_validator?
14 8 validators.count > 0
15 9 end
... ...
app/models/scrap.rb
1 1 class Scrap < ActiveRecord::Base
  2 + SEARCHABLE_FIELDS = {
  3 + :content => 1,
  4 + }
2 5 validates_presence_of :content
3 6 validates_presence_of :sender_id, :receiver_id
4 7  
... ...
app/models/spammer_logger.rb 0 → 100644
... ... @@ -0,0 +1,24 @@
  1 +class SpammerLogger < Logger
  2 + @logpath = File.join(Rails.root, 'log', "#{ENV['RAILS_ENV']}_spammers.log")
  3 + @logger = new(@logpath)
  4 +
  5 + def self.log(spammer_ip, object=nil)
  6 + if object
  7 + if object.kind_of?(Comment)
  8 + @logger << "[#{Time.now.strftime('%F %T %z')}] Comment-id: #{object.id} IP: #{spammer_ip}\n"
  9 + end
  10 + else
  11 + @logger << "[#{Time.now.strftime('%F %T %z')}] IP: #{spammer_ip}\n"
  12 + end
  13 + end
  14 +
  15 + def self.clean_log
  16 + File.delete(@logpath) if File.exists?(@logpath)
  17 + end
  18 +
  19 + def self.reload_log
  20 + clean_log
  21 + @logger = new(@logpath)
  22 + end
  23 +
  24 +end
... ...
app/models/tags_block.rb
... ... @@ -20,7 +20,8 @@ class TagsBlock &lt; Block
20 20 end
21 21  
22 22 def content(args={})
23   - tags = owner.article_tags
  23 + is_env = owner.class == Environment
  24 + tags = is_env ? owner.tag_counts : owner.article_tags
24 25 return '' if tags.empty?
25 26  
26 27 if limit
... ... @@ -29,18 +30,28 @@ class TagsBlock &lt; Block
29 30 tags_tmp.map{ |k,v| tags[k] = v }
30 31 end
31 32  
  33 + url = is_env ? {:host=>owner.default_hostname, :controller=>'search', :action => 'tag'} :
  34 + owner.public_profile_url.merge(:controller => 'profile', :action => 'tags')
  35 + tagname_option = is_env ? :tag : :id
  36 +
32 37 block_title(title) +
33   - "\n<div class='tag_cloud'>\n"+
34   - tag_cloud( tags, :id,
35   - owner.public_profile_url.merge(:controller => 'profile', :action => 'tags'),
36   - :max_size => 16, :min_size => 9 ) +
37   - "\n</div><!-- end class='tag_cloud' -->\n";
  38 + "\n<div class='tag_cloud'>\n".html_safe+
  39 + tag_cloud( tags, tagname_option, url, :max_size => 16, :min_size => 9 ) +
  40 + "\n</div><!-- end class='tag_cloud' -->\n".html_safe
38 41 end
39 42  
40 43 def footer
41   - owner_id = owner.identifier
42   - lambda do
43   - link_to s_('tags|View all'), :profile => owner_id, :controller => 'profile', :action => 'tags'
  44 + if owner.class == Environment
  45 + lambda do
  46 + link_to s_('tags|View all'),
  47 + :controller => 'search', :action => 'tags'
  48 + end
  49 + else
  50 + owner_id = owner.identifier
  51 + lambda do
  52 + link_to s_('tags|View all'),
  53 + :profile => owner_id, :controller => 'profile', :action => 'tags'
  54 + end
44 55 end
45 56 end
46 57  
... ...
app/models/task_mailer.rb
... ... @@ -14,7 +14,7 @@ class TaskMailer &lt; ActionMailer::Base
14 14  
15 15 recipients task.target.notification_emails
16 16  
17   - url_for_tasks_list = task.target.kind_of?(Environment) ? '' : url_for(task.target.url.merge(:controller => 'tasks', :action => 'index'))
  17 + url_for_tasks_list = task.target.kind_of?(Environment) ? '' : url_for(task.target.tasks_url)
18 18  
19 19 from self.class.generate_from(task)
20 20 subject '[%s] %s' % [task.environment.name, task.target_notification_description]
... ...
app/models/uploaded_file.rb
... ... @@ -115,7 +115,7 @@ class UploadedFile &lt; Article
115 115  
116 116 content_tag(
117 117 'div',
118   - link_to_previous + content_tag('span', _('image %d of %d'), :class => 'total-of-images') % [current_index + 1, total_of_images] + link_to_next,
  118 + link_to_previous + (content_tag('span', _('image %d of %d'), :class => 'total-of-images') % [current_index + 1, total_of_images]).html_safe + link_to_next,
119 119 :class => 'gallery-navigation'
120 120 )
121 121 end.to_s +
... ...
app/models/user.rb
... ... @@ -18,12 +18,9 @@ class User &lt; ActiveRecord::Base
18 18 # FIXME ugly workaround
19 19 def self.human_attribute_name(attrib)
20 20 case attrib.to_sym
21   - when :login
22   - return _('Username')
23   - when :email
24   - return _('e-Mail')
25   - else
26   - _(self.superclass.human_attribute_name(attrib))
  21 + when :login: return [_('Username'), _('Email')].join(' / ')
  22 + when :email: return _('e-Mail')
  23 + else _(self.superclass.human_attribute_name(attrib))
27 24 end
28 25 end
29 26  
... ... @@ -134,10 +131,11 @@ class User &lt; ActiveRecord::Base
134 131  
135 132 validates_inclusion_of :terms_accepted, :in => [ '1' ], :if => lambda { |u| ! u.terms_of_use.blank? }, :message => N_('%{fn} must be checked in order to signup.').fix_i18n
136 133  
137   - # Authenticates a user by their login name and unencrypted password. Returns the user or nil.
  134 + # Authenticates a user by their login name or email and unencrypted password. Returns the user or nil.
138 135 def self.authenticate(login, password, environment = nil)
139 136 environment ||= Environment.default
140   - u = first :conditions => ['login = ? AND environment_id = ? AND activated_at IS NOT NULL', login, environment.id] # need to get the salt
  137 + u = self.first :conditions => ['(login = ? OR email = ?) AND environment_id = ? AND activated_at IS NOT NULL',
  138 + login, login, environment.id] # need to get the salt
141 139 u && u.authenticated?(password) ? u : nil
142 140 end
143 141  
... ...
app/views/account/_signup_form.html.erb
  1 +<% if @block_bot %>
  2 + <div class="atention" style="font-size: 150%;">
  3 + <strong><%=_('Are you a robot?')%></strong> <br />
  4 + <%=_('Please, prove that you are human by filling the captcha.')%>
  5 + </div>
  6 +<% end %>
  7 +
1 8 <% @profile_data = @person %>
2 9  
3 10 <%= error_messages_for :user, :person, :header_message => _('The account could not be created') %>
4 11  
5   -<%= labelled_form_for :user, @user, :html => { :multipart => true, :id => 'signup-form' } do |f| %>
  12 +<%= labelled_form_for :user, @user, :html => { :multipart => true, :id => 'signup-form', :honeypot => true } do |f| %>
  13 +
  14 +<input type="hidden" id="signup_time_key" name="signup_time_key" />
  15 +<script type="text/javascript">
  16 + jQuery.ajax({
  17 + type: "POST",
  18 + url: "<%= url_for :controller=>'account', :action=>'signup_time' %>",
  19 + dataType: 'json',
  20 + success: function(data) {
  21 + if (data.ok) jQuery('#signup_time_key').val(data.key);
  22 + }
  23 + });
  24 +</script>
6 25  
7 26 <%= hidden_field_tag :invitation_code, @invitation_code %>
8 27  
... ... @@ -13,7 +32,8 @@
13 32 <span id="signup-domain"><%= environment.default_hostname %>/</span>
14 33 <div id='signup-login'>
15 34 <div id='signup-login-field' class='formfield'>
16   - <%= required text_field(:user, :login, :id => 'user_login', :onchange => 'this.value = convToValidLogin(this.value);') %>
  35 + <%= required text_field(:user, :login, :id => 'user_login',
  36 + :onchange => 'this.value = convToValidUsername(this.value);') %>
17 37 <div id='url-check'><p>&nbsp;</p></div>
18 38 </div>
19 39 <%= content_tag(:small, _('Choose your login name carefully! It will be your network access and you will not be able to change it later.'), :id => 'signup-balloon') %>
... ... @@ -97,6 +117,8 @@
97 117 <% end %>
98 118 </div>
99 119  
  120 +<%= recaptcha_tags :ajax => true, :display => {:theme => 'clean'} if @block_bot %>
  121 +
100 122 <p style="text-align: center">
101 123 <%= submit_button('save', _('Create my account')) %>
102 124 </p>
... ...
app/views/account/forgot_password.html.erb
... ... @@ -5,7 +5,7 @@
5 5 <%= labelled_form_for :change_password, @change_password, :url => { :action => 'forgot_password' } do |f| %>
6 6  
7 7 <%= f.text_field :login,
8   - :onchange => 'this.value = convToValidLogin( this.value )' %>
  8 + :onchange => 'this.value = convToValidUsername( this.value )' %>
9 9  
10 10 <%= f.text_field :email %>
11 11  
... ...
app/views/admin_panel/site_info.html.erb
... ... @@ -4,7 +4,7 @@
4 4  
5 5 <%= render :file => 'shared/tiny_mce' %>
6 6  
7   -<%= labelled_form_for :environment, @environment, :url => {:host => @environment.default_hostname, :port => request.port} do |f| %>
  7 +<%= labelled_form_for :environment, @environment do |f| %>
8 8 <% tabs = [] %>
9 9 <% tabs << {:title => _('Site info'), :id => 'site-info',
10 10 :content => (render :partial => 'site_info', :locals => {:f => f})} %>
... ...
app/views/box_organizer/_article_block.html.erb
1   -<div class='article-block-edition'>
  1 +<div class="article-block-edition">
2 2 <% if @block.box.owner.kind_of?(Environment) and @block.box.owner.portal_community.nil? %>
3   - <p id='no_portal_community'>
  3 + <p id="no_portal_community">
4 4 <%= _("You don't have an community defined as the portal community. Define it before use this block properly.") %>
5 5 </p>
6 6 <% else %>
7   - <% articles = @block.available_articles.select {|article| !article.folder? } %>
8   - <%= select_tag('block[article_id]', options_for_select_with_title(articles.map {|item| [item.path, item.id]}, @block.article ? @block.article.id : nil)) %>
  7 + <%
  8 + articles = @block.available_articles.select {|a| !a.folder? || a.blog? }
  9 + first_text = articles[articles.find_index{|a| a.kind_of? TextArticle}||-1]
  10 + selected = @block.article || first_text
  11 + %>
  12 + <%= select_tag(
  13 + 'block[article_id]',
  14 + options_for_select_with_title(articles.map {|item| [item.path, item.id]}, selected.id),
  15 + :onchange => 'this.changedTo(this.value)'
  16 + )%>
  17 + <div id="block_blog_options" style="display:none">
  18 + <%= labelled_form_field(
  19 + _('Number of posts:'),
  20 + text_field_tag('block[posts_per_page]', @block.posts_per_page)
  21 + )%>
  22 + </div>
  23 + <%= labelled_form_field(
  24 + _('How to display this content:'),
  25 + select_tag(
  26 + 'block[visualization_format]',
  27 + options_for_select([[_('Lead'), 'short'], [_('Full post'), 'full']], @block.visualization_format)
  28 + )
  29 + )%>
  30 + <% blogs = @block.available_articles.select{|a|a.blog?} %>
  31 + <script>
  32 + var select = jQuery("#block_article_id")[0];
  33 + select.blogs = <%= blogs.map{|b| b.id.to_s }.to_json %>;
  34 + select.changedTo = function(articleId) {
  35 + var blogSelected = this.blogs.indexOf(articleId) != -1;
  36 + jQuery("#block_blog_options").toggle(blogSelected);
  37 + }
  38 + select.changedTo('<%= selected.id %>');
  39 + </script>
9 40 <% end %>
10 41 </div>
... ...
app/views/box_organizer/_highlights_block.html.erb
1 1 <strong><%= _('Highlights') %></strong>
2   -<div id='edit-highlights-block' style='width:450px'>
3   -<table id='highlights' class='noborder'>
4   - <tr><th><%= _('Image') %></th><th><%= _('Address') %></th><th><%= _('Position') %></th><th><%= _('Title') %></th></tr>
  2 +
  3 +<table class="noborder"><tbody id="highlights-data-table">
  4 + <tr><th><%= _('Image') %></th><th><%= _('Address') %></th><th><%= _('Position') %></th></tr>
5 5 <% for image in @block.images do %>
6   - <tr>
7   - <td>
8   - <%= select_tag 'block[images][][image_id]', content_tag(:option) + option_groups_from_collection_for_select(@block.folder_choices, :images, :name, :id, :name, image[:image_id].to_i), :style => "width: 100px" %></p>
9   - </td>
10   - <td><%= text_field_tag 'block[images][][address]', image[:address], :class => 'highlight-address', :size => 10 %></td>
11   - <td><%= text_field_tag 'block[images][][position]', image[:position], :class => 'highlight-position', :size => 3 %></td>
12   - <td><%= text_field_tag 'block[images][][title]', image[:title], :class => 'highlight-title', :size => 10 %></td>
13   - </tr>
  6 + <%= highlights_block_config_image_fields @block, image %>
14 7 <% end %>
15   -</table>
16   -</div>
  8 +</tbody></table>
17 9  
18 10 <%= link_to_function(_('New highlight'), nil, :class => 'button icon-add with-text') do |page|
19   - page.insert_html :bottom, 'highlights', content_tag('tr',
20   - content_tag('td', select_tag('block[images][][image_id]', content_tag(:option) + option_groups_from_collection_for_select(@block.folder_choices, :images, :name, :id, :name), :style => "width: 100px")) +
21   - content_tag('td', text_field_tag('block[images][][address]', nil, :class => 'highlight-address', :size => 10)) +
22   - content_tag('td', text_field_tag('block[images][][position]', nil, :class => 'highlight-position', :size => 3)) +
23   - content_tag('td', text_field_tag('block[images][][title]', nil, :class => 'highlight-position', :size => 10))
24   - ) +
25   - javascript_tag("$('edit-link-list-block').scrollTop = $('edit-link-list-block').scrollHeight")
  11 + page.insert_html :bottom, 'highlights-data-table', highlights_block_config_image_fields(@block)
26 12 end %>
27 13  
28 14 <%= labelled_form_field _('Image transition:'), select('block', 'interval', [[_('No automatic transition'), 0]] + [1, 2, 3, 4, 5, 10, 20, 30, 60].map {|item| [n_('Every 1 second', 'Every %d seconds', item) % item, item]}) %>
... ...
app/views/box_organizer/add_block.html.erb
1   -<div style='height:350px'>
  1 +<div id="add-block-dialog">
2 2 <% form_tag do %>
3 3  
4 4 <p><%= _('In what area do you want to put your new block?') %></p>
5 5  
  6 + <div id="box-position">
6 7 <% @boxes.each do |box| %>
7   - <%= labelled_radio_button(_("Area %d") % box.position, :box_id, box.id, box.central?, { :class => 'box-position', 'data-position' => box.position }) %>
  8 + <% name = box.central? ? _('Main area') : _('Area %d') % box.position %>
  9 + <%= labelled_radio_button(name, :box_id, box.id, box.central?, { 'data-position' => box.position }) %>
8 10 <% end %>
  11 + </div>
9 12  
10 13 <script type="text/javascript">
11   - (function ($) {
12   - $(document).ready(function () {
13   - $(".box-position").live('change', function () {
14   - if ($(this).attr('data-position') == '1') {
15   - $('#center-block-types').show();
16   - $('#side-block-types').hide();
17   - } else {
18   - $('#center-block-types').hide();
19   - $('#side-block-types').show();
20   - };
21   - });
22   - })})(jQuery);
  14 + jQuery('#box-position input').bind('change',
  15 + function () {
  16 + showCenter = jQuery(this).attr('data-position') == '1';
  17 + jQuery('#center-block-types').toggle(showCenter);
  18 + jQuery('#side-block-types').toggle(!showCenter);
  19 + }
  20 + );
23 21 </script>
24 22  
25 23 <p><%= _('Select the type of block you want to add to your page.') %></p>
26 24  
27   - <div id='center-block-types'>
28   - <%= render :partial => 'block_types', :locals => { :block_types => @center_block_types } %>
  25 + <div id="center-block-types" class="block-types">
  26 + <% @center_block_types.each do |block| %>
  27 + <div class='block-type'>
  28 + <%= labelled_radio_button(block.description, :type, block.name) %>
  29 + </div>
  30 + <% end %>
29 31 </div>
30 32  
31   - <div id='side-block-types' style='display:none'>
32   - <%= render :partial => 'block_types', :locals => { :block_types => @side_block_types } %>
  33 + <div id="side-block-types" class="block-types" style="display:none">
  34 + <% @side_block_types.each do |block| %>
  35 + <div class='block-type'>
  36 + <%= labelled_radio_button(block.description, :type, block.name) %>
  37 + </div>
  38 + <% end %>
33 39 </div>
34 40  
35 41 <br style='clear: both'/>
... ...
app/views/box_organizer/edit.html.erb
1   -<div style='width: 500px;'>
2   - <h2><%= _('Editing block') %></h2>
  1 +<div class="block-config-options <%= @block.class.name %>-options">
  2 + <h2 class="title"><%= _('Editing block') %></h2>
3 3  
4 4 <% form_tag(:action => 'save', :id => @block.id) do %>
5 5  
... ...
app/views/box_organizer/index.html.erb
1 1 <h1><%= _('Editing sideboxes')%></h1>
2 2  
3   -<% button_bar do %>
  3 +<% button_bar :class=>'design-menu' do %>
4 4 <%= colorbox_button('add', _('Add a block'), { :action => 'add_block' }) %>
5 5 <%= button(:back, _('Back to control panel'), :controller => (profile.nil? ? 'admin_panel': 'profile_editor')) %>
6 6 <% end %>
... ...
app/views/catalog/index.html.erb
1 1 <% extra_content = [] %>
2 2 <% extra_content_list = [] %>
3 3  
4   -<ul id="product-list">
5   - <li><h1><%= _('Products/Services') %></h1></li>
  4 +<h1><%= _('Products/Services') %></h1>
6 5  
  6 +<%= breadcrumb(@category) if params[:level] %>
  7 +
  8 +<div class='l-sidebar-left-bar'>
  9 + <ul>
  10 + <%= content_tag('li', link_to(_('Homepage'), profile.url), :class => 'catalog-categories-link') %>
  11 + <%= content_tag('li', link_to(_('Catalog start'), profile.catalog_url), :class => 'catalog-categories-link') %>
  12 + <% if @categories.present? %>
  13 + <% @categories.each do |category| %>
  14 + <%= category_link(category) %>
  15 + <%= category_sub_links(category) %>
  16 + <% end %>
  17 + <% elsif @category.present? %>
  18 + <%= content_tag('li', _('There are no sub-categories for %s') % @category.name, :id => 'catalog-categories-notice') %>
  19 + <% else %>
  20 + <%= content_tag('li', _('There are no categories available.'), :id => 'catalog-categories-notice') %>
  21 + <% end %>
  22 + </ul>
  23 +</div>
  24 +
  25 +<ul id="product-list" class="l-sidebar-left-content">
7 26 <% @products.each do |product| %>
8 27 <% extra_content = @plugins.dispatch(:catalog_item_extras, product).collect { |content| instance_eval(&content) } %>
9 28 <% extra_content_list = @plugins.dispatch(:catalog_list_item_extras, product).collect { |content| instance_eval(&content) } %>
10 29  
11   - <li class="product <%= "not-available" unless product.available %>">
  30 + <% status = [] %>
  31 + <% status << 'not-available' if !product.available %>
  32 + <% status << 'highlighted' if product.highlighted %>
  33 +
  34 + <li id="product-<%= product.id %>" class="product <%= status.join(' ') %>">
12 35 <ul>
13 36 <li class="product-image-link">
  37 + <% if product.highlighted? %>
  38 + <%= link_to image_tag(themed_path('/images/star.png'), :class => 'star', :alt => _('Highlighted product')), product_path(product) %>
  39 + <% end %>
14 40 <% if product.image %>
15 41 <div class="zoomable-image">
16 42 <%= link_to_product product, :class => 'product-big', :style => "background-image: url(#{product.default_image(:big)})" %>
... ... @@ -42,20 +68,20 @@
42 68  
43 69 <% if product.description %>
44 70 <li class="product-description expand-box">
45   - <span id="product-description-button"><%= _('description') %></span>
46   - <div>
  71 + <span class="product-description-button"><%= _('description') %></span>
  72 + <div class="float-box">
47 73 <div class="arrow"></div>
48   - <div class="content" id="product-description"><%= txt2html(product.description || '') %></div>
  74 + <div class="content"><%= product.description %></div>
49 75 </div>
50 76 </li>
51 77 <% end %>
52 78  
53 79 <% if product.price_described? %>
54 80 <li class="product-price-composition expand-box">
55   - <span id="product-price-composition-button"><%= _('price composition') %></span>
56   - <div>
  81 + <span class="product-price-composition-button"><%= _('price composition') %></span>
  82 + <div class="float-box">
57 83 <div class="arrow"></div>
58   - <div class="content" id="product-price-composition">
  84 + <div class="content">
59 85 <% product.inputs.relevant_to_price.each do |i| %>
60 86 <div class="search-product-input-dots-to-price">
61 87 <div class="search-product-input-name"><%= i.product_category.name %></div>
... ... @@ -76,9 +102,9 @@
76 102 <% if product.inputs.count > 0 %>
77 103 <li class="product-inputs expand-box">
78 104 <span id="inputs-button"><%= _('inputs and raw materials') %></span>
79   - <div>
  105 + <div class="float-box">
80 106 <div class="arrow"></div>
81   - <div class="content" id="inputs-description">
  107 + <div class="content">
82 108 <% product.inputs.each do |i| %>
83 109 <div>
84 110 <%= _('%{amount_used} %{unit} of') % {:amount_used => i.amount_used, :unit => i.unit.singular} + ' ' if i.has_all_price_details? %>
... ...
app/views/cms/_blog.html.erb
... ... @@ -4,7 +4,7 @@
4 4  
5 5 <%= render :file => 'shared/tiny_mce' %>
6 6  
7   -<%= required f.text_field(:name, :size => '64', :onchange => "updateUrlField(this, 'article_slug')") %>
  7 +<%= required f.text_field(:name, :size => '64', :maxlength => 150, :onchange => "updateUrlField(this, 'article_slug')") %>
8 8  
9 9 <%= render :partial => 'general_fields' %>
10 10  
... ...
app/views/cms/_event.html.erb
... ... @@ -3,7 +3,7 @@
3 3 <%# TODO add Textile help here %>
4 4 <%= render :file => 'shared/tiny_mce' %>
5 5  
6   -<%= required f.text_field('name', :size => '64') %>
  6 +<%= required f.text_field('name', :size => '64', :maxlength => 150) %>
7 7  
8 8 <%= render :partial => 'general_fields' %>
9 9 <%= render :partial => 'translatable' %>
... ...
app/views/cms/_folder.html.erb
1 1 <%= required_fields_message %>
2 2  
3   -<%= required f.text_field('name', :size => '64') %>
  3 +<%= required f.text_field('name', :size => '64', :maxlength => 150) %>
4 4 <%= render :partial => 'general_fields' %>
5 5  
6 6 <%= labelled_form_field(_('Description:'), text_area(:article, :body, :rows => 3, :cols => 64)) %>
... ...
app/views/cms/_forum.html.erb
... ... @@ -4,7 +4,7 @@
4 4  
5 5 <%= render :file => 'shared/tiny_mce' %>
6 6  
7   -<%= required f.text_field(:name, :size => '64', :onchange => "updateUrlField(this, 'article_slug')") %>
  7 +<%= required f.text_field(:name, :size => '64', :maxlength => 150, :onchange => "updateUrlField(this, 'article_slug')") %>
8 8  
9 9 <%= render :partial => 'general_fields' %>
10 10  
... ...
app/views/cms/_gallery.html.erb
1 1 <%= required_fields_message %>
2 2  
3   -<%= required f.text_field('name', :size => '64') %>
  3 +<%= required f.text_field('name', :size => '64', :maxlength => 150) %>
4 4  
5 5 <%= render :partial => 'general_fields' %>
6 6  
... ...
app/views/cms/_published_article.html.erb
1   -<%= f.text_field 'name', :size => '64' %>
  1 +<%= f.text_field 'name', :size => '64', :maxlength => 150 %>
2 2 <%= render :partial => 'general_fields' %>
3 3  
4 4 <p><%= _('This is a republication of "%s", by %s.') % [link_to(h(@article.reference_article.name), @article.reference_article.url), @article.reference_article.profile.name] %></p>
... ...
app/views/cms/_raw_html_article.html.erb
1 1 <%= required_fields_message %>
2 2  
3   -<%= required labelled_form_field(_('Title'), text_field(:article, 'name', :size => '64')) %>
  3 +<%= required labelled_form_field(_('Title'), text_field(:article, 'name', :size => '64', :maxlength => 150)) %>
4 4  
5 5 <%= render :partial => 'general_fields' %>
6 6 <%= render :partial => 'translatable' %>
... ...
app/views/cms/_text_editor_sidebar.html.erb
... ... @@ -9,7 +9,12 @@
9 9 <div id='media-upload-form'>
10 10 <% form_tag({ :action => 'media_upload' }, :multipart => true) do %>
11 11 <div class='formfield'>
12   - <%= select_profile_folder(_('Choose folder to upload files:'), :parent_id, profile) %>
  12 + <% default_folder = content_id_to_str default_folder_for_image_upload(profile) %>
  13 + <%= select_profile_folder(
  14 + _('Choose folder to upload files:'),
  15 + :parent_id, profile, default_folder, {}, {},
  16 + "type='Folder' or type='Gallery'"
  17 + ) %>
13 18 </div>
14 19 <p><%= file_field_tag('file1') %></p>
15 20 <p><%= file_field_tag('file2') %></p>
... ...
app/views/cms/_textile_article.html.erb
... ... @@ -2,7 +2,7 @@
2 2  
3 3 <%# TODO add Textile help here %>
4 4  
5   -<%= required labelled_form_field(_('Title'), text_field(:article, 'name', :size => '72')) %>
  5 +<%= required labelled_form_field(_('Title'), text_field(:article, 'name', :size => '72', :maxlength => 150)) %>
6 6  
7 7 <%= render :partial => 'general_fields' %>
8 8 <%= render :partial => 'translatable' %>
... ...
app/views/cms/_tiny_mce_article.html.erb
... ... @@ -3,7 +3,7 @@
3 3 <%= render :file => 'shared/tiny_mce' %>
4 4  
5 5 <div>
6   - <%= required labelled_form_field(_('Title'), text_field(:article, 'name', :size => '64')) %>
  6 + <%= required labelled_form_field(_('Title'), text_field(:article, 'name', :size => '64', :maxlength => 150)) %>
7 7  
8 8 <%= render :partial => 'general_fields' %>
9 9 <%= render :partial => 'translatable' %>
... ...
app/views/cms/select_article_type.html.erb
  1 +<div class="select-article-type">
  2 +
1 3 <h2> <%= _('Choose the type of content:') %> </h2>
2 4  
3   -<ul id="article_types">
  5 +<ul class="article-types">
4 6 <% for type in @article_types %>
5 7 <% action = type[:class].name == 'UploadedFile' ? {:action => 'upload_files'} : {:action => 'new', :type => type[:class].name} %>
6 8 <% content_tag('a', :href => url_for(action.merge(:parent_id => @parent_id, :back_to => @back_to))) do %>
... ... @@ -14,3 +16,5 @@
14 16 <br style="clear:both" />
15 17  
16 18 <%= colorbox_close_button(_('Cancel')) %>
  19 +
  20 +</div>
... ...
app/views/content_viewer/_comment_form.html.erb
... ... @@ -21,8 +21,6 @@ function submit_comment_form(button) {
21 21 }
22 22 </script>
23 23  
24   -<% focus_on = logged_in? ? 'title' : 'name' %>
25   -
26 24 <% if @comment && @comment.errors.any? && @comment.reply_of_id.blank? %>
27 25 <%= error_messages_for :comment %>
28 26 <script type="text/javascript">jQuery(function() { document.location.href = '#page-comment-form'; });</script>
... ... @@ -32,17 +30,7 @@ function submit_comment_form(button) {
32 30  
33 31 <div class="post_comment_box <%= @form_div %>">
34 32  
35   -<% if display_link %>
36   - <h4 onclick="var d = jQuery(this).parent('.post_comment_box');
37   - if (d.hasClass('closed')) {
38   - d.removeClass('closed');
39   - d.addClass('opened');
40   - d.find('input[name=comment[title]], textarea').val('');
41   - d.find('.comment_form input[name=comment[<%= focus_on %>]]').focus();
42   - }">
43   - <%= content_tag('a', '', :name => 'comment_form') + _('Post a comment') %>
44   - </h4>
45   -<% end %>
  33 + <%= link_to(_('Post a comment'), '#', :class => 'display-comment-form') if display_link %>
46 34  
47 35 <% unless pass_without_comment_captcha? %>
48 36 <div id="recaptcha-container" style="display: none">
... ... @@ -62,8 +50,6 @@ function submit_comment_form(button) {
62 50 <% end %>
63 51  
64 52 <% form_tag( url, { :class => 'comment_form' } ) do %>
65   - <%= hidden_field_tag(:confirm, 'false') %>
66   -
67 53 <%= required_fields_message %>
68 54  
69 55 <% unless logged_in? %>
... ... @@ -84,10 +70,13 @@ function submit_comment_form(button) {
84 70 <%= labelled_form_field(_('Title'), text_field(:comment, :title)) %>
85 71 <%= required labelled_form_field(_('Enter your comment'), text_area(:comment, :body, :rows => 5)) %>
86 72  
  73 + <%= hidden_field_tag(:confirm, 'false') %>
  74 + <%= hidden_field_tag(:view, params[:view])%>
  75 +
87 76 <% button_bar do %>
88 77 <%= submit_button('add', _('Post comment'), :onclick => "submit_comment_form(this); return false") %>
89 78 <% if cancel_triggers_hide %>
90   - <%= button_to_function :cancel, _('Cancel'), "f=jQuery(this).parents('.post_comment_box'); f.removeClass('opened'); f.addClass('closed'); return false" %>
  79 + <%= button :cancel, _('Cancel'), '', :id => 'cancel-comment' %>
91 80 <% else %>
92 81 <%= button('cancel', _('Cancel'), {:action => 'view_page', :profile => profile.identifier, :page => @comment.article.explode_path})%>
93 82 <% end %>
... ... @@ -95,3 +84,5 @@ function submit_comment_form(button) {
95 84 <% end %>
96 85  
97 86 </div><!-- end class="post_comment_box" -->
  87 +
  88 +<%= javascript_include_tag 'comment_form'%>
... ...
app/views/content_viewer/blog_page.html.erb
1   -<% add_rss_feed_to_head(@page.name, @page.feed.url) if @page.blog? && @page.feed %>
  1 +<% add_rss_feed_to_head(blog.name, blog.feed.url) if blog.blog? && blog.feed %>
2 2  
3   -<%= content_tag('em', _('(external feed was not loaded yet)'), :id => 'external-feed-info', :class => 'metadata') if @page.blog? && @page.external_feed && @page.external_feed.enabled && @page.external_feed.fetched_at.nil? %>
  3 +<%= content_tag('em', _('(external feed was not loaded yet)'), :id => 'external-feed-info', :class => 'metadata') if blog.blog? && blog.external_feed && blog.external_feed.enabled && blog.external_feed.fetched_at.nil? %>
4 4  
5 5 <div>
6 6 <div class='blog-description'>
7   - <%= @page.body %>
  7 + <%= blog.body %>
8 8 </div>
9 9 </div>
10 10 <hr class="pre-posts"/>
11 11 <div class="blog-posts">
12   - <%= (@page.empty? ? content_tag('em', _('(no posts)')) : list_posts(@posts, @page.visualization_format)) %>
  12 + <%=
  13 + posts = @posts
  14 + format = blog.visualization_format
  15 + if inside_block
  16 + posts = blog.posts.paginate(:page=>1, :per_page=>inside_block.posts_per_page)
  17 + format = inside_block.visualization_format
  18 + end
  19 + (blog.empty? ? content_tag('em', _('(no posts)')) : list_posts(posts, format))
  20 + %>
13 21 </div>
... ...
app/views/content_viewer/view_page.html.erb
... ... @@ -90,7 +90,7 @@
90 90 <% end %>
91 91  
92 92 <% if @page.accept_comments? && @comments_count > 1 %>
93   - <p class="post-comment-button"><a href="#comment_form" onclick="jQuery('#page-comment-form h4').first().trigger('click')"><%= _('Post a comment') %></a></p>
  93 + <%= link_to(_('Post a comment'), '#', :class => 'display-comment-form', :id => 'top-post-comment-button') %>
94 94 <% end %>
95 95  
96 96 <ul class="article-comments-list">
... ...
app/views/favorite_enterprises/index.html.erb
... ... @@ -5,7 +5,7 @@
5 5 <ul class="profile-list">
6 6 <% @favorite_enterprises.each do |enterprise| %>
7 7 <li>
8   - <%= link_to_profile profile_image(enterprise) + '<br/>' + enterprise.name,
  8 + <%= link_to_profile profile_image(enterprise) + '<br/>'.html_safe + enterprise.name,
9 9 enterprise.identifier, :class => 'profile-link' %>
10 10 <%# profile_image_link enterprise, :portrait, 'div' %>
11 11 <div class="controll">
... ...
app/views/layouts/_user.html.erb 0 → 100644
... ... @@ -0,0 +1,24 @@
  1 +<div id="user">
  2 + <span class='logged-in' style='display: none;'>
  3 + <%= usermenu_logged_in %>
  4 + </span>
  5 + <span class='not-logged-in' style='display: none'>
  6 +
  7 + <%= _("<span class='login'>%s</span>") % thickbox_inline_popup_link('<i class="icon-menu-login"></i><strong>' + _('Login') + '</strong>', login_url, 'inlineLoginBox', :id => 'link_login') %>
  8 + <%= @plugins.dispatch(:alternative_authentication_link).collect { |content| instance_eval(&content) }.join("") %>
  9 +
  10 + <div id='inlineLoginBox' style='display: none;'>
  11 + <%= render :file => 'account/login', :locals => { :is_thickbox => true } %>
  12 + </div>
  13 +
  14 + <% unless @plugins.dispatch(:allow_user_registration).include?(false) %>
  15 + <%= _("<span class='or'>or</span> <span class='signup'>%s</span>") % link_to('<strong>' + _('Sign up') + '</strong>', :controller => 'account', :action => 'signup')%>
  16 + <% end %>
  17 +
  18 + </span>
  19 + <form action="/search" id="top-search" class="search_form clean" method="get">
  20 + <input name="query" size="15" title="<%=_('Search...')%>" onfocus="this.form.className='focused';" onblur="this.form.className=''" />
  21 + <div><%=_('Press <strong>Enter</strong> to send the search query.')%></div>
  22 + <%= javascript_tag 'jQuery("#user form input").hint();' %>
  23 + </form>
  24 +</div><!-- end id="user" -->
... ...
app/views/layouts/application-ng.html.erb
... ... @@ -8,38 +8,19 @@
8 8 <meta name="description" content="<%= @environment.name %>" />
9 9 <link rel="shortcut icon" href="<%= image_path(theme_favicon) %>" type="image/x-icon" />
10 10 <%= noosfero_javascript %>
11   - <%= stylesheet_link_tag *noosfero_stylesheets, :cache => 'cache' %>
12   - <%= stylesheet_link_tag *template_stylesheet_path %>
13   - <%= stylesheet_link_tag *icon_theme_stylesheet_path %>
14   - <%= stylesheet_link_tag *jquery_ui_theme_stylesheet_path %>
15   - <%
16   - plugins_stylesheets = @plugins.select(&:stylesheet?).map { |plugin| plugin.class.public_path('style.css') }
17   - %>
18   - <%= stylesheet_link_tag(*plugins_stylesheets, :cache => 'cache/plugins-' + Digest::MD5.hexdigest(plugins_stylesheets.to_s)) unless plugins_stylesheets.empty? %>
19   - <%= stylesheet_link_tag *theme_stylesheet_path %>
  11 + <%= noosfero_stylesheets %>
20 12  
21 13 <%# Add custom tags/styles/etc via content_for %>
22 14 <%= yield :head %>
23   - <%= javascript_tag('render_all_jquery_ui_widgets()') %>
24   - <%
25   - plugins_javascripts = @plugins.map { |plugin| plugin.js_files.map { |js| plugin.class.public_path(js) } }.flatten
26   - %>
27   - <%= javascript_include_tag(*plugins_javascripts, :cache => 'cache/plugins-' + Digest::MD5.hexdigest(plugins_javascripts.to_s)) unless plugins_javascripts.empty? %>
28 15 <%=
29 16 @plugins.dispatch(:head_ending).collect do |content|
30 17 content.respond_to?(:call) ? content.call : content
31 18 end.join("\n")
32 19 %>
33 20 </head>
34   - <body class="<%=
35   - # Identify the current controller and action for the CSS:
36   - " controller-"+ controller.controller_name() +
37   - " action-"+ controller.controller_name() +"-"+ controller.action_name() +
38   - " template-"+ ( profile.nil? ? "default" : profile.layout_template ) +
39   - (!profile.nil? && profile.is_on_homepage?(request.path,@page) ? " profile-homepage" : "")
40   - %>" >
41   -
  21 + <body class="<%= body_classes %>">
42 22 <a href="#content" id="link-go-content"><span><%= _("Go to the content") %></span></a>
  23 +
43 24 <%=
44 25 @plugins.dispatch(:body_beginning).collect do |content|
45 26 content.respond_to?(:call) ? content.call : content
... ... @@ -51,31 +32,7 @@
51 32 <%= theme_header %>
52 33 </div>
53 34 <div id="wrap-2">
54   - <div id="user">
55   - <span class='logged-in' style='display: none;'>
56   - <%= usermenu_logged_in %>
57   - </span>
58   - <span class='not-logged-in' style='display: none'>
59   -
60   - <%= _("<span class='login'>%s</span>") % thickbox_inline_popup_link('<i class="icon-menu-login"></i><strong>' + _('Login') + '</strong>', login_url, 'inlineLoginBox', :id => 'link_login') %>
61   - <%= @plugins.dispatch(:alternative_authentication_link).collect { |content| instance_eval(&content) }.join("") %>
62   -
63   - <div id='inlineLoginBox' style='display: none;'>
64   - <%= render :file => 'account/login', :locals => { :is_thickbox => true } %>
65   - </div>
66   -
67   - <% unless @plugins.dispatch(:allow_user_registration).include?(false) %>
68   - <%= _("<span class='or'>or</span> <span class='signup'>%s</span>") % link_to('<strong>' + _('Sign up') + '</strong>', :controller => 'account', :action => 'signup')%>
69   - <% end %>
70   -
71   - </span>
72   - <form action="/search" class="search_form" method="get" class="clean">
73   - <input name="query" size="15" title="<%=_('Search...')%>" onfocus="this.form.className='focused';" onblur="this.form.className=''" />
74   - <div><%=_('Press <strong>Enter</strong> to send the search query.')%></div>
75   - <%= javascript_tag 'jQuery("#user form input").hint();' %>
76   - </form>
77   - </div><!-- end id="user" -->
78   -
  35 + <%= render :partial => 'layouts/user' %>
79 36 <h1 id="site-title">
80 37 <%= theme_site_title %>
81 38 </h1>
... ...
app/views/map_balloon/product.html.erb
1 1 <div id="balloon">
2   - <%= render :partial => 'search/product', :locals => {:product => @product} %>
  2 + <%= render :partial => 'search/full_product', :locals => {:product => @product} %>
3 3 </div>
... ...
app/views/profile/_create_article.html.erb
... ... @@ -9,7 +9,7 @@
9 9 <div class='profile-activity-lead'>
10 10 <div class='article-name'><%= link_to(activity.params['name'], activity.params['url']) %></div>
11 11 <span title='<%= activity.target.class.short_description %>' class='profile-activity-icon icon-new icon-new<%= activity.target.class.icon_name %>'></span>
12   - <%= image_tag(activity.params['first_image']) unless activity.params['first_image'].blank? %><%= strip_tags(truncate(activity.params['lead'], :length => 1000, :ommision => '...')).gsub(/(\xA0|\xC2|\s)+/, ' ').gsub(/^\s+/, '') %> <small><%= link_to(_('See more'), activity.params['url']) unless activity.get_lead.blank? %></small>
  12 + <%= image_tag(activity.params['first_image']) unless activity.params['first_image'].blank? %><%= strip_tags(truncate(activity.params['lead'], :length => 1000, :ommision => '...')).gsub(/(\xC2\xA0|\s)+/, ' ').gsub(/^\s+/, '') %> <small><%= link_to(_('See more'), activity.params['url']) unless activity.get_lead.blank? %></small>
13 13 </div>
14 14 <%= content_tag(:p, link_to(_('See complete forum'), activity.get_url), :class => 'see-forum') if activity.target.is_a?(Forum) %>
15 15 <p class='profile-activity-time'><%= time_ago_as_sentence(activity.created_at) %></p>
... ...
app/views/profile/_profile_wall.html.erb
1 1 <h3><%= _("%s's wall") % @profile.name %></h3>
2 2 <div id='leave_scrap'>
3 3 <%= flash[:error] %>
4   - <% form_remote_tag :url => {:controller => 'profile', :action => 'leave_scrap', :tab_action => 'wall' }, :update => 'profile_activities', :success => "$('leave_scrap_content').value=''" do %>
  4 + <% form_remote_tag :url => {:controller => 'profile', :action => 'leave_scrap', :tab_action => 'wall' }, :update => 'profile_activities', :success => "$('leave_scrap_content').value=''", :complete => "jQuery('#leave_scrap_form').removeClass('loading').find('*').attr('disabled', false)", :loading => "jQuery('#leave_scrap_form').addClass('loading').find('*').attr('disabled', true)", :html => {:id => 'leave_scrap_form' } do %>
5 5 <%= limited_text_area :scrap, :content, 420, 'leave_scrap_content', :cols => 50, :rows => 2 %>
6 6 <%= submit_button :new, _('Share') %>
7 7 <% end %>
... ...
app/views/profile_editor/_person_form.html.erb
... ... @@ -21,6 +21,8 @@
21 21 <%= optional_field(@person, 'city', f.text_field(:city, :rel => _('City'))) %>
22 22 <%= optional_field(@person, 'zip_code', labelled_form_field(_('ZIP code'), text_field(:profile_data, :zip_code, :rel => _('ZIP code')))) %>
23 23 <%= optional_field(@person, 'address', labelled_form_field(_('Address (street and number)'), text_field(:profile_data, :address, :rel => _('Address')))) %>
  24 +<%= optional_field(@person, 'address_reference', labelled_form_field(_('Address reference'), text_field(:profile_data, :address_reference, :rel => _('Address reference')))) %>
  25 +<%= optional_field(@person, 'district', labelled_form_field(_('District'), text_field(:profile_data, :district, :rel => _('District')))) %>
24 26  
25 27 <% optional_field(@person, 'schooling') do %>
26 28 <div class="formfieldline">
... ...
app/views/profile_members/_manage_roles.html.erb
... ... @@ -13,11 +13,11 @@
13 13  
14 14 <% @roles.each do |role| %>
15 15 <% search_url = url_for(:action => 'search_user', :profile => profile.identifier, :role => role.id) %>
16   - <% @pre_population ||= profile.members_by_role_to_json(role) %>
  16 + <% pre_population = params[:action] == 'last_admin' ? [].to_json : profile.members_by_role_to_json(role) %>
17 17 <script type="text/javascript">
18 18 jQuery(<%= ('#search_' + role.key).to_json %>)
19 19 .tokenInput("<%= search_url %>", {
20   - prePopulate: <%= @pre_population %>,
  20 + prePopulate: <%= pre_population %>,
21 21 hintText: <%= _('Type in a search term for users').to_json %>,
22 22 noResultsText: <%= _('No results').to_json %>,
23 23 searchingText: <%= _('Searching...').to_json %>,
... ...
app/views/search/_compact_profile.html.erb 0 → 100644
... ... @@ -0,0 +1,5 @@
  1 +<% filter_label = profile.send(@filter + '_label') %>
  2 +<% filter_label += show_date(profile.created_at) if @filter == 'more_recent' %>
  3 +<li class="search-profile-item">
  4 + <%= profile_image_link profile, :portrait, 'div', filter_label %>
  5 +</li>
... ...
app/views/search/_display_results.html.erb
1 1 <div id="search-results" class="<%= !multiple_search? ? 'only-one-result-box' : 'multiple-results-boxes' %>">
2 2 <% @order.each do |name| %>
3   - <% results = @results[name] %>
4   - <% empty = results.nil? || results.empty? %>
  3 + <% search = @searches[name] %>
5 4  
6   - <div class="search-results-<%= name %> search-results-box <%= "search-results-empty" if empty %>">
7   - <% if not empty %>
8   - <% partial = partial_for_class(results.first.class.class_name.constantize) %>
  5 + <div class="search-results-<%= name %> search-results-box <%= "search-results-empty" if search[:results].blank? %>">
  6 + <% if !search[:results].blank? %>
9 7  
10   - <% if multiple_search? %>
  8 + <% if multiple_search?(@searches) %>
11 9 <h3><%= @names[name] %></h3>
12   - <% if results.total_entries > SearchController::MULTIPLE_SEARCH_LIMIT %>
13   - <%= link_to(_('see all (%d)') % results.total_entries, params.merge(:action => name), :class => 'see-more' ) %>
  10 + <% if search[:results].total_entries > SearchController::MULTIPLE_SEARCH_LIMIT %>
  11 + <%= link_to(_('see all (%d)') % search[:results].total_entries, params.merge(:action => name), :class => 'see-more' ) %>
14 12 <% end %>
15 13 <% end %>
16 14  
17   - <div class="search-results-innerbox search-results-type-<%= partial %> <%= 'common-profile-list-block' if partial == 'profile' %>">
  15 + <% display = display_filter(name, params[:display]) %>
  16 +
  17 + <div class="search-results-innerbox search-results-type-<%= name.to_s.singularize %> <%= 'common-profile-list-block' if [:enterprises, :people, :communities].include?(name) %>">
18 18 <ul>
19   - <% results.each do |hit| %>
20   - <%= render :partial => partial_for_class(hit.class), :object => hit %>
21   - <% end %>
  19 + <% search[:results].each do |hit| %>
  20 + <% partial = partial_for_class(hit.class, display) %>
  21 + <% variable_name = partial.gsub("#{display}_", '').to_sym %>
  22 + <%= render :partial => partial, :locals => {variable_name => hit} %>
  23 + <% end %>
22 24 </ul>
23 25 </div>
24 26 <% else %>
... ...
app/views/search/_full_article.html.erb 0 → 100644
... ... @@ -0,0 +1,12 @@
  1 +<li class="search-article-item article-item">
  2 + <%= link_to(article.title, article.url, :class => "search-result-title") %>
  3 + <div class="search-content-first-column">
  4 + <%= render :partial => 'image', :object => article %>
  5 + </div>
  6 + <table class="noborder search-content-second-column">
  7 + <%= render :partial => 'article_common', :object => article %>
  8 + </table>
  9 + <%= render :partial => 'article_last_change', :object => article %>
  10 +
  11 + <div style="clear:both"></div>
  12 +</li>
... ...
app/views/search/_full_blog.html.erb 0 → 100644
... ... @@ -0,0 +1,24 @@
  1 +<li class="search-blog article-item">
  2 + <%= link_to blog.title, blog.view_url, :class => 'search-result-title' %>
  3 + <div class="search-content-first-column">
  4 + <%= render :partial => 'image', :object => blog %>
  5 + </div>
  6 + <table class="noborder search-content-second-column">
  7 + <tr class="search-blog-items">
  8 + <td class="search-field-label"><%= _("Last posts") %></td>
  9 +
  10 + <% r = blog.children.find(:all, :order => :updated_at, :conditions => ['type != ?', 'RssFeed']).last(3) %>
  11 + <td class="<%= "search-field-none" if r.empty? %>">
  12 + <% r.each do |a| %>
  13 + <%= link_to a.title, a.view_url, :class => 'search-blog-sample-item '+icon_for_article(a) %>
  14 + <% end %>
  15 + <%= _('None') if r.empty? %>
  16 + </td>
  17 + </tr>
  18 +
  19 + <%= render :partial => 'article_common', :object => blog %>
  20 + </table>
  21 + <%= render :partial => 'article_last_change', :object => blog %>
  22 +
  23 + <div style="clear: both;"/></div>
  24 +</li>
... ...
app/views/search/_full_enterprise.html.erb 0 → 100644
... ... @@ -0,0 +1,38 @@
  1 +<li class="search-profile-item">
  2 + <div class="search-enterprise-item">
  3 + <div class="search-enterprise-item-column-left">
  4 + <%= profile_image_link enterprise, :portrait, 'div',
  5 + @filter == 'more_recent' ? enterprise.send(@filter + '_label') + show_date(enterprise.created_at) : enterprise.send(@filter + '_label') %>
  6 + </div>
  7 + <div class="search-enterprise-item-column-right">
  8 + <%= link_to_homepage(enterprise.name, enterprise.identifier, :class => "search-result-title") %>
  9 + <div class="search-enterprise-description">
  10 + <% if enterprise.description %>
  11 + <% body_stripped = strip_tags(enterprise.description) %>
  12 + <% elsif enterprise.home_page and enterprise.home_page.body %>
  13 + <% body_stripped = strip_tags(enterprise.home_page.body) %>
  14 + <% end %>
  15 + <%= excerpt(body_stripped, body_stripped.first(3), 200) if body_stripped %>
  16 + </div>
  17 + <div class="search-enterprise-region">
  18 + <span class="search-enterprise-region-label"><%= _("City") %></span>
  19 + <% if enterprise.region %>
  20 + <span class="search-enterprise-region-name"><%= city_with_state(enterprise.region) %></span>
  21 + <% end %>
  22 + </div>
  23 +
  24 + <div class="search-enterprise-categorization">
  25 + <% enterprise.top_level_categorization.each do |parent, children| %>
  26 + <div class="search-enterprise-category-<%=parent.id%> search-enterprise-category">
  27 + <span class="search-enterprise-categorization-parent"><%= parent.name %></span>
  28 + <span class="search-enterprise-categorization-children">
  29 + <%= children.collect(&:name).join(', ') %>
  30 + </span>
  31 + </div>
  32 + <% end %>
  33 + </div>
  34 + </div>
  35 +
  36 + <hr class="clearfix" />
  37 + </div>
  38 +</li>
... ...
app/views/search/_full_event.html.erb 0 → 100644
... ... @@ -0,0 +1,25 @@
  1 +<li class="search-event-item article-item">
  2 +<%= link_to(event.title, event.url, :class => "search-result-title") %>
  3 +<div class="search-content-first-column">
  4 + <%= render :partial => 'image', :object => event %>
  5 +</div>
  6 +<table class="noborder search-content-second-column">
  7 + <% if event.start_date %>
  8 + <tr class="search-article-event-date">
  9 + <td class="search-field-label"><%= _('Start date') %></td>
  10 + <td class="article-item-date"><%= event.start_date %></td>
  11 + </tr>
  12 + <% end %>
  13 + <% if event.end_date %>
  14 + <tr class="search-article-event-date">
  15 + <td class="search-field-label"><%= _('End date') %></td>
  16 + <td class="article-item-date"><%= event.end_date %></td>
  17 + </tr>
  18 + <% end %>
  19 +
  20 + <%= render :partial => 'article_common', :object => event %>
  21 +</table>
  22 +<%= render :partial => 'article_last_change', :object => event %>
  23 +
  24 +<div style="clear: both"></div>
  25 +</li>
... ...