Commit 37c45c16031556e59fb59e4800933be3cd17f74e
Exists in
theme-brasil-digital-from-staging
and in
9 other branches
fix conflit with next
Showing
54 changed files
with
1004 additions
and
127 deletions
Show diff stats
Gemfile
... | ... | @@ -27,6 +27,11 @@ gem 'grape-swagger' |
27 | 27 | # FIXME list here all actual dependencies (i.e. the ones in debian/control), |
28 | 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 | 35 | group :production do |
31 | 36 | gem 'dalli', '~> 2.7.0' |
32 | 37 | end | ... | ... |
... | ... | @@ -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/controllers/application_controller.rb
... | ... | @@ -179,6 +179,7 @@ class ApplicationController < ActionController::Base |
179 | 179 | include SearchTermHelper |
180 | 180 | |
181 | 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 | 183 | search = plugins.dispatch_first(:find_by_contents, asset, scope, query, paginate_options, options) |
183 | 184 | register_search_term(query, scope.count, search[:results].count, context, asset) |
184 | 185 | search | ... | ... |
app/controllers/public/search_controller.rb
... | ... | @@ -9,6 +9,7 @@ class SearchController < PublicController |
9 | 9 | before_filter :load_search_assets, :except => :suggestions |
10 | 10 | before_filter :load_query, :except => :suggestions |
11 | 11 | before_filter :load_order, :except => :suggestions |
12 | + before_filter :load_templates, :except => :suggestions | |
12 | 13 | |
13 | 14 | # Backwards compatibility with old URLs |
14 | 15 | def redirect_asset_param |
... | ... | @@ -210,6 +211,11 @@ class SearchController < PublicController |
210 | 211 | end |
211 | 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 | 219 | def limit |
214 | 220 | if map_search?(@searches) |
215 | 221 | MAP_SEARCH_LIMIT |
... | ... | @@ -230,7 +236,7 @@ class SearchController < PublicController |
230 | 236 | end |
231 | 237 | |
232 | 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 | 240 | end |
235 | 241 | |
236 | 242 | private | ... | ... |
app/helpers/application_helper.rb
... | ... | @@ -212,6 +212,7 @@ module ApplicationHelper |
212 | 212 | end |
213 | 213 | |
214 | 214 | def button(type, label, url, html_options = {}) |
215 | + html_options ||= {} | |
215 | 216 | the_class = 'with-text' |
216 | 217 | if html_options.has_key?(:class) |
217 | 218 | the_class << ' ' << html_options[:class] |
... | ... | @@ -398,19 +399,27 @@ module ApplicationHelper |
398 | 399 | end |
399 | 400 | end |
400 | 401 | |
401 | - def theme_view_file(template) | |
402 | + def theme_view_file(template, theme=nil) | |
402 | 403 | # Since we cannot control what people are doing in external themes, we |
403 | 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 | 407 | return file if File.exists?(file) |
406 | 408 | nil |
407 | 409 | end |
408 | 410 | |
409 | 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 | 421 | if file |
413 | - render options | |
422 | + render options.merge(file: file, use_full_path: false) | |
414 | 423 | else |
415 | 424 | nil |
416 | 425 | end |
... | ... | @@ -446,6 +455,14 @@ module ApplicationHelper |
446 | 455 | @theme_extra_navigation ||= theme_include 'navigation' |
447 | 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 | 466 | def is_testing_theme |
450 | 467 | !controller.session[:theme].nil? |
451 | 468 | end |
... | ... | @@ -902,18 +919,6 @@ module ApplicationHelper |
902 | 919 | end |
903 | 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 | 922 | def page_title |
918 | 923 | CGI.escapeHTML( |
919 | 924 | (@page ? @page.title + ' - ' : '') + | ... | ... |
app/helpers/layout_helper.rb
... | ... | @@ -28,12 +28,12 @@ module LayoutHelper |
28 | 28 | end |
29 | 29 | |
30 | 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 | 33 | output = '' |
34 | 34 | output += render 'layouts/javascript' |
35 | 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 | 37 | end |
38 | 38 | output += theme_javascript_ng.to_s |
39 | 39 | output += javascript_tag 'render_all_jquery_ui_widgets()' |
... | ... | @@ -42,35 +42,27 @@ module LayoutHelper |
42 | 42 | end |
43 | 43 | |
44 | 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 | 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 | 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 | 66 | end |
75 | 67 | |
76 | 68 | def noosfero_layout_features |
... | ... | @@ -90,7 +82,7 @@ module LayoutHelper |
90 | 82 | icon_themes = [] |
91 | 83 | theme_icon_themes = theme_option(:icon_theme) || [] |
92 | 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 | 86 | if File.exists?(Rails.root.join('public', theme_path)) |
95 | 87 | icon_themes << theme_path |
96 | 88 | end |
... | ... | @@ -103,7 +95,7 @@ module LayoutHelper |
103 | 95 | end |
104 | 96 | |
105 | 97 | def theme_stylesheet_path |
106 | - theme_path + '/style.css' | |
98 | + "/assets#{theme_path}/style.css" | |
107 | 99 | end |
108 | 100 | |
109 | 101 | def layout_template | ... | ... |
app/helpers/macros_helper.rb
... | ... | @@ -42,7 +42,9 @@ module MacrosHelper |
42 | 42 | [macro.configuration[:js_files]].flatten.map { |js| plugins_javascripts << macro.plugin.public_path(js) } |
43 | 43 | end |
44 | 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 | 48 | end |
47 | 49 | |
48 | 50 | def macro_css_files | ... | ... |
app/helpers/plugins_helper.rb
... | ... | @@ -6,4 +6,11 @@ module PluginsHelper |
6 | 6 | end |
7 | 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 | 16 | end | ... | ... |
app/helpers/search_helper.rb
... | ... | @@ -148,4 +148,11 @@ module SearchHelper |
148 | 148 | link_to(@enabled_searches[asset], "/search/#{asset}") |
149 | 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 | 158 | end | ... | ... |
app/models/comment.rb
app/models/organization.rb
... | ... | @@ -188,4 +188,9 @@ class Organization < Profile |
188 | 188 | def allow_invitation_from?(person) |
189 | 189 | (followed_by?(person) && self.allow_members_to_invite) || person.has_permission?('invite-members', self) |
190 | 190 | end |
191 | + | |
192 | + def is_admin?(user) | |
193 | + self.admins.where(:id => user.id).exists? | |
194 | + end | |
195 | + | |
191 | 196 | end | ... | ... |
app/models/profile.rb
... | ... | @@ -85,7 +85,15 @@ class Profile < ActiveRecord::Base |
85 | 85 | #FIXME: these will work only if the subclass is already loaded |
86 | 86 | scope :enterprises, lambda { {:conditions => (Enterprise.send(:subclasses).map(&:name) << 'Enterprise').map { |klass| "profiles.type = '#{klass}'"}.join(" OR ")} } |
87 | 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 | 97 | scope :no_templates, {:conditions => {:is_template => false}} |
90 | 98 | |
91 | 99 | #FIXME make this test | ... | ... |
app/views/content_viewer/_article_toolbar.html.erb
... | ... | @@ -46,6 +46,10 @@ |
46 | 46 | <%= button(:clock, _('All versions'), {:controller => 'content_viewer', :profile => profile.identifier, :action => 'article_versions'}, :id => 'article-versions-link') %> |
47 | 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 | 53 | <%= report_abuse(profile, :link, @page) %> |
50 | 54 | |
51 | 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 | 3 | <% language = FastGettext.locale %> |
12 | 4 | <% %w{messages methods}.each do |type| %> | ... | ... |
app/views/layouts/application-ng.html.erb
... | ... | @@ -25,7 +25,7 @@ |
25 | 25 | end.join("\n") |
26 | 26 | %> |
27 | 27 | |
28 | - <script type='text/javascript'> | |
28 | + <script type="text/javascript"> | |
29 | 29 | DEFAULT_LOADING_MESSAGE = <%="'#{ _('loading...') }'" %>; |
30 | 30 | </script> |
31 | 31 | |
... | ... | @@ -38,9 +38,12 @@ |
38 | 38 | if content.respond_to?(:call) then instance_exec(&content).to_s.html_safe else content.to_s.html_safe end |
39 | 39 | end.join("\n") |
40 | 40 | %> |
41 | + <div id="global-header"> | |
42 | + <%= global_header %> | |
43 | + </div> | |
41 | 44 | |
42 | 45 | <div id="wrap-1"> |
43 | - <div id='theme-header'> | |
46 | + <div id="theme-header"> | |
44 | 47 | <%= theme_header %> |
45 | 48 | </div> |
46 | 49 | <div id="wrap-2"> |
... | ... | @@ -60,9 +63,14 @@ |
60 | 63 | </div><!-- end id="wrap-2" --> |
61 | 64 | </div><!-- end id="wrap-1" --> |
62 | 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 | 74 | <%= noosfero_layout_features %> |
67 | 75 | <%= addthis_javascript %> |
68 | 76 | <%= | ... | ... |
app/views/layouts/application.html.erb
... | ... | @@ -21,7 +21,7 @@ |
21 | 21 | import_controller_stylesheets(:themed_source => true) |
22 | 22 | %> |
23 | 23 | <%= stylesheet_link_tag template_stylesheet_path %> |
24 | - <%= stylesheet_link_tag icon_theme_stylesheet_path %> | |
24 | + <%= stylesheet_link_tag *icon_theme_stylesheet_path %> | |
25 | 25 | <%= stylesheet_link_tag jquery_ui_theme_stylesheet_path %> |
26 | 26 | |
27 | 27 | <%# Add custom tags/styles/etc via content_for %> |
... | ... | @@ -52,6 +52,9 @@ |
52 | 52 | registerDocumentSize(); |
53 | 53 | // --> |
54 | 54 | </script> |
55 | + <div id="global-header"> | |
56 | + <%= global_header %> | |
57 | + </div> | |
55 | 58 | |
56 | 59 | <div id="accessibility_menu"> |
57 | 60 | <a href="#content" id="link_go_content"><span><%= _('Go to content') %></span></a> |
... | ... | @@ -112,8 +115,13 @@ |
112 | 115 | </div><!-- id="wrap" --> |
113 | 116 | |
114 | 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 | 126 | <%# if you need to add HTML stuff to the layout, include it in |
119 | 127 | app/views/shared/noosfero_layout_features.html.erb! %> | ... | ... |
app/views/layouts/slideshow.html.erb
... | ... | @@ -11,7 +11,7 @@ |
11 | 11 | %></title> |
12 | 12 | |
13 | 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 | 15 | <script type="text/javascript"> |
16 | 16 | $(document).ready(function (){ |
17 | 17 | $("#slideshow").PikaChoose({ | ... | ... |
app/views/search/_search_content.html.erb
1 | 1 | <div id='search-content'> |
2 | + <div class='total'> | |
3 | + <%= _('Total of %s results ') % @searches[@asset][:results].total_entries.inspect %> | |
4 | + </div> | |
5 | + | |
2 | 6 | <%= display_results(@searches, @asset) %> |
3 | 7 | <% if params[:display] != 'map' %> |
4 | 8 | <%= pagination_links @searches[@asset][:results] %> | ... | ... |
app/views/search/_search_form.html.erb
... | ... | @@ -5,8 +5,12 @@ |
5 | 5 | <div id='search-header'> |
6 | 6 | <%= assets_menu(@asset) %> |
7 | 7 | <%= filters(@asset) %> |
8 | + <div class="clear"></div> | |
8 | 9 | </div> |
9 | 10 | |
11 | + <div id='search-subheader'> | |
12 | + <%= assets_submenu(@asset) %> | |
13 | + </div> | |
10 | 14 | <div class="search-field"> |
11 | 15 | <span class="formfield"> |
12 | 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 | 88 | config.active_record.whitelist_attributes = true |
89 | 89 | |
90 | 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 | 103 | # Version of your assets, change this if you want to expire all your assets |
94 | 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 | 110 | def noosfero_session_secret |
97 | 111 | require 'fileutils' |
98 | 112 | target_dir = File.join(File.dirname(__FILE__), '../tmp') | ... | ... |
config/environments/production.rb
... | ... | @@ -14,12 +14,15 @@ Noosfero::Application.configure do |
14 | 14 | # Compress JavaScripts and CSS |
15 | 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 | 17 | # Generate digests for assets URLs |
21 | 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 | 26 | # Defaults to nil and saved in location specified by config.assets.prefix |
24 | 27 | # config.assets.manifest = YOUR_PATH |
25 | 28 | ... | ... |
config/routes.rb
... | ... | @@ -52,7 +52,6 @@ Noosfero::Application.routes.draw do |
52 | 52 | |
53 | 53 | # categories index |
54 | 54 | match 'cat/*category_path' => 'search#category_index', :as => :category |
55 | - match 'assets/:asset(/*category_path)' => 'search#assets', :as => :assets | |
56 | 55 | # search |
57 | 56 | match 'search(/:action(/*category_path))', :controller => 'search' |
58 | 57 | ... | ... |
db/schema.rb
... | ... | @@ -11,7 +11,7 @@ |
11 | 11 | # |
12 | 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 | 16 | create_table "abuse_reports", :force => true do |t| |
17 | 17 | t.integer "reporter_id" |
... | ... | @@ -263,6 +263,7 @@ ActiveRecord::Schema.define(:version => 20150223180807) do |
263 | 263 | t.string "source_type" |
264 | 264 | t.string "user_agent" |
265 | 265 | t.string "referrer" |
266 | + t.text "settings" | |
266 | 267 | end |
267 | 268 | |
268 | 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 | 22 | public/designs/themes/default |
23 | 23 | public/designs/themes/* |
24 | 24 | public/designs/icons/default |
25 | + | |
26 | +public/assets | |
27 | +.sass-cache | |
25 | 28 | public/javascripts/cache* |
26 | 29 | public/stylesheets/cache* |
30 | + | |
27 | 31 | public/plugins |
28 | 32 | db/development.db |
29 | 33 | db/production.db | ... | ... |
lib/noosfero/plugin.rb
... | ... | @@ -150,8 +150,8 @@ class Noosfero::Plugin |
150 | 150 | self.name.underscore.gsub('_plugin','') |
151 | 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 | 155 | end |
156 | 156 | |
157 | 157 | def root_path |
... | ... | @@ -430,6 +430,19 @@ class Noosfero::Plugin |
430 | 430 | [] |
431 | 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 | 446 | # -> Adds adicional content to article |
434 | 447 | # returns = lambda block that creates html code |
435 | 448 | def article_extra_contents(article) |
... | ... | @@ -678,6 +691,8 @@ class Noosfero::Plugin |
678 | 691 | # returns = string with reason of expiration |
679 | 692 | elsif method.to_s =~ /^content_expire_(#{content_actions.join('|')})$/ |
680 | 693 | nil |
694 | + elsif context.respond_to?(method) | |
695 | + context.send(method) | |
681 | 696 | else |
682 | 697 | super |
683 | 698 | end | ... | ... |
plugins/pg_search/test/functional/search_controller_test.rb
0 → 100644
... | ... | @@ -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 | 8 | themes: {}, |
9 | 9 | |
10 | 10 | load: function() { |
11 | - var target = jQuery('#content'); | |
11 | + var target = jQuery('#wrap-1'); | |
12 | 12 | var content = jQuery('#content-inner'); |
13 | 13 | var loadingTarget = jQuery('#content'); |
14 | 14 | |
... | ... | @@ -52,7 +52,7 @@ pjax = { |
52 | 52 | from_state = this.current_state || this.initial_state; |
53 | 53 | |
54 | 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 | 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 | 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 | 82 | css.attr('href', css.attr('href').replace(/themes\/.+\/style/, 'themes/'+state.theme.id+'/style')); |
83 | 83 | |
84 | 84 | jQuery('head link[rel="shortcut icon"]').attr('href', state.theme.favicon); |
... | ... | @@ -88,7 +88,7 @@ pjax = { |
88 | 88 | jQuery('#navigation ul').html(state.theme.extra_navigation); |
89 | 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 | 92 | if (state.theme.js_src) { |
93 | 93 | var script = document.createElement('script'); |
94 | 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 | 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 | 8 | render "layouts/content" %> |
9 | 9 | |
10 | 10 | <%= javascript_tag do %> | ... | ... |
public/javascripts/application.js
1 | 1 | // Place your application-specific JavaScript functions and classes here |
2 | 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 | 32 | // scope for noosfero stuff |
5 | 33 | noosfero = { | ... | ... |
public/javascripts/codepress/languages/asp.css
... | ... | @@ -6,7 +6,7 @@ |
6 | 6 | |
7 | 7 | b { |
8 | 8 | color:#000080; |
9 | -} | |
9 | +} | |
10 | 10 | /* comments */ |
11 | 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 | 12 | color:gray; |
... | ... | @@ -17,12 +17,12 @@ strong dfn, strong dfn a,strong dfn var, strong dfn a u, strong dfn u{ |
17 | 17 | color:gray; |
18 | 18 | font-weight:normal; |
19 | 19 | } |
20 | - /* attributes */ | |
20 | + /* attributes */ | |
21 | 21 | s, s b, span s u, span s cite, strong span s { |
22 | 22 | color:#5656fa ; |
23 | 23 | font-weight:normal; |
24 | 24 | } |
25 | - /* strings */ | |
25 | + /* strings */ | |
26 | 26 | strong s,strong s b, strong s u, strong s cite { |
27 | 27 | color:#009900; |
28 | 28 | font-weight:normal; |
... | ... | @@ -34,7 +34,6 @@ strong ins{ |
34 | 34 | /* Syntax */ |
35 | 35 | strong a, strong a u { |
36 | 36 | color:#0000FF; |
37 | - font-weight:; | |
38 | 37 | } |
39 | 38 | /* Native Keywords */ |
40 | 39 | strong u { |
... | ... | @@ -58,7 +57,7 @@ em { |
58 | 57 | color:#800080; |
59 | 58 | font-style:normal; |
60 | 59 | } |
61 | - /* script */ | |
60 | + /* script */ | |
62 | 61 | ins { |
63 | 62 | color:#800000; |
64 | 63 | font-weight:bold; |
... | ... | @@ -68,4 +67,4 @@ ins { |
68 | 67 | cite, s cite { |
69 | 68 | color:red; |
70 | 69 | font-weight:bold; |
71 | -} | |
72 | 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 | 3 | * By Martin D. Kirk |
4 | 4 | */ |
5 | 5 | |
6 | 6 | /* tags */ |
7 | 7 | b { |
8 | 8 | color:#000080; |
9 | -} | |
9 | +} | |
10 | 10 | /* comments */ |
11 | 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 | 12 | color:gray; |
... | ... | @@ -17,12 +17,12 @@ strong dfn, strong dfn a,strong dfn var, strong dfn a u, strong dfn u{ |
17 | 17 | color:gray; |
18 | 18 | font-weight:normal; |
19 | 19 | } |
20 | - /* attributes */ | |
20 | + /* attributes */ | |
21 | 21 | s, s b, span s u, span s cite, strong span s { |
22 | 22 | color:#5656fa ; |
23 | 23 | font-weight:normal; |
24 | 24 | } |
25 | - /* strings */ | |
25 | + /* strings */ | |
26 | 26 | strong s,strong s b, strong s u, strong s cite { |
27 | 27 | color:#009900; |
28 | 28 | font-weight:normal; |
... | ... | @@ -34,7 +34,6 @@ strong ins{ |
34 | 34 | /* Syntax */ |
35 | 35 | strong a, strong a u { |
36 | 36 | color:#0000FF; |
37 | - font-weight:; | |
38 | 37 | } |
39 | 38 | /* Native Keywords */ |
40 | 39 | strong u { |
... | ... | @@ -58,7 +57,7 @@ em { |
58 | 57 | color:#800080; |
59 | 58 | font-style:normal; |
60 | 59 | } |
61 | - /* script */ | |
60 | + /* script */ | |
62 | 61 | ins { |
63 | 62 | color:#800000; |
64 | 63 | font-weight:bold; |
... | ... | @@ -68,4 +67,4 @@ ins { |
68 | 67 | cite, s cite { |
69 | 68 | color:red; |
70 | 69 | font-weight:bold; |
71 | -} | |
72 | 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
public/javascripts/search.js
... | ... | @@ -15,9 +15,17 @@ |
15 | 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 | 23 | // Custom styled select |
19 | 24 | $('#search-filters select').selectOrDie(); |
20 | 25 | |
26 | + // Custom styled select | |
27 | + $('#search-subheader select').selectOrDie(); | |
28 | + | |
21 | 29 | // Form Ajax submission |
22 | 30 | $('form.search_form').submit(function () { |
23 | 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 | 19 | /* browser fixes */ |
2 | 20 | |
3 | 21 | img:-moz-broken { |
... | ... | @@ -77,19 +95,6 @@ div#errorExplanation h2 { |
77 | 95 | #footer_content { |
78 | 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 | 98 | div#profile-disabled { |
94 | 99 | border: 2px solid #944; |
95 | 100 | text-align: center; |
... | ... | @@ -4427,7 +4432,8 @@ h1#agenda-title { |
4427 | 4432 | #groups-list li { |
4428 | 4433 | display: block; |
4429 | 4434 | list-style: none; |
4430 | - margin-bottom: 20px background-color: #B8CFE7; | |
4435 | + margin-bottom: 20px; | |
4436 | + background-color: #B8CFE7; | |
4431 | 4437 | } |
4432 | 4438 | |
4433 | 4439 | #groups-list li .vcard { |
... | ... | @@ -6932,8 +6938,8 @@ li.profile-activity-item.upload_image .activity-gallery-images-count-1 img { |
6932 | 6938 | } |
6933 | 6939 | |
6934 | 6940 | .fetching-overlay { |
6935 | - position: absolute; | |
6936 | - top: 0px; | |
6941 | + position: absolute; | |
6942 | + top: 0px; | |
6937 | 6943 | left: 0px; |
6938 | 6944 | right: 0px; |
6939 | 6945 | bottom: 0px; | ... | ... |
public/stylesheets/search.css
... | ... | @@ -563,7 +563,8 @@ li.search-product-item { |
563 | 563 | } |
564 | 564 | li.search-product-item { |
565 | 565 | display:block; |
566 | - float:none overflow:visible; | |
566 | + float:none; | |
567 | + overflow:visible; | |
567 | 568 | padding:10px 0; |
568 | 569 | margin:10px 0; |
569 | 570 | border-bottom:1px solid #ccc; |
... | ... | @@ -953,7 +954,7 @@ ul#assets-menu { |
953 | 954 | text-align: justify; |
954 | 955 | text-justify: distribute-all-lines; /* distribute items in IE */ |
955 | 956 | list-style-type: none; |
956 | - margin: 5px 0 13px; | |
957 | + margin: 5px 0px 10px 0px; | |
957 | 958 | padding: 0; |
958 | 959 | width: 500px; |
959 | 960 | float: left; |
... | ... | @@ -984,6 +985,15 @@ ul#assets-menu li.selected a { |
984 | 985 | color: #EF2929; |
985 | 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 | 998 | #search-filters { |
989 | 999 | float: right; |
... | ... | @@ -1037,3 +1047,13 @@ ul#assets-menu li.selected a { |
1037 | 1047 | border-bottom:1px solid #ccc; |
1038 | 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 | +} | ... | ... |
... | ... | @@ -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 < ActionController::TestCase |
1436 | 1436 | |
1437 | 1437 | assert_no_tag :tag => 'h1', :attributes => { :class => /title/ }, :content => article.name |
1438 | 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 | 1534 | end | ... | ... |
test/functional/search_controller_test.rb
... | ... | @@ -13,14 +13,14 @@ class SearchControllerTest < ActionController::TestCase |
13 | 13 | @request.stubs(:ssl?).returns(false) |
14 | 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 | 20 | if !domain |
21 | 21 | domain = Domain.create!(:name => "127.0.0.1") |
22 | - env.domains = [domain] | |
23 | - env.save! | |
22 | + @environment.domains = [domain] | |
23 | + @environment.save! | |
24 | 24 | end |
25 | 25 | domain.google_maps_key = 'ENVIRONMENT_KEY' |
26 | 26 | domain.save! |
... | ... | @@ -37,6 +37,8 @@ class SearchControllerTest < ActionController::TestCase |
37 | 37 | Person.any_instance.stubs(:user).returns(user) |
38 | 38 | end |
39 | 39 | |
40 | + attr_reader :environment | |
41 | + | |
40 | 42 | def create_article_with_optional_category(name, profile, category = nil) |
41 | 43 | fast_create(Article, {:name => name, :profile_id => profile.id }, :search => true, :category => category) |
42 | 44 | end |
... | ... | @@ -651,6 +653,122 @@ class SearchControllerTest < ActionController::TestCase |
651 | 653 | assert_equal [st1,st2].to_json, response.body |
652 | 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 | 772 | protected |
655 | 773 | |
656 | 774 | def create_event(profile, options) | ... | ... |
test/unit/application_helper_test.rb
... | ... | @@ -463,13 +463,13 @@ class ApplicationHelperTest < ActionView::TestCase |
463 | 463 | |
464 | 464 | should 'base theme uses default icon theme' do |
465 | 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 | 467 | end |
468 | 468 | |
469 | 469 | should 'base theme uses config to specify more then an icon theme' do |
470 | 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 | 473 | end |
474 | 474 | |
475 | 475 | should 'not display active field if only required' do |
... | ... | @@ -961,6 +961,47 @@ class ApplicationHelperTest < ActionView::TestCase |
961 | 961 | assert_equal '', manage_communities |
962 | 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 | 1005 | protected |
965 | 1006 | include NoosferoTestHelper |
966 | 1007 | ... | ... |
test/unit/community_test.rb
... | ... | @@ -393,4 +393,30 @@ class CommunityTest < ActiveSupport::TestCase |
393 | 393 | assert_not_includes community.activities.map { |a| a.klass.constantize.find(a.id) }, article.activity |
394 | 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 | 422 | end | ... | ... |
test/unit/enterprise_test.rb
... | ... | @@ -499,5 +499,30 @@ class EnterpriseTest < ActiveSupport::TestCase |
499 | 499 | assert_equal({:profile => enterprise.identifier, :controller => 'catalog'}, enterprise.catalog_url) |
500 | 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 | 528 | end | ... | ... |
test/unit/layout_helper_test.rb
1 | 1 | require_relative "../test_helper" |
2 | 2 | |
3 | 3 | class LayoutHelperTest < ActionView::TestCase |
4 | + include ApplicationHelper | |
4 | 5 | |
5 | 6 | should 'append logged-in class in body when user is logged-in' do |
6 | 7 | expects(:logged_in?).returns(true) |
... | ... | @@ -14,4 +15,19 @@ class LayoutHelperTest < ActionView::TestCase |
14 | 15 | assert_not_includes body_classes.split, 'logged-in' |
15 | 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 | 33 | end | ... | ... |
test/unit/organization_test.rb
... | ... | @@ -452,4 +452,29 @@ class OrganizationTest < ActiveSupport::TestCase |
452 | 452 | end |
453 | 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 | 480 | end | ... | ... |
test/unit/plugin_test.rb
... | ... | @@ -560,4 +560,11 @@ class PluginTest < ActiveSupport::TestCase |
560 | 560 | assert_equivalent [st4.term, st2.term], limited_suggestions |
561 | 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 | 570 | end | ... | ... |
... | ... | @@ -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 < ActiveSupport::TestCase |
1416 | 1416 | assert_not_includes environment.profiles.templates, profile |
1417 | 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 | 1484 | should 'return a list of profiles that are not templates' do |
1420 | 1485 | environment = Environment.default |
1421 | 1486 | p1 = fast_create(Profile, :is_template => false) | ... | ... |
test/unit/search_helper_test.rb
... | ... | @@ -3,6 +3,9 @@ require_relative "../test_helper" |
3 | 3 | class SearchHelperTest < ActiveSupport::TestCase |
4 | 4 | |
5 | 5 | include SearchHelper |
6 | + include ActionView::Helpers::FormOptionsHelper | |
7 | + include ActionView::Helpers::FormTagHelper | |
8 | + | |
6 | 9 | |
7 | 10 | should 'return whether on a multiple search' do |
8 | 11 | stubs(:params).returns({:action => 'index', :display => 'map'}) |
... | ... | @@ -122,4 +125,84 @@ class SearchHelperTest < ActiveSupport::TestCase |
122 | 125 | end |
123 | 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 | 208 | end | ... | ... |