Commit 37c45c16031556e59fb59e4800933be3cd17f74e

Authored by Leandro Santos
2 parents 2f177970 6edafc75

fix conflit with next

Showing 54 changed files with 1004 additions and 127 deletions   Show diff stats
@@ -27,6 +27,11 @@ gem 'grape-swagger' @@ -27,6 +27,11 @@ gem 'grape-swagger'
27 # FIXME list here all actual dependencies (i.e. the ones in debian/control), 27 # FIXME list here all actual dependencies (i.e. the ones in debian/control),
28 # with their GEM names (not the Debian package names) 28 # with their GEM names (not the Debian package names)
29 29
  30 +group :assets do
  31 + gem 'uglifier', '>= 1.0.3'
  32 + gem 'sass-rails'
  33 +end
  34 +
30 group :production do 35 group :production do
31 gem 'dalli', '~> 2.7.0' 36 gem 'dalli', '~> 2.7.0'
32 end 37 end
HACKING.themes.md 0 → 100644
@@ -0,0 +1,60 @@ @@ -0,0 +1,60 @@
  1 +Noosfero Instructions for Theme Developers
  2 +==========================================
  3 +
  4 +To build Noosfero themes you must to know HTML and CSS. You may also get some advantages with Ruby and Noosfero hacking knowledge because all customizable pieces of the theme's HTML structure are [erb](http://en.wikipedia.org/wiki/ERuby) files.
  5 +
  6 +
  7 +Organization Basics
  8 +-------------------
  9 +
  10 +A theme is a directory and must inside `noosfero/public/designs/themes`, and you will find tis themes in a fresh installation:
  11 +`noosfero`, `aluminium`, `base`, `butter`, `chameleon`, `chocolate`, `orange`, `plum`, `scarletred` and `skyblue`. The `default` is only a link to `noosfero` and you can change this link to any other.
  12 +
  13 +`noosfero` is the default theme with a big header. All other are colored themes with a thin header. That colored ones can be used as additional themes for any environment, as they will search for `/images/thin-logo.png` inside the current environment.theme, to use as top left logo.
  14 +
  15 +Inside a theme we can found:
  16 +* `theme.yml` — Theme description with some nice configuration options.
  17 +* `preview.png` — A 100x100 screenshot of this theme to the theme selection UI.
  18 +* `style.css` — The main file. The magic happens here.
  19 +* `errors.css` — Change the error page look. (only if this theme is linked by `defaut`)
  20 +* `favicon.ico` — The identifier icon for your web site.
  21 +* `images` — Another name can be found by your CSS, but will not allow to reuse the logo.
  22 + * `thin-logo.png` — The logo to be reused by the colored themes.
  23 + * *many images...*
  24 +* `site_title.html.erb` — A nice place to put your logo, any code here will be placed inside `h1#site-title`.
  25 +* `header.html.erb` — That goes inside `div#theme-header`.
  26 +* `navigation.html.erb` — That goes inside `div#navigation ul`, so use `<li>`s.
  27 +* `footer.html.erb` — That goes inside `div#theme-footer`.
  28 +
  29 +You can add more files like javascript and modularized CSS, but you must to refer that by the described files above.
  30 +
  31 +To refer one of this files trough the web the path is `<domain>/designs/themes/<thistheme>/<somefile>`.
  32 +
  33 +
  34 +theme.yml
  35 +---------
  36 +
  37 +A simple definition file. See this example:
  38 +```yml
  39 +name: "My Cool Theme"
  40 +layout: "application-ng"
  41 +jquery_theme: "smoothness"
  42 +icon_theme: [default, pidgin]
  43 +gravatar: "retro"
  44 +```
  45 +
  46 +About non obvious:
  47 +* `layout` is about the theme structure to use. The `application-ng` is enough for 99.97358% use cases. If you want to use another structure, you must add a new `*.html.erb` file at `app/views/layouts/`.
  48 +* `icon_theme` point to something inside `public/designs/icons/`.
  49 +* `gravatar` set the default gravatar *(avatar picture)* for people without picture.
  50 +
  51 +
  52 +Theme Intervention from Environment Theme
  53 +-----------------------------------------
  54 +
  55 +Sometimes an environment (as instace http://cirandas.net) wants to allow profiles to set its own theme, but with some environment identification or functions, like a top bar with the social network logo and a top menu (as instace http://cirandas.net/rango-vegan).
  56 +To make the magic happens you can add some files to the environment theme.
  57 +All are optional:
  58 +* `global.css` — this must be used to style all extra html added by your intervention partials. As it is a free form css file you can style anything, but this is a conflict risk.
  59 +* `global_header.html.erb` — Will add content to `#global-header`.
  60 +* `global_footer.html.erb` — Will add content to `#global-footer`.
app/assets/designs/icons 0 → 120000
@@ -0,0 +1 @@ @@ -0,0 +1 @@
  1 +../../../public/designs/icons
0 \ No newline at end of file 2 \ No newline at end of file
app/assets/designs/themes 0 → 120000
@@ -0,0 +1 @@ @@ -0,0 +1 @@
  1 +../../../public/designs/themes
0 \ No newline at end of file 2 \ No newline at end of file
app/assets/images 0 → 120000
@@ -0,0 +1 @@ @@ -0,0 +1 @@
  1 +../../public/images
0 \ No newline at end of file 2 \ No newline at end of file
app/assets/javascripts 0 → 120000
@@ -0,0 +1 @@ @@ -0,0 +1 @@
  1 +../../public/javascripts
0 \ No newline at end of file 2 \ No newline at end of file
app/assets/plugins 0 → 120000
@@ -0,0 +1 @@ @@ -0,0 +1 @@
  1 +../../public/plugins
0 \ No newline at end of file 2 \ No newline at end of file
app/assets/stylesheets 0 → 120000
@@ -0,0 +1 @@ @@ -0,0 +1 @@
  1 +../../public/stylesheets
0 \ No newline at end of file 2 \ No newline at end of file
app/controllers/application_controller.rb
@@ -179,6 +179,7 @@ class ApplicationController &lt; ActionController::Base @@ -179,6 +179,7 @@ class ApplicationController &lt; ActionController::Base
179 include SearchTermHelper 179 include SearchTermHelper
180 180
181 def find_by_contents(asset, context, scope, query, paginate_options={:page => 1}, options={}) 181 def find_by_contents(asset, context, scope, query, paginate_options={:page => 1}, options={})
  182 + scope = scope.with_templates(options[:template_id]) unless options[:template_id].blank?
182 search = plugins.dispatch_first(:find_by_contents, asset, scope, query, paginate_options, options) 183 search = plugins.dispatch_first(:find_by_contents, asset, scope, query, paginate_options, options)
183 register_search_term(query, scope.count, search[:results].count, context, asset) 184 register_search_term(query, scope.count, search[:results].count, context, asset)
184 search 185 search
app/controllers/public/search_controller.rb
@@ -9,6 +9,7 @@ class SearchController &lt; PublicController @@ -9,6 +9,7 @@ class SearchController &lt; PublicController
9 before_filter :load_search_assets, :except => :suggestions 9 before_filter :load_search_assets, :except => :suggestions
10 before_filter :load_query, :except => :suggestions 10 before_filter :load_query, :except => :suggestions
11 before_filter :load_order, :except => :suggestions 11 before_filter :load_order, :except => :suggestions
  12 + before_filter :load_templates, :except => :suggestions
12 13
13 # Backwards compatibility with old URLs 14 # Backwards compatibility with old URLs
14 def redirect_asset_param 15 def redirect_asset_param
@@ -210,6 +211,11 @@ class SearchController &lt; PublicController @@ -210,6 +211,11 @@ class SearchController &lt; PublicController
210 end 211 end
211 end 212 end
212 213
  214 + def load_templates
  215 + @templates = {}
  216 + @templates[@asset] = environment.send(@asset.to_s).templates if [:people, :enterprises, :communities].include?(@asset)
  217 + end
  218 +
213 def limit 219 def limit
214 if map_search?(@searches) 220 if map_search?(@searches)
215 MAP_SEARCH_LIMIT 221 MAP_SEARCH_LIMIT
@@ -230,7 +236,7 @@ class SearchController &lt; PublicController @@ -230,7 +236,7 @@ class SearchController &lt; PublicController
230 end 236 end
231 237
232 def full_text_search 238 def full_text_search
233 - @searches[@asset] = find_by_contents(@asset, environment, @scope, @query, paginate_options, {:category => @category, :filter => @order}) 239 + @searches[@asset] = find_by_contents(@asset, environment, @scope, @query, paginate_options, {:category => @category, :filter => @order, :template_id => params[:template_id]})
234 end 240 end
235 241
236 private 242 private
app/helpers/application_helper.rb
@@ -212,6 +212,7 @@ module ApplicationHelper @@ -212,6 +212,7 @@ module ApplicationHelper
212 end 212 end
213 213
214 def button(type, label, url, html_options = {}) 214 def button(type, label, url, html_options = {})
  215 + html_options ||= {}
215 the_class = 'with-text' 216 the_class = 'with-text'
216 if html_options.has_key?(:class) 217 if html_options.has_key?(:class)
217 the_class << ' ' << html_options[:class] 218 the_class << ' ' << html_options[:class]
@@ -398,19 +399,27 @@ module ApplicationHelper @@ -398,19 +399,27 @@ module ApplicationHelper
398 end 399 end
399 end 400 end
400 401
401 - def theme_view_file(template) 402 + def theme_view_file(template, theme=nil)
402 # Since we cannot control what people are doing in external themes, we 403 # Since we cannot control what people are doing in external themes, we
403 # will keep looking for the deprecated .rhtml extension here. 404 # will keep looking for the deprecated .rhtml extension here.
404 - file = Rails.root.join('public', theme_path[1..-1], template + '.html.erb') 405 + addr = theme ? "designs/themes/#{theme}" : theme_path[1..-1]
  406 + file = Rails.root.join('public', addr, template + '.html.erb')
405 return file if File.exists?(file) 407 return file if File.exists?(file)
406 nil 408 nil
407 end 409 end
408 410
409 def theme_include(template, options = {}) 411 def theme_include(template, options = {})
410 - file = theme_view_file(template)  
411 - options.merge!({:file => file, :use_full_path => false}) 412 + from_theme_include(nil, template, options)
  413 + end
  414 +
  415 + def env_theme_include(template, options = {})
  416 + from_theme_include(environment.theme, template, options)
  417 + end
  418 +
  419 + def from_theme_include(theme, template, options = {})
  420 + file = theme_view_file(template, theme)
412 if file 421 if file
413 - render options 422 + render options.merge(file: file, use_full_path: false)
414 else 423 else
415 nil 424 nil
416 end 425 end
@@ -446,6 +455,14 @@ module ApplicationHelper @@ -446,6 +455,14 @@ module ApplicationHelper
446 @theme_extra_navigation ||= theme_include 'navigation' 455 @theme_extra_navigation ||= theme_include 'navigation'
447 end 456 end
448 457
  458 + def global_header
  459 + @global_header ||= env_theme_include 'global_header'
  460 + end
  461 +
  462 + def global_footer
  463 + @global_footer ||= env_theme_include 'global_footer'
  464 + end
  465 +
449 def is_testing_theme 466 def is_testing_theme
450 !controller.session[:theme].nil? 467 !controller.session[:theme].nil?
451 end 468 end
@@ -902,18 +919,6 @@ module ApplicationHelper @@ -902,18 +919,6 @@ module ApplicationHelper
902 end 919 end
903 end 920 end
904 921
905 - def icon_theme_stylesheet_path  
906 - icon_themes = []  
907 - theme_icon_themes = theme_option(:icon_theme) || []  
908 - for icon_theme in theme_icon_themes do  
909 - theme_path = "/designs/icons/#{icon_theme}/style.css"  
910 - if File.exists?(Rails.root.join('public', theme_path[1..-1]))  
911 - icon_themes << theme_path  
912 - end  
913 - end  
914 - icon_themes  
915 - end  
916 -  
917 def page_title 922 def page_title
918 CGI.escapeHTML( 923 CGI.escapeHTML(
919 (@page ? @page.title + ' - ' : '') + 924 (@page ? @page.title + ' - ' : '') +
app/helpers/layout_helper.rb
@@ -28,12 +28,12 @@ module LayoutHelper @@ -28,12 +28,12 @@ module LayoutHelper
28 end 28 end
29 29
30 def noosfero_javascript 30 def noosfero_javascript
31 - plugins_javascripts = @plugins.map { |plugin| [plugin.js_files].flatten.map { |js| plugin.class.public_path(js) } }.flatten 31 + plugins_javascripts = @plugins.flat_map{ |plugin| plugin.js_files.map{ |js| plugin.class.public_path(js, true) } }.flatten
32 32
33 output = '' 33 output = ''
34 output += render 'layouts/javascript' 34 output += render 'layouts/javascript'
35 unless plugins_javascripts.empty? 35 unless plugins_javascripts.empty?
36 - output += javascript_include_tag plugins_javascripts, :cache => "cache/plugins-#{Digest::MD5.hexdigest plugins_javascripts.to_s}" 36 + output += javascript_include_tag *plugins_javascripts
37 end 37 end
38 output += theme_javascript_ng.to_s 38 output += theme_javascript_ng.to_s
39 output += javascript_tag 'render_all_jquery_ui_widgets()' 39 output += javascript_tag 'render_all_jquery_ui_widgets()'
@@ -42,35 +42,27 @@ module LayoutHelper @@ -42,35 +42,27 @@ module LayoutHelper
42 end 42 end
43 43
44 def noosfero_stylesheets 44 def noosfero_stylesheets
45 - standard_stylesheets = [  
46 - 'application',  
47 - 'search',  
48 - 'colorbox',  
49 - 'selectordie',  
50 - 'inputosaurus',  
51 - 'chat',  
52 - pngfix_stylesheet_path,  
53 - ] + tokeninput_stylesheets  
54 - plugins_stylesheets = @plugins.select(&:stylesheet?).map { |plugin| plugin.class.public_path('style.css') }  
55 -  
56 - output = ''  
57 - output += stylesheet_link_tag standard_stylesheets, :cache => 'cache/application'  
58 - output += stylesheet_link_tag template_stylesheet_path  
59 - output += stylesheet_link_tag icon_theme_stylesheet_path  
60 - output += stylesheet_link_tag jquery_ui_theme_stylesheet_path 45 + plugins_stylesheets = @plugins.select(&:stylesheet?).map { |plugin|
  46 + plugin.class.public_path('style.css', true)
  47 + }
  48 + global_css_pub = "/designs/themes/#{environment.theme}/global.css"
  49 + global_css_at_fs = Rails.root.join 'public' + global_css_pub
  50 +
  51 + output = []
  52 + output << stylesheet_link_tag('application')
  53 + output << stylesheet_link_tag(template_stylesheet_path)
  54 + output << stylesheet_link_tag(*icon_theme_stylesheet_path)
  55 + output << stylesheet_link_tag(jquery_ui_theme_stylesheet_path)
61 unless plugins_stylesheets.empty? 56 unless plugins_stylesheets.empty?
62 - output += stylesheet_link_tag plugins_stylesheets, :cache => "cache/plugins-#{Digest::MD5.hexdigest plugins_stylesheets.to_s}" 57 + # FIXME: caching does not work with asset pipeline
  58 + #cacheid = "cache/plugins-#{Digest::MD5.hexdigest plugins_stylesheets.to_s}"
  59 + output << stylesheet_link_tag(*plugins_stylesheets)
63 end 60 end
64 - output += stylesheet_link_tag theme_stylesheet_path  
65 - output  
66 - end  
67 -  
68 - def pngfix_stylesheet_path  
69 - 'iepngfix/iepngfix.css'  
70 - end  
71 -  
72 - def tokeninput_stylesheets  
73 - ['token-input', 'token-input-facebook', 'token-input-mac', 'token-input-facet'] 61 + if File.exists? global_css_at_fs
  62 + output << stylesheet_link_tag(global_css_pub)
  63 + end
  64 + output << stylesheet_link_tag(theme_stylesheet_path)
  65 + output.join "\n"
74 end 66 end
75 67
76 def noosfero_layout_features 68 def noosfero_layout_features
@@ -90,7 +82,7 @@ module LayoutHelper @@ -90,7 +82,7 @@ module LayoutHelper
90 icon_themes = [] 82 icon_themes = []
91 theme_icon_themes = theme_option(:icon_theme) || [] 83 theme_icon_themes = theme_option(:icon_theme) || []
92 for icon_theme in theme_icon_themes do 84 for icon_theme in theme_icon_themes do
93 - theme_path = "/designs/icons/#{icon_theme}/style.css" 85 + theme_path = "designs/icons/#{icon_theme}/style.css"
94 if File.exists?(Rails.root.join('public', theme_path)) 86 if File.exists?(Rails.root.join('public', theme_path))
95 icon_themes << theme_path 87 icon_themes << theme_path
96 end 88 end
@@ -103,7 +95,7 @@ module LayoutHelper @@ -103,7 +95,7 @@ module LayoutHelper
103 end 95 end
104 96
105 def theme_stylesheet_path 97 def theme_stylesheet_path
106 - theme_path + '/style.css' 98 + "/assets#{theme_path}/style.css"
107 end 99 end
108 100
109 def layout_template 101 def layout_template
app/helpers/macros_helper.rb
@@ -42,7 +42,9 @@ module MacrosHelper @@ -42,7 +42,9 @@ module MacrosHelper
42 [macro.configuration[:js_files]].flatten.map { |js| plugins_javascripts << macro.plugin.public_path(js) } 42 [macro.configuration[:js_files]].flatten.map { |js| plugins_javascripts << macro.plugin.public_path(js) }
43 end 43 end
44 end 44 end
45 - javascript_include_tag(plugins_javascripts, :cache => 'cache/plugins-' + Digest::MD5.hexdigest(plugins_javascripts.to_s)) unless plugins_javascripts.empty? 45 + unless plugins_javascripts.empty?
  46 + javascript_include_tag *plugins_javascripts
  47 + end
46 end 48 end
47 49
48 def macro_css_files 50 def macro_css_files
app/helpers/plugins_helper.rb
@@ -6,4 +6,11 @@ module PluginsHelper @@ -6,4 +6,11 @@ module PluginsHelper
6 end 6 end
7 end 7 end
8 8
  9 + def plugins_toolbar_actions_for_article(article)
  10 + toolbar_actions = Array.wrap(@plugins.dispatch(:article_extra_toolbar_buttons, article))
  11 + toolbar_actions.each do |action|
  12 + [:title, :url, :icon].each { |param| raise "No #{param} was passed as parameter for #{action}" unless action.has_key?(param) }
  13 + end
  14 + end
  15 +
9 end 16 end
app/helpers/search_helper.rb
@@ -148,4 +148,11 @@ module SearchHelper @@ -148,4 +148,11 @@ module SearchHelper
148 link_to(@enabled_searches[asset], "/search/#{asset}") 148 link_to(@enabled_searches[asset], "/search/#{asset}")
149 end 149 end
150 150
  151 + def assets_submenu(asset)
  152 + return '' if @templates[asset].blank? || @templates[asset].length == 1
  153 + options = @templates[asset].map {|template| [template.name, template.id]}
  154 + options = options_for_select([[_('Choose a template'), nil]] + options, selected: (params[:template_id]))
  155 + select_tag('template_id', options, :id => 'submenu')
  156 + end
  157 +
151 end 158 end
app/models/comment.rb
@@ -44,6 +44,8 @@ class Comment &lt; ActiveRecord::Base @@ -44,6 +44,8 @@ class Comment &lt; ActiveRecord::Base
44 end 44 end
45 end 45 end
46 46
  47 + acts_as_having_settings
  48 +
47 xss_terminate :only => [ :body, :title, :name ], :on => 'validation' 49 xss_terminate :only => [ :body, :title, :name ], :on => 'validation'
48 50
49 def comment_root 51 def comment_root
app/models/organization.rb
@@ -188,4 +188,9 @@ class Organization &lt; Profile @@ -188,4 +188,9 @@ class Organization &lt; Profile
188 def allow_invitation_from?(person) 188 def allow_invitation_from?(person)
189 (followed_by?(person) && self.allow_members_to_invite) || person.has_permission?('invite-members', self) 189 (followed_by?(person) && self.allow_members_to_invite) || person.has_permission?('invite-members', self)
190 end 190 end
  191 +
  192 + def is_admin?(user)
  193 + self.admins.where(:id => user.id).exists?
  194 + end
  195 +
191 end 196 end
app/models/profile.rb
@@ -85,7 +85,15 @@ class Profile &lt; ActiveRecord::Base @@ -85,7 +85,15 @@ class Profile &lt; ActiveRecord::Base
85 #FIXME: these will work only if the subclass is already loaded 85 #FIXME: these will work only if the subclass is already loaded
86 scope :enterprises, lambda { {:conditions => (Enterprise.send(:subclasses).map(&:name) << 'Enterprise').map { |klass| "profiles.type = '#{klass}'"}.join(" OR ")} } 86 scope :enterprises, lambda { {:conditions => (Enterprise.send(:subclasses).map(&:name) << 'Enterprise').map { |klass| "profiles.type = '#{klass}'"}.join(" OR ")} }
87 scope :communities, lambda { {:conditions => (Community.send(:subclasses).map(&:name) << 'Community').map { |klass| "profiles.type = '#{klass}'"}.join(" OR ")} } 87 scope :communities, lambda { {:conditions => (Community.send(:subclasses).map(&:name) << 'Community').map { |klass| "profiles.type = '#{klass}'"}.join(" OR ")} }
88 - scope :templates, {:conditions => {:is_template => true}} 88 + scope :templates, lambda { |template_id = nil|
  89 + conditions = {:conditions => {:is_template => true}}
  90 + conditions[:conditions].merge!({:id => template_id}) unless template_id.nil?
  91 + conditions
  92 + }
  93 +
  94 + scope :with_templates, lambda { |templates|
  95 + {:conditions => {:template_id => templates}}
  96 + }
89 scope :no_templates, {:conditions => {:is_template => false}} 97 scope :no_templates, {:conditions => {:is_template => false}}
90 98
91 #FIXME make this test 99 #FIXME make this test
app/views/content_viewer/_article_toolbar.html.erb
@@ -46,6 +46,10 @@ @@ -46,6 +46,10 @@
46 <%= button(:clock, _('All versions'), {:controller => 'content_viewer', :profile => profile.identifier, :action => 'article_versions'}, :id => 'article-versions-link') %> 46 <%= button(:clock, _('All versions'), {:controller => 'content_viewer', :profile => profile.identifier, :action => 'article_versions'}, :id => 'article-versions-link') %>
47 <% end %> 47 <% end %>
48 48
  49 + <% plugins_toolbar_actions_for_article(@page).each do |plugin_button| %>
  50 + <%= button plugin_button[:icon], plugin_button[:title], plugin_button[:url], plugin_button[:html_options] %>
  51 + <% end %>
  52 +
49 <%= report_abuse(profile, :link, @page) %> 53 <%= report_abuse(profile, :link, @page) %>
50 54
51 </div> 55 </div>
app/views/layouts/_javascript.html.erb
1 -<%= javascript_include_tag 'jquery-2.1.1.min', 'jquery-migrate-1.2.1', 'jrails', 'rails.js',  
2 - 'jquery.cycle.all.min.js', 'jquery.colorbox-min.js',  
3 - 'jquery-ui-1.10.4/js/jquery-ui-1.10.4.min', 'jquery.scrollTo', 'jquery.form.js', 'jquery-validation/jquery.validate',  
4 - 'jquery.cookie', 'jquery.ba-bbq.min.js', 'reflection', 'jquery.tokeninput', 'jquery.typewatch', 'jquery.textchange',  
5 - 'jquery-timepicker-addon/dist/jquery-ui-timepicker-addon', 'inputosaurus.js', 'select-or-die/_src/selectordie',  
6 - # noosfero libraries  
7 - 'application.js', 'modal.js',  
8 - 'add-and-join', 'report-abuse', 'catalog', 'manage-products', 'autogrow',  
9 - :cache => 'cache/application' %> 1 +<%= javascript_include_tag 'application.js' %>
10 2
11 <% language = FastGettext.locale %> 3 <% language = FastGettext.locale %>
12 <% %w{messages methods}.each do |type| %> 4 <% %w{messages methods}.each do |type| %>
app/views/layouts/application-ng.html.erb
@@ -25,7 +25,7 @@ @@ -25,7 +25,7 @@
25 end.join("\n") 25 end.join("\n")
26 %> 26 %>
27 27
28 - <script type='text/javascript'> 28 + <script type="text/javascript">
29 DEFAULT_LOADING_MESSAGE = <%="'#{ _('loading...') }'" %>; 29 DEFAULT_LOADING_MESSAGE = <%="'#{ _('loading...') }'" %>;
30 </script> 30 </script>
31 31
@@ -38,9 +38,12 @@ @@ -38,9 +38,12 @@
38 if content.respond_to?(:call) then instance_exec(&content).to_s.html_safe else content.to_s.html_safe end 38 if content.respond_to?(:call) then instance_exec(&content).to_s.html_safe else content.to_s.html_safe end
39 end.join("\n") 39 end.join("\n")
40 %> 40 %>
  41 + <div id="global-header">
  42 + <%= global_header %>
  43 + </div>
41 44
42 <div id="wrap-1"> 45 <div id="wrap-1">
43 - <div id='theme-header'> 46 + <div id="theme-header">
44 <%= theme_header %> 47 <%= theme_header %>
45 </div> 48 </div>
46 <div id="wrap-2"> 49 <div id="wrap-2">
@@ -60,9 +63,14 @@ @@ -60,9 +63,14 @@
60 </div><!-- end id="wrap-2" --> 63 </div><!-- end id="wrap-2" -->
61 </div><!-- end id="wrap-1" --> 64 </div><!-- end id="wrap-1" -->
62 <%= render_environment_features(:logged_in) if logged_in? %> 65 <%= render_environment_features(:logged_in) if logged_in? %>
63 - <div id="theme-footer">  
64 - <%= theme_footer %>  
65 - </div><!-- end id="theme-footer" --> 66 + <div id="footer">
  67 + <div id="theme-footer">
  68 + <%= theme_footer %>
  69 + </div><!-- end id="theme-footer" -->
  70 + <div id="global-footer">
  71 + <%= global_footer %>
  72 + </div><!-- end id="global-footer" -->
  73 + </div><!-- end id="footer" -->
66 <%= noosfero_layout_features %> 74 <%= noosfero_layout_features %>
67 <%= addthis_javascript %> 75 <%= addthis_javascript %>
68 <%= 76 <%=
app/views/layouts/application.html.erb
@@ -21,7 +21,7 @@ @@ -21,7 +21,7 @@
21 import_controller_stylesheets(:themed_source => true) 21 import_controller_stylesheets(:themed_source => true)
22 %> 22 %>
23 <%= stylesheet_link_tag template_stylesheet_path %> 23 <%= stylesheet_link_tag template_stylesheet_path %>
24 - <%= stylesheet_link_tag icon_theme_stylesheet_path %> 24 + <%= stylesheet_link_tag *icon_theme_stylesheet_path %>
25 <%= stylesheet_link_tag jquery_ui_theme_stylesheet_path %> 25 <%= stylesheet_link_tag jquery_ui_theme_stylesheet_path %>
26 26
27 <%# Add custom tags/styles/etc via content_for %> 27 <%# Add custom tags/styles/etc via content_for %>
@@ -52,6 +52,9 @@ @@ -52,6 +52,9 @@
52 registerDocumentSize(); 52 registerDocumentSize();
53 // --> 53 // -->
54 </script> 54 </script>
  55 + <div id="global-header">
  56 + <%= global_header %>
  57 + </div>
55 58
56 <div id="accessibility_menu"> 59 <div id="accessibility_menu">
57 <a href="#content" id="link_go_content"><span><%= _('Go to content') %></span></a> 60 <a href="#content" id="link_go_content"><span><%= _('Go to content') %></span></a>
@@ -112,8 +115,13 @@ @@ -112,8 +115,13 @@
112 </div><!-- id="wrap" --> 115 </div><!-- id="wrap" -->
113 116
114 <div id="footer"> 117 <div id="footer">
115 - <%= theme_footer %>  
116 - </div><!-- id="footer" --> 118 + <div id="theme-footer">
  119 + <%= theme_footer %>
  120 + </div><!-- end id="theme-footer" -->
  121 + <div id="global-footer">
  122 + <%= global_footer %>
  123 + </div><!-- end id="global-footer" -->
  124 + </div><!-- end id="footer" -->
117 125
118 <%# if you need to add HTML stuff to the layout, include it in 126 <%# if you need to add HTML stuff to the layout, include it in
119 app/views/shared/noosfero_layout_features.html.erb! %> 127 app/views/shared/noosfero_layout_features.html.erb! %>
app/views/layouts/slideshow.html.erb
@@ -11,7 +11,7 @@ @@ -11,7 +11,7 @@
11 %></title> 11 %></title>
12 12
13 <%= stylesheet_import "slideshow" %> 13 <%= stylesheet_import "slideshow" %>
14 - <%= javascript_include_tag 'jquery-2.1.1.min', 'sliderjs', 'pikachoose', :cache => 'cache/slideshow' %> 14 + <%= javascript_include_tag 'jquery-2.1.1.min', 'sliderjs', 'pikachoose' %>
15 <script type="text/javascript"> 15 <script type="text/javascript">
16 $(document).ready(function (){ 16 $(document).ready(function (){
17 $("#slideshow").PikaChoose({ 17 $("#slideshow").PikaChoose({
app/views/search/_search_content.html.erb
1 <div id='search-content'> 1 <div id='search-content'>
  2 + <div class='total'>
  3 + <%= _('Total of %s results ') % @searches[@asset][:results].total_entries.inspect %>
  4 + </div>
  5 +
2 <%= display_results(@searches, @asset) %> 6 <%= display_results(@searches, @asset) %>
3 <% if params[:display] != 'map' %> 7 <% if params[:display] != 'map' %>
4 <%= pagination_links @searches[@asset][:results] %> 8 <%= pagination_links @searches[@asset][:results] %>
app/views/search/_search_form.html.erb
@@ -5,8 +5,12 @@ @@ -5,8 +5,12 @@
5 <div id='search-header'> 5 <div id='search-header'>
6 <%= assets_menu(@asset) %> 6 <%= assets_menu(@asset) %>
7 <%= filters(@asset) %> 7 <%= filters(@asset) %>
  8 + <div class="clear"></div>
8 </div> 9 </div>
9 10
  11 + <div id='search-subheader'>
  12 + <%= assets_submenu(@asset) %>
  13 + </div>
10 <div class="search-field"> 14 <div class="search-field">
11 <span class="formfield"> 15 <span class="formfield">
12 <%= search_input_with_suggestions('query', @asset, @query, {:id => 'search-input', :size => 50, :placeholder => hint}) %> 16 <%= search_input_with_suggestions('query', @asset, @query, {:id => 'search-input', :size => 50, :placeholder => hint}) %>
config/application.rb
@@ -88,11 +88,25 @@ module Noosfero @@ -88,11 +88,25 @@ module Noosfero
88 config.active_record.whitelist_attributes = true 88 config.active_record.whitelist_attributes = true
89 89
90 # Enable the asset pipeline 90 # Enable the asset pipeline
91 - config.assets.enabled = false 91 + config.assets.enabled = true
  92 +
  93 + # don't let rails prepend app/assets to config.assets.paths
  94 + # as we are doing it
  95 + config.paths['app/assets'] = ''
  96 +
  97 + config.assets.paths =
  98 + Dir.glob("app/assets/plugins/*/{,stylesheets,javascripts}") +
  99 + Dir.glob("app/assets/{,stylesheets,javascripts}") +
  100 + # no precedence over core
  101 + Dir.glob("app/assets/designs/{icons,themes,user_themes}/*")
92 102
93 # Version of your assets, change this if you want to expire all your assets 103 # Version of your assets, change this if you want to expire all your assets
94 config.assets.version = '1.0' 104 config.assets.version = '1.0'
95 105
  106 + config.sass.preferred_syntax = :scss
  107 + config.sass.cache = true
  108 + config.sass.line_comments = false
  109 +
96 def noosfero_session_secret 110 def noosfero_session_secret
97 require 'fileutils' 111 require 'fileutils'
98 target_dir = File.join(File.dirname(__FILE__), '../tmp') 112 target_dir = File.join(File.dirname(__FILE__), '../tmp')
config/environments/production.rb
@@ -14,12 +14,15 @@ Noosfero::Application.configure do @@ -14,12 +14,15 @@ Noosfero::Application.configure do
14 # Compress JavaScripts and CSS 14 # Compress JavaScripts and CSS
15 config.assets.compress = true 15 config.assets.compress = true
16 16
17 - # Don't fallback to assets pipeline if a precompiled asset is missed  
18 - config.assets.compile = false  
19 -  
20 # Generate digests for assets URLs 17 # Generate digests for assets URLs
21 config.assets.digest = true 18 config.assets.digest = true
22 19
  20 + # pre-compile every asset
  21 + config.assets.precompile = Dir.glob("app/assets/**/*").map do |file|
  22 + next unless File.exists?(file) and File.file?(file)
  23 + File.basename file
  24 + end.compact
  25 +
23 # Defaults to nil and saved in location specified by config.assets.prefix 26 # Defaults to nil and saved in location specified by config.assets.prefix
24 # config.assets.manifest = YOUR_PATH 27 # config.assets.manifest = YOUR_PATH
25 28
config/routes.rb
@@ -52,7 +52,6 @@ Noosfero::Application.routes.draw do @@ -52,7 +52,6 @@ Noosfero::Application.routes.draw do
52 52
53 # categories index 53 # categories index
54 match 'cat/*category_path' => 'search#category_index', :as => :category 54 match 'cat/*category_path' => 'search#category_index', :as => :category
55 - match 'assets/:asset(/*category_path)' => 'search#assets', :as => :assets  
56 # search 55 # search
57 match 'search(/:action(/*category_path))', :controller => 'search' 56 match 'search(/:action(/*category_path))', :controller => 'search'
58 57
db/migrate/20150408231524_add_settings_to_comments.rb 0 → 100644
@@ -0,0 +1,5 @@ @@ -0,0 +1,5 @@
  1 +class AddSettingsToComments < ActiveRecord::Migration
  2 + def change
  3 + add_column :comments, :settings, :text
  4 + end
  5 +end
@@ -11,7 +11,7 @@ @@ -11,7 +11,7 @@
11 # 11 #
12 # It's strongly recommended to check this file into your version control system. 12 # It's strongly recommended to check this file into your version control system.
13 13
14 -ActiveRecord::Schema.define(:version => 20150223180807) do 14 +ActiveRecord::Schema.define(:version => 20150408231524) do
15 15
16 create_table "abuse_reports", :force => true do |t| 16 create_table "abuse_reports", :force => true do |t|
17 t.integer "reporter_id" 17 t.integer "reporter_id"
@@ -263,6 +263,7 @@ ActiveRecord::Schema.define(:version =&gt; 20150223180807) do @@ -263,6 +263,7 @@ ActiveRecord::Schema.define(:version =&gt; 20150223180807) do
263 t.string "source_type" 263 t.string "source_type"
264 t.string "user_agent" 264 t.string "user_agent"
265 t.string "referrer" 265 t.string "referrer"
  266 + t.text "settings"
266 end 267 end
267 268
268 add_index "comments", ["source_id", "spam"], :name => "index_comments_on_source_id_and_spam" 269 add_index "comments", ["source_id", "spam"], :name => "index_comments_on_source_id_and_spam"
gitignore.example
@@ -22,8 +22,12 @@ public/user_themes @@ -22,8 +22,12 @@ public/user_themes
22 public/designs/themes/default 22 public/designs/themes/default
23 public/designs/themes/* 23 public/designs/themes/*
24 public/designs/icons/default 24 public/designs/icons/default
  25 +
  26 +public/assets
  27 +.sass-cache
25 public/javascripts/cache* 28 public/javascripts/cache*
26 public/stylesheets/cache* 29 public/stylesheets/cache*
  30 +
27 public/plugins 31 public/plugins
28 db/development.db 32 db/development.db
29 db/production.db 33 db/production.db
lib/noosfero/plugin.rb
@@ -150,8 +150,8 @@ class Noosfero::Plugin @@ -150,8 +150,8 @@ class Noosfero::Plugin
150 self.name.underscore.gsub('_plugin','') 150 self.name.underscore.gsub('_plugin','')
151 end 151 end
152 152
153 - def public_path(file = '')  
154 - File.join('/plugins', public_name, file) 153 + def public_path file = '', relative=false
  154 + File.join "#{if relative then '' else '/' end}plugins", public_name, file
155 end 155 end
156 156
157 def root_path 157 def root_path
@@ -430,6 +430,19 @@ class Noosfero::Plugin @@ -430,6 +430,19 @@ class Noosfero::Plugin
430 [] 430 []
431 end 431 end
432 432
  433 + # -> Adds aditional action buttons to article
  434 + # returns = { :title => title, :icon => icon, :url => url, :html_options => {} }
  435 + # title = name that will be displayed.
  436 + # icon = css class name (for customized icons include them in a css file).
  437 + # url = url or route to which the button will redirect.
  438 + # html_options = Html options for customization
  439 + #
  440 + # Multiple values could be passed as parameter.
  441 + # returns = [{:title => title, :icon => icon}, {:title => title, :icon => icon}]
  442 + def article_extra_toolbar_buttons(article)
  443 + []
  444 + end
  445 +
433 # -> Adds adicional content to article 446 # -> Adds adicional content to article
434 # returns = lambda block that creates html code 447 # returns = lambda block that creates html code
435 def article_extra_contents(article) 448 def article_extra_contents(article)
@@ -678,6 +691,8 @@ class Noosfero::Plugin @@ -678,6 +691,8 @@ class Noosfero::Plugin
678 # returns = string with reason of expiration 691 # returns = string with reason of expiration
679 elsif method.to_s =~ /^content_expire_(#{content_actions.join('|')})$/ 692 elsif method.to_s =~ /^content_expire_(#{content_actions.join('|')})$/
680 nil 693 nil
  694 + elsif context.respond_to?(method)
  695 + context.send(method)
681 else 696 else
682 super 697 super
683 end 698 end
plugins/pg_search/test/functional/search_controller_test.rb 0 → 100644
@@ -0,0 +1,32 @@ @@ -0,0 +1,32 @@
  1 +require "test_helper"
  2 +
  3 +class SearchControllerTest < ActionController::TestCase
  4 +
  5 + def setup
  6 + environment = Environment.default
  7 + environment.enable_plugin(PgSearchPlugin)
  8 + end
  9 +
  10 + should 'list all communities' do
  11 + plugin = PgSearchPlugin.new
  12 + c1 = fast_create(Community, :name => 'Testing community 1')
  13 + c2 = fast_create(Community, :name => 'Testing community 3')
  14 + c3 = fast_create(Community, :name => 'Testing community 3')
  15 +
  16 + get :communities
  17 + assert_equivalent [c1, c2, c3], assigns(:searches)[:communities][:results]
  18 + end
  19 +
  20 + should 'list communities of a specific template' do
  21 + plugin = PgSearchPlugin.new
  22 + t1 = fast_create(Community, :is_template => true)
  23 + t2 = fast_create(Community, :is_template => true)
  24 + c1 = fast_create(Community, :template_id => t1.id, :name => 'Testing community 1')
  25 + c2 = fast_create(Community, :template_id => t2.id, :name => 'Testing community 2')
  26 + c3 = fast_create(Community, :template_id => t1.id, :name => 'Testing community 3')
  27 + c4 = fast_create(Community, :name => 'Testing community 3')
  28 +
  29 + get :communities, :template_id => t1.id
  30 + assert_equivalent [c1, c3], assigns(:searches)[:communities][:results]
  31 + end
  32 +end
plugins/pjax/public/javascripts/pjax.js
@@ -8,7 +8,7 @@ pjax = { @@ -8,7 +8,7 @@ pjax = {
8 themes: {}, 8 themes: {},
9 9
10 load: function() { 10 load: function() {
11 - var target = jQuery('#content'); 11 + var target = jQuery('#wrap-1');
12 var content = jQuery('#content-inner'); 12 var content = jQuery('#content-inner');
13 var loadingTarget = jQuery('#content'); 13 var loadingTarget = jQuery('#content');
14 14
@@ -52,7 +52,7 @@ pjax = { @@ -52,7 +52,7 @@ pjax = {
52 from_state = this.current_state || this.initial_state; 52 from_state = this.current_state || this.initial_state;
53 53
54 if (state.layout_template != from_state.layout_template) { 54 if (state.layout_template != from_state.layout_template) {
55 - var lt_css = jQuery('head link[href^="/designs/templates"]'); 55 + var lt_css = jQuery('head link[href*="designs/templates"]');
56 lt_css.attr('href', lt_css.attr('href').replace(/templates\/.+\/stylesheets/, 'templates/'+state.layout_template+'/stylesheets')); 56 lt_css.attr('href', lt_css.attr('href').replace(/templates\/.+\/stylesheets/, 'templates/'+state.layout_template+'/stylesheets'));
57 } 57 }
58 58
@@ -78,7 +78,7 @@ pjax = { @@ -78,7 +78,7 @@ pjax = {
78 return !pjax.css_loaded('/designs/themes/'+state.theme.id+'/style.css'); 78 return !pjax.css_loaded('/designs/themes/'+state.theme.id+'/style.css');
79 }); 79 });
80 80
81 - var css = jQuery('head link[href^="/designs/themes/'+from_state.theme.id+'/style"]'); 81 + var css = jQuery('head link[href*="designs/themes/'+from_state.theme.id+'/style"]');
82 css.attr('href', css.attr('href').replace(/themes\/.+\/style/, 'themes/'+state.theme.id+'/style')); 82 css.attr('href', css.attr('href').replace(/themes\/.+\/style/, 'themes/'+state.theme.id+'/style'));
83 83
84 jQuery('head link[rel="shortcut icon"]').attr('href', state.theme.favicon); 84 jQuery('head link[rel="shortcut icon"]').attr('href', state.theme.favicon);
@@ -88,7 +88,7 @@ pjax = { @@ -88,7 +88,7 @@ pjax = {
88 jQuery('#navigation ul').html(state.theme.extra_navigation); 88 jQuery('#navigation ul').html(state.theme.extra_navigation);
89 jQuery('#theme-footer').html(state.theme.footer); 89 jQuery('#theme-footer').html(state.theme.footer);
90 90
91 - jQuery('head script[src^="/designs/themes/'+from_state.theme.id+'/theme.js"]').remove(); 91 + jQuery('head script[src*="designs/themes/'+from_state.theme.id+'/theme.js"]').remove();
92 if (state.theme.js_src) { 92 if (state.theme.js_src) {
93 var script = document.createElement('script'); 93 var script = document.createElement('script');
94 script.type = 'text/javascript', script.src = state.theme.js_src; 94 script.type = 'text/javascript', script.src = state.theme.js_src;
plugins/pjax/views/layouts/pjax.html.erb
1 <% 1 <%
2 - update_js = render(:file => "#{Rails.root}/public/designs/themes/#{current_theme}/pjax_update.js.erb").to_json rescue nil 2 + update_js = render(file: "#{Rails.root}/public/designs/themes/#{current_theme}/pjax_update.js.erb").to_json rescue nil
3 %> 3 %>
4 4
5 <title><%= h page_title %></title> 5 <title><%= h page_title %></title>
6 6
7 -<%= render :file => "#{Rails.root}/public/designs/themes/#{current_theme}/layouts/_content.html.erb" rescue 7 +<%= render file: "#{Rails.root}/public/designs/themes/#{current_theme}/layouts/_content.html.erb" rescue
8 render "layouts/content" %> 8 render "layouts/content" %>
9 9
10 <%= javascript_tag do %> 10 <%= javascript_tag do %>
public/javascripts/application.js
1 // Place your application-specific JavaScript functions and classes here 1 // Place your application-specific JavaScript functions and classes here
2 // This file is automatically included by javascript_include_tag :defaults 2 // This file is automatically included by javascript_include_tag :defaults
  3 +/*
  4 +* third party libraries
  5 +*= require jquery-2.1.1.min.js
  6 +*= require jquery-migrate-1.2.1.js
  7 +*= require jquery.cycle.all.min.js
  8 +*= require jquery.colorbox-min.js
  9 +*= require jquery-ui-1.10.4/js/jquery-ui-1.10.4.min.js
  10 +*= require jquery.scrollTo.js
  11 +*= require jquery.form.js
  12 +*= require jquery-validation/jquery.validate.js
  13 +*= require jquery.cookie.js
  14 +*= require jquery.ba-bbq.min.js
  15 +*= require jquery.tokeninput.js
  16 +*= require jquery-timepicker-addon/dist/jquery-ui-timepicker-addon.js
  17 +*= require inputosaurus.js
  18 +*= require reflection.js
  19 +*= require rails.js
  20 +*= require jrails.js
  21 +* noosfero libraries
  22 +*= require_self
  23 +*= require modal.js
  24 +* views speficics
  25 +*= require add-and-join.js
  26 +*= require report-abuse.js
  27 +*= require manage-products.js
  28 +*= require catalog.js
  29 +*= require autogrow.js
  30 +*/
3 31
4 // scope for noosfero stuff 32 // scope for noosfero stuff
5 noosfero = { 33 noosfero = {
public/javascripts/codepress/languages/asp.css
@@ -6,7 +6,7 @@ @@ -6,7 +6,7 @@
6 6
7 b { 7 b {
8 color:#000080; 8 color:#000080;
9 -} 9 +}
10 /* comments */ 10 /* comments */
11 big, big b, big em, big ins, big s, strong i, strong i b, strong i s, strong i u, strong i a, strong i a u, strong i s u { 11 big, big b, big em, big ins, big s, strong i, strong i b, strong i s, strong i u, strong i a, strong i a u, strong i s u {
12 color:gray; 12 color:gray;
@@ -17,12 +17,12 @@ strong dfn, strong dfn a,strong dfn var, strong dfn a u, strong dfn u{ @@ -17,12 +17,12 @@ strong dfn, strong dfn a,strong dfn var, strong dfn a u, strong dfn u{
17 color:gray; 17 color:gray;
18 font-weight:normal; 18 font-weight:normal;
19 } 19 }
20 - /* attributes */ 20 + /* attributes */
21 s, s b, span s u, span s cite, strong span s { 21 s, s b, span s u, span s cite, strong span s {
22 color:#5656fa ; 22 color:#5656fa ;
23 font-weight:normal; 23 font-weight:normal;
24 } 24 }
25 - /* strings */ 25 + /* strings */
26 strong s,strong s b, strong s u, strong s cite { 26 strong s,strong s b, strong s u, strong s cite {
27 color:#009900; 27 color:#009900;
28 font-weight:normal; 28 font-weight:normal;
@@ -34,7 +34,6 @@ strong ins{ @@ -34,7 +34,6 @@ strong ins{
34 /* Syntax */ 34 /* Syntax */
35 strong a, strong a u { 35 strong a, strong a u {
36 color:#0000FF; 36 color:#0000FF;
37 - font-weight:;  
38 } 37 }
39 /* Native Keywords */ 38 /* Native Keywords */
40 strong u { 39 strong u {
@@ -58,7 +57,7 @@ em { @@ -58,7 +57,7 @@ em {
58 color:#800080; 57 color:#800080;
59 font-style:normal; 58 font-style:normal;
60 } 59 }
61 - /* script */ 60 + /* script */
62 ins { 61 ins {
63 color:#800000; 62 color:#800000;
64 font-weight:bold; 63 font-weight:bold;
@@ -68,4 +67,4 @@ ins { @@ -68,4 +67,4 @@ ins {
68 cite, s cite { 67 cite, s cite {
69 color:red; 68 color:red;
70 font-weight:bold; 69 font-weight:bold;
71 -}  
72 \ No newline at end of file 70 \ No newline at end of file
  71 +}
public/javascripts/codepress/languages/vbscript.css
1 /* 1 /*
2 - * CodePress color styles for ASP-VB syntax highlighting 2 + * CodePress color styles for ASP-VB syntax highlighting
3 * By Martin D. Kirk 3 * By Martin D. Kirk
4 */ 4 */
5 5
6 /* tags */ 6 /* tags */
7 b { 7 b {
8 color:#000080; 8 color:#000080;
9 -} 9 +}
10 /* comments */ 10 /* comments */
11 big, big b, big em, big ins, big s, strong i, strong i b, strong i s, strong i u, strong i a, strong i a u, strong i s u { 11 big, big b, big em, big ins, big s, strong i, strong i b, strong i s, strong i u, strong i a, strong i a u, strong i s u {
12 color:gray; 12 color:gray;
@@ -17,12 +17,12 @@ strong dfn, strong dfn a,strong dfn var, strong dfn a u, strong dfn u{ @@ -17,12 +17,12 @@ strong dfn, strong dfn a,strong dfn var, strong dfn a u, strong dfn u{
17 color:gray; 17 color:gray;
18 font-weight:normal; 18 font-weight:normal;
19 } 19 }
20 - /* attributes */ 20 + /* attributes */
21 s, s b, span s u, span s cite, strong span s { 21 s, s b, span s u, span s cite, strong span s {
22 color:#5656fa ; 22 color:#5656fa ;
23 font-weight:normal; 23 font-weight:normal;
24 } 24 }
25 - /* strings */ 25 + /* strings */
26 strong s,strong s b, strong s u, strong s cite { 26 strong s,strong s b, strong s u, strong s cite {
27 color:#009900; 27 color:#009900;
28 font-weight:normal; 28 font-weight:normal;
@@ -34,7 +34,6 @@ strong ins{ @@ -34,7 +34,6 @@ strong ins{
34 /* Syntax */ 34 /* Syntax */
35 strong a, strong a u { 35 strong a, strong a u {
36 color:#0000FF; 36 color:#0000FF;
37 - font-weight:;  
38 } 37 }
39 /* Native Keywords */ 38 /* Native Keywords */
40 strong u { 39 strong u {
@@ -58,7 +57,7 @@ em { @@ -58,7 +57,7 @@ em {
58 color:#800080; 57 color:#800080;
59 font-style:normal; 58 font-style:normal;
60 } 59 }
61 - /* script */ 60 + /* script */
62 ins { 61 ins {
63 color:#800000; 62 color:#800000;
64 font-weight:bold; 63 font-weight:bold;
@@ -68,4 +67,4 @@ ins { @@ -68,4 +67,4 @@ ins {
68 cite, s cite { 67 cite, s cite {
69 color:red; 68 color:red;
70 font-weight:bold; 69 font-weight:bold;
71 -}  
72 \ No newline at end of file 70 \ No newline at end of file
  71 +}
public/javascripts/jquery-ui-1.10.4/development-bundle/themes/base/minified/jquery.ui.theme.min.css
@@ -1,5 +0,0 @@ @@ -1,5 +0,0 @@
1 -/*! jQuery UI - v1.10.4 - 2014-04-02  
2 -* http://jqueryui.com  
3 -* Copyright 2014 jQuery Foundation and other contributors; Licensed MIT */  
4 -  
5 -undefined  
6 \ No newline at end of file 0 \ No newline at end of file
public/javascripts/search.js
@@ -15,9 +15,17 @@ @@ -15,9 +15,17 @@
15 $('form.search_form').submit(); 15 $('form.search_form').submit();
16 }); 16 });
17 17
  18 + // Filter submenu
  19 + $('#search-subheader select').change(function(){
  20 + $('form.search_form').submit();
  21 + });
  22 +
18 // Custom styled select 23 // Custom styled select
19 $('#search-filters select').selectOrDie(); 24 $('#search-filters select').selectOrDie();
20 25
  26 + // Custom styled select
  27 + $('#search-subheader select').selectOrDie();
  28 +
21 // Form Ajax submission 29 // Form Ajax submission
22 $('form.search_form').submit(function () { 30 $('form.search_form').submit(function () {
23 $.ajax({ 31 $.ajax({
public/stylesheets/application.css
  1 +/*
  2 + * thidparty libraries
  3 + *= require colorbox
  4 + *= require selectordie
  5 + *= require selectordie-theme
  6 + *= require inputosaurus
  7 + *= require token-input
  8 + *= require token-input-facebook
  9 + *= require token-input-mac
  10 + *= require token-input-facet
  11 + * noosfero libraries
  12 + *= require_self
  13 + *= require iepngfix/iepngfix
  14 + * views specifics
  15 + *= require chat
  16 + *= require search
  17 + */
  18 +
1 /* browser fixes */ 19 /* browser fixes */
2 20
3 img:-moz-broken { 21 img:-moz-broken {
@@ -77,19 +95,6 @@ div#errorExplanation h2 { @@ -77,19 +95,6 @@ div#errorExplanation h2 {
77 #footer_content { 95 #footer_content {
78 clear: both; 96 clear: both;
79 } 97 }
80 -#footer {  
81 - text-align: center;  
82 - clear: both;  
83 - font-size: 10px;  
84 - color: #777;  
85 -}  
86 -#footer a {  
87 - color: #777;  
88 - text-decoration: none;  
89 -}  
90 -#footer a:hover {  
91 - color: #555;  
92 -}  
93 div#profile-disabled { 98 div#profile-disabled {
94 border: 2px solid #944; 99 border: 2px solid #944;
95 text-align: center; 100 text-align: center;
@@ -4427,7 +4432,8 @@ h1#agenda-title { @@ -4427,7 +4432,8 @@ h1#agenda-title {
4427 #groups-list li { 4432 #groups-list li {
4428 display: block; 4433 display: block;
4429 list-style: none; 4434 list-style: none;
4430 - margin-bottom: 20px background-color: #B8CFE7; 4435 + margin-bottom: 20px;
  4436 + background-color: #B8CFE7;
4431 } 4437 }
4432 4438
4433 #groups-list li .vcard { 4439 #groups-list li .vcard {
@@ -6932,8 +6938,8 @@ li.profile-activity-item.upload_image .activity-gallery-images-count-1 img { @@ -6932,8 +6938,8 @@ li.profile-activity-item.upload_image .activity-gallery-images-count-1 img {
6932 } 6938 }
6933 6939
6934 .fetching-overlay { 6940 .fetching-overlay {
6935 - position: absolute;  
6936 - top: 0px; 6941 + position: absolute;
  6942 + top: 0px;
6937 left: 0px; 6943 left: 0px;
6938 right: 0px; 6944 right: 0px;
6939 bottom: 0px; 6945 bottom: 0px;
public/stylesheets/search.css
@@ -563,7 +563,8 @@ li.search-product-item { @@ -563,7 +563,8 @@ li.search-product-item {
563 } 563 }
564 li.search-product-item { 564 li.search-product-item {
565 display:block; 565 display:block;
566 - float:none overflow:visible; 566 + float:none;
  567 + overflow:visible;
567 padding:10px 0; 568 padding:10px 0;
568 margin:10px 0; 569 margin:10px 0;
569 border-bottom:1px solid #ccc; 570 border-bottom:1px solid #ccc;
@@ -953,7 +954,7 @@ ul#assets-menu { @@ -953,7 +954,7 @@ ul#assets-menu {
953 text-align: justify; 954 text-align: justify;
954 text-justify: distribute-all-lines; /* distribute items in IE */ 955 text-justify: distribute-all-lines; /* distribute items in IE */
955 list-style-type: none; 956 list-style-type: none;
956 - margin: 5px 0 13px; 957 + margin: 5px 0px 10px 0px;
957 padding: 0; 958 padding: 0;
958 width: 500px; 959 width: 500px;
959 float: left; 960 float: left;
@@ -984,6 +985,15 @@ ul#assets-menu li.selected a { @@ -984,6 +985,15 @@ ul#assets-menu li.selected a {
984 color: #EF2929; 985 color: #EF2929;
985 font-weight: bold; 986 font-weight: bold;
986 } 987 }
  988 +ul#assets-links li.selected a {
  989 + border-bottom: 4px solid #dd4b39;
  990 + padding-bottom: 6px;
  991 +}
  992 +
  993 +ul#assets-links li.selected a {
  994 + color: #dd4b39;
  995 + font-weight: bold;
  996 +}
987 997
988 #search-filters { 998 #search-filters {
989 float: right; 999 float: right;
@@ -1037,3 +1047,13 @@ ul#assets-menu li.selected a { @@ -1037,3 +1047,13 @@ ul#assets-menu li.selected a {
1037 border-bottom:1px solid #ccc; 1047 border-bottom:1px solid #ccc;
1038 margin-bottom: 10px; 1048 margin-bottom: 10px;
1039 } 1049 }
  1050 +
  1051 +#search-header{
  1052 + border-bottom: 1px solid #ebebeb;
  1053 +}
  1054 +
  1055 +#search-content .total{
  1056 + color: #808080;
  1057 + line-height: 20px;
  1058 + font-style: oblique;
  1059 +}
public/stylesheets/selectordie-theme.css 0 → 100644
@@ -0,0 +1,75 @@ @@ -0,0 +1,75 @@
  1 +/* Default custom select styles */
  2 +
  3 +#search-subheader div.sod_select {
  4 + display: inline-block;
  5 + vertical-align: middle;
  6 + position: relative;
  7 + text-align: left;
  8 + background: #fff;
  9 + z-index: 100;
  10 + -webkit-touch-callout: none;
  11 + -webkit-user-select: none;
  12 + -khtml-user-select: none;
  13 + -moz-user-select: none;
  14 + -ms-user-select: none;
  15 + user-select: none;
  16 + background: transparent;
  17 + max-width: 400px;
  18 +}
  19 +
  20 +#search-subheader div.sod_select:focus {
  21 + outline: none; /* For better accessibility add a style for this in your skin */
  22 +}
  23 +
  24 +#search-subheader .sod_select select {
  25 + display: none;
  26 +}
  27 +
  28 +#search-subheader .sod_label::after {
  29 + font-family: Arial, 'Liberation Sans', sans-serif;
  30 + font-weight: bold;
  31 + content: '+';
  32 + left: 0px;
  33 + -webkit-transform: translate3d(0,-50%,0) rotate3d(0,0,1,0deg);;
  34 + transform: translate3d(0,-50%,0) rotate3d(0,0,1,0deg);;
  35 + -webkit-transition: -webkit-transform 0.5s;
  36 + transition: transform 0.5s;
  37 + position: absolute;
  38 + top: 50%;
  39 + font-size: 2.1em;
  40 +}
  41 +
  42 +#search-subheader .sod_select.open .sod_label::after {
  43 + -webkit-transform: translate3d(0,-50%,0) rotate3d(0,0,1,225deg);
  44 + transform: translate3d(0,-50%,0) rotate3d(0,0,1,225deg);
  45 +}
  46 +
  47 +/* Changes on select or die*/
  48 +#search-subheader .sod_select{
  49 + border: none;
  50 + padding-top: 10px;
  51 + padding-left: 20px;
  52 + padding-bottom: 10px;
  53 + width: auto;
  54 + font-weight: normal;
  55 + text-transform: none;
  56 + font-size: 12px;
  57 +}
  58 +
  59 +#search-subheader .sod_select.open{
  60 +}
  61 +
  62 +#search-subheader .sod_select .sod_list{
  63 + border: 1px solid #ebebeb;
  64 + margin-left: -1px;
  65 + width: auto;
  66 +}
  67 +
  68 +#search-subheader .sod_select:before,
  69 +#search-subheader .sod_select:after {
  70 + content: "";
  71 +}
  72 +
  73 +#search-subheader .sod_select.focus {
  74 + box-shadow: none;
  75 +}
test/functional/content_viewer_controller_test.rb
@@ -1436,4 +1436,99 @@ class ContentViewerControllerTest &lt; ActionController::TestCase @@ -1436,4 +1436,99 @@ class ContentViewerControllerTest &lt; ActionController::TestCase
1436 1436
1437 assert_no_tag :tag => 'h1', :attributes => { :class => /title/ }, :content => article.name 1437 assert_no_tag :tag => 'h1', :attributes => { :class => /title/ }, :content => article.name
1438 end 1438 end
  1439 +
  1440 + should 'add extra toolbar actions on article from plugins' do
  1441 + class Plugin1 < Noosfero::Plugin
  1442 + def article_extra_toolbar_buttons(article)
  1443 + {:title => 'some_title1', :icon => 'some_icon1', :url => {}}
  1444 + end
  1445 + end
  1446 + Noosfero::Plugin.stubs(:all).returns([Plugin1.name])
  1447 +
  1448 + Environment.default.enable_plugin(Plugin1.name)
  1449 +
  1450 + page = profile.articles.create!(:name => 'myarticle', :body => 'the body of the text')
  1451 +
  1452 + get :view_page, :profile => profile.identifier, :page => [ 'myarticle' ]
  1453 + assert_tag :tag => 'div', :attributes => { :id => 'article-actions' }, :descendant => { :tag => 'a', :attributes => { :title => "some_title1" }}
  1454 + end
  1455 +
  1456 + should 'add more than one extra toolbar actions on article from plugins' do
  1457 + class Plugin1 < Noosfero::Plugin
  1458 + def article_extra_toolbar_buttons(article)
  1459 + {:title => 'some_title1', :icon => 'some_icon1', :url => {}}
  1460 + end
  1461 + end
  1462 + class Plugin2 < Noosfero::Plugin
  1463 + def article_extra_toolbar_buttons(article)
  1464 + {:title => 'some_title2', :icon => 'some_icon2', :url => {}}
  1465 + end
  1466 + end
  1467 + Noosfero::Plugin.stubs(:all).returns([Plugin1.name, Plugin2.name])
  1468 +
  1469 + Environment.default.enable_plugin(Plugin1.name)
  1470 + Environment.default.enable_plugin(Plugin2.name)
  1471 +
  1472 + page = profile.articles.create!(:name => 'myarticle', :body => 'the body of the text')
  1473 +
  1474 + get :view_page, :profile => profile.identifier, :page => [ 'myarticle' ]
  1475 + assert_tag :tag => 'div', :attributes => { :id => 'article-actions' }, :descendant => { :tag => 'a', :attributes => { :title => "some_title1" }}
  1476 + assert_tag :tag => 'div', :attributes => { :id => 'article-actions' }, :descendant => { :tag => 'a', :attributes => { :title => "some_title2" }}
  1477 + end
  1478 +
  1479 + should 'add icon attribute in extra toolbar actions on article from plugins' do
  1480 + class Plugin1 < Noosfero::Plugin
  1481 + def article_extra_toolbar_buttons(article)
  1482 + {:title => 'some_title', :icon => 'some_icon', :url => {}}
  1483 + end
  1484 + end
  1485 + Noosfero::Plugin.stubs(:all).returns([Plugin1.name])
  1486 +
  1487 + Environment.default.enable_plugin(Plugin1.name)
  1488 +
  1489 + page = profile.articles.create!(:name => 'myarticle', :body => 'the body of the text')
  1490 +
  1491 + get :view_page, :profile => profile.identifier, :page => [ 'myarticle' ]
  1492 + assert_tag :tag => 'div', :attributes => { :id => 'article-actions' }, :descendant => { :tag => 'a', :attributes => { :class => /some_icon/ }}
  1493 + end
  1494 +
  1495 + should 'add url attribute in extra toolbar actions on article from plugins' do
  1496 + class Plugin1 < Noosfero::Plugin
  1497 + def article_extra_toolbar_buttons(article)
  1498 + {:title => 'some_title', :icon => 'some_icon', :url => '/someurl'}
  1499 + end
  1500 + end
  1501 + Noosfero::Plugin.stubs(:all).returns([Plugin1.name])
  1502 +
  1503 + Environment.default.enable_plugin(Plugin1.name)
  1504 +
  1505 + page = profile.articles.create!(:name => 'myarticle', :body => 'the body of the text')
  1506 +
  1507 + get :view_page, :profile => profile.identifier, :page => [ 'myarticle' ]
  1508 + assert_tag :tag => 'div', :attributes => { :id => 'article-actions' }, :descendant => { :tag => 'a', :attributes => { :href => "/someurl" }}
  1509 + end
  1510 +
  1511 + should 'use context method in extra toolbar actions on article from plugins' do
  1512 + class Plugin1 < Noosfero::Plugin
  1513 + def article_extra_toolbar_buttons(article)
  1514 + if current_person.public?
  1515 + {:title => 'some_title', :icon => 'some_icon', :url => '/someurl'}
  1516 + else
  1517 + {:title => 'another_title', :icon => 'another_icon', :url => '/anotherurl'}
  1518 + end
  1519 + end
  1520 + end
  1521 + Noosfero::Plugin.stubs(:all).returns([Plugin1.name])
  1522 +
  1523 + Environment.default.enable_plugin(Plugin1.name)
  1524 +
  1525 + page = profile.articles.create!(:name => 'myarticle', :body => 'the body of the text')
  1526 +
  1527 + profile.public_profile = false
  1528 + profile.save
  1529 + login_as(profile.identifier)
  1530 + get :view_page, :profile => profile.identifier, :page => [ 'myarticle' ]
  1531 + assert_tag :tag => 'div', :attributes => { :id => 'article-actions' }, :descendant => { :tag => 'a', :attributes => { :href => "/anotherurl" }}
  1532 + end
  1533 +
1439 end 1534 end
test/functional/search_controller_test.rb
@@ -13,14 +13,14 @@ class SearchControllerTest &lt; ActionController::TestCase @@ -13,14 +13,14 @@ class SearchControllerTest &lt; ActionController::TestCase
13 @request.stubs(:ssl?).returns(false) 13 @request.stubs(:ssl?).returns(false)
14 @response = ActionController::TestResponse.new 14 @response = ActionController::TestResponse.new
15 15
16 - @category = Category.create!(:name => 'my-category', :environment => Environment.default) 16 + @environment = Environment.default
  17 + @category = Category.create!(:name => 'my-category', :environment => @environment)
17 18
18 - env = Environment.default  
19 - domain = env.domains.first 19 + domain = @environment.domains.first
20 if !domain 20 if !domain
21 domain = Domain.create!(:name => "127.0.0.1") 21 domain = Domain.create!(:name => "127.0.0.1")
22 - env.domains = [domain]  
23 - env.save! 22 + @environment.domains = [domain]
  23 + @environment.save!
24 end 24 end
25 domain.google_maps_key = 'ENVIRONMENT_KEY' 25 domain.google_maps_key = 'ENVIRONMENT_KEY'
26 domain.save! 26 domain.save!
@@ -37,6 +37,8 @@ class SearchControllerTest &lt; ActionController::TestCase @@ -37,6 +37,8 @@ class SearchControllerTest &lt; ActionController::TestCase
37 Person.any_instance.stubs(:user).returns(user) 37 Person.any_instance.stubs(:user).returns(user)
38 end 38 end
39 39
  40 + attr_reader :environment
  41 +
40 def create_article_with_optional_category(name, profile, category = nil) 42 def create_article_with_optional_category(name, profile, category = nil)
41 fast_create(Article, {:name => name, :profile_id => profile.id }, :search => true, :category => category) 43 fast_create(Article, {:name => name, :profile_id => profile.id }, :search => true, :category => category)
42 end 44 end
@@ -651,6 +653,122 @@ class SearchControllerTest &lt; ActionController::TestCase @@ -651,6 +653,122 @@ class SearchControllerTest &lt; ActionController::TestCase
651 assert_equal [st1,st2].to_json, response.body 653 assert_equal [st1,st2].to_json, response.body
652 end 654 end
653 655
  656 + should 'templates variable be an hash in articles asset' do
  657 + get :articles
  658 + assert assigns(:templates).kind_of?(Hash)
  659 + end
  660 +
  661 + should 'not load people templates in articles asset' do
  662 + t1 = fast_create(Person, :is_template => true, :environment_id => environment.id)
  663 + t2 = fast_create(Person, :is_template => true, :environment_id => environment.id)
  664 + get :articles
  665 + assert_nil assigns(:templates)[:people]
  666 + end
  667 +
  668 + should 'not load communities templates in articles asset' do
  669 + t1 = fast_create(Community, :is_template => true, :environment_id => environment.id)
  670 + t2 = fast_create(Community, :is_template => true, :environment_id => environment.id)
  671 + get :articles
  672 + assert_nil assigns(:templates)[:communities]
  673 + end
  674 +
  675 + should 'not load enterprises templates in articles asset' do
  676 + t1 = fast_create(Enterprise, :is_template => true, :environment_id => environment.id)
  677 + t2 = fast_create(Enterprise, :is_template => true, :environment_id => environment.id)
  678 + get :articles
  679 + assert_nil assigns(:templates)[:enterprises]
  680 + end
  681 +
  682 + should 'templates variable be equals to people templates in people assert' do
  683 + t1 = fast_create(Person, :is_template => true, :environment_id => environment.id)
  684 + t2 = fast_create(Person, :is_template => true, :environment_id => environment.id)
  685 + get :people
  686 +
  687 + assert_equivalent [t1,t2], assigns(:templates)[:people]
  688 + end
  689 +
  690 + should 'not load communities templates in people asset' do
  691 + t1 = fast_create(Community, :is_template => true, :environment_id => environment.id)
  692 + t2 = fast_create(Community, :is_template => true, :environment_id => environment.id)
  693 + get :people
  694 + assert_nil assigns(:templates)[:communities]
  695 + end
  696 +
  697 + should 'not load enterprises templates in people asset' do
  698 + t1 = fast_create(Enterprise, :is_template => true, :environment_id => environment.id)
  699 + t2 = fast_create(Enterprise, :is_template => true, :environment_id => environment.id)
  700 + get :people
  701 + assert_nil assigns(:templates)[:enterprises]
  702 + end
  703 +
  704 + should 'templates variable be equals to communities templates in communities assert' do
  705 + t1 = fast_create(Community, :is_template => true, :environment_id => environment.id)
  706 + t2 = fast_create(Community, :is_template => true, :environment_id => environment.id)
  707 + get :communities
  708 +
  709 + assert_equivalent [t1,t2], assigns(:templates)[:communities]
  710 + end
  711 +
  712 + should 'not load people templates in communities asset' do
  713 + t1 = fast_create(Person, :is_template => true, :environment_id => environment.id)
  714 + t2 = fast_create(Person, :is_template => true, :environment_id => environment.id)
  715 + get :communities
  716 + assert_nil assigns(:templates)[:people]
  717 + end
  718 +
  719 + should 'not load enterprises templates in communities asset' do
  720 + t1 = fast_create(Enterprise, :is_template => true, :environment_id => environment.id)
  721 + t2 = fast_create(Enterprise, :is_template => true, :environment_id => environment.id)
  722 + get :communities
  723 + assert_nil assigns(:templates)[:enterprises]
  724 + end
  725 +
  726 + should 'templates variable be equals to enterprises templates in enterprises assert' do
  727 + t1 = fast_create(Enterprise, :is_template => true, :environment_id => environment.id)
  728 + t2 = fast_create(Enterprise, :is_template => true, :environment_id => environment.id)
  729 + get :enterprises
  730 +
  731 + assert_equivalent [t1,t2], assigns(:templates)[:enterprises]
  732 + end
  733 +
  734 + should 'not load communities templates in enterprises asset' do
  735 + t1 = fast_create(Community, :is_template => true, :environment_id => environment.id)
  736 + t2 = fast_create(Community, :is_template => true, :environment_id => environment.id)
  737 + get :enterprises
  738 + assert_nil assigns(:templates)[:communities]
  739 + end
  740 +
  741 + should 'not load people templates in enterprises asset' do
  742 + t1 = fast_create(Person, :is_template => true, :environment_id => environment.id)
  743 + t2 = fast_create(Person, :is_template => true, :environment_id => environment.id)
  744 + get :enterprises
  745 + assert_nil assigns(:templates)[:people]
  746 + end
  747 +
  748 + should 'list all community of on specific template' do
  749 + t1 = fast_create(Community, :is_template => true, :environment_id => environment.id)
  750 + t2 = fast_create(Community, :is_template => true, :environment_id => environment.id)
  751 + c1 = fast_create(Community, :template_id => t1.id, :name => 'Testing community 1', :created_at => DateTime.now - 2)
  752 + c2 = fast_create(Community, :template_id => t2.id, :name => 'Testing community 2', :created_at => DateTime.now - 1)
  753 + c3 = fast_create(Community, :template_id => t1.id, :name => 'Testing community 3')
  754 + c4 = fast_create(Community, :name => 'Testing community 3')
  755 +
  756 + get :communities, :template_id => t1.id
  757 + assert_equivalent [c1,c3] , assigns(:searches)[:communities][:results]
  758 + end
  759 +
  760 + should 'list all communities of no template is passed' do
  761 + t1 = fast_create(Community, :is_template => true, :environment_id => environment.id)
  762 + t2 = fast_create(Community, :is_template => true, :environment_id => environment.id)
  763 + c1 = create(Community, :template_id => t1.id, :name => 'Testing community 1', :created_at => DateTime.now - 2)
  764 + c2 = create(Community, :template_id => t2.id, :name => 'Testing community 2', :created_at => DateTime.now - 1)
  765 + c3 = create(Community, :template_id => t1.id, :name => 'Testing community 3')
  766 + c4 = create(Community, :name => 'Testing community 3')
  767 +
  768 + get :communities, :template_id => nil
  769 + assert_equivalent [t1,t2,c1,c2,c3,c4] , assigns(:searches)[:communities][:results]
  770 + end
  771 +
654 protected 772 protected
655 773
656 def create_event(profile, options) 774 def create_event(profile, options)
test/unit/application_helper_test.rb
@@ -463,13 +463,13 @@ class ApplicationHelperTest &lt; ActionView::TestCase @@ -463,13 +463,13 @@ class ApplicationHelperTest &lt; ActionView::TestCase
463 463
464 should 'base theme uses default icon theme' do 464 should 'base theme uses default icon theme' do
465 stubs(:current_theme).returns('base') 465 stubs(:current_theme).returns('base')
466 - assert_equal "/designs/icons/default/style.css", icon_theme_stylesheet_path.first 466 + assert_equal "designs/icons/default/style.css", icon_theme_stylesheet_path.first
467 end 467 end
468 468
469 should 'base theme uses config to specify more then an icon theme' do 469 should 'base theme uses config to specify more then an icon theme' do
470 stubs(:current_theme).returns('base') 470 stubs(:current_theme).returns('base')
471 - assert_includes icon_theme_stylesheet_path, "/designs/icons/default/style.css"  
472 - assert_includes icon_theme_stylesheet_path, "/designs/icons/pidgin/style.css" 471 + assert_includes icon_theme_stylesheet_path, "designs/icons/default/style.css"
  472 + assert_includes icon_theme_stylesheet_path, "designs/icons/pidgin/style.css"
473 end 473 end
474 474
475 should 'not display active field if only required' do 475 should 'not display active field if only required' do
@@ -961,6 +961,47 @@ class ApplicationHelperTest &lt; ActionView::TestCase @@ -961,6 +961,47 @@ class ApplicationHelperTest &lt; ActionView::TestCase
961 assert_equal '', manage_communities 961 assert_equal '', manage_communities
962 end 962 end
963 963
  964 + should 'include file from current theme out of a profile page' do
  965 + def profile; nil; end
  966 + def environment; e={}; def e.theme; 'env-theme'; end; e; end
  967 + def render(opt); opt; end
  968 + File.stubs(:exists?).returns(false)
  969 + file = Rails.root.join 'public/designs/themes/env-theme/somefile.html.erb'
  970 + assert_nil theme_include('somefile') # exists? = false
  971 + File.expects(:exists?).with(file).returns(true).at_least_once
  972 + assert_equal file, theme_include('somefile')[:file] # exists? = true
  973 + end
  974 +
  975 + should 'include file from current theme inside a profile page' do
  976 + def profile; p={}; def p.theme; 'my-theme'; end; p; end
  977 + def render(opt); opt; end
  978 + File.stubs(:exists?).returns(false)
  979 + file = Rails.root.join 'public/designs/themes/my-theme/otherfile.html.erb'
  980 + assert_nil theme_include('otherfile') # exists? = false
  981 + File.expects(:exists?).with(file).returns(true).at_least_once
  982 + assert_equal file, theme_include('otherfile')[:file] # exists? = true
  983 + end
  984 +
  985 + should 'include file from env theme' do
  986 + def profile; p={}; def p.theme; 'my-theme'; end; p; end
  987 + def environment; e={}; def e.theme; 'env-theme'; end; e; end
  988 + def render(opt); opt; end
  989 + File.stubs(:exists?).returns(false)
  990 + file = Rails.root.join 'public/designs/themes/env-theme/afile.html.erb'
  991 + assert_nil env_theme_include('afile') # exists? = false
  992 + File.expects(:exists?).with(file).returns(true).at_least_once
  993 + assert_equal file, env_theme_include('afile')[:file] # exists? = true
  994 + end
  995 +
  996 + should 'include file from some theme' do
  997 + def render(opt); opt; end
  998 + File.stubs(:exists?).returns(false)
  999 + file = Rails.root.join 'public/designs/themes/atheme/afile.html.erb'
  1000 + assert_nil from_theme_include('atheme', 'afile') # exists? = false
  1001 + File.expects(:exists?).with(file).returns(true).at_least_once
  1002 + assert_equal file, from_theme_include('atheme', 'afile')[:file] # exists? = true
  1003 + end
  1004 +
964 protected 1005 protected
965 include NoosferoTestHelper 1006 include NoosferoTestHelper
966 1007
test/unit/community_test.rb
@@ -393,4 +393,30 @@ class CommunityTest &lt; ActiveSupport::TestCase @@ -393,4 +393,30 @@ class CommunityTest &lt; ActiveSupport::TestCase
393 assert_not_includes community.activities.map { |a| a.klass.constantize.find(a.id) }, article.activity 393 assert_not_includes community.activities.map { |a| a.klass.constantize.find(a.id) }, article.activity
394 end 394 end
395 395
  396 +
  397 + should 'check if a community admin user is really a community admin' do
  398 + c = fast_create(Community, :name => 'my test profile', :identifier => 'mytestprofile')
  399 + admin = create_user('adminuser').person
  400 + c.add_admin(admin)
  401 +
  402 + assert c.is_admin?(admin)
  403 + end
  404 +
  405 + should 'a member user not be a community admin' do
  406 + c = fast_create(Community, :name => 'my test profile', :identifier => 'mytestprofile')
  407 + admin = create_user('adminuser').person
  408 + c.add_admin(admin)
  409 +
  410 + member = create_user('memberuser').person
  411 + c.add_member(member)
  412 + assert !c.is_admin?(member)
  413 + end
  414 +
  415 + should 'a moderator user not be a community admin' do
  416 + c = fast_create(Community, :name => 'my test profile', :identifier => 'mytestprofile')
  417 + moderator = create_user('moderatoruser').person
  418 + c.add_moderator(moderator)
  419 + assert !c.is_admin?(moderator)
  420 + end
  421 +
396 end 422 end
test/unit/enterprise_test.rb
@@ -499,5 +499,30 @@ class EnterpriseTest &lt; ActiveSupport::TestCase @@ -499,5 +499,30 @@ class EnterpriseTest &lt; ActiveSupport::TestCase
499 assert_equal({:profile => enterprise.identifier, :controller => 'catalog'}, enterprise.catalog_url) 499 assert_equal({:profile => enterprise.identifier, :controller => 'catalog'}, enterprise.catalog_url)
500 end 500 end
501 501
  502 + should 'check if a community admin user is really a community admin' do
  503 + c = fast_create(Enterprise, :name => 'my test profile', :identifier => 'mytestprofile')
  504 + admin = create_user('adminuser').person
  505 + c.add_admin(admin)
  506 +
  507 + assert c.is_admin?(admin)
  508 + end
  509 +
  510 + should 'a member user not be a community admin' do
  511 + c = fast_create(Enterprise, :name => 'my test profile', :identifier => 'mytestprofile')
  512 + admin = create_user('adminuser').person
  513 + c.add_admin(admin)
  514 +
  515 + member = create_user('memberuser').person
  516 + c.add_member(member)
  517 + assert !c.is_admin?(member)
  518 + end
  519 +
  520 + should 'a moderator user not be a community admin' do
  521 + c = fast_create(Enterprise, :name => 'my test profile', :identifier => 'mytestprofile')
  522 + moderator = create_user('moderatoruser').person
  523 + c.add_moderator(moderator)
  524 + assert !c.is_admin?(moderator)
  525 + end
  526 +
502 527
503 end 528 end
test/unit/layout_helper_test.rb
1 require_relative "../test_helper" 1 require_relative "../test_helper"
2 2
3 class LayoutHelperTest < ActionView::TestCase 3 class LayoutHelperTest < ActionView::TestCase
  4 + include ApplicationHelper
4 5
5 should 'append logged-in class in body when user is logged-in' do 6 should 'append logged-in class in body when user is logged-in' do
6 expects(:logged_in?).returns(true) 7 expects(:logged_in?).returns(true)
@@ -14,4 +15,19 @@ class LayoutHelperTest &lt; ActionView::TestCase @@ -14,4 +15,19 @@ class LayoutHelperTest &lt; ActionView::TestCase
14 assert_not_includes body_classes.split, 'logged-in' 15 assert_not_includes body_classes.split, 'logged-in'
15 end 16 end
16 17
  18 + should 'add global.css to noosfero_stylesheets if env theme has it' do
  19 + env = fast_create Environment
  20 + env.theme = 'my-theme'
  21 + @plugins = []
  22 + expects(:profile).returns(nil).at_least_once
  23 + expects(:environment).returns(env).at_least_once
  24 + expects(:theme_option).with(:icon_theme).returns(['my-icons']).at_least_once
  25 + expects(:jquery_theme).returns('jquery-nice').at_least_once
  26 + global_css = Rails.root.join "public/designs/themes/#{env.theme}/global.css"
  27 + File.stubs(:exists?).returns(false)
  28 + File.expects(:exists?).with(global_css).returns(true).at_least_once
  29 + css = noosfero_stylesheets
  30 + assert_match /<link [^<]*href="\/designs\/themes\/my-theme\/global.css"/, css
  31 + end
  32 +
17 end 33 end
test/unit/organization_test.rb
@@ -452,4 +452,29 @@ class OrganizationTest &lt; ActiveSupport::TestCase @@ -452,4 +452,29 @@ class OrganizationTest &lt; ActiveSupport::TestCase
452 end 452 end
453 end 453 end
454 454
  455 + should 'check if a community admin user is really a community admin' do
  456 + c = fast_create(Organization, :name => 'my test profile', :identifier => 'mytestprofile')
  457 + admin = create_user('adminuser').person
  458 + c.add_admin(admin)
  459 +
  460 + assert c.is_admin?(admin)
  461 + end
  462 +
  463 + should 'a member user not be a community admin' do
  464 + c = fast_create(Organization, :name => 'my test profile', :identifier => 'mytestprofile')
  465 + admin = create_user('adminuser').person
  466 + c.add_admin(admin)
  467 +
  468 + member = create_user('memberuser').person
  469 + c.add_member(member)
  470 + assert !c.is_admin?(member)
  471 + end
  472 +
  473 + should 'a moderator user not be a community admin' do
  474 + c = fast_create(Organization, :name => 'my test profile', :identifier => 'mytestprofile')
  475 + moderator = create_user('moderatoruser').person
  476 + c.add_moderator(moderator)
  477 + assert !c.is_admin?(moderator)
  478 + end
  479 +
455 end 480 end
test/unit/plugin_test.rb
@@ -560,4 +560,11 @@ class PluginTest &lt; ActiveSupport::TestCase @@ -560,4 +560,11 @@ class PluginTest &lt; ActiveSupport::TestCase
560 assert_equivalent [st4.term, st2.term], limited_suggestions 560 assert_equivalent [st4.term, st2.term], limited_suggestions
561 end 561 end
562 562
  563 + should 'article_extra_toolbar_buttons return an empty array by default' do
  564 + class Plugin1 < Noosfero::Plugin
  565 + end
  566 + p = Plugin1.new
  567 + assert_equal [], p.article_extra_toolbar_buttons(nil)
  568 + end
  569 +
563 end 570 end
test/unit/plugins_helper_test.rb 0 → 100644
@@ -0,0 +1,47 @@ @@ -0,0 +1,47 @@
  1 +require_relative "../test_helper"
  2 +
  3 +class PluginsHelperTest < ActionView::TestCase
  4 +
  5 + def setup
  6 + @environment = Environment.default
  7 + @plugins = mock
  8 + end
  9 +
  10 + attr_accessor :environment, :plugins
  11 +
  12 + should 'plugins_toolbar_actions_for_article return an array if the plugin return a single hash' do
  13 + hash = {:title => 'some title', :url => 'some_url', :icon => 'some icon'}
  14 + plugins.expects(:dispatch).with(:article_extra_toolbar_buttons, nil).returns(hash)
  15 + assert_equal [hash], plugins_toolbar_actions_for_article(nil)
  16 + end
  17 +
  18 + should 'plugins_toolbar_actions_for_article return an empty array if an array is passed as parameter' do
  19 + plugins.expects(:dispatch).with(:article_extra_toolbar_buttons, nil).returns([])
  20 + assert_equal [], plugins_toolbar_actions_for_article(nil)
  21 + end
  22 +
  23 + should 'plugins_toolbar_actions_for_article throw raise if no title is passed as parameter' do
  24 + plugins.expects(:dispatch).with(:article_extra_toolbar_buttons, nil).returns({:url => 'some_url', :icon => 'some icon'})
  25 +
  26 + assert_raise(RuntimeError) do
  27 + plugins_toolbar_actions_for_article(nil)
  28 + end
  29 + end
  30 +
  31 + should 'plugins_toolbar_actions_for_article throw raise if no icon is passed as parameter' do
  32 + plugins.expects(:dispatch).with(:article_extra_toolbar_buttons, nil).returns({:title => 'some title', :url => 'some_url'})
  33 +
  34 + assert_raise(RuntimeError) do
  35 + plugins_toolbar_actions_for_article(nil)
  36 + end
  37 + end
  38 +
  39 + should 'plugins_toolbar_actions_for_article throw raise if no url is passed as parameter' do
  40 + plugins.expects(:dispatch).with(:article_extra_toolbar_buttons, nil).returns({:title => 'some title', :icon => 'some icon'})
  41 +
  42 + assert_raise(RuntimeError) do
  43 + plugins_toolbar_actions_for_article(nil)
  44 + end
  45 + end
  46 +
  47 +end
test/unit/profile_test.rb
@@ -1416,6 +1416,71 @@ class ProfileTest &lt; ActiveSupport::TestCase @@ -1416,6 +1416,71 @@ class ProfileTest &lt; ActiveSupport::TestCase
1416 assert_not_includes environment.profiles.templates, profile 1416 assert_not_includes environment.profiles.templates, profile
1417 end 1417 end
1418 1418
  1419 + should 'return an specific template when specified' do
  1420 + environment = Environment.default
  1421 + t1 = fast_create(Profile, :is_template => true)
  1422 + t2 = fast_create(Profile, :is_template => true)
  1423 + profile = fast_create(Profile)
  1424 +
  1425 + assert_equal [t1], environment.profiles.templates(t1)
  1426 + assert_equal [t2], environment.profiles.templates(t2)
  1427 + end
  1428 +
  1429 + should 'not return a template when and invalid template is specified' do
  1430 + environment = Environment.default
  1431 + t1 = fast_create(Profile, :is_template => true)
  1432 + t2 = fast_create(Profile, :is_template => true)
  1433 + t3 = fast_create(Profile)
  1434 +
  1435 + assert_equal [], environment.profiles.templates(t3)
  1436 + end
  1437 +
  1438 + should 'return profiles of specified template passing object' do
  1439 + environment = Environment.default
  1440 + t1 = fast_create(Profile, :is_template => true)
  1441 + t2 = fast_create(Profile, :is_template => true)
  1442 + p1 = fast_create(Profile, :template_id => t1.id)
  1443 + p2 = fast_create(Profile, :template_id => t2.id)
  1444 + p3 = fast_create(Profile, :template_id => t1.id)
  1445 +
  1446 + assert_equivalent [p1,p3], environment.profiles.with_templates(t1)
  1447 + end
  1448 +
  1449 + should 'return profiles of specified template passing id' do
  1450 + environment = Environment.default
  1451 + t1 = fast_create(Profile, :is_template => true)
  1452 + t2 = fast_create(Profile, :is_template => true)
  1453 + p1 = fast_create(Profile, :template_id => t1.id)
  1454 + p2 = fast_create(Profile, :template_id => t2.id)
  1455 + p3 = fast_create(Profile, :template_id => t1.id)
  1456 +
  1457 + assert_equivalent [p1,p3], environment.profiles.with_templates(t1.id)
  1458 + end
  1459 +
  1460 + should 'return profiles of a list of specified templates' do
  1461 + environment = Environment.default
  1462 + t1 = fast_create(Profile, :is_template => true)
  1463 + t2 = fast_create(Profile, :is_template => true)
  1464 + t3 = fast_create(Profile, :is_template => true)
  1465 + p1 = fast_create(Profile, :template_id => t1.id)
  1466 + p2 = fast_create(Profile, :template_id => t2.id)
  1467 + p3 = fast_create(Profile, :template_id => t3.id)
  1468 +
  1469 + assert_equivalent [p1,p2], environment.profiles.with_templates([t1,t2])
  1470 + end
  1471 +
  1472 + should 'return all profiles without any template if nil is passed as parameter' do
  1473 + environment = Environment.default
  1474 + Profile.delete_all
  1475 + t1 = fast_create(Profile, :is_template => true)
  1476 + t2 = fast_create(Profile, :is_template => true)
  1477 + p1 = fast_create(Profile, :template_id => t1.id)
  1478 + p2 = fast_create(Profile, :template_id => t2.id)
  1479 + p3 = fast_create(Profile)
  1480 +
  1481 + assert_equivalent [t1,t2,p3], environment.profiles.with_templates(nil)
  1482 + end
  1483 +
1419 should 'return a list of profiles that are not templates' do 1484 should 'return a list of profiles that are not templates' do
1420 environment = Environment.default 1485 environment = Environment.default
1421 p1 = fast_create(Profile, :is_template => false) 1486 p1 = fast_create(Profile, :is_template => false)
test/unit/search_helper_test.rb
@@ -3,6 +3,9 @@ require_relative &quot;../test_helper&quot; @@ -3,6 +3,9 @@ require_relative &quot;../test_helper&quot;
3 class SearchHelperTest < ActiveSupport::TestCase 3 class SearchHelperTest < ActiveSupport::TestCase
4 4
5 include SearchHelper 5 include SearchHelper
  6 + include ActionView::Helpers::FormOptionsHelper
  7 + include ActionView::Helpers::FormTagHelper
  8 +
6 9
7 should 'return whether on a multiple search' do 10 should 'return whether on a multiple search' do
8 stubs(:params).returns({:action => 'index', :display => 'map'}) 11 stubs(:params).returns({:action => 'index', :display => 'map'})
@@ -122,4 +125,84 @@ class SearchHelperTest &lt; ActiveSupport::TestCase @@ -122,4 +125,84 @@ class SearchHelperTest &lt; ActiveSupport::TestCase
122 end 125 end
123 end 126 end
124 127
  128 + should 'return an empty string in assets_submenu for articles assets' do
  129 + @templates = {}
  130 + assert_equal '', assets_submenu(:articles)
  131 + @templates = {:articles => nil}
  132 + assert_equal '', assets_submenu(:articles)
  133 + end
  134 +
  135 + should 'return an empty string in assets_submenu for people asset without template' do
  136 + @templates = {:people => nil}
  137 + assert_equal '', assets_submenu(:people)
  138 +
  139 + @templates = {:people => []}
  140 + assert_equal '', assets_submenu(:people)
  141 + end
  142 +
  143 + should 'return an empty string in assets_submenu for people asset with only one template' do
  144 + t = fast_create(Person, :is_template => true)
  145 + @templates = {:people => [t]}
  146 + assert_equal '', assets_submenu(:people)
  147 + end
  148 +
  149 + should 'return a select of templates for people asset with more then one template' do
  150 + t1 = fast_create(Person, :is_template => true)
  151 + t2 = fast_create(Person, :is_template => true)
  152 + @templates = {:people => [t1,t2]}
  153 + SearchHelperTest.any_instance.stubs(:params).returns({})
  154 + assert_match /select/, assets_submenu(:people)
  155 + assert_match /#{t1.name}/, assets_submenu(:people)
  156 + assert_match /#{t2.name}/, assets_submenu(:people)
  157 + end
  158 +
  159 + should 'return an empty string in assets_submenu for communities asset without template' do
  160 + @templates = {:communities => nil}
  161 + assert_equal '', assets_submenu(:communities)
  162 +
  163 + @templates = {:communities => []}
  164 + assert_equal '', assets_submenu(:communities)
  165 + end
  166 +
  167 + should 'return an empty string in assets_submenu for communities asset with only one template' do
  168 + t = fast_create(Community, :is_template => true)
  169 + @templates = {:communities => [t]}
  170 + assert_equal '', assets_submenu(:communities)
  171 + end
  172 +
  173 + should 'return a select of templates for communities asset with more then one template' do
  174 + t1 = fast_create(Community, :is_template => true)
  175 + t2 = fast_create(Community, :is_template => true)
  176 + @templates = {:communities => [t1,t2]}
  177 + SearchHelperTest.any_instance.stubs(:params).returns({})
  178 + assert_match /select/, assets_submenu(:communities)
  179 + assert_match /#{t1.name}/, assets_submenu(:communities)
  180 + assert_match /#{t2.name}/, assets_submenu(:communities)
  181 + end
  182 +
  183 + should 'return an empty string in assets_submenu for enterprises asset without template' do
  184 + @templates = {:enterprises => nil}
  185 + assert_equal '', assets_submenu(:enterprises)
  186 +
  187 + @templates = {:enterprises => []}
  188 + assert_equal '', assets_submenu(:enterprises)
  189 + end
  190 +
  191 + should 'return an empty string in assets_submenu for enterprises asset with only one template' do
  192 + t = fast_create(Enterprise, :is_template => true)
  193 + @templates = {:enterprises => [t]}
  194 + assert_equal '', assets_submenu(:enterprises)
  195 + end
  196 +
  197 + should 'return a select of templates for enterprises asset with more then one template' do
  198 + t1 = fast_create(Enterprise, :is_template => true)
  199 + t2 = fast_create(Enterprise, :is_template => true)
  200 + @templates = {:enterprises => [t1,t2]}
  201 + SearchHelperTest.any_instance.stubs(:params).returns({})
  202 + assert_match /select/, assets_submenu(:enterprises)
  203 + assert_match /#{t1.name}/, assets_submenu(:enterprises)
  204 + assert_match /#{t2.name}/, assets_submenu(:enterprises)
  205 + end
  206 +
  207 +
125 end 208 end