Commit ed6f20bb506691b63fefab297614180ca8815024

Authored by Leandro Santos
2 parents 9d45a161 763189ac
Exists in staging

fix merge with master conflit

Showing 209 changed files with 2548 additions and 1973 deletions   Show diff stats

Too many changes.

To preserve performance only 100 of 209 files displayed.

.gitlab-ci.yml
... ... @@ -6,12 +6,13 @@ before_script:
6 6 - ./script/silent-quick-start
7 7  
8 8 stages:
9   - - smoke-tests
  9 + #FIXME Selenium tests are randomly failing and this avoid other tests to run.
  10 + #- smoke-tests
10 11 - all-tests
11 12  
12   -smoke:
13   - script: bundle exec rake ci:smoke
14   - stage: smoke-tests
  13 +#smoke:
  14 +# script: bundle exec rake ci:smoke
  15 +# stage: smoke-tests
15 16  
16 17 units:
17 18 script: bundle exec rake test:units
... ...
.travis.yml
... ... @@ -55,7 +55,10 @@ env:
55 55 - TASK=test:integration
56 56 - TASK=cucumber LANG=en
57 57 - TASK=selenium
58   - - TASK=test:noosfero_plugins BUNDLE_OPTS=install
  58 + - SLICE=1/4 TASK=test:noosfero_plugins BUNDLE_OPTS=install
  59 + - SLICE=2/4 TASK=test:noosfero_plugins BUNDLE_OPTS=install
  60 + - SLICE=3/4 TASK=test:noosfero_plugins BUNDLE_OPTS=install
  61 + - SLICE=4/4 TASK=test:noosfero_plugins BUNDLE_OPTS=install
59 62  
60 63 script:
61 64 - ./script/ci
... ...
CHANGELOG 0 → 100644
... ... @@ -0,0 +1,12 @@
  1 +If you made any significant change to the code that you consider worth being
  2 +reminded on the Release Notes, also include a correspondent entry here. If you
  3 +are not sure in which release your code will be released, include it on the
  4 +latest release and leave it to the commiter or RM responsible for it.
  5 +
  6 +v 1.5.0 (unreleased)
  7 + - Allow groups to disable admin email notificationo
  8 + - Add option to HighlightsBlock to open link in a new tab
  9 + - Move blocks html generation from models to helpers
  10 +
  11 +v 1.4.0
  12 + - Migration from Rails 3 to Rails 4!
... ...
Gemfile
... ... @@ -34,7 +34,7 @@ gem 'slim'
34 34  
35 35 # API dependencies
36 36 gem 'grape', '~> 0.12'
37   -gem 'grape-entity', '= 0.4.8'
  37 +gem 'grape-entity', '0.4.8'
38 38 gem 'grape_logging'
39 39 gem 'grape-swagger'
40 40 gem 'swagger-ui_rails'
... ... @@ -43,7 +43,7 @@ gem 'rack-cors'
43 43 gem 'rack-contrib'
44 44 gem 'liquid', '~> 3.0.3'
45 45  
46   -gem 'api-pagination', '~> 4.1.1'
  46 +gem 'api-pagination', '>= 4.1.1'
47 47  
48 48 # asset pipeline
49 49 gem 'uglifier', '>= 1.0.3'
... ...
Gemfile.lock
... ... @@ -21,14 +21,14 @@ PATH
21 21 access_control (0.0.0)
22 22  
23 23 PATH
24   - remote: vendor/plugins/action_tracker
  24 + remote: vendor/plugins/action_tracker_has_comments
25 25 specs:
26   - action_tracker (0.0.1)
  26 + action_tracker_has_comments (0.0.0)
27 27  
28 28 PATH
29   - remote: vendor/plugins/action_tracker_has_comments
  29 + remote: vendor/plugins/action_tracker
30 30 specs:
31   - action_tracker_has_comments (0.0.0)
  31 + action_tracker (0.0.1)
32 32  
33 33 PATH
34 34 remote: vendor/plugins/acts_as_list
... ... @@ -425,7 +425,7 @@ DEPENDENCIES
425 425 acts_as_tree (= 0.0.0)!
426 426 acts_as_versioned (> 0.0.0)!
427 427 airbrake (~> 4)
428   - api-pagination (~> 4.1.1)
  428 + api-pagination (>= 4.1.1)
429 429 capybara (~> 2.2)
430 430 contacts (> 0.0.0)!
431 431 cucumber
... ... @@ -491,3 +491,6 @@ DEPENDENCIES
491 491 whenever
492 492 will_paginate (~> 3.0.7)
493 493 xss_terminate (= 0.0.0)!
  494 +
  495 +BUNDLED WITH
  496 + 1.11.2
... ...
app/controllers/my_profile/tasks_controller.rb
... ... @@ -2,6 +2,8 @@ class TasksController < MyProfileController
2 2  
3 3 protect [:perform_task, :view_tasks], :profile, :only => [:index, :save_tags, :search_tags]
4 4 protect :perform_task, :profile, :only => [:processed, :change_responsible, :close, :new, :list_requested, :ticket_details, :search_tags]
  5 + include TasksHelper
  6 +
5 7  
6 8 def index
7 9 @rejection_email_templates = profile.email_templates.find_all_by_template_type(:task_rejection)
... ... @@ -84,12 +86,12 @@ class TasksController < MyProfileController
84 86 end
85 87 end
86 88  
87   - url = { :action => 'index' }
  89 + url = tasks_url(:action => 'index')
88 90 if failed.blank?
89 91 session[:notice] = _("All decisions were applied successfully.")
90 92 else
91 93 session[:notice] = _("Some decisions couldn't be applied.")
92   - url[:failed] = failed
  94 + url = tasks_url(:action => 'index', :failed => failed)
93 95 end
94 96 redirect_to url
95 97 end
... ...
app/helpers/application_helper.rb
... ... @@ -50,6 +50,12 @@ module ApplicationHelper
50 50  
51 51 include TaskHelper
52 52  
  53 + include ButtonsHelper
  54 +
  55 + include ProfileImageHelper
  56 +
  57 + include ThemeLoaderHelper
  58 +
53 59 def locale
54 60 (@page && !@page.language.blank?) ? @page.language : FastGettext.locale
55 61 end
... ... @@ -211,52 +217,6 @@ module ApplicationHelper
211 217 result
212 218 end
213 219  
214   - def button(type, label, url, html_options = {})
215   - html_options ||= {}
216   - the_class = 'with-text'
217   - if html_options.has_key?(:class)
218   - the_class << ' ' << html_options[:class]
219   - end
220   - button_without_text type, label, url, html_options.merge(:class => the_class)
221   - end
222   -
223   - def button_without_text(type, label, url, html_options = {})
224   - the_class = "button icon-#{type}"
225   - if html_options.has_key?(:class)
226   - the_class << ' ' << html_options[:class]
227   - end
228   - the_title = html_options[:title] || label
229   - if html_options[:disabled]
230   - content_tag('a', '&nbsp;'+content_tag('span', label), html_options.merge(:class => the_class, :title => the_title))
231   - else
232   - link_to('&nbsp;'+content_tag('span', label), url, html_options.merge(:class => the_class, :title => the_title))
233   - end
234   - end
235   -
236   - def button_to_function(type, label, js_code, html_options = {}, &block)
237   - html_options[:class] = "button with-text" unless html_options[:class]
238   - html_options[:class] << " icon-#{type}"
239   - link_to_function(label, js_code, html_options, &block)
240   - end
241   -
242   - def button_to_function_without_text(type, label, js_code, html_options = {}, &block)
243   - html_options[:class] = "" unless html_options[:class]
244   - html_options[:class] << " button icon-#{type}"
245   - link_to_function(content_tag('span', label), js_code, html_options, &block)
246   - end
247   -
248   - def button_to_remote(type, label, options, html_options = {})
249   - html_options[:class] = "button with-text" unless html_options[:class]
250   - html_options[:class] << " icon-#{type}"
251   - link_to_remote(label, options, html_options)
252   - end
253   -
254   - def button_to_remote_without_text(type, label, options, html_options = {})
255   - html_options[:class] = "" unless html_options[:class]
256   - html_options[:class] << " button icon-#{type}"
257   - link_to_remote(content_tag('span', label), options, html_options.merge(:title => label))
258   - end
259   -
260 220 def icon(icon_name, html_options = {})
261 221 the_class = "button #{icon_name}"
262 222 if html_options.has_key?(:class)
... ... @@ -327,48 +287,6 @@ module ApplicationHelper
327 287 end
328 288 end
329 289  
330   - def theme_path
331   - if session[:theme]
332   - '/user_themes/' + current_theme
333   - else
334   - '/designs/themes/' + current_theme
335   - end
336   - end
337   -
338   - def current_theme
339   - @current_theme ||=
340   - begin
341   - if session[:theme]
342   - session[:theme]
343   - else
344   - # utility for developers: set the theme to 'random' in development mode and
345   - # you will get a different theme every request. This is interesting for
346   - # testing
347   - if Rails.env.development? && environment.theme == 'random'
348   - @random_theme ||= Dir.glob('public/designs/themes/*').map { |f| File.basename(f) }.rand
349   - @random_theme
350   - elsif Rails.env.development? && respond_to?(:params) && params[:theme] && File.exists?(Rails.root.join('public/designs/themes', params[:theme]))
351   - params[:theme]
352   - else
353   - if profile && !profile.theme.nil?
354   - profile.theme
355   - elsif environment
356   - environment.theme
357   - else
358   - if logger
359   - logger.warn("No environment found. This is weird.")
360   - logger.warn("Request environment: %s" % request.env.inspect)
361   - logger.warn("Request parameters: %s" % params.inspect)
362   - end
363   -
364   - # could not determine the theme, so return the default one
365   - 'default'
366   - end
367   - end
368   - end
369   - end
370   - end
371   -
372 290 def theme_view_file(template, theme=nil)
373 291 # Since we cannot control what people are doing in external themes, we
374 292 # will keep looking for the deprecated .rhtml extension here.
... ... @@ -441,141 +359,6 @@ module ApplicationHelper
441 359 Theme.find(current_theme).owner.identifier
442 360 end
443 361  
444   - # generates a image tag for the profile.
445   - #
446   - # If the profile has no image set yet, then a default image is used.
447   - def profile_image(profile, size=:portrait, opt={})
448   - return '' if profile.nil?
449   - opt[:alt] ||= profile.name()
450   - opt[:title] ||= ''
451   - opt[:class] ||= ''
452   - opt[:class] += ( profile.class == Person ? ' photo' : ' logo' )
453   - image_tag(profile_icon(profile, size), opt )
454   - end
455   -
456   - def profile_icon( profile, size=:portrait, return_mimetype=false )
457   - filename, mimetype = '', 'image/png'
458   - if profile.image
459   - filename = profile.image.public_filename( size )
460   - mimetype = profile.image.content_type
461   - else
462   - icon =
463   - if profile.organization?
464   - if profile.kind_of?(Community)
465   - '/images/icons-app/community-'+ size.to_s() +'.png'
466   - else
467   - '/images/icons-app/enterprise-'+ size.to_s() +'.png'
468   - end
469   - else
470   - pixels = Image.attachment_options[:thumbnails][size].split('x').first
471   - gravatar_profile_image_url(
472   - profile.email,
473   - :size => pixels,
474   - :d => gravatar_default
475   - )
476   - end
477   - filename = default_or_themed_icon(icon)
478   - end
479   - return_mimetype ? [filename, mimetype] : filename
480   - end
481   -
482   - def default_or_themed_icon(icon)
483   - if File.exists?(Rails.root.join('public', theme_path, icon))
484   - theme_path + icon
485   - else
486   - icon
487   - end
488   - end
489   -
490   - def profile_sex_icon( profile )
491   - return '' unless profile.is_a?(Person)
492   - return '' unless !environment.enabled?('disable_gender_icon')
493   - sex = ( profile.sex ? profile.sex.to_s() : 'undef' )
494   - title = ( sex == 'undef' ? _('non registered gender') : ( sex == 'male' ? _('Male') : _('Female') ) )
495   - sex = content_tag 'span',
496   - content_tag( 'span', sex ),
497   - :class => 'sex-'+sex,
498   - :title => title
499   - sex
500   - end
501   -
502   - def links_for_balloon(profile)
503   - if environment.enabled?(:show_balloon_with_profile_links_when_clicked)
504   - if profile.kind_of?(Person)
505   - [
506   - {_('Wall') => {:href => url_for(profile.public_profile_url)}},
507   - {_('Friends') => {:href => url_for(:controller => :profile, :action => :friends, :profile => profile.identifier)}},
508   - {_('Communities') => {:href => url_for(:controller => :profile, :action => :communities, :profile => profile.identifier)}},
509   - {_('Send an e-mail') => {:href => url_for(:profile => profile.identifier, :controller => 'contact', :action => 'new'), :class => 'send-an-email', :style => 'display: none'}},
510   - {_('Add') => {:href => url_for(profile.add_url), :class => 'add-friend', :style => 'display: none'}}
511   - ]
512   - elsif profile.kind_of?(Community)
513   - [
514   - {_('Wall') => {:href => url_for(profile.public_profile_url)}},
515   - {_('Members') => {:href => url_for(:controller => :profile, :action => :members, :profile => profile.identifier)}},
516   - {_('Agenda') => {:href => url_for(:controller => :profile, :action => :events, :profile => profile.identifier)}},
517   - {_('Join') => {:href => url_for(profile.join_url), :class => 'join-community', :style => 'display: none'}},
518   - {_('Leave community') => {:href => url_for(profile.leave_url), :class => 'leave-community', :style => 'display: none'}},
519   - {_('Send an e-mail') => {:href => url_for(:profile => profile.identifier, :controller => 'contact', :action => 'new'), :class => 'send-an-email', :style => 'display: none'}}
520   - ]
521   - elsif profile.kind_of?(Enterprise)
522   - [
523   - {_('Products') => {:href => catalog_path(profile.identifier)}},
524   - {_('Members') => {:href => url_for(:controller => :profile, :action => :members, :profile => profile.identifier)}},
525   - {_('Agenda') => {:href => url_for(:controller => :profile, :action => :events, :profile => profile.identifier)}},
526   - {_('Send an e-mail') => {:href => url_for(:profile => profile.identifier, :controller => 'contact', :action => 'new'), :class => 'send-an-email', :style => 'display: none'}},
527   - ]
528   - else
529   - []
530   - end
531   - end
532   - end
533   -
534   - # displays a link to the profile homepage with its image (as generated by
535   - # #profile_image) and its name below it.
536   - def profile_image_link( profile, size=:portrait, tag='li', extra_info = nil )
537   - if content = @plugins.dispatch_first(:profile_image_link, profile, size, tag, extra_info)
538   - return instance_exec(&content)
539   - end
540   - name = profile.short_name
541   - if profile.person?
542   - url = url_for(profile.check_friendship_url)
543   - trigger_class = 'person-trigger'
544   - else
545   - city = ''
546   - url = url_for(profile.check_membership_url)
547   - if profile.community?
548   - trigger_class = 'community-trigger'
549   - elsif profile.enterprise?
550   - trigger_class = 'enterprise-trigger'
551   - end
552   - end
553   -
554   - extra_info_tag = ''
555   - img_class = 'profile-image'
556   -
557   - if extra_info.is_a? Hash
558   - extra_info_tag = content_tag( 'span', extra_info[:value], :class => 'extra_info '+extra_info[:class])
559   - img_class +=' '+extra_info[:class]
560   - else
561   - extra_info_tag = content_tag( 'span', extra_info, :class => 'extra_info' )
562   - end
563   -
564   - links = links_for_balloon(profile)
565   - content_tag('div', content_tag(tag,
566   - (environment.enabled?(:show_balloon_with_profile_links_when_clicked) ?
567   - popover_menu(_('Profile links'),profile.short_name,links,{:class => trigger_class, :url => url}) : "") +
568   - link_to(
569   - content_tag( 'span', profile_image( profile, size ), :class => img_class ) +
570   - content_tag( 'span', h(name), :class => ( profile.class == Person ? 'fn' : 'org' ) ) +
571   - extra_info_tag + profile_sex_icon( profile ),
572   - profile.url,
573   - :class => 'profile_link url',
574   - :help => _('Click on this icon to go to the <b>%s</b>\'s home page') % profile.name,
575   - :title => profile.name ),
576   - :class => 'vcard'), :class => 'common-profile-list-block')
577   - end
578   -
579 362 def popover_menu(title,menu_title,links,html_options={})
580 363 html_options[:class] = "" unless html_options[:class]
581 364 html_options[:class] << " menu-submenu-trigger"
... ... @@ -584,10 +367,6 @@ module ApplicationHelper
584 367 link_to(content_tag(:span, title), '#', html_options)
585 368 end
586 369  
587   - def gravatar_default
588   - (respond_to?(:theme_option) && theme_option.present? && theme_option['gravatar']) || NOOSFERO_CONF['gravatar'] || 'mm'
589   - end
590   -
591 370 attr_reader :environment
592 371  
593 372 def select_categories(object_name, title=nil, title_size=4)
... ... @@ -936,13 +715,6 @@ module ApplicationHelper
936 715 content_for(:head) { stylesheet_link_tag(*args) }
937 716 end
938 717  
939   - def article_to_html(article, options = {})
940   - options.merge!(:page => params[:npage])
941   - content = article.to_html(options)
942   - content = content.kind_of?(Proc) ? self.instance_exec(&content).html_safe : content.html_safe
943   - filter_html(content, article)
944   - end
945   -
946 718 # Please, use link_to by default!
947 719 # This method was created to work around to inexplicable
948 720 # chain of problems when display_short_format was called
... ... @@ -1379,16 +1151,6 @@ module ApplicationHelper
1379 1151 @no_design_blocks = true
1380 1152 end
1381 1153  
1382   - def filter_html(html, source)
1383   - if @plugins && source && source.has_macro?
1384   - html = convert_macro(html, source) unless @plugins.enabled_macros.blank?
1385   - #TODO This parse should be done through the macro infra, but since there
1386   - # are old things that do not support it we are keeping this hot spot.
1387   - html = @plugins.pipeline(:parse_content, html, source).first
1388   - end
1389   - html && html.html_safe
1390   - end
1391   -
1392 1154 def convert_macro(html, source)
1393 1155 doc = Nokogiri::HTML.fragment html
1394 1156 #TODO This way is more efficient but do not support macro inside of
... ...
app/helpers/article_helper.rb
... ... @@ -195,4 +195,21 @@ module ArticleHelper
195 195 end
196 196 end
197 197  
  198 + def filter_html(html, source)
  199 + if @plugins && source && source.has_macro?
  200 + html = convert_macro(html, source) unless @plugins.enabled_macros.blank?
  201 + #TODO This parse should be done through the macro infra, but since there
  202 + # are old things that do not support it we are keeping this hot spot.
  203 + html = @plugins.pipeline(:parse_content, html, source).first
  204 + end
  205 + html && html.html_safe
  206 + end
  207 +
  208 + def article_to_html(article, options = {})
  209 + options.merge!(:page => params[:npage])
  210 + content = article.to_html(options)
  211 + content = content.kind_of?(Proc) ? self.instance_exec(&content).html_safe : content.html_safe
  212 + filter_html(content, article)
  213 + end
  214 +
198 215 end
... ...
app/helpers/boxes_helper.rb
... ... @@ -87,10 +87,38 @@ module BoxesHelper
87 87 box_decorator == DontMoveBlocks
88 88 end
89 89  
90   - def display_block_content(block, person, main_content = nil)
91   - content = block.main? ? wrap_main_content(main_content) : block.content({:person => person})
  90 + def render_block block, prefix = nil, klass = block.class
  91 + template_name = klass.name.underscore.sub '_block', ''
  92 + begin
  93 + render template: "blocks/#{prefix}#{template_name}", locals: { block: block }
  94 + rescue ActionView::MissingTemplate
  95 + return if klass.superclass === Block
  96 + render_block block, prefix, klass.superclass
  97 + end
  98 + end
  99 +
  100 + def render_block_content block
  101 + # FIXME: this conditional should be removed after all
  102 + # block footer from plugins methods get refactored into helpers and views.
  103 + # They are a failsafe until all of them are done.
  104 + return block.content if block.method(:content).owner != Block
  105 + render_block block
  106 + end
  107 +
  108 + def render_block_footer block
  109 + return block.footer if block.method(:footer).owner != Block
  110 + render_block block, 'footers/'
  111 + end
  112 +
  113 + def display_block_content(block, main_content = nil)
  114 + content = nil
  115 + if block.main?
  116 + content = wrap_main_content(main_content)
  117 + else
  118 + content = render_block_content block
  119 + end
92 120 result = extract_block_content(content)
93   - footer_content = extract_block_content(block.footer)
  121 + footer_content = extract_block_content(render_block_footer block)
94 122 unless footer_content.blank?
95 123 footer_content = content_tag('div', footer_content, :class => 'block-footer-content' )
96 124 end
... ...
app/helpers/buttons_helper.rb 0 → 100644
... ... @@ -0,0 +1,47 @@
  1 +module ButtonsHelper
  2 + def button(type, label, url, html_options = {})
  3 + html_options ||= {}
  4 + the_class = 'with-text'
  5 + if html_options.has_key?(:class)
  6 + the_class << ' ' << html_options[:class]
  7 + end
  8 + button_without_text type, label, url, html_options.merge(:class => the_class)
  9 + end
  10 +
  11 + def button_without_text(type, label, url, html_options = {})
  12 + the_class = "button icon-#{type}"
  13 + if html_options.has_key?(:class)
  14 + the_class << ' ' << html_options[:class]
  15 + end
  16 + the_title = html_options[:title] || label
  17 + if html_options[:disabled]
  18 + content_tag('a', '&nbsp;'+content_tag('span', label), html_options.merge(:class => the_class, :title => the_title))
  19 + else
  20 + link_to('&nbsp;'+content_tag('span', label), url, html_options.merge(:class => the_class, :title => the_title))
  21 + end
  22 + end
  23 +
  24 + def button_to_function(type, label, js_code, html_options = {}, &block)
  25 + html_options[:class] = "button with-text" unless html_options[:class]
  26 + html_options[:class] << " icon-#{type}"
  27 + link_to_function(label, js_code, html_options, &block)
  28 + end
  29 +
  30 + def button_to_function_without_text(type, label, js_code, html_options = {}, &block)
  31 + html_options[:class] = "" unless html_options[:class]
  32 + html_options[:class] << " button icon-#{type}"
  33 + link_to_function(content_tag('span', label), js_code, html_options, &block)
  34 + end
  35 +
  36 + def button_to_remote(type, label, options, html_options = {})
  37 + html_options[:class] = "button with-text" unless html_options[:class]
  38 + html_options[:class] << " icon-#{type}"
  39 + link_to_remote(label, options, html_options)
  40 + end
  41 +
  42 + def button_to_remote_without_text(type, label, options, html_options = {})
  43 + html_options[:class] = "" unless html_options[:class]
  44 + html_options[:class] << " button icon-#{type}"
  45 + link_to_remote(content_tag('span', label), options, html_options.merge(:title => label))
  46 + end
  47 +end
... ...
app/helpers/forms_helper.rb
... ... @@ -137,7 +137,7 @@ module FormsHelper
137 137 content_tag('table',rows.join("\n"))
138 138 end
139 139  
140   - def date_field(name, value, format = '%Y-%m-%d', datepicker_options = {}, html_options = {})
  140 + def date_field(name, value, datepicker_options = {}, html_options = {})
141 141 datepicker_options[:disabled] ||= false
142 142 datepicker_options[:alt_field] ||= ''
143 143 datepicker_options[:alt_format] ||= ''
... ... @@ -152,7 +152,7 @@ module FormsHelper
152 152 datepicker_options[:close_text] ||= _('Done')
153 153 datepicker_options[:constrain_input] ||= true
154 154 datepicker_options[:current_text] ||= _('Today')
155   - datepicker_options[:date_format] ||= 'yy/mm/dd'
  155 + datepicker_options[:date_format] ||= 'yy-mm-dd'
156 156 datepicker_options[:day_names] ||= [_('Sunday'), _('Monday'), _('Tuesday'), _('Wednesday'), _('Thursday'), _('Friday'), _('Saturday')]
157 157 datepicker_options[:day_names_min] ||= [_('Su'), _('Mo'), _('Tu'), _('We'), _('Th'), _('Fr'), _('Sa')]
158 158 datepicker_options[:day_names_short] ||= [_('Sun'), _('Mon'), _('Tue'), _('Wed'), _('Thu'), _('Fri'), _('Sat')]
... ... @@ -184,10 +184,11 @@ module FormsHelper
184 184 datepicker_options[:year_range] ||= 'c-10:c+10'
185 185 datepicker_options[:year_suffix] ||= ''
186 186  
  187 + date_format = datepicker_options[:time] ? "%Y-%m-%d %H:%M" : "%Y-%m-%d"
  188 + value = value.strftime(date_format) if value.present?
  189 +
187 190 element_id = html_options[:id] || 'datepicker-date'
188   - value = value.strftime(format) if value.present?
189 191 method = datepicker_options[:time] ? 'datetimepicker' : 'datepicker'
190   - current_date_or_nil = value.present? ? "new Date('#{value}')" : "null"
191 192 result = text_field_tag(name, value, html_options)
192 193 result +=
193 194 "
... ... @@ -238,17 +239,17 @@ module FormsHelper
238 239 weekHeader: #{datepicker_options[:week_header].to_json},
239 240 yearRange: #{datepicker_options[:year_range].to_json},
240 241 yearSuffix: #{datepicker_options[:year_suffix].to_json}
241   - }).datepicker('setDate', current_date_or_nil)
  242 + }).datepicker()
242 243 </script>
243 244 ".html_safe
244 245 result
245 246 end
246 247  
247   - def date_range_field(from_name, to_name, from_value, to_value, format = '%Y-%m-%d', datepicker_options = {}, html_options = {})
  248 + def date_range_field(from_name, to_name, from_value, to_value, datepicker_options = {}, html_options = {})
248 249 from_id = html_options[:from_id] || 'datepicker-from-date'
249 250 to_id = html_options[:to_id] || 'datepicker-to-date'
250   - return _('From') +' '+ date_field(from_name, from_value, format, datepicker_options, html_options.merge({:id => from_id})) +
251   - ' ' + _('until') +' '+ date_field(to_name, to_value, format, datepicker_options, html_options.merge({:id => to_id}))
  251 + return _('From') +' '+ date_field(from_name, from_value, datepicker_options, html_options.merge({:id => from_id})) +
  252 + ' ' + _('until') +' '+ date_field(to_name, to_value, datepicker_options, html_options.merge({:id => to_id}))
252 253 end
253 254  
254 255 def select_folder(label_text, field_id, collection, default_value=nil, html_options = {}, js_options = {})
... ...
app/helpers/profile_image_helper.rb 0 → 100644
... ... @@ -0,0 +1,140 @@
  1 +module ProfileImageHelper
  2 + def default_or_themed_icon(icon)
  3 + if File.exists?(Rails.root.join('public', theme_path, icon))
  4 + theme_path + icon
  5 + else
  6 + icon
  7 + end
  8 + end
  9 +
  10 + def gravatar_default
  11 + (respond_to?(:theme_option) && theme_option.present? && theme_option['gravatar']) || NOOSFERO_CONF['gravatar'] || 'mm'
  12 + end
  13 +
  14 + def profile_sex_icon( profile )
  15 + return '' unless profile.is_a?(Person)
  16 + return '' unless !environment.enabled?('disable_gender_icon')
  17 + sex = ( profile.sex ? profile.sex.to_s() : 'undef' )
  18 + title = ( sex == 'undef' ? _('non registered gender') : ( sex == 'male' ? _('Male') : _('Female') ) )
  19 + sex = content_tag 'span',
  20 + content_tag( 'span', sex ),
  21 + :class => 'sex-'+sex,
  22 + :title => title
  23 + sex
  24 + end
  25 +
  26 + def profile_icon( profile, size=:portrait, return_mimetype=false )
  27 + filename, mimetype = '', 'image/png'
  28 + if profile.image
  29 + filename = profile.image.public_filename( size )
  30 + mimetype = profile.image.content_type
  31 + else
  32 + icon =
  33 + if profile.organization?
  34 + if profile.kind_of?(Community)
  35 + '/images/icons-app/community-'+ size.to_s() +'.png'
  36 + else
  37 + '/images/icons-app/enterprise-'+ size.to_s() +'.png'
  38 + end
  39 + else
  40 + pixels = Image.attachment_options[:thumbnails][size].split('x').first
  41 + gravatar_profile_image_url(
  42 + profile.email,
  43 + :size => pixels,
  44 + :d => gravatar_default
  45 + )
  46 + end
  47 + filename = default_or_themed_icon(icon)
  48 + end
  49 + return_mimetype ? [filename, mimetype] : filename
  50 + end
  51 +
  52 + # generates a image tag for the profile.
  53 + #
  54 + # If the profile has no image set yet, then a default image is used.
  55 + def profile_image(profile, size=:portrait, opt={})
  56 + return '' if profile.nil?
  57 + opt[:alt] ||= profile.name()
  58 + opt[:title] ||= ''
  59 + opt[:class] ||= ''
  60 + opt[:class] += ( profile.class == Person ? ' photo' : ' logo' )
  61 + image_tag(profile_icon(profile, size), opt )
  62 + end
  63 +
  64 + def links_for_balloon(profile)
  65 + if environment.enabled?(:show_balloon_with_profile_links_when_clicked)
  66 + if profile.kind_of?(Person)
  67 + [
  68 + {_('Wall') => {:href => url_for(profile.public_profile_url)}},
  69 + {_('Friends') => {:href => url_for(:controller => :profile, :action => :friends, :profile => profile.identifier)}},
  70 + {_('Communities') => {:href => url_for(:controller => :profile, :action => :communities, :profile => profile.identifier)}},
  71 + {_('Send an e-mail') => {:href => url_for(:profile => profile.identifier, :controller => 'contact', :action => 'new'), :class => 'send-an-email', :style => 'display: none'}},
  72 + {_('Add') => {:href => url_for(profile.add_url), :class => 'add-friend', :style => 'display: none'}}
  73 + ]
  74 + elsif profile.kind_of?(Community)
  75 + [
  76 + {_('Wall') => {:href => url_for(profile.public_profile_url)}},
  77 + {_('Members') => {:href => url_for(:controller => :profile, :action => :members, :profile => profile.identifier)}},
  78 + {_('Agenda') => {:href => url_for(:controller => :profile, :action => :events, :profile => profile.identifier)}},
  79 + {_('Join') => {:href => url_for(profile.join_url), :class => 'join-community', :style => 'display: none'}},
  80 + {_('Leave community') => {:href => url_for(profile.leave_url), :class => 'leave-community', :style => 'display: none'}},
  81 + {_('Send an e-mail') => {:href => url_for(:profile => profile.identifier, :controller => 'contact', :action => 'new'), :class => 'send-an-email', :style => 'display: none'}}
  82 + ]
  83 + elsif profile.kind_of?(Enterprise)
  84 + [
  85 + {_('Products') => {:href => catalog_path(profile.identifier)}},
  86 + {_('Members') => {:href => url_for(:controller => :profile, :action => :members, :profile => profile.identifier)}},
  87 + {_('Agenda') => {:href => url_for(:controller => :profile, :action => :events, :profile => profile.identifier)}},
  88 + {_('Send an e-mail') => {:href => url_for(:profile => profile.identifier, :controller => 'contact', :action => 'new'), :class => 'send-an-email', :style => 'display: none'}},
  89 + ]
  90 + else
  91 + []
  92 + end
  93 + end
  94 + end
  95 +
  96 + # displays a link to the profile homepage with its image (as generated by
  97 + # #profile_image) and its name below it.
  98 + def profile_image_link( profile, size=:portrait, tag='li', extra_info = nil )
  99 + if content = @plugins.dispatch_first(:profile_image_link, profile, size, tag, extra_info)
  100 + return instance_exec(&content)
  101 + end
  102 + name = profile.short_name
  103 + if profile.person?
  104 + url = url_for(profile.check_friendship_url)
  105 + trigger_class = 'person-trigger'
  106 + else
  107 + city = ''
  108 + url = url_for(profile.check_membership_url)
  109 + if profile.community?
  110 + trigger_class = 'community-trigger'
  111 + elsif profile.enterprise?
  112 + trigger_class = 'enterprise-trigger'
  113 + end
  114 + end
  115 +
  116 + extra_info_tag = ''
  117 + img_class = 'profile-image'
  118 +
  119 + if extra_info.is_a? Hash
  120 + extra_info_tag = content_tag( 'span', extra_info[:value], :class => 'extra_info '+extra_info[:class])
  121 + img_class +=' '+extra_info[:class]
  122 + else
  123 + extra_info_tag = content_tag( 'span', extra_info, :class => 'extra_info' )
  124 + end
  125 +
  126 + links = links_for_balloon(profile)
  127 + content_tag('div', content_tag(tag,
  128 + (environment.enabled?(:show_balloon_with_profile_links_when_clicked) ?
  129 + popover_menu(_('Profile links'),profile.short_name,links,{:class => trigger_class, :url => url}) : "") +
  130 + link_to(
  131 + content_tag( 'span', profile_image( profile, size ), :class => img_class ) +
  132 + content_tag( 'span', h(name), :class => ( profile.class == Person ? 'fn' : 'org' ) ) +
  133 + extra_info_tag + profile_sex_icon( profile ),
  134 + profile.url,
  135 + :class => 'profile_link url',
  136 + :help => _('Click on this icon to go to the <b>%s</b>\'s home page') % profile.name,
  137 + :title => profile.name ),
  138 + :class => 'vcard'), :class => 'common-profile-list-block')
  139 + end
  140 +end
0 141 \ No newline at end of file
... ...
app/helpers/tasks_helper.rb 0 → 100644
... ... @@ -0,0 +1,12 @@
  1 +module TasksHelper
  2 +
  3 + def tasks_url options = {}
  4 + url_for(options.merge(filter_params))
  5 + end
  6 +
  7 + def filter_params
  8 + filter_fields = ['filter_type', 'filter_text', 'filter_responsible', 'filter_tags']
  9 + params.select {|filter| filter if filter_fields.include? filter }
  10 + end
  11 +
  12 +end
... ...
app/helpers/theme_loader_helper.rb 0 → 100644
... ... @@ -0,0 +1,43 @@
  1 +module ThemeLoaderHelper
  2 + def current_theme
  3 + @current_theme ||=
  4 + begin
  5 + if session[:theme]
  6 + session[:theme]
  7 + else
  8 + # utility for developers: set the theme to 'random' in development mode and
  9 + # you will get a different theme every request. This is interesting for
  10 + # testing
  11 + if Rails.env.development? && environment.theme == 'random'
  12 + @random_theme ||= Dir.glob('public/designs/themes/*').map { |f| File.basename(f) }.rand
  13 + @random_theme
  14 + elsif Rails.env.development? && respond_to?(:params) && params[:theme] && File.exists?(Rails.root.join('public/designs/themes', params[:theme]))
  15 + params[:theme]
  16 + else
  17 + if profile && !profile.theme.nil?
  18 + profile.theme
  19 + elsif environment
  20 + environment.theme
  21 + else
  22 + if logger
  23 + logger.warn("No environment found. This is weird.")
  24 + logger.warn("Request environment: %s" % request.env.inspect)
  25 + logger.warn("Request parameters: %s" % params.inspect)
  26 + end
  27 +
  28 + # could not determine the theme, so return the default one
  29 + 'default'
  30 + end
  31 + end
  32 + end
  33 + end
  34 + end
  35 +
  36 + def theme_path
  37 + if session[:theme]
  38 + '/user_themes/' + current_theme
  39 + else
  40 + '/designs/themes/' + current_theme
  41 + end
  42 + end
  43 +end
... ...
app/models/article_block.rb
... ... @@ -18,18 +18,6 @@ class ArticleBlock &lt; Block
18 18 _('This block displays one of your articles. You can edit the block to select which one of your articles is going to be displayed in the block.')
19 19 end
20 20  
21   - def content(args={})
22   - block = self
23   - proc do
24   - block_title(block.title) +
25   - (block.article ? article_to_html(FilePresenter.for(block.article),
26   - :gallery_view => false,
27   - :inside_block => block, # For Blogs and folders
28   - :format => block.visualization_format # For Articles and contents
29   - ).html_safe : _('Article not selected yet.'))
30   - end
31   - end
32   -
33 21 def article_id
34 22 self.settings[:article_id]
35 23 end
... ...
app/models/blog.rb
... ... @@ -93,4 +93,20 @@ class Blog &lt; Folder
93 93 posts.where("type != 'RssFeed'").order(:updated_at).limit(limit)
94 94 end
95 95  
  96 + def total_number_of_posts(group_by, year = nil)
  97 + case group_by
  98 + when :by_year
  99 + posts.published.native_translations
  100 + .except(:order)
  101 + .count(:all, :group => 'EXTRACT(YEAR FROM published_at)')
  102 + .sort_by {|year, count| -year.to_i}
  103 + when :by_month
  104 + posts.published.native_translations
  105 + .except(:order)
  106 + .where('EXTRACT(YEAR FROM published_at)=?', year.to_i)
  107 + .group('EXTRACT(MONTH FROM published_at)')
  108 + .count
  109 + .sort_by {|month, count| -month.to_i}
  110 + end
  111 + end
96 112 end
... ...
app/models/blog_archives_block.rb
... ... @@ -21,30 +21,6 @@ class BlogArchivesBlock &lt; Block
21 21 blog_id && owner.blogs.exists?(blog_id) ? owner.blogs.find(blog_id) : owner.blog
22 22 end
23 23  
24   - def visible_posts(person)
25   - #FIXME Performance issues with display_to. Must convert it to a scope.
26   - # Checkout this page for further information: http://noosfero.org/Development/ActionItem2705
27   - blog.posts.published.native_translations #.select {|post| post.display_to?(person)}
28   - end
29   -
30   - def content(args={})
31   - owner_blog = self.blog
32   - return nil unless owner_blog
33   - results = ''
34   - posts = visible_posts(args[:person])
35   - posts.except(:order).count(:all, :group => 'EXTRACT(YEAR FROM published_at)').sort_by {|year, count| -year.to_i}.each do |year, count|
36   - results << content_tag('li', content_tag('strong', "#{year.to_i} (#{count})"))
37   - results << "<ul class='#{year.to_i}-archive'>"
38   - posts.except(:order).where('EXTRACT(YEAR FROM published_at)=?', year.to_i).group('EXTRACT(MONTH FROM published_at)').count.sort_by {|month, count| -month.to_i}.each do |month, count|
39   - results << content_tag('li', link_to("#{month_name(month.to_i)} (#{count})", owner_blog.url.merge(year: year.to_i, month: month.to_i)))
40   - end
41   - results << "</ul>"
42   - end
43   - block_title(title) +
44   - content_tag('ul', results, :class => 'blog-archives') +
45   - content_tag('div', link_to(_('Subscribe RSS Feed'), owner_blog.feed.url), :class => 'subscribe-feed')
46   - end
47   -
48 24 def self.expire_on
49 25 { :profile => [:article], :environment => [:article] }
50 26 end
... ...
app/models/categories_block.rb
... ... @@ -30,13 +30,6 @@ class CategoriesBlock &lt; Block
30 30 Category.top_level_for(self.owner).from_types(self.category_types)
31 31 end
32 32  
33   - def content(args={})
34   - block = self
35   - proc do
36   - render :file => 'blocks/categories', :locals => { :block => block }
37   - end
38   - end
39   -
40 33 def self.expire_on
41 34 { :profile => [], :environment => [:category] }
42 35 end
... ...
app/models/comment.rb
... ... @@ -117,7 +117,15 @@ class Comment &lt; ActiveRecord::Base
117 117 end
118 118  
119 119 delegate :environment, :to => :profile
120   - delegate :profile, :to => :source, :allow_nil => true
  120 +
  121 + def environment
  122 + profile && profile.respond_to?(:environment) ? profile.environment : nil
  123 + end
  124 +
  125 + def profile
  126 + return unless source
  127 + source.kind_of?(Profile) ? source : source.profile
  128 + end
121 129  
122 130 include Noosfero::Plugin::HotSpot
123 131  
... ...
app/models/communities_block.rb
... ... @@ -27,15 +27,6 @@ class CommunitiesBlock &lt; ProfileListBlock
27 27 owner.profile_suggestions.of_community.enabled.limit(3).includes(:suggestion)
28 28 end
29 29  
30   - def footer
31   - owner = self.owner
32   - suggestions = self.suggestions
33   - return '' unless owner.kind_of?(Profile) || owner.kind_of?(Environment)
34   - proc do
35   - render :file => 'blocks/communities', :locals => { :owner => owner, :suggestions => suggestions }
36   - end
37   - end
38   -
39 30 def profiles
40 31 owner.communities
41 32 end
... ...
app/models/disabled_enterprise_message_block.rb
... ... @@ -12,13 +12,6 @@ class DisabledEnterpriseMessageBlock &lt; Block
12 12 _('Message')
13 13 end
14 14  
15   - def content(args={})
16   - message = self.owner.environment.message_for_disabled_enterprise || ''
17   - lambda do |_|
18   - render :file => 'blocks/disabled_enterprise_message', :locals => {:message => message}
19   - end
20   - end
21   -
22 15 def editable?(user=nil)
23 16 false
24 17 end
... ...
app/models/enterprises_block.rb
... ... @@ -12,22 +12,6 @@ class EnterprisesBlock &lt; ProfileListBlock
12 12 _('Enterprises')
13 13 end
14 14  
15   - def footer
16   - owner = self.owner
17   - case owner
18   - when Profile
19   - proc do
20   - link_to s_('enterprises|View all'), :profile => owner.identifier, :controller => 'profile', :action => 'enterprises'
21   - end
22   - when Environment
23   - proc do
24   - link_to s_('enterprises|View all'), :controller => 'search', :action => 'assets', :asset => 'enterprises'
25   - end
26   - else
27   - ''
28   - end
29   - end
30   -
31 15 def profiles
32 16 owner.enterprises
33 17 end
... ...
app/models/fans_block.rb
... ... @@ -12,14 +12,6 @@ class FansBlock &lt; ProfileListBlock
12 12 _('This block presents the fans of an enterprise.')
13 13 end
14 14  
15   - def footer
16   - profile = self.owner
17   - proc do
18   - link_to _('View all'), :profile => profile.identifier, :controller =>
19   - 'profile', :action => 'fans'
20   - end
21   - end
22   -
23 15 def profiles
24 16 owner.fans
25 17 end
... ...
app/models/favorite_enterprises_block.rb
... ... @@ -12,14 +12,6 @@ class FavoriteEnterprisesBlock &lt; ProfileListBlock
12 12 _('Favorite Enterprises')
13 13 end
14 14  
15   - def footer
16   - owner = self.owner
17   - return '' unless owner.kind_of?(Person)
18   - proc do
19   - link_to _('enterprises|View all'), {:profile => owner.identifier, :controller => 'profile', :action => 'favorite_enterprises'}, :class => 'view-all'
20   - end
21   - end
22   -
23 15 def profiles
24 16 owner.favorite_enterprises
25 17 end
... ...
app/models/featured_products_block.rb
... ... @@ -32,11 +32,4 @@ class FeaturedProductsBlock &lt; Block
32 32 self.owner.highlighted_products_with_image
33 33 end
34 34  
35   - def content(args={})
36   - block = self
37   - proc do
38   - render :file => 'blocks/featured_products', :locals => { :block => block }
39   - end
40   - end
41   -
42 35 end
... ...
app/models/feed_reader_block.rb
... ... @@ -52,24 +52,6 @@ class FeedReaderBlock &lt; Block
52 52 self.feed_title.nil? ? _('Feed Reader') : self.feed_title
53 53 end
54 54  
55   - def formatted_feed_content
56   - if error_message.blank?
57   - "<ul>\n".html_safe +
58   - self.feed_items[0..(limit-1)].map{ |item| "<li><a href='#{item[:link]}'>#{item[:title]}</a></li>" }.join("\n").html_safe +
59   - "</ul>".html_safe
60   - else
61   - "<p>#{error_message}</p>".html_safe
62   - end
63   - end
64   -
65   - def footer
66   - if self.fetched_at.nil? or self.feed_items.empty?
67   - _('Feed content was not loaded yet')
68   - else
69   - _("Updated: %s") % show_date(self.fetched_at)
70   - end
71   - end
72   -
73 55 def add_item(title, link, date, content)
74 56 self.feed_items.unshift( {:title => title, :link => link})
75 57 end
... ... @@ -85,8 +67,4 @@ class FeedReaderBlock &lt; Block
85 67 self.save!
86 68 end
87 69  
88   - def content(args={})
89   - block_title(title) + formatted_feed_content
90   - end
91   -
92 70 end
... ...
app/models/highlights_block.rb
... ... @@ -43,13 +43,6 @@ class HighlightsBlock &lt; Block
43 43 end
44 44 end
45 45  
46   - def content(args={})
47   - block = self
48   - proc do
49   - render :file => 'blocks/highlights', :locals => { :block => block }
50   - end
51   - end
52   -
53 46 def folder_choices
54 47 owner.image_galleries
55 48 end
... ...
app/models/link_list_block.rb
... ... @@ -59,20 +59,6 @@ class LinkListBlock &lt; Block
59 59 _('Link list')
60 60 end
61 61  
62   - def content(args={})
63   - block_title(title) +
64   - content_tag('ul',
65   - links.select{|i| !i[:name].blank? and !i[:address].blank?}.map{|i| content_tag('li', link_html(i))}.join
66   - )
67   - end
68   -
69   - def link_html(link)
70   - klass = 'icon-' + link[:icon] if link[:icon]
71   - sanitize_link(
72   - link_to(link[:name], expand_address(link[:address]), :target => link[:target], :class => klass, :title => link[:title])
73   - )
74   - end
75   -
76 62 def expand_address(address)
77 63 add = if owner.respond_to?(:identifier)
78 64 address.gsub('{profile}', owner.identifier)
... ... @@ -99,8 +85,6 @@ class LinkListBlock &lt; Block
99 85 end
100 86 end
101 87  
102   - private
103   -
104 88 def sanitize_link(text)
105 89 sanitizer = HTML::WhiteListSanitizer.new
106 90 sanitizer.sanitize(text)
... ...
app/models/location_block.rb
... ... @@ -13,12 +13,4 @@ class LocationBlock &lt; Block
13 13 _('Shows where the profile is on the material world.')
14 14 end
15 15  
16   - def content(args={})
17   - block = self
18   - profile = self.owner
19   - proc do
20   - render :file => 'blocks/location', :locals => {:block => block, :profile => profile}
21   - end
22   - end
23   -
24 16 end
... ...
app/models/login_block.rb
... ... @@ -8,12 +8,6 @@ class LoginBlock &lt; Block
8 8 _('This block presents a login/logout block.')
9 9 end
10 10  
11   - def content(args={})
12   - lambda do |context|
13   - render :file => 'blocks/login_block'
14   - end
15   - end
16   -
17 11 def cacheable?
18 12 false
19 13 end
... ...
app/models/main_block.rb
... ... @@ -8,10 +8,6 @@ class MainBlock &lt; Block
8 8 _('This block presents the main content of your pages.')
9 9 end
10 10  
11   - def content(args={})
12   - nil
13   - end
14   -
15 11 def main?
16 12 true
17 13 end
... ...
app/models/my_network_block.rb
... ... @@ -14,16 +14,6 @@ class MyNetworkBlock &lt; Block
14 14 _('This block displays some info about your networking.')
15 15 end
16 16  
17   - def content(args={})
18   - block = self
19   - proc do
20   - render :file => 'blocks/my_network', :locals => {
21   - :title => block.title,
22   - :owner => block.owner
23   - }
24   - end
25   - end
26   -
27 17 def cacheable?
28 18 false
29 19 end
... ...
app/models/product_categories_block.rb
... ... @@ -13,26 +13,6 @@ class ProductCategoriesBlock &lt; Block
13 13 _('Helps to filter the products catalog.')
14 14 end
15 15  
16   - def content(args={})
17   - profile = owner
18   - proc do
19   - if @categories.nil? or @categories.length == 0
20   - categories = ProductCategory.on_level(nil).order(:name)
21   - if @categories and @categories.length == 0
22   - notice = _('There are no sub-categories for %s') % @category.name
23   - end
24   - else
25   - categories = @categories
26   - end
27   - render :file => 'blocks/product_categories',
28   - :locals => {
29   - :profile => profile,
30   - :categories => categories,
31   - :notice => notice
32   - }
33   - end
34   - end
35   -
36 16 DISPLAY_OPTIONS = DISPLAY_OPTIONS.merge('catalog_only' => _('Only on the catalog'))
37 17  
38 18 def display
... ...
app/models/products_block.rb
... ... @@ -19,26 +19,6 @@ class ProductsBlock &lt; Block
19 19 _('This block presents a list of your products.')
20 20 end
21 21  
22   - def content(args={})
23   - block_title(title) +
24   - content_tag(
25   - 'ul',
26   - products.map {|product|
27   - content_tag('li',
28   - link_to( product.name,
29   - product.url,
30   - :style => 'background-image:url(%s)' % product.default_image('minor')
31   - ),
32   - :class => 'product'
33   - )
34   - }.join
35   - )
36   - end
37   -
38   - def footer
39   - link_to(_('View all products'), owner.public_profile_url.merge(:controller => 'catalog', :action => 'index'))
40   - end
41   -
42 22 settings_items :product_ids, type: Array
43 23 def product_ids=(array)
44 24 self.settings[:product_ids] = array
... ...
app/models/profile.rb
... ... @@ -5,8 +5,8 @@ class Profile &lt; ActiveRecord::Base
5 5  
6 6 attr_accessible :name, :identifier, :public_profile, :nickname, :custom_footer, :custom_header, :address, :zip_code, :contact_phone, :image_builder, :description, :closed, :template_id, :environment, :lat, :lng, :is_template, :fields_privacy, :preferred_domain_id, :category_ids, :country, :city, :state, :national_region_code, :email, :contact_email, :redirect_l10n, :notification_time,
7 7 :redirection_after_login, :custom_url_redirection,
8   - :email_suggestions, :allow_members_to_invite, :invite_friends_only, :secret,
9   - :custom_fields, :administrator_mail_notification, :region, :region_id
  8 + :email_suggestions, :allow_members_to_invite, :invite_friends_only, :secret, :profile_admin_mail_notification,
  9 + :custom_fields, :region, :region_id
10 10  
11 11 # use for internationalizable human type names in search facets
12 12 # reimplement on subclasses
... ... @@ -277,7 +277,7 @@ class Profile &lt; ActiveRecord::Base
277 277 settings_items :description
278 278 settings_items :fields_privacy, :type => :hash, :default => {}
279 279 settings_items :email_suggestions, :type => :boolean, :default => false
280   - settings_items :administrator_mail_notification, :type => :boolean, :default => true
  280 + settings_items :profile_admin_mail_notification, :type => :boolean, :default => true
281 281  
282 282 validates_length_of :description, :maximum => 550, :allow_nil => true
283 283  
... ...
app/models/profile_image_block.rb
... ... @@ -12,17 +12,6 @@ class ProfileImageBlock &lt; Block
12 12 _('This block presents the profile image')
13 13 end
14 14  
15   - def content(args={})
16   - block = self
17   - s = show_name
18   - lambda do |object|
19   - render(
20   - :file => 'blocks/profile_image',
21   - :locals => { :block => block, :show_name => s }
22   - )
23   - end
24   - end
25   -
26 15 def cacheable?
27 16 false
28 17 end
... ...
app/models/profile_info_block.rb
... ... @@ -16,13 +16,6 @@ class ProfileInfoBlock &lt; Block
16 16 _('Basic information about <i>%{user}</i>: how long <i>%{user}</i> is part of <i>%{env}</i> and useful links.') % { :user => self.owner.name(), :env => self.owner.environment.name() }
17 17 end
18 18  
19   - def content(args={})
20   - block = self
21   - lambda do |_|
22   - render :file => 'blocks/profile_info', :locals => { :block => block }
23   - end
24   - end
25   -
26 19 def cacheable?
27 20 false
28 21 end
... ...
app/models/profile_list_block.rb
... ... @@ -40,26 +40,6 @@ result = public_profiles.all(:limit =&gt; get_limit, :order =&gt; &#39;profiles.updated_at
40 40 _('Clicking on the people or groups will take you to their home page.')
41 41 end
42 42  
43   - def content(args={})
44   - profiles = self.profile_list
45   - title = self.view_title
46   - nl = "\n"
47   - proc do |context|
48   - count=0
49   - list = profiles.map {|item|
50   - count+=1
51   - send(:profile_image_link, item, :minor )
52   - }.join("\n ")
53   - if list.empty?
54   - list = content_tag 'div', _('None'), :class => 'common-profile-list-block-none'
55   - else
56   - list = content_tag 'ul', nl +' '+ list + nl
57   - end
58   - block_title(title) + nl +
59   - content_tag('div', nl + list + nl + tag('br', :style => 'clear:both'))
60   - end
61   - end
62   -
63 43 def view_title
64 44 title.gsub('{#}', profile_count.to_s)
65 45 end
... ...
app/models/profile_search_block.rb
... ... @@ -4,11 +4,4 @@ class ProfileSearchBlock &lt; Block
4 4 _('Display a form to search the profile')
5 5 end
6 6  
7   - def content(args={})
8   - title = self.title
9   - lambda do |_|
10   - render :file => 'blocks/profile_search', :locals => { :title => title }
11   - end
12   - end
13   -
14 7 end
... ...
app/models/raw_html_block.rb
... ... @@ -12,10 +12,6 @@ class RawHTMLBlock &lt; Block
12 12  
13 13 attr_accessible :html
14 14  
15   - def content(args={})
16   - (title.blank? ? '' : block_title(title)).html_safe + html.to_s.html_safe
17   - end
18   -
19 15 def has_macro?
20 16 true
21 17 end
... ...
app/models/recent_documents_block.rb
... ... @@ -22,24 +22,6 @@ class RecentDocumentsBlock &lt; Block
22 22  
23 23 settings_items :limit, :type => :integer, :default => 5
24 24  
25   - def content(args={})
26   - docs = self.docs
27   - title = self.title
28   - proc do
29   - block_title(title) +
30   - content_tag('ul', docs.map {|item| content_tag('li', link_to(h(item.title), item.url))}.join("\n"))
31   - end
32   - end
33   -
34   - def footer
35   - return nil unless self.owner.is_a?(Profile)
36   -
37   - profile = self.owner
38   - proc do
39   - link_to _('All content'), :profile => profile.identifier, :controller => 'profile', :action => 'sitemap'
40   - end
41   - end
42   -
43 25 def docs
44 26 self.limit.nil? ? owner.recent_documents(nil, {}, false) : owner.recent_documents(self.get_limit, {}, false)
45 27 end
... ...
app/models/sellers_search_block.rb
... ... @@ -22,10 +22,4 @@ class SellersSearchBlock &lt; Block
22 22 _('This block presents a search engine for products.')
23 23 end
24 24  
25   - def content(args={})
26   - title = self.title
27   - lambda do |object|
28   - render :file => 'search/_sellers_form', :locals => { :title => title }
29   - end
30   - end
31 25 end
... ...
app/models/slideshow_block.rb
... ... @@ -33,23 +33,6 @@ class SlideshowBlock &lt; Block
33 33 gallery.images.reject {|item| item.folder?}
34 34 end
35 35  
36   - def content(args={})
37   - block = self
38   - if gallery
39   - images = block_images
40   - if shuffle
41   - images = images.shuffle
42   - end
43   - proc do
44   - render :file => 'blocks/slideshow', :locals => { :block => block, :images => images }
45   - end
46   - else
47   - proc do
48   - render :file => 'blocks/slideshow', :locals => { :block => block, :images => nil }
49   - end
50   - end
51   - end
52   -
53 36 def folder_choices
54 37 owner.image_galleries
55 38 end
... ...
app/models/tags_block.rb
... ... @@ -28,42 +28,6 @@ class TagsBlock &lt; Block
28 28 Try to add some tags to some articles and you'l see your tag cloud growing.")
29 29 end
30 30  
31   - def content(args={})
32   - is_env = owner.class == Environment
33   - tags = is_env ? owner.tag_counts : owner.article_tags
34   - return '' if tags.empty?
35   -
36   - if limit
37   - tags_tmp = tags.sort_by{ |k,v| -v }[0..(limit-1)]
38   - tags = {}
39   - tags_tmp.map{ |k,v| tags[k] = v }
40   - end
41   -
42   - url = is_env ? {:host=>owner.default_hostname, :controller=>'search', :action => 'tag'} :
43   - owner.public_profile_url.merge(:controller => 'profile', :action => 'content_tagged')
44   - tagname_option = is_env ? :tag : :id
45   -
46   - block_title(title) +
47   - "\n<div class='tag_cloud'>\n".html_safe+
48   - tag_cloud( tags, tagname_option, url, :max_size => 16, :min_size => 9 ) +
49   - "\n</div><!-- end class='tag_cloud' -->\n".html_safe
50   - end
51   -
52   - def footer
53   - if owner.class == Environment
54   - proc do
55   - link_to s_('tags|View all'),
56   - :controller => 'search', :action => 'tags'
57   - end
58   - else
59   - owner_id = owner.identifier
60   - proc do
61   - link_to s_('tags|View all'),
62   - :profile => owner_id, :controller => 'profile', :action => 'tags'
63   - end
64   - end
65   - end
66   -
67 31 def timeout
68 32 15.minutes
69 33 end
... ...
app/models/task.rb
... ... @@ -81,17 +81,13 @@ class Task &lt; ActiveRecord::Base
81 81 end
82 82  
83 83 def target_profile_accepts_notification?(task)
84   - if target_is_profile?(task)
85   - return task.target.administrator_mail_notification
  84 + if task.target.kind_of? Organization
  85 + return task.target.profile_admin_mail_notification
86 86 else
87 87 true
88 88 end
89 89 end
90 90  
91   - def target_is_profile?(task)
92   - task.target.kind_of? Profile
93   - end
94   -
95 91 # this method finished the task. It calls #perform, which must be overriden
96 92 # by subclasses. At the end a message (as returned by #finish_message) is
97 93 # sent to the requestor with #notify_requestor.
... ...
app/views/blocks/article.html.erb 0 → 100644
... ... @@ -0,0 +1,12 @@
  1 +<%= block_title(block.title) %>
  2 +<% if block.article %>
  3 + <%=
  4 + h(article_to_html(FilePresenter.for(block.article),
  5 + :gallery_view => false,
  6 + :inside_block => block, # For Blogs and folders
  7 + :format => block.visualization_format # For Articles and contents
  8 + ))
  9 + %>
  10 +<% else %>
  11 + <%= _('Article not selected yet.') %>
  12 +<% end %>
... ...
app/views/blocks/blog_archives.html.erb 0 → 100644
... ... @@ -0,0 +1,16 @@
  1 +<% if block.blog %>
  2 + <%= block_title(block.title) %>
  3 +
  4 + <ul class='blog-archives'>
  5 + <% block.blog.total_number_of_posts(:by_year).each do |year, count| %>
  6 + <%= content_tag('li', content_tag('strong', "#{year.to_i} (#{count})")) %>
  7 + <ul class='<%= year.to_i %>-archive'>
  8 + <% block.blog.total_number_of_posts(:by_month, year).each do |month, count| %>
  9 + <%= content_tag('li', link_to("#{month_name(month.to_i)} (#{count})", block.blog.url.merge(year: year.to_i, month: month.to_i))) %>
  10 + <% end %>
  11 + </ul>
  12 + <% end %>
  13 + </ul>
  14 +
  15 + <%= content_tag('div', link_to(_('Subscribe RSS Feed'), block.blog.feed.url), :class => 'subscribe-feed') %>
  16 +<% end %>
... ...
app/views/blocks/communities.html.erb
... ... @@ -1,17 +0,0 @@
1   -<% if owner.kind_of?(Profile) %>
2   - <%= link_to s_('communities|View all'), {:profile => owner.identifier, :controller => 'profile', :action => 'communities'}, :class => 'view-all' %>
3   -<% elsif owner.kind_of?(Environment) %>
4   - <%= link_to s_('communities|View all'), {:controller => 'search', :action => 'communities'}, :class => 'view-all' %>
5   -<% end %>
6   -
7   -<% if user && user == profile && suggestions && !suggestions.empty? %>
8   - <div class='suggestions-block common-profile-list-block'>
9   - <h4 class='block-subtitle'><%= _('Some suggestions for you') %></h4>
10   - <div class='profiles-suggestions'>
11   - <%= render :partial => 'shared/profile_suggestions_list', :locals => { :suggestions => suggestions, :collection => :communities_suggestions, :per_page => 3 } %>
12   - </div>
13   - <div class='more-suggestions'>
14   - <%= link_to _('See all suggestions'), profile.communities_suggestions_url %>
15   - </div>
16   - </div>
17   -<% end %>
app/views/blocks/communities.html.erb 0 → 120000
... ... @@ -0,0 +1 @@
  1 +profile_list.html.erb
0 2 \ No newline at end of file
... ...
app/views/blocks/disabled_enterprise_message.html.erb
  1 +<% message = block.owner.environment.message_for_disabled_enterprise || '' %>
  2 +
1 3 <div id='enterprise-disabled'>
2 4 <%= message %>
3 5 <% if profile.blocked? && user && user.is_admin?(profile.environment) %>
... ...
app/views/blocks/enterprises.html.erb 0 → 120000
... ... @@ -0,0 +1 @@
  1 +profile_list.html.erb
0 2 \ No newline at end of file
... ...
app/views/blocks/fans.html.erb 0 → 120000
... ... @@ -0,0 +1 @@
  1 +profile_list.html.erb
0 2 \ No newline at end of file
... ...
app/views/blocks/favorite_enterprises.html.erb 0 → 120000
... ... @@ -0,0 +1 @@
  1 +profile_list.html.erb
0 2 \ No newline at end of file
... ...
app/views/blocks/feed_reader.html.erb 0 → 100644
... ... @@ -0,0 +1,11 @@
  1 +<%= block_title(block.title) %>
  2 +
  3 +<%=
  4 + if block.error_message.blank?
  5 + "<ul>\n".html_safe +
  6 + block.feed_items[0..(block.limit-1)].map{ |item| "<li><a href='#{item[:link]}'>#{item[:title]}</a></li>" }.join("\n").html_safe +
  7 + "</ul>".html_safe
  8 + else
  9 + "<p>#{block.error_message}</p>".html_safe
  10 + end
  11 +%>
... ...
app/views/blocks/footers/communities.html.erb 0 → 100644
... ... @@ -0,0 +1,19 @@
  1 +<% if block.owner.kind_of?(Profile) || block.owner.kind_of?(Environment) %>
  2 + <% if block.owner.kind_of?(Profile) %>
  3 + <%= link_to s_('communities|View all'), {:profile => block.owner.identifier, :controller => 'profile', :action => 'communities'}, :class => 'view-all' %>
  4 + <% elsif block.owner.kind_of?(Environment) %>
  5 + <%= link_to s_('communities|View all'), {:controller => 'search', :action => 'communities'}, :class => 'view-all' %>
  6 + <% end %>
  7 +
  8 + <% if user && user == profile && block.suggestions && !block.suggestions.empty? %>
  9 + <div class='suggestions-block common-profile-list-block'>
  10 + <h4 class='block-subtitle'><%= _('Some suggestions for you') %></h4>
  11 + <div class='profiles-suggestions'>
  12 + <%= render :partial => 'shared/profile_suggestions_list', :locals => { :suggestions => block.suggestions, :collection => :communities_suggestions, :per_page => 3 } %>
  13 + </div>
  14 + <div class='more-suggestions'>
  15 + <%= link_to _('See all suggestions'), profile.communities_suggestions_url %>
  16 + </div>
  17 + </div>
  18 + <% end %>
  19 +<% end %>
... ...
app/views/blocks/footers/enterprises.html.erb 0 → 100644
... ... @@ -0,0 +1,5 @@
  1 +<% if block.owner.is_a?(Profile) %>
  2 + <%= link_to s_('enterprises|View all'), :profile => block.owner.identifier, :controller => 'profile', :action => 'enterprises' %>
  3 +<% elsif block.owner.is_a?(Environment) %>
  4 + <%= link_to s_('enterprises|View all'), :controller => 'search', :action => 'assets', :asset => 'enterprises' %>
  5 +<% end %>
... ...
app/views/blocks/footers/fans.html.erb 0 → 100644
... ... @@ -0,0 +1 @@
  1 +<%= link_to _('View all'), :profile => block.owner.identifier, :controller => 'profile', :action => 'fans' %>
... ...
app/views/blocks/footers/favorite_enterprises.html.erb 0 → 100644
... ... @@ -0,0 +1,3 @@
  1 +<% if block.owner.is_a?(Person) %>
  2 + <%= link_to _('enterprises|View all'), {:profile => block.owner.identifier, :controller => 'profile', :action => 'favorite_enterprises'}, :class => 'view-all' %>
  3 +<% end %>
... ...
app/views/blocks/footers/feed_reader.html.erb 0 → 100644
... ... @@ -0,0 +1,5 @@
  1 +<% if block.fetched_at.nil? or block.feed_items.empty? %>
  2 + <%= _('Feed content was not loaded yet') %>
  3 +<% else %>
  4 + <%= _("Updated: %s") % show_date(block.fetched_at) %>
  5 +<% end %>
... ...
app/views/blocks/footers/products.html.erb 0 → 100644
... ... @@ -0,0 +1 @@
  1 +<%= link_to(_('View all products'), block.owner.public_profile_url.merge(:controller => 'catalog', :action => 'index')) %>
... ...
app/views/blocks/footers/recent_documents.html.erb 0 → 100644
... ... @@ -0,0 +1,3 @@
  1 +<% if block.owner.is_a?(Profile) %>
  2 + <%= link_to _('All content'), :profile => block.owner.identifier, :controller => 'profile', :action => 'sitemap' %>
  3 +<% end %>
... ...
app/views/blocks/footers/tags.html.erb 0 → 100644
... ... @@ -0,0 +1,5 @@
  1 +<% if block.owner.is_a?(Environment) %>
  2 + <%= link_to s_('tags|View all'), :controller => 'search', :action => 'tags' %>
  3 +<% else %>
  4 + <%= link_to s_('tags|View all'), :profile => block.owner.identifier, :controller => 'profile', :action => 'tags' %>
  5 +<% end %>
... ...
app/views/blocks/link_list.html.erb 0 → 100644
... ... @@ -0,0 +1,14 @@
  1 +<%= block_title(block.title) %>
  2 +
  3 +<%= block.links.empty? && block.title.empty? ? content_tag('em', _('Please, edit this block to add links')) : '' %>
  4 +
  5 +<ul>
  6 + <% block.links.select{|i| !i[:name].blank? and !i[:address].blank?}.each do |link| %>
  7 + <li>
  8 + <%= block.sanitize_link(link_to(link[:name], block.expand_address(link[:address]),
  9 + :target => link[:target],
  10 + :class => (link[:icon] ? "icon-#{link[:icon]}" : ''),
  11 + :title => link[:title])) %>
  12 + </li>
  13 + <% end %>
  14 +</ul>
... ...
app/views/blocks/location.html.erb
1   -<% if profile.lat %>
  1 +<% if block.owner.lat %>
2 2 <%= block_title block.title %>
3 3 <div class='the-localization-map'>
4   - <img src="https://maps.google.com/maps/api/staticmap?center=<%=profile.lat%>,<%=profile.lng%>&zoom=<%=block.zoom%>&size=190x250&maptype=<%=block.map_type%>&markers=<%=profile.lat%>,<%=profile.lng%>&sensor=false"/>
  4 + <img src="https://maps.google.com/maps/api/staticmap?center=<%=block.owner.lat%>,<%=block.owner.lng%>&zoom=<%=block.zoom%>&size=190x250&maptype=<%=block.map_type%>&markers=<%=block.owner.lat%>,<%=block.owner.lng%>&sensor=false"/>
5 5 </div>
6 6 <% else %>
7 7 <i><%= _('This profile has no geographical position registered.') %></i>
... ...
app/views/blocks/login.html.erb 0 → 100644
... ... @@ -0,0 +1,16 @@
  1 +<% if user.present? %>
  2 + <div class="logged-user-info">
  3 + <h2><%= _('Logged in as %s') % user.identifier %></h2>
  4 + <ul>
  5 + <li><%= _('User since %s/%s') % [user.created_at.month, user.created_at.year] %></li>
  6 + <li><%= link_to _('Homepage'), user.public_profile_url %></li>
  7 + </ul>
  8 + <div class="user-actions">
  9 + <%= button(:'menu-logout', _('Logout'), :controller => 'account', :action => 'logout') %>
  10 + </div>
  11 + </div>
  12 +<% else %>
  13 + <div class='not-logged-user'>
  14 + <%= render :file => 'account/login_block' %>
  15 + </div>
  16 +<% end%>
... ...
app/views/blocks/login_block.html.erb
... ... @@ -1,16 +0,0 @@
1   -<% if user.present? %>
2   - <div class="logged-user-info">
3   - <h2><%= _('Logged in as %s') % user.identifier %></h2>
4   - <ul>
5   - <li><%= _('User since %s/%s') % [user.created_at.month, user.created_at.year] %></li>
6   - <li><%= link_to _('Homepage'), user.public_profile_url %></li>
7   - </ul>
8   - <div class="user-actions">
9   - <%= button(:'menu-logout', _('Logout'), :controller => 'account', :action => 'logout') %>
10   - </div>
11   - </div>
12   -<% else %>
13   - <div class='not-logged-user'>
14   - <%= render :file => 'account/login_block' %>
15   - </div>
16   -<% end%>
app/views/blocks/my_network.html.erb
1   -<%= block_title(title) %>
  1 +<%= block_title(block.title) %>
2 2  
3 3 <ul>
4   - <li><%= link_to(_('Homepage'), owner.url, :class => 'url') %></li>
5   - <li><%= link_to(_('View profile'), owner.public_profile_url) %></li>
6   - <% if !user.nil? and owner.organization? and user.has_permission?('edit_profile', profile) %>
  4 + <li><%= link_to(_('Homepage'), block.owner.url, :class => 'url') %></li>
  5 + <li><%= link_to(_('View profile'), block.owner.public_profile_url) %></li>
  6 + <% if !user.nil? and block.owner.organization? and user.has_permission?('edit_profile', profile) %>
7 7 <li><%= link_to _('Control panel'), :controller => 'profile_editor', :profile => profile.identifier %></li>
8 8 <% end %>
9 9 </ul>
10 10  
11 11 <div class="my-network-actions">
12   - <%= render_profile_actions owner.class %>
  12 + <%= render_profile_actions block.owner.class %>
13 13 </div>
... ...
app/views/blocks/product_categories.html.erb
1   -<%= link_to _('Catalog start'), profile.catalog_url, :class=>'catalog-home-link' %>
  1 +<%
  2 + if @categories.nil? or @categories.length == 0
  3 + categories = ProductCategory.on_level(nil).order(:name)
  4 + else
  5 + categories = @categories
  6 + end
  7 +%>
  8 +
  9 +<%= link_to _('Catalog start'), block.owner.catalog_url, :class=>'catalog-home-link' %>
2 10 <ul class="catalog-categories-list">
3 11 <% categories.each do |category| %>
4 12 <%= category_with_sub_list(category) %>
5 13 <% end %>
6 14 </ul>
7   -<% if notice %>
8   - <div class="catalog-categories-notice"><%= notice %></div>
  15 +<% if @categories and @categories.length == 0 %>
  16 + <div class="catalog-categories-notice">
  17 + <%= _('There are no sub-categories for %s') % @category.name %>
  18 + </div>
9 19 <% end %>
... ...
app/views/blocks/products.html.erb 0 → 100644
... ... @@ -0,0 +1,9 @@
  1 +<%= block_title(block.title) %>
  2 +
  3 +<ul>
  4 + <% block.products.each do |product| %>
  5 + <li class='product'>
  6 + <%= link_to(product.name, product.url, :style => 'background-image:url(%s)' % product.default_image('minor')) %>
  7 + </li>
  8 + <% end %>
  9 +</ul>
... ...
app/views/blocks/profile_image.html.erb
... ... @@ -12,7 +12,7 @@
12 12 </div>
13 13 </div>
14 14  
15   -<% if show_name %>
  15 +<% if block.show_name %>
16 16 <p><%= h block.owner.short_name %></p>
17 17 <% end %>
18 18  
... ...
app/views/blocks/profile_list.html.erb 0 → 100644
... ... @@ -0,0 +1,17 @@
  1 +<%= block_title(block.view_title) %>
  2 +
  3 +<%
  4 + list = block.profile_list.map do |item|
  5 + profile_image_link(item, :minor)
  6 + end.join("\n ")
  7 +%>
  8 +
  9 +<div>
  10 + <% if list.empty? %>
  11 + <div class='common-profile-list-block-none'><%= _('None') %></div>
  12 + <% else %>
  13 + <ul><%= list %></ul>
  14 + <% end %>
  15 +</div>
  16 +
  17 +<br style='clear:both'/>
... ...
app/views/blocks/profile_search.html.erb
1   -<%= block_title(title) %>
  1 +<%= block_title(block.title) %>
2 2  
3 3 <%= render :partial => 'shared/profile_search_form' %>
... ...
app/views/blocks/raw_html.html.erb 0 → 100644
... ... @@ -0,0 +1,3 @@
  1 +<%=h block_title(block.title) %>
  2 +
  3 +<%=h block.html %>
... ...
app/views/blocks/recent_documents.html.erb 0 → 100644
... ... @@ -0,0 +1,7 @@
  1 +<%= block_title(block.title) %>
  2 +
  3 +<ul>
  4 + <% block.docs.map do |item| %>
  5 + <%= content_tag('li', link_to(h(item.title), item.url)) %>
  6 + <% end %>
  7 +</ul>
... ...
app/views/blocks/sellers_search.html.erb 0 → 100644
... ... @@ -0,0 +1,24 @@
  1 +<h3><%= block.title %></h3>
  2 +
  3 +<%= form_tag({:controller => 'search', :action => 'assets'}, {:method => 'get'}) do %>
  4 +
  5 + <div class="search-in-opt"><%= _('Search in:') %>
  6 + <dir>
  7 + <%= labelled_radio_button _('Enterprises'), 'asset', 'enterprises', true %><br />
  8 + <%= labelled_radio_button _('Products'), 'asset', 'products', false %>
  9 + </dir>
  10 + </div>
  11 +
  12 + <div class="formfield search-from-opt">
  13 + <%= select_city(true) %>
  14 + </div>
  15 +
  16 + <div class="formfield search-distance-opt">
  17 + <%= labelled_select(_('Distance:'), 'radius', :first, :last, nil, [15, 30, 50, 100, 150, 200, 300, 400, 500, 1000].map{|n|[n, n.to_s + 'km']}) %>
  18 + </div>
  19 +
  20 + <div class="button-bar">
  21 + <%= submit_button :search, _('Search') %>
  22 + </div>
  23 +
  24 +<% end %>
... ...
app/views/blocks/slideshow.html.erb
  1 +<%
  2 + if block.gallery
  3 + images = block.block_images
  4 + if block.shuffle
  5 + images = images.shuffle
  6 + end
  7 + end
  8 +%>
  9 +
1 10 <%= block_title(block.title) %>
  11 +
2 12 <% if images %>
3 13 <% description = images.any? { |img| !img.abstract.blank? } %>
4 14 <div class='slideshow-border<%= (description ? ' with-descriptions' : '')%>'>
... ...
app/views/blocks/tags.html.erb 0 → 100644
... ... @@ -0,0 +1,25 @@
  1 +<%= block_title(block.title) %>
  2 +
  3 +<%
  4 + is_env = block.owner.class == Environment
  5 + tags = is_env ? block.owner.tag_counts : block.owner.article_tags
  6 + if block.limit
  7 + tags_tmp = tags.sort_by{ |k,v| -v }[0..(block.limit-1)]
  8 + tags = {}
  9 + tags_tmp.map{ |k,v| tags[k] = v }
  10 + end
  11 +%>
  12 +
  13 +<% unless tags.empty? %>
  14 + <div class='tag_cloud'>
  15 + <% if is_env %>
  16 + <%= tag_cloud(tags, :tag,
  17 + {:host => block.owner.default_hostname, :controller=>'search', :action => 'tag'},
  18 + :max_size => 16, :min_size => 9) %>
  19 + <% else %>
  20 + <%= tag_cloud(tags, :id,
  21 + block.owner.public_profile_url.merge(:controller => 'profile', :action => 'content_tagged'),
  22 + :max_size => 16, :min_size => 9) %>
  23 + <% end %>
  24 + </div>
  25 +<% end %>
... ...
app/views/cms/_event.html.erb
... ... @@ -8,7 +8,7 @@
8 8 <%= render :partial => 'general_fields' %>
9 9 <%= render :partial => 'translatable' %>
10 10  
11   -<%= date_range_field('article[start_date]', 'article[end_date]', @article.start_date, @article.end_date, _('%Y-%m-%d %H:%M'), {:time => true}, {:id => 'article_start_date'} ) %>
  11 +<%= date_range_field('article[start_date]', 'article[end_date]', @article.start_date, @article.end_date, {:time => true}, {:id => 'article_start_date'} ) %>
12 12  
13 13 <%= labelled_form_field(_('Presenter:'), text_field(:article, :presenter)) %>
14 14  
... ...
app/views/cms/_text_fields.html.erb
1   -<%= labelled_form_field(_('Publish date'), date_field('article[published_at]', @article.published_at || DateTime.current, '%Y-%m-%d', {:max_date => '+0d', :date_format => 'yy-mm-dd'}, {:id => "article_published_at"})) %>
  1 +<%= labelled_form_field(_('Publish date'), date_field('article[published_at]', @article.published_at || DateTime.current, {:max_date => '+0d', :date_format => 'yy-mm-dd'}, {:id => "article_published_at"})) %>
... ...
app/views/custom_fields/_date.html.erb
1   -<%= labelled_form_field(field.name, date_field(name, profile.custom_value(field.name).to_date, '%Y-%m-%d', {:change_month => true, :change_year => true, :year_range => '-100:-5', :date_format => 'yy-mm-dd'}, {:id => field.name.parameterize.underscore}))%>
  1 +<%= labelled_form_field(field.name, date_field(name, profile.custom_value(field.name).to_date, {:change_month => true, :change_year => true, :year_range => '-100:-5', :date_format => 'yy-mm-dd'}, {:id => field.name.parameterize.underscore}))%>
... ...
app/views/profile_editor/_moderation.html.erb
... ... @@ -4,9 +4,9 @@
4 4 <h4><%= _('Email Configuration:')%></h4>
5 5 </div>
6 6 <div style='margin-bottom: 0.5em'>
7   - <%= check_box(:profile_data, :administrator_mail_notification, :style => 'float: left') %>
  7 + <%= check_box(:profile_data, :profile_admin_mail_notification, :style => 'float: left') %>
8 8 <div style='margin-left: 30px'>
9   - <%= _('Send administrator Email for every task (Default: yes)') %>
  9 + <%= _('Send administrator Email for every task') %>
10 10 </div>
11 11 </div>
12 12  
... ...
app/views/profile_editor/_person_form.html.erb
... ... @@ -16,7 +16,7 @@
16 16 <%= optional_field(@person, 'jabber_id', f.text_field(:jabber_id, :rel => _('Jabber'))) %>
17 17 <%= optional_field(@person, 'personal_website', f.text_field(:personal_website, :rel => _('Personal website'))) %>
18 18 <%= optional_field(@person, 'sex', f.radio_group(:profile_data, :sex, [ ['male',_('Male')], ['female',_('Female')] ])) %>
19   -<%= optional_field(@person, 'birth_date', labelled_form_field(_('Birth date'), date_field('profile_data[birth_date]', @profile_data. birth_date, '%Y-%m-%d', {:change_month => true, :change_year => true, :year_range => '-100:-5', :date_format => 'yy-mm-dd'}, {:id => 'profile_data_birth_date'}))) %>
  19 +<%= optional_field(@person, 'birth_date', labelled_form_field(_('Birth date'), date_field('profile_data[birth_date]', @profile_data. birth_date, {:change_month => true, :change_year => true, :year_range => '-100:-5', :date_format => 'yy-mm-dd'}, {:id => 'profile_data_birth_date'}))) %>
20 20 <%= optional_field(@person, 'nationality', f.text_field(:nationality, :rel => _('Nationality'))) %>
21 21 <%= optional_field(@person, 'country', select_country(_('Country'), 'profile_data', 'country', {:class => 'type-select'})) %>
22 22 <%= optional_field(@person, 'state', f.text_field(:state, :id => 'state_field', :rel => _('State'))) %>
... ...
app/views/search/_sellers_form.html.erb
... ... @@ -1,24 +0,0 @@
1   -<h3><%= title %></h3>
2   -
3   -<%= form_tag({:controller => 'search', :action => 'assets'}, {:method => 'get'}) do %>
4   -
5   - <div class="search-in-opt"><%= _('Search in:') %>
6   - <dir>
7   - <%= labelled_radio_button _('Enterprises'), 'asset', 'enterprises', true %><br />
8   - <%= labelled_radio_button _('Products'), 'asset', 'products', false %>
9   - </dir>
10   - </div>
11   -
12   - <div class="formfield search-from-opt">
13   - <%= select_city(true) %>
14   - </div>
15   -
16   - <div class="formfield search-distance-opt">
17   - <%= labelled_select(_('Distance:'), 'radius', :first, :last, nil, [15, 30, 50, 100, 150, 200, 300, 400, 500, 1000].map{|n|[n, n.to_s + 'km']}) %>
18   - </div>
19   -
20   - <div class="button-bar">
21   - <%= submit_button :search, _('Search') %>
22   - </div>
23   -
24   -<% end %>
app/views/shared/block.html.erb
1 1 <% if block.cacheable? && use_cache %>
2 2 <% cache_timeout(block.cache_key(language, user), block.timeout) do %>
3   - <%= display_block_content(block, user, main_content) %>
  3 + <%= display_block_content(block, main_content) %>
4 4 <% end %>
5 5 <% else %>
6   - <%= display_block_content(block, user, main_content) %>
  6 + <%= display_block_content(block, main_content) %>
7 7 <% end %>
... ...
app/views/tasks/index.html.erb
... ... @@ -50,7 +50,7 @@
50 50 <em><%= _('No pending tasks for %s') % profile.name %></em>
51 51 </p>
52 52 <% else %>
53   - <%= form_tag task_action('close') do%>
  53 + <%= form_tag tasks_url(:action => 'close') do%>
54 54 <% button_bar(:class => 'task-actions') do %>
55 55 <%# FiXME button(:edit, _('View my requests'), :action => 'list_requested') %>
56 56 <%# FIXME button('menu-mail', _('Send request'), :action => 'new') %>
... ...
debian/control
... ... @@ -47,6 +47,7 @@ Depends: adduser,
47 47 ruby-activerecord-session-store,
48 48 ruby-activerecord-deprecated-finders,
49 49 ruby-acts-as-taggable-on (>= 3.5),
  50 + ruby-api-pagination,
50 51 ruby-daemons,
51 52 ruby-dalli,
52 53 ruby-delayed-job,
... ... @@ -60,7 +61,7 @@ Depends: adduser,
60 61 ruby-feedparser (>= 0.7-3~),
61 62 ruby-gettext,
62 63 ruby-grape,
63   - ruby-grape-entity,
  64 + ruby-grape-entity (= 0.4.8),
64 65 ruby-grape-logging,
65 66 ruby-minitest,
66 67 ruby-nokogiri,
... ...
features/manage_tasks.feature 0 → 100644
... ... @@ -0,0 +1,45 @@
  1 +Feature: manage tasks
  2 + As an community admin user
  3 + I want to manage pending tasks
  4 + In order to approve or disapprove them
  5 +
  6 + Background:
  7 + Given the following users
  8 + | login | name | email |
  9 + | bob | Bob Rezende | bob@invalid.br |
  10 + | maria | Maria Sousa | maria@invalid.br |
  11 + | marie | Marie Curie | marie@invalid.br |
  12 + | mario | Mario Souto | mario@invalid.br |
  13 + And the following community
  14 + | identifier | name |
  15 + | mycommunity | My Community |
  16 + And the community "My Community" is closed
  17 + And the articles of "My Community" are moderated
  18 + And "Bob Rezende" is admin of "My Community"
  19 + And "Mario Souto" is a member of "My Community"
  20 +
  21 + @selenium
  22 + Scenario: keep filters after close tasks
  23 + Given "Marie Curie" asked to join "My Community"
  24 + And "Maria Sousa" asked to join "My Community"
  25 + And someone suggested the following article to be published
  26 + |name | target | email | body | person |
  27 + |Sample Article | mycommunity | mario@invalid.br | Corpo | mario |
  28 + |Other Article | mycommunity | maria@invalid.br | Corpo | maria |
  29 + |Another Article | mycommunity | marie@invalid.br | Corpo | marie |
  30 + And I am logged in as "bob"
  31 + And I go to mycommunity's control panel
  32 + And I follow "Tasks"
  33 + And I should see "Marie Curie wants to be a member of 'My Community'"
  34 + And I should see "Maria Sousa wants to be a member of 'My Community'"
  35 + And I should see "Mario Souto suggested the publication of the article: Sample Article"
  36 + And I should see "Maria Sousa suggested the publication of the article: Other Article"
  37 + And I should see "Marie Curie suggested the publication of the article: Another Article"
  38 + When I select "New member" from "Type of task"
  39 + And I press "Search"
  40 + And I should see "wants to be a member of 'My Community'"
  41 + And I should not see "suggested the publication of the article:"
  42 + And I choose "Accept"
  43 + And I press "Apply"
  44 + And I should see "wants to be a member of 'My Community'"
  45 + Then I should not see "suggested the publication of the article:"
... ...
features/step_definitions/noosfero_steps.rb
... ... @@ -497,7 +497,9 @@ end
497 497 Given /^someone suggested the following article to be published$/ do |table|
498 498 table.hashes.map{|item| item.dup}.each do |item|
499 499 target = Community[item.delete('target')]
500   - task = SuggestArticle.create!(:target => target, :data => item)
  500 + article = {:name => item.delete('name'), :body => item.delete('body')}
  501 + person = Profile[item.delete('person')]
  502 + task = SuggestArticle.create!(:target => target, :article => article, :requestor => person)
501 503 end
502 504 end
503 505  
... ...
lib/noosfero/api/entities.rb
... ... @@ -132,7 +132,6 @@ module Noosfero
132 132 expose :articles_count do |person, options|
133 133 person.articles.count
134 134 end
135   -
136 135 end
137 136  
138 137 class Enterprise < Profile
... ... @@ -246,7 +245,6 @@ module Noosfero
246 245 type_map.first.represent(activity.target) unless type_map.nil?
247 246 end
248 247 end
249   -
250 248 end
251 249 end
252 250 end
... ...
lib/noosfero/api/helpers.rb
... ... @@ -5,7 +5,7 @@ require_relative &#39;../../find_by_contents&#39;
5 5 module API
6 6 module APIHelpers
7 7 PRIVATE_TOKEN_PARAM = :private_token
8   - DEFAULT_ALLOWED_PARAMETERS = [:parent_id, :from, :until, :content_type, :author_id, :archived, :identifier]
  8 + DEFAULT_ALLOWED_PARAMETERS = [:parent_id, :from, :until, :content_type, :author_id, :identifier, :archived]
9 9  
10 10 include SanitizeParams
11 11 include Noosfero::Plugin::HotSpot
... ... @@ -116,6 +116,7 @@ require_relative &#39;../../find_by_contents&#39;
116 116 end
117 117 end
118 118  
  119 + ARTICLE_TYPES = ['Article'] + Article.descendants.map{|a| a.to_s}
119 120 TASK_TYPES = ['Task'] + Task.descendants.map{|a| a.to_s}
120 121  
121 122 def find_article(articles, id)
... ... @@ -127,8 +128,7 @@ require_relative &#39;../../find_by_contents&#39;
127 128 return forbidden! unless current_person.can_post_content?(asset)
128 129  
129 130 klass_type= params[:content_type].nil? ? TinyMceArticle.name : params[:content_type]
130   - article_types = ['Article'] + Article.descendants.map{|a| a.to_s}
131   - return forbidden! unless article_types.include?(klass_type)
  131 + return forbidden! unless ARTICLE_TYPES.include?(klass_type)
132 132  
133 133 article = klass_type.constantize.new(params[:article])
134 134 article.last_changed_by = current_person
... ... @@ -152,12 +152,7 @@ require_relative &#39;../../find_by_contents&#39;
152 152 end
153 153  
154 154 def present_articles(articles)
155   - present_partial articles, :with => Entities::Article
156   - end
157   -
158   - def present_articles_paginated(articles, per_page=nil)
159   - articles = paginate(articles)
160   - present_partial articles, :with => Entities::Article
  155 + present_partial paginate(articles), :with => Entities::Article
161 156 end
162 157  
163 158 def find_articles(asset, method = 'articles')
... ... @@ -239,15 +234,6 @@ require_relative &#39;../../find_by_contents&#39;
239 234 return order
240 235 end
241 236  
242   - def make_page_number_with_parameters(params)
243   - params[:page] || 1
244   - end
245   -
246   - def make_per_page_with_parameters(params)
247   - params[:per_page] ||= limit
248   - params[:per_page].to_i
249   - end
250   -
251 237 def make_timestamp_with_parameters_and_method(params, method)
252 238 timestamp = nil
253 239 if params[:timestamp]
... ... @@ -281,17 +267,17 @@ require_relative &#39;../../find_by_contents&#39;
281 267 def select_filtered_collection_of(object, method, params)
282 268 conditions = make_conditions_with_parameter(params)
283 269 order = make_order_with_parameters(object,method,params)
284   - page_number = make_page_number_with_parameters(params)
285   - per_page = make_per_page_with_parameters(params)
286 270 timestamp = make_timestamp_with_parameters_and_method(params, method)
287 271  
288 272 objects = object.send(method)
289 273 objects = by_reference(objects, params)
290 274 objects = by_categories(objects, params)
291 275  
292   - objects = objects.where(conditions).where(timestamp).page(page_number).per_page(per_page).reorder(order)
  276 + objects = objects.where(conditions).where(timestamp).reorder(order)
293 277  
294   - objects
  278 + params[:page] ||= 1
  279 + params[:per_page] ||= limit
  280 + paginate(objects)
295 281 end
296 282  
297 283 def authenticate!
... ...
lib/noosfero/api/v1/activities.rb
... ... @@ -17,7 +17,7 @@ module Noosfero
17 17 get ':id/network_activities' do
18 18 #TODO
19 19 end
20   -
  20 +
21 21 end
22 22 end
23 23 end
... ...
lib/noosfero/api/v1/articles.rb
... ... @@ -9,8 +9,7 @@ module Noosfero
9 9  
10 10 resource :articles do
11 11  
12   - paginate per_page: MAX_PER_PAGE, max_per_page: MAX_PER_PAGE
13   -
  12 + paginate max_per_page: MAX_PER_PAGE
14 13 # Collect articles
15 14 #
16 15 # Parameters:
... ... @@ -132,8 +131,7 @@ module Noosfero
132 131 named 'ArticleFollowers'
133 132 end
134 133 get 'voted_by_me' do
135   - #FIXME refactor this method
136   - present_articles_paginated(current_person.votes.where(:voteable_type => 'Article').collect(&:voteable))
  134 + present_articles(current_person.votes.where(:voteable_type => 'Article').collect(&:voteable))
137 135 end
138 136  
139 137 desc 'Perform a vote on a article by id' do
... ... @@ -176,6 +174,11 @@ module Noosfero
176 174 {:total_followers => total}
177 175 end
178 176  
  177 + desc "Return the articles followed by me"
  178 + get 'followed_by_me' do
  179 + present_articles_for_asset(current_person, 'following_articles')
  180 + end
  181 +
179 182 desc "Add a follower for the article" do
180 183 detail 'Add the current user identified by private token, like a follower of a article'
181 184 params Noosfero::API::Entities::UserLogin.documentation
... ...
lib/noosfero/api/v1/boxes.rb
... ... @@ -17,10 +17,29 @@ module Noosfero
17 17 end
18 18 end
19 19 end
20   -
21 20 end
22 21  
23 22 end
  23 +
  24 + resource :environments do
  25 + [ '/default', '/context', ':environment_id' ].each do |route|
  26 + segment route do
  27 + resource :boxes do
  28 + get do
  29 + if (route.match(/default/))
  30 + env = Environment.default
  31 + elsif (route.match(/context/))
  32 + env = environment
  33 + else
  34 + env = Environment.find(params[:environment_id])
  35 + end
  36 + present env.boxes, :with => Entities::Box
  37 + end
  38 + end
  39 + end
  40 + end
  41 + end
  42 +
24 43 end
25 44  
26 45 end
... ...
lib/noosfero/api/v1/comments.rb
... ... @@ -32,8 +32,7 @@ module Noosfero
32 32 article = find_article(environment.articles, params[:id])
33 33 options = params.select { |key,v| !['id','private_token'].include?(key) }.merge(:author => current_person, :source => article)
34 34 begin
35   - comment = Comment.create(options)
36   - comment.save!
  35 + comment = Comment.create!(options)
37 36 rescue ActiveRecord::RecordInvalid => e
38 37 render_api_error!(e.message, 400)
39 38 end
... ...
lib/noosfero/api/v1/environments.rb
... ... @@ -9,7 +9,17 @@ module Noosfero
9 9 get '/signup_person_fields' do
10 10 present environment.signup_person_fields
11 11 end
12   -
  12 +
  13 + get ':id' do
  14 + if (params[:id] == "default")
  15 + present Environment.default
  16 + elsif (params[:id] == "context")
  17 + present environment
  18 + else
  19 + present Environment.find(params[:id])
  20 + end
  21 + end
  22 +
13 23 end
14 24  
15 25 end
... ...
lib/noosfero/api/v1/people.rb
... ... @@ -9,6 +9,7 @@ module Noosfero
9 9 desc 'API Root'
10 10  
11 11 resource :people do
  12 + paginate max_per_page: MAX_PER_PAGE
12 13  
13 14 # -- A note about privacy --
14 15 # We wold find people by location, but we must test if the related
... ... @@ -111,7 +112,7 @@ module Noosfero
111 112 resource :profiles do
112 113 segment '/:profile_id' do
113 114 resource :members do
114   - paginate per_page: MAX_PER_PAGE, max_per_page: MAX_PER_PAGE
  115 + paginate max_per_page: MAX_PER_PAGE
115 116 get do
116 117 profile = environment.profiles.find_by_id(params[:profile_id])
117 118 members = select_filtered_collection_of(profile, 'members', params)
... ... @@ -120,7 +121,6 @@ module Noosfero
120 121 end
121 122 end
122 123 end
123   -
124 124 end
125 125 end
126 126 end
... ...
lib/noosfero/api/v1/search.rb
... ... @@ -5,7 +5,7 @@ module Noosfero
5 5  
6 6 resource :search do
7 7 resource :article do
8   - paginate per_page: 20, max_per_page: 200
  8 + paginate max_per_page: 200
9 9 get do
10 10 # Security checks
11 11 sanitize_params_hash(params)
... ... @@ -24,17 +24,11 @@ module Noosfero
24 24  
25 25 options = {:filter => order, :template_id => params[:template_id]}
26 26  
27   - paginate_options = params.select{|k,v| [:page, :per_page].include?(k.to_sym)}.symbolize_keys
28   - paginate_options.each_pair{|k,v| v=v.to_i}
29   - paginate_options[:page]=1 if !paginate_options.keys.include?(:page)
30   -
31   - search_result = find_by_contents(asset, context, scope, query, paginate_options, options)
  27 + search_result = find_by_contents(asset, context, scope, query, {:page => 1}, options)
32 28  
33 29 articles = search_result[:results]
34 30  
35   - result = present_articles_paginated(articles)
36   -
37   - result
  31 + present_articles(articles)
38 32 end
39 33 end
40 34 end
... ...
lib/noosfero/plugin.rb
... ... @@ -762,6 +762,10 @@ class Noosfero::Plugin
762 762 # returns = string with reason of expiration
763 763 elsif method.to_s =~ /^content_expire_(#{content_actions.join('|')})$/
764 764 nil
  765 + # -> Generic hotspots for models callbacks
  766 + # Example: article_after_create_callback
  767 + elsif method.to_s =~ /^(.+)_#{Noosfero::Plugin::HotSpot::CALLBACK_HOTSPOTS.join('|')}_callback$/
  768 + nil
765 769 elsif context.respond_to?(method)
766 770 context.send(method, *args)
767 771 else
... ...
lib/noosfero/plugin/hot_spot.rb
... ... @@ -6,6 +6,7 @@
6 6 # Environment will be used to determine which plugins are enabled and therefore
7 7 # which plugins should be instantiated.
8 8 module Noosfero::Plugin::HotSpot
  9 + CALLBACK_HOTSPOTS =[:after_save, :after_destroy, :before_save, :before_destroy, :after_create, :before_create]
9 10  
10 11 # Returns an instance of Noosfero::Plugin::Manager.
11 12 #
... ... @@ -15,4 +16,26 @@ module Noosfero::Plugin::HotSpot
15 16 @plugins ||= Noosfero::Plugin::Manager.new(environment, self)
16 17 end
17 18  
  19 + def self.included(klass)
  20 + klass.extend(ClassMethods)
  21 + end
  22 +
  23 + module ClassMethods
  24 + def self.extended base
  25 + CALLBACK_HOTSPOTS.each do |callback|
  26 + if base.respond_to?(callback)
  27 + base.class_eval do
  28 + self.send callback do |object|
  29 + current=self.class
  30 + while current.included_modules.include? Noosfero::Plugin::HotSpot do
  31 + callback_name = "#{current.name.underscore}_#{callback}_callback"
  32 + plugins.dispatch(callback_name, object)
  33 + current=current.superclass
  34 + end
  35 + end
  36 + end
  37 + end
  38 + end
  39 + end
  40 + end
18 41 end
... ...
lib/noosfero/plugin/manager.rb
... ... @@ -75,7 +75,8 @@ class Noosfero::Plugin::Manager
75 75 end
76 76  
77 77 def enabled_plugins
78   - @enabled_plugins ||= (Noosfero::Plugin.all & environment.enabled_plugins).map do |plugin|
  78 + environment_enabled_plugins = environment.present? ? environment.enabled_plugins : []
  79 + @enabled_plugins ||= (Noosfero::Plugin.all & environment_enabled_plugins).map do |plugin|
79 80 Noosfero::Plugin.load_plugin_identifier(plugin).new context
80 81 end
81 82 end
... ...