Commit cc81e07501b41177911bd389ce1bba503e1bd206
Exists in
theme-brasil-digital-from-staging
and in
9 other branches
merging with master
Showing
136 changed files
with
2164 additions
and
423 deletions
Show diff stats
Too many changes.
To preserve performance only 100 of 136 files displayed.
AUTHORS.md
... | ... | @@ -92,6 +92,7 @@ Daniel Alves + Rafael Manzo <rr.manzo@gmail.com> |
92 | 92 | Daniela Soares Feitosa <danielafeitosa@colivre.coop.br> |
93 | 93 | Daniel Bucher <daniel.bucher88@gmail.com> |
94 | 94 | Daniel Cunha <daniel@colivre.coop.br> |
95 | +daniel <dtygel@eita.org.br> | |
95 | 96 | David Carlos <ddavidcarlos1392@gmail.com> |
96 | 97 | diegoamc <diegoamc90@gmail.com> |
97 | 98 | Diego Araújo + Alessandro Palmeira <diegoamc90@gmail.com> |
... | ... | @@ -120,6 +121,7 @@ Diego Araujo + Rodrigo Souto + Rafael Manzo <rr.manzo@gmail.com> |
120 | 121 | Diego + Jefferson <diegoamc90@gmail.com> |
121 | 122 | Diego Martinez <diegoamc90@gmail.com> |
122 | 123 | Diego + Renan <renanteruoc@gmail.com> |
124 | +dtygel <dtygel@gmail.com> | |
123 | 125 | DylanGuedes <djmgguedes@gmail.com> |
124 | 126 | Eduardo Passos <eduardo@risa.localdomain.localhost> |
125 | 127 | Eduardo Passos <eduardosteps@gmail.com> |
... | ... | @@ -144,6 +146,7 @@ Italo Valcy <italo@dcc.ufba.br> |
144 | 146 | Jefferson Fernandes + Diego Araujo + Rafael Manzo <jeffs.fernandes@gmail.com> |
145 | 147 | Jefferson Fernandes + Joao M. M. da Silva <jeffs.fernandes@gmail.com> |
146 | 148 | Jefferson Fernandes + Joao M. M. Silva <jeffs.fernandes@gmail.com> |
149 | +Jérôme Jutteau <j.jutteau@gmail.com> | |
147 | 150 | João da Silva + Eduardo Morais + Rafael Manzo <rr.manzo@gmail.com> |
148 | 151 | João da Silva <jaodsilv@linux.ime.usp.br> |
149 | 152 | João Marco Maciel da Silva + Rafael Manzo + Renan Teruo <jaodsilv@linux.ime.usp.br> |
... | ... | @@ -247,8 +250,10 @@ Tallys Martins <tallysmartins@gmail.com> |
247 | 250 | Tallys Martins <tallysmartins@yahoo.com.br> |
248 | 251 | tallys <tallys@tallys> |
249 | 252 | tallys <tallys@tallys.(none)> |
253 | +Thiago Casotti <thiago.casotti@uol.com.br> | |
250 | 254 | Thiago Zoroastro <thiago.zoroastro@bol.com.br> |
251 | 255 | Tuux <tuxa@galaxie.eu.org> |
256 | +TWS <tablettws@gmail.com> | |
252 | 257 | Valessio Brito <contato@valessiobrito.com.br> |
253 | 258 | Valessio Brito <contato@valessiobrito.info> |
254 | 259 | Valessio Brito <valessio@gmail.com> | ... | ... |
Gemfile
... | ... | @@ -20,18 +20,17 @@ gem 'locale', '~> 2.0.5' |
20 | 20 | gem 'whenever', :require => false |
21 | 21 | gem 'eita-jrails', '>= 0.9.5', :require => 'jrails' |
22 | 22 | |
23 | -group :assets do | |
24 | - gem 'uglifier', '>= 1.0.3' | |
25 | - gem 'sass-rails' | |
26 | -end | |
23 | +# asset pipeline | |
24 | +gem 'uglifier', '>= 1.0.3' | |
25 | +gem 'sass-rails' | |
27 | 26 | |
28 | 27 | group :production do |
29 | 28 | gem 'dalli', '~> 2.7.0' |
30 | 29 | end |
31 | 30 | |
32 | 31 | group :test do |
33 | - gem 'rspec', '~> 2.10.0' | |
34 | - gem 'rspec-rails', '~> 2.10.1' | |
32 | + gem 'rspec', '~> 2.14.0' | |
33 | + gem 'rspec-rails', '~> 2.14.1' | |
35 | 34 | gem 'mocha', '~> 1.1.0', :require => false |
36 | 35 | end |
37 | 36 | ... | ... |
app/controllers/admin/role_controller.rb
app/controllers/application_controller.rb
... | ... | @@ -9,6 +9,7 @@ class ApplicationController < ActionController::Base |
9 | 9 | before_filter :allow_cross_domain_access |
10 | 10 | before_filter :login_required, :if => :private_environment? |
11 | 11 | before_filter :verify_members_whitelist, :if => [:private_environment?, :user] |
12 | + before_filter :redirect_to_current_user | |
12 | 13 | |
13 | 14 | def verify_members_whitelist |
14 | 15 | render_access_denied unless user.is_admin? || environment.in_whitelist?(user) |
... | ... | @@ -192,4 +193,15 @@ class ApplicationController < ActionController::Base |
192 | 193 | def private_environment? |
193 | 194 | @environment.enabled?(:restrict_to_members) |
194 | 195 | end |
196 | + | |
197 | + def redirect_to_current_user | |
198 | + if params[:profile] == '~' | |
199 | + if logged_in? | |
200 | + redirect_to params.merge(:profile => user.identifier) | |
201 | + else | |
202 | + render_not_found | |
203 | + end | |
204 | + end | |
205 | + end | |
206 | + | |
195 | 207 | end | ... | ... |
app/controllers/my_profile/cms_controller.rb
... | ... | @@ -357,7 +357,8 @@ class CmsController < MyProfileController |
357 | 357 | @task.ip_address = request.remote_ip |
358 | 358 | @task.user_agent = request.user_agent |
359 | 359 | @task.referrer = request.referrer |
360 | - if verify_recaptcha(:model => @task, :message => _('Please type the words correctly')) && @task.save | |
360 | + @task.requestor = current_person if logged_in? | |
361 | + if (logged_in? || verify_recaptcha(:model => @task, :message => _('Please type the words correctly'))) && @task.save | |
361 | 362 | session[:notice] = _('Thanks for your suggestion. The community administrators were notified.') |
362 | 363 | redirect_to @back_to |
363 | 364 | end | ... | ... |
app/controllers/my_profile/profile_design_controller.rb
... | ... | @@ -4,11 +4,19 @@ class ProfileDesignController < BoxOrganizerController |
4 | 4 | |
5 | 5 | protect 'edit_profile_design', :profile |
6 | 6 | |
7 | - before_filter :protect_fixed_block, :only => [:save, :move_block] | |
7 | + before_filter :protect_uneditable_block, :only => [:save] | |
8 | + before_filter :protect_fixed_block, :only => [:move_block] | |
9 | + | |
10 | + def protect_uneditable_block | |
11 | + block = boxes_holder.blocks.find(params[:id].gsub(/^block-/, '')) | |
12 | + if !current_person.is_admin? && !block.editable? | |
13 | + render_access_denied | |
14 | + end | |
15 | + end | |
8 | 16 | |
9 | 17 | def protect_fixed_block |
10 | 18 | block = boxes_holder.blocks.find(params[:id].gsub(/^block-/, '')) |
11 | - if block.fixed && !current_person.is_admin? | |
19 | + if !current_person.is_admin? && !block.movable? | |
12 | 20 | render_access_denied |
13 | 21 | end |
14 | 22 | end | ... | ... |
app/controllers/my_profile/profile_members_controller.rb
... | ... | @@ -58,6 +58,7 @@ class ProfileMembersController < MyProfileController |
58 | 58 | |
59 | 59 | def change_role |
60 | 60 | @roles = Profile::Roles.organization_member_roles(environment.id) |
61 | + @custom_roles = profile.custom_roles | |
61 | 62 | begin |
62 | 63 | @member = profile.members.find(params[:id]) |
63 | 64 | rescue ActiveRecord::RecordNotFound | ... | ... |
... | ... | @@ -0,0 +1,116 @@ |
1 | +class ProfileRolesController < MyProfileController | |
2 | + | |
3 | + protect 'manage_custom_roles', :profile | |
4 | + | |
5 | + def index | |
6 | + @roles = profile.custom_roles | |
7 | + end | |
8 | + | |
9 | + def new | |
10 | + @role = Role.new | |
11 | + end | |
12 | + | |
13 | + def create | |
14 | + @role = Role.new({:name => params[:role][:name], :permissions => params[:role][:permissions], :environment => environment }, :without_protection => true) | |
15 | + if @role.save | |
16 | + profile.custom_roles << @role | |
17 | + redirect_to :action => 'show', :id => @role | |
18 | + else | |
19 | + session[:notice] = _('Failed to create role') | |
20 | + render :action => 'new' | |
21 | + end | |
22 | + end | |
23 | + | |
24 | + def show | |
25 | + @role = environment.roles.find(params[:id]) | |
26 | + end | |
27 | + | |
28 | + def edit | |
29 | + @role = environment.roles.find(params[:id]) | |
30 | + end | |
31 | + | |
32 | + def assign_role_by_members | |
33 | + return redirect_to "/" if params[:q].nil? or !request.xhr? | |
34 | + arg = params[:q].downcase | |
35 | + result = find_by_contents(:people, environment, profile.members, params[:q])[:results] | |
36 | + render :text => prepare_to_token_input(result).to_json | |
37 | + end | |
38 | + | |
39 | + def destroy | |
40 | + @role = environment.roles.find(params[:id]) | |
41 | + @members = profile.members_by_role(@role) | |
42 | + @roles_list = all_roles(environment, profile) | |
43 | + @roles_list.delete(@role) | |
44 | + end | |
45 | + | |
46 | + def remove | |
47 | + @role = environment.roles.find(params[:id]) | |
48 | + @members = profile.members_by_role(@role) | |
49 | + member_roles = params[:roles] ? environment.roles.find(params[:roles].select{|r|!r.to_i.zero?}) : [] | |
50 | + append_roles(@members, member_roles, profile) | |
51 | + if @role.destroy | |
52 | + session[:notice] = _('Role successfuly removed!') | |
53 | + else | |
54 | + session[:notice] = _('Failed to remove role!') | |
55 | + end | |
56 | + redirect_to :action => 'index' | |
57 | + end | |
58 | + | |
59 | + def update | |
60 | + @role = environment.roles.find(params[:id]) | |
61 | + if @role.update_attributes(params[:role]) | |
62 | + redirect_to :action => 'show', :id => @role | |
63 | + else | |
64 | + session[:notice] = _('Failed to edit role') | |
65 | + render :action => 'edit' | |
66 | + end | |
67 | + end | |
68 | + | |
69 | + def assign | |
70 | + @role = environment.roles.find(params[:id]) | |
71 | + @roles_list = all_roles(environment, profile) | |
72 | + @roles_list.delete(@role) | |
73 | + end | |
74 | + | |
75 | + def define | |
76 | + @role = environment.roles.find(params[:id]) | |
77 | + selected_role = params[:selected_role] ? environment.roles.find(params[:selected_role].to_i) : nil | |
78 | + if params[:assign_role_by].eql? "members" | |
79 | + members_list = params[:person_id].split(',').collect {|id| environment.profiles.find(id.to_i)} | |
80 | + members_list.collect{|person| person.add_role(@role, profile)} | |
81 | + elsif params[:assign_role_by].eql? "roles" | |
82 | + members = profile.members_by_role(selected_role) | |
83 | + replace_role(members, selected_role, @role, profile) | |
84 | + else | |
85 | + session[:notice] = _("Error") | |
86 | + end | |
87 | + redirect_to :action => 'index' | |
88 | + end | |
89 | + | |
90 | + protected | |
91 | + | |
92 | + def append_roles(members, roles, profile) | |
93 | + members.each do |person| | |
94 | + all_roles = person.find_roles(profile).map(&:role) + roles | |
95 | + person.define_roles(all_roles, profile) | |
96 | + end | |
97 | + end | |
98 | + | |
99 | + def all_roles(environment, profile) | |
100 | + Profile::Roles.organization_member_roles(environment.id) + profile.custom_roles | |
101 | + end | |
102 | + | |
103 | + def replace_roles(members, roles, profile) | |
104 | + members.each do |person| | |
105 | + person.define_roles(roles, profile) | |
106 | + end | |
107 | + end | |
108 | + | |
109 | + def replace_role(members, role, new_role, profile) | |
110 | + members.each do |person| | |
111 | + person.remove_role(role, profile) | |
112 | + person.add_role(new_role, profile) | |
113 | + end | |
114 | + end | |
115 | + | |
116 | +end | ... | ... |
app/helpers/application_helper.rb
... | ... | @@ -707,6 +707,24 @@ module ApplicationHelper |
707 | 707 | javascript_include_tag script if script |
708 | 708 | end |
709 | 709 | |
710 | + def template_path | |
711 | + if profile.nil? | |
712 | + "/designs/templates/#{environment.layout_template}" | |
713 | + else | |
714 | + "/designs/templates/#{profile.layout_template}" | |
715 | + end | |
716 | + end | |
717 | + | |
718 | + def template_javascript_src | |
719 | + script = File.join template_path, '/javascripts/template.js' | |
720 | + script if File.exists? File.join(Rails.root, 'public', script) | |
721 | + end | |
722 | + | |
723 | + def templete_javascript_ng | |
724 | + script = template_javascript_src | |
725 | + javascript_include_tag script if script | |
726 | + end | |
727 | + | |
710 | 728 | def file_field_or_thumbnail(label, image, i) |
711 | 729 | display_form_field label, ( |
712 | 730 | render :partial => (image && image.valid? ? 'shared/show_thumbnail' : 'shared/change_image'), | ... | ... |
app/helpers/blog_helper.rb
... | ... | @@ -17,28 +17,28 @@ module BlogHelper |
17 | 17 | _('Configure blog') |
18 | 18 | end |
19 | 19 | |
20 | - def list_posts(articles, format = 'full', paginate = true) | |
20 | + def list_posts(articles, conf = { format: 'full', paginate: true }) | |
21 | 21 | pagination = will_paginate(articles, { |
22 | 22 | :param_name => 'npage', |
23 | 23 | :previous_label => _('« Newer posts'), |
24 | 24 | :next_label => _('Older posts »'), |
25 | 25 | :params => {:action=>"view_page", :page=>articles.first.parent.path.split('/'), :controller=>"content_viewer"} |
26 | - }) if articles.present? && paginate | |
26 | + }) if articles.present? && conf[:paginate] | |
27 | 27 | content = [] |
28 | 28 | artic_len = articles.length |
29 | 29 | articles.each_with_index{ |art,i| |
30 | - css_add = [ 'position-'+(i+1).to_s() ] | |
30 | + css_add = [ 'blog-post', 'position-'+(i+1).to_s() ] | |
31 | 31 | position = (i%2 == 0) ? 'odd-post' : 'even-post' |
32 | 32 | css_add << 'first' if i == 0 |
33 | 33 | css_add << 'last' if i == (artic_len-1) |
34 | 34 | css_add << 'not-published' if !art.published? |
35 | - css_add << position + '-inner' | |
36 | - content << content_tag('div', | |
37 | - content_tag('div', | |
38 | - display_post(art, format).html_safe + '<br style="clear:both"/>'.html_safe, | |
39 | - :class => 'blog-post ' + css_add.join(' '), | |
40 | - :id => "post-#{art.id}"), :class => position | |
41 | - ) | |
35 | + css_add << position | |
36 | + content << (content_tag 'div', id: "post-#{art.id}", class: css_add do | |
37 | + content_tag 'div', class: position + '-inner blog-post-inner' do | |
38 | + display_post(art, conf[:format]).html_safe + | |
39 | + '<br style="clear:both"/>'.html_safe | |
40 | + end | |
41 | + end) | |
42 | 42 | } |
43 | 43 | content.join("\n<hr class='sep-posts'/>\n") + (pagination or '') |
44 | 44 | end |
... | ... | @@ -46,7 +46,16 @@ module BlogHelper |
46 | 46 | def display_post(article, format = 'full') |
47 | 47 | no_comments = (format == 'full') ? false : true |
48 | 48 | title = article_title(article, :no_comments => no_comments) |
49 | - html = send("display_#{format}_format", FilePresenter.for(article)).html_safe | |
49 | + method = "display_#{format.split('+')[0]}_format" | |
50 | + html = send(method, FilePresenter.for(article)).html_safe | |
51 | + if format.split('+')[1] == 'pic' | |
52 | + img = article.first_image | |
53 | + if img.blank? | |
54 | + '<div class="post-pic empty"></div>' | |
55 | + else | |
56 | + '<div class="post-pic" style="background-image:url('+img+')"></div>' | |
57 | + end | |
58 | + end.to_s + | |
50 | 59 | title + html |
51 | 60 | end |
52 | 61 | ... | ... |
app/helpers/boxes_helper.rb
... | ... | @@ -190,7 +190,7 @@ module BoxesHelper |
190 | 190 | else |
191 | 191 | "before-block-#{block.id}" |
192 | 192 | end |
193 | - if block.nil? or modifiable?(block) | |
193 | + if block.nil? || movable?(block) | |
194 | 194 | content_tag('div', ' ', :id => id, :class => 'block-target' ) + drop_receiving_element(id, :url => { :action => 'move_block', :target => id }, :accept => box.acceptable_blocks, :hoverclass => 'block-target-hover') |
195 | 195 | else |
196 | 196 | "" |
... | ... | @@ -199,14 +199,14 @@ module BoxesHelper |
199 | 199 | |
200 | 200 | # makes the given block draggable so it can be moved away. |
201 | 201 | def block_handle(block) |
202 | - modifiable?(block) ? draggable_element("block-#{block.id}", :revert => true) : "" | |
202 | + movable?(block) ? draggable_element("block-#{block.id}", :revert => true) : "" | |
203 | 203 | end |
204 | 204 | |
205 | 205 | def block_edit_buttons(block) |
206 | 206 | buttons = [] |
207 | 207 | nowhere = 'javascript: return false;' |
208 | 208 | |
209 | - if modifiable?(block) | |
209 | + if movable?(block) | |
210 | 210 | if block.first? |
211 | 211 | buttons << icon_button('up-disabled', _("Can't move up anymore."), nowhere) |
212 | 212 | else |
... | ... | @@ -229,15 +229,15 @@ module BoxesHelper |
229 | 229 | buttons << icon_button('left', _('Move to the opposite side'), { :action => 'move_block', :target => 'end-of-box-' + holder.boxes[1].id.to_s, :id => block.id }, :method => 'post' ) |
230 | 230 | end |
231 | 231 | end |
232 | + end | |
232 | 233 | |
233 | - if block.editable? | |
234 | - buttons << modal_icon_button(:edit, _('Edit'), { :action => 'edit', :id => block.id }) | |
235 | - end | |
234 | + if editable?(block) | |
235 | + buttons << modal_icon_button(:edit, _('Edit'), { :action => 'edit', :id => block.id }) | |
236 | + end | |
236 | 237 | |
237 | - if !block.main? | |
238 | - buttons << icon_button(:delete, _('Remove block'), { :action => 'remove', :id => block.id }, { :method => 'post', :confirm => _('Are you sure you want to remove this block?')}) | |
239 | - buttons << icon_button(:clone, _('Clone'), { :action => 'clone_block', :id => block.id }, { :method => 'post' }) | |
240 | - end | |
238 | + if movable?(block) && !block.main? | |
239 | + buttons << icon_button(:delete, _('Remove block'), { :action => 'remove', :id => block.id }, { :method => 'post', :confirm => _('Are you sure you want to remove this block?')}) | |
240 | + buttons << icon_button(:clone, _('Clone'), { :action => 'clone_block', :id => block.id }, { :method => 'post' }) | |
241 | 241 | end |
242 | 242 | |
243 | 243 | if block.respond_to?(:help) |
... | ... | @@ -273,7 +273,11 @@ module BoxesHelper |
273 | 273 | classes |
274 | 274 | end |
275 | 275 | |
276 | - def modifiable?(block) | |
277 | - return !block.fixed || environment.admins.include?(user) | |
276 | + def movable?(block) | |
277 | + return block.movable? || user.is_admin? | |
278 | + end | |
279 | + | |
280 | + def editable?(block) | |
281 | + return block.editable? || user.is_admin? | |
278 | 282 | end |
279 | 283 | end | ... | ... |
app/helpers/layout_helper.rb
... | ... | @@ -28,7 +28,7 @@ module LayoutHelper |
28 | 28 | end |
29 | 29 | |
30 | 30 | def noosfero_javascript |
31 | - plugins_javascripts = @plugins.flat_map{ |plugin| plugin.js_files.map{ |js| plugin.class.public_path(js, true) } }.flatten | |
31 | + plugins_javascripts = @plugins.flat_map{ |plugin| Array.wrap(plugin.js_files).map{ |js| plugin.class.public_path(js, true) } }.flatten | |
32 | 32 | |
33 | 33 | output = '' |
34 | 34 | output += render 'layouts/javascript' |
... | ... | @@ -38,6 +38,8 @@ module LayoutHelper |
38 | 38 | output += theme_javascript_ng.to_s |
39 | 39 | output += javascript_tag 'render_all_jquery_ui_widgets()' |
40 | 40 | |
41 | + output += templete_javascript_ng.to_s | |
42 | + | |
41 | 43 | output |
42 | 44 | end |
43 | 45 | |
... | ... | @@ -70,11 +72,7 @@ module LayoutHelper |
70 | 72 | end |
71 | 73 | |
72 | 74 | def template_stylesheet_path |
73 | - if profile.nil? | |
74 | - "/designs/templates/#{environment.layout_template}/stylesheets/style.css" | |
75 | - else | |
76 | - "/designs/templates/#{profile.layout_template}/stylesheets/style.css" | |
77 | - end | |
75 | + File.join template_path, "/stylesheets/style.css" | |
78 | 76 | end |
79 | 77 | |
80 | 78 | ... | ... |
app/helpers/tinymce_helper.rb
... | ... | @@ -17,6 +17,7 @@ module TinymceHelper |
17 | 17 | searchreplace wordcount visualblocks visualchars code fullscreen |
18 | 18 | insertdatetime media nonbreaking save table contextmenu directionality |
19 | 19 | emoticons template paste textcolor colorpicker textpattern], |
20 | + :image_advtab => true, | |
20 | 21 | :language => tinymce_language |
21 | 22 | |
22 | 23 | options[:toolbar1] = "insertfile undo redo | copy paste | bold italic underline | styleselect fontsizeselect | forecolor backcolor | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link image" | ... | ... |
app/models/article.rb
... | ... | @@ -5,7 +5,7 @@ class Article < ActiveRecord::Base |
5 | 5 | :allow_members_to_edit, :translation_of_id, :language, |
6 | 6 | :license_id, :parent_id, :display_posts_in_current_language, |
7 | 7 | :category_ids, :posts_per_page, :moderate_comments, |
8 | - :accept_comments, :feed, :published, :source, | |
8 | + :accept_comments, :feed, :published, :source, :source_name, | |
9 | 9 | :highlighted, :notify_comments, :display_hits, :slug, |
10 | 10 | :external_feed_builder, :display_versions, :external_link, |
11 | 11 | :image_builder, :show_to_followers |
... | ... | @@ -769,7 +769,9 @@ class Article < ActiveRecord::Base |
769 | 769 | end |
770 | 770 | |
771 | 771 | def first_image |
772 | - img = Nokogiri::HTML.fragment(self.lead.to_s).css('img[src]').first || Nokogiri::HTML.fragment(self.body.to_s).search('img').first | |
772 | + img = ( image.present? && { 'src' => image.public_filename } ) || | |
773 | + Nokogiri::HTML.fragment(self.lead.to_s).css('img[src]').first || | |
774 | + Nokogiri::HTML.fragment(self.body.to_s).search('img').first | |
773 | 775 | img.nil? ? '' : img['src'] |
774 | 776 | end |
775 | 777 | ... | ... |
app/models/block.rb
1 | 1 | class Block < ActiveRecord::Base |
2 | 2 | |
3 | - attr_accessible :title, :display, :limit, :box_id, :posts_per_page, :visualization_format, :language, :display_user, :box, :fixed | |
3 | + attr_accessible :title, :display, :limit, :box_id, :posts_per_page, | |
4 | + :visualization_format, :language, :display_user, | |
5 | + :box, :edit_modes, :move_modes | |
4 | 6 | |
5 | 7 | # to be able to generate HTML |
6 | 8 | include ActionView::Helpers::UrlHelper |
... | ... | @@ -23,7 +25,7 @@ class Block < ActiveRecord::Base |
23 | 25 | end |
24 | 26 | |
25 | 27 | def get_limit |
26 | - [0,limit].max | |
28 | + [0,limit.to_i].max | |
27 | 29 | end |
28 | 30 | |
29 | 31 | def embed_code |
... | ... | @@ -110,8 +112,13 @@ class Block < ActiveRecord::Base |
110 | 112 | # * <tt>'all'</tt>: the block is always displayed |
111 | 113 | settings_items :language, :type => :string, :default => 'all' |
112 | 114 | |
113 | - # The block can be configured to be fixed. Only can be edited by environment admins | |
114 | - settings_items :fixed, :type => :boolean, :default => false | |
115 | + # The block can be configured to define the edition modes options. Only can be edited by environment admins | |
116 | + # It can assume the following values: | |
117 | + # | |
118 | + # * <tt>'all'</tt>: the block owner has all edit options for this block | |
119 | + # * <tt>'none'</tt>: the block owner can't do anything with the block | |
120 | + settings_items :edit_modes, :type => :string, :default => 'all' | |
121 | + settings_items :move_modes, :type => :string, :default => 'all' | |
115 | 122 | |
116 | 123 | # returns the description of the block, used when the user sees a list of |
117 | 124 | # blocks to choose one to include in the design. |
... | ... | @@ -148,7 +155,11 @@ class Block < ActiveRecord::Base |
148 | 155 | |
149 | 156 | # Is this block editable? (Default to <tt>false</tt>) |
150 | 157 | def editable? |
151 | - true | |
158 | + self.edit_modes == "all" | |
159 | + end | |
160 | + | |
161 | + def movable? | |
162 | + self.move_modes == "all" | |
152 | 163 | end |
153 | 164 | |
154 | 165 | # must always return false, except on MainBlock clas. |
... | ... | @@ -228,6 +239,21 @@ class Block < ActiveRecord::Base |
228 | 239 | } |
229 | 240 | end |
230 | 241 | |
242 | + def edit_block_options | |
243 | + @edit_options ||= { | |
244 | + 'all' => _('Can be modified'), | |
245 | + 'none' => _('Cannot be modified') | |
246 | + } | |
247 | + end | |
248 | + | |
249 | + def move_block_options | |
250 | + @move_options ||= { | |
251 | + 'all' => _('Can be moved'), | |
252 | + 'none' => _('Cannot be moved') | |
253 | + } | |
254 | + end | |
255 | + | |
256 | + | |
231 | 257 | def duplicate |
232 | 258 | duplicated_block = self.dup |
233 | 259 | duplicated_block.display = 'never' | ... | ... |
app/models/blog.rb
... | ... | @@ -76,7 +76,7 @@ class Blog < Folder |
76 | 76 | end |
77 | 77 | |
78 | 78 | settings_items :visualization_format, :type => :string, :default => 'full' |
79 | - validates_inclusion_of :visualization_format, :in => [ 'full', 'short' ], :if => :visualization_format | |
79 | + validates_inclusion_of :visualization_format, :in => [ 'full', 'short', 'short+pic' ], :if => :visualization_format | |
80 | 80 | |
81 | 81 | settings_items :display_posts_in_current_language, :type => :boolean, :default => false |
82 | 82 | ... | ... |
app/models/environment.rb
... | ... | @@ -19,6 +19,8 @@ class Environment < ActiveRecord::Base |
19 | 19 | filename |
20 | 20 | end |
21 | 21 | |
22 | + NUMBER_OF_BOXES = 4 | |
23 | + | |
22 | 24 | PERMISSIONS['Environment'] = { |
23 | 25 | 'view_environment_admin_panel' => N_('View environment admin panel'), |
24 | 26 | 'edit_environment_features' => N_('Edit environment features'), |
... | ... | @@ -172,7 +174,7 @@ class Environment < ActiveRecord::Base |
172 | 174 | acts_as_having_boxes |
173 | 175 | |
174 | 176 | after_create do |env| |
175 | - 3.times do | |
177 | + NUMBER_OF_BOXES.times do | |
176 | 178 | env.boxes << Box.new |
177 | 179 | end |
178 | 180 | |
... | ... | @@ -737,8 +739,8 @@ class Environment < ActiveRecord::Base |
737 | 739 | end |
738 | 740 | |
739 | 741 | def is_default_template?(template) |
740 | - is_default = template == community_default_template | |
741 | - is_default = is_default || template == person_default_template | |
742 | + is_default = template == community_default_template | |
743 | + is_default = is_default || template == person_default_template | |
742 | 744 | is_default = is_default || template == enterprise_default_template |
743 | 745 | is_default |
744 | 746 | end | ... | ... |
app/models/highlights_block.rb
... | ... | @@ -26,8 +26,16 @@ class HighlightsBlock < Block |
26 | 26 | end |
27 | 27 | |
28 | 28 | def featured_images |
29 | - block_images = images.select{|i| !i[:image_src].nil? }.sort { |x, y| x[:position] <=> y[:position] } | |
30 | - shuffle ? block_images.shuffle : block_images | |
29 | + images = get_images | |
30 | + shuffle ? images.shuffle : images | |
31 | + end | |
32 | + | |
33 | + def get_images | |
34 | + images.select do |i| | |
35 | + !i[:image_src].nil? | |
36 | + end.sort do |x, y| | |
37 | + x[:position] <=> y[:position] | |
38 | + end | |
31 | 39 | end |
32 | 40 | |
33 | 41 | def content(args={}) | ... | ... |
app/models/organization.rb
... | ... | @@ -29,6 +29,8 @@ class Organization < Profile |
29 | 29 | |
30 | 30 | has_many :mailings, :class_name => 'OrganizationMailing', :foreign_key => :source_id, :as => 'source' |
31 | 31 | |
32 | + has_many :custom_roles, :class_name => 'Role', :foreign_key => :profile_id | |
33 | + | |
32 | 34 | scope :more_popular, :order => 'members_count DESC' |
33 | 35 | |
34 | 36 | validate :presence_of_required_fieds, :unless => :is_template | ... | ... |
app/models/profile.rb
... | ... | @@ -22,6 +22,8 @@ class Profile < ActiveRecord::Base |
22 | 22 | :display => %w[compact] |
23 | 23 | } |
24 | 24 | |
25 | + NUMBER_OF_BOXES = 4 | |
26 | + | |
25 | 27 | def self.default_search_display |
26 | 28 | 'compact' |
27 | 29 | end |
... | ... | @@ -43,7 +45,7 @@ class Profile < ActiveRecord::Base |
43 | 45 | find_role('editor', env_id) |
44 | 46 | end |
45 | 47 | def self.organization_member_roles(env_id) |
46 | - all_roles(env_id).select{ |r| r.key.match(/^profile_/) unless r.key.blank? } | |
48 | + all_roles(env_id).select{ |r| r.key.match(/^profile_/) unless r.key.blank? || !r.profile_id.nil?} | |
47 | 49 | end |
48 | 50 | def self.all_roles(env_id) |
49 | 51 | Role.all :conditions => { :environment_id => env_id } |
... | ... | @@ -75,6 +77,7 @@ class Profile < ActiveRecord::Base |
75 | 77 | 'publish_content' => N_('Publish content'), |
76 | 78 | 'invite_members' => N_('Invite members'), |
77 | 79 | 'send_mail_to_members' => N_('Send e-Mail to members'), |
80 | + 'manage_custom_roles' => N_('Manage custom roles'), | |
78 | 81 | } |
79 | 82 | |
80 | 83 | acts_as_accessible |
... | ... | @@ -361,7 +364,7 @@ class Profile < ActiveRecord::Base |
361 | 364 | if template |
362 | 365 | apply_template(template, :copy_articles => false) |
363 | 366 | else |
364 | - 3.times do | |
367 | + NUMBER_OF_BOXES.times do | |
365 | 368 | self.boxes << Box.new |
366 | 369 | end |
367 | 370 | |
... | ... | @@ -404,6 +407,7 @@ class Profile < ActiveRecord::Base |
404 | 407 | alias_method_chain :template, :default |
405 | 408 | |
406 | 409 | def apply_template(template, options = {:copy_articles => true}) |
410 | + self.template = template | |
407 | 411 | copy_blocks_from(template) |
408 | 412 | copy_articles_from(template) if options[:copy_articles] |
409 | 413 | self.apply_type_specific_template(template) | ... | ... |
app/models/suggest_article.rb
1 | 1 | class SuggestArticle < Task |
2 | 2 | |
3 | - validates_presence_of :target_id, :article_name, :email, :name, :article_body | |
3 | + validates_presence_of :target_id | |
4 | + validates_presence_of :email, :name, :if => Proc.new { |task| task.requestor.blank? } | |
5 | + validates_associated :article_object | |
4 | 6 | |
5 | 7 | settings_items :email, :type => String |
6 | 8 | settings_items :name, :type => String |
7 | - settings_items :article_name, :type => String | |
8 | - settings_items :article_body, :type => String | |
9 | - settings_items :article_abstract, :type => String | |
10 | - settings_items :article_parent_id, :type => String | |
11 | - settings_items :source, :type => String | |
12 | - settings_items :source_name, :type => String | |
13 | - settings_items :highlighted, :type => :boolean, :default => false | |
14 | 9 | settings_items :ip_address, :type => String |
15 | 10 | settings_items :user_agent, :type => String |
16 | 11 | settings_items :referrer, :type => String |
12 | + settings_items :article, :type => Hash, :default => {} | |
17 | 13 | |
18 | 14 | after_create :schedule_spam_checking |
19 | 15 | |
... | ... | @@ -24,34 +20,49 @@ class SuggestArticle < Task |
24 | 20 | include Noosfero::Plugin::HotSpot |
25 | 21 | |
26 | 22 | def sender |
27 | - "#{name} (#{email})" | |
23 | + requestor ? "#{requestor.name}" : "#{name} (#{email})" | |
24 | + end | |
25 | + | |
26 | + def article_object | |
27 | + if @article_object.nil? | |
28 | + @article_object = article_type.new(article.merge({:profile => target}).except(:type)) | |
29 | + if requestor.present? | |
30 | + @article_object.author = requestor | |
31 | + else | |
32 | + @article_object.author_name = name | |
33 | + end | |
34 | + end | |
35 | + @article_object | |
36 | + end | |
37 | + | |
38 | + def article_type | |
39 | + if article[:type].present? | |
40 | + type = article[:type].constantize | |
41 | + return type if type < Article | |
42 | + end | |
43 | + TinyMceArticle | |
28 | 44 | end |
29 | 45 | |
30 | 46 | def perform |
31 | - task = TinyMceArticle.new | |
32 | - task.profile = target | |
33 | - task.name = article_name | |
34 | - task.author_name = name | |
35 | - task.body = article_body | |
36 | - task.abstract = article_abstract | |
37 | - task.parent_id = article_parent_id | |
38 | - task.source = source | |
39 | - task.source_name = source_name | |
40 | - task.highlighted = highlighted | |
41 | - task.save! | |
47 | + article_object.save! | |
42 | 48 | end |
43 | 49 | |
44 | 50 | def title |
45 | 51 | _("Article suggestion") |
46 | 52 | end |
47 | 53 | |
54 | + def article_name | |
55 | + article[:name] | |
56 | + end | |
57 | + | |
48 | 58 | def subject |
49 | 59 | article_name |
50 | 60 | end |
51 | 61 | |
52 | 62 | def information |
53 | - { :message => _('%{sender} suggested the publication of the article: %{subject}.'), | |
54 | - :variables => {:sender => sender} } | |
63 | + variables = requestor.blank? ? {:requestor => sender} : {} | |
64 | + { :message => _('%{requestor} suggested the publication of the article: %{subject}.'), | |
65 | + :variables => variables } | |
55 | 66 | end |
56 | 67 | |
57 | 68 | def accept_details |
... | ... | @@ -63,8 +74,8 @@ class SuggestArticle < Task |
63 | 74 | end |
64 | 75 | |
65 | 76 | def target_notification_description |
66 | - _('%{sender} suggested the publication of the article: %{article}.') % | |
67 | - {:sender => sender, :article => article_name} | |
77 | + _('%{requestor} suggested the publication of the article: %{article}.') % | |
78 | + {:requestor => sender, :article => article_name} | |
68 | 79 | end |
69 | 80 | |
70 | 81 | def target_notification_message | ... | ... |
app/models/user.rb
... | ... | @@ -45,7 +45,7 @@ class User < ActiveRecord::Base |
45 | 45 | p = Person.new |
46 | 46 | |
47 | 47 | p.attributes = user.person_data |
48 | - p.identifier = user.login | |
48 | + p.identifier = user.login if p.identifier.blank? | |
49 | 49 | p.user = user |
50 | 50 | p.environment = user.environment |
51 | 51 | p.name ||= user.name || user.login | ... | ... |
app/views/blocks/profile_info_actions/_join_leave_community.html.erb
app/views/box_organizer/edit.html.erb
... | ... | @@ -5,12 +5,6 @@ |
5 | 5 | |
6 | 6 | <%= labelled_form_field(_('Custom title for this block: '), text_field(:block, :title, :maxlength => 20)) %> |
7 | 7 | |
8 | - <% if environment.admins.include?(user) %> | |
9 | - <div class="fixed_block"> | |
10 | - <%= labelled_check_box(_("Fixed"), "block[fixed]", value = "1", checked = @block.fixed) %> | |
11 | - </div> | |
12 | - <% end %> | |
13 | - | |
14 | 8 | <%= render :partial => partial_for_class(@block.class) %> |
15 | 9 | |
16 | 10 | <div class="display"> |
... | ... | @@ -25,6 +19,15 @@ |
25 | 19 | |
26 | 20 | <%= labelled_form_field(_('Show for:'), select(:block, :language, [ [ _('all languages'), 'all']] + environment.locales.map {|key, value| [value, key]} )) %> |
27 | 21 | |
22 | + <% if user.is_admin? %> | |
23 | + <div class="edit-modes"> | |
24 | + <%= labelled_form_field _('Edit options:'), select_tag('block[edit_modes]', options_from_collection_for_select(@block.edit_block_options, :first, :last, @block.edit_modes)) %> | |
25 | + </div> | |
26 | + <div class="move-modes"> | |
27 | + <%= labelled_form_field _('Move options:'), select_tag('block[move_modes]', options_from_collection_for_select(@block.move_block_options, :first, :last, @block.move_modes)) %> | |
28 | + </div> | |
29 | + <% end %> | |
30 | + | |
28 | 31 | <% button_bar do %> |
29 | 32 | <%= submit_button(:save, _('Save')) %> |
30 | 33 | <%= modal_close_button(_('Cancel')) %> | ... | ... |
app/views/cms/_blog.html.erb
... | ... | @@ -64,7 +64,11 @@ |
64 | 64 | <%= labelled_check_box(_('Remove cover image'),'remove_image',true,false)%> |
65 | 65 | <% end %> |
66 | 66 | |
67 | -<%= labelled_form_field(_('How to display posts:'), f.select(:visualization_format, [ [ _('Full post'), 'full'], [ _('First paragraph'), 'short'] ])) %> | |
67 | +<%= labelled_form_field(_('How to display posts:'), f.select(:visualization_format, [ | |
68 | + [ _('Full post'), 'full'], | |
69 | + [ _('First paragraph'), 'short'], | |
70 | + [ _('First paragraph, with post picture'), 'short+pic'] | |
71 | +])) %> | |
68 | 72 | |
69 | 73 | <%= labelled_form_field(_('Posts per page:'), f.select(:posts_per_page, Blog.posts_per_page_options)) %> |
70 | 74 | ... | ... |
app/views/cms/suggest_an_article.html.erb
... | ... | @@ -6,21 +6,22 @@ |
6 | 6 | |
7 | 7 | <%= labelled_form_for 'task' do |f| %> |
8 | 8 | |
9 | - <%= required labelled_form_field(_('Title'), text_field(:task, 'article_name', :size => 50)) %> | |
9 | + <%= required labelled_form_field(_('Title'), text_field('task[article]', 'name', :size => 50)) %> | |
10 | 10 | |
11 | - <%= labelled_form_field(_('Source'), text_field(:task, 'source_name')) %> | |
11 | + <%= labelled_form_field(_('Source'), text_field('task[article]', 'source_name')) %> | |
12 | 12 | |
13 | - <%= labelled_form_field(_('Source URL'), text_field(:task, 'source')) %> | |
13 | + <%= labelled_form_field(_('Source URL'), text_field('task[article]', 'source')) %> | |
14 | 14 | |
15 | - <%= required labelled_form_field(_('Your name'), text_field(:task, 'name')) %> | |
16 | - | |
17 | - <%= required labelled_form_field(_('Email'), text_field(:task, 'email')) %> | |
15 | + <% unless logged_in? %> | |
16 | + <%= required labelled_form_field(_('Your name'), text_field(:task, 'name')) %> | |
17 | + <%= required labelled_form_field(_('Email'), text_field(:task, 'email')) %> | |
18 | + <% end %> | |
18 | 19 | |
19 | - <%= render :partial => 'shared/lead_and_body', :locals => {:tiny_mce => true, :object => :task, :abstract_method => 'article_abstract', :body_method => 'article_body'} %> | |
20 | + <%= render :partial => 'shared/lead_and_body', :locals => {:tiny_mce => true, :object => 'task[article]'} %> | |
20 | 21 | |
21 | 22 | <%= hidden_field_tag('back_to', @back_to) %> |
22 | 23 | |
23 | - <%= recaptcha_tags(:display => { :theme => 'clean' }, :ajax => true) %> | |
24 | + <%= recaptcha_tags(:display => { :theme => 'clean' }, :ajax => true) unless logged_in? %> | |
24 | 25 | |
25 | 26 | <% button_bar do %> |
26 | 27 | <%= submit_button :save, _('Save') %> | ... | ... |
app/views/content_viewer/blog_page.html.erb
... | ... | @@ -18,6 +18,9 @@ |
18 | 18 | format = inside_block.visualization_format |
19 | 19 | paginate = false |
20 | 20 | end |
21 | - (blog.empty? ? content_tag('em', _('(no posts)')) : list_posts(posts, format, paginate)) | |
21 | + (blog.empty? ? | |
22 | + content_tag('em', _('(no posts)')) : | |
23 | + list_posts(posts, format: format, paginate: paginate) | |
24 | + ) | |
22 | 25 | %> |
23 | 26 | </div> | ... | ... |
app/views/features/manage_fields.html.erb
1 | 1 | <h1><%= _('Manage fields displayed for profiles') %></h1> |
2 | 2 | |
3 | +<%= javascript_include_tag "manage-fields.js" %> | |
4 | + | |
3 | 5 | <% tabs = [] %> |
4 | 6 | <% tabs << {:title => _("Person's fields"), :id => 'person-fields', |
5 | 7 | :content => (render :partial => 'manage_person_fields')} %> |
... | ... | @@ -11,5 +13,3 @@ |
11 | 13 | <% end %> |
12 | 14 | |
13 | 15 | <%= render_tabs(tabs) %> |
14 | - | |
15 | -<%= javascript_include_tag "manage-fields.js" %> | ... | ... |
app/views/profile/report_abuse.html.erb
... | ... | @@ -24,7 +24,7 @@ |
24 | 24 | $('#report-abuse-submit-button').css('cursor', 'progress'); |
25 | 25 | $.ajax({ |
26 | 26 | type: 'POST', |
27 | - url: <%= url_for({:controller => 'profile', :action => 'register_report', :profile => profile.identifier}) %>, | |
27 | + url: <%= url_for({:controller => 'profile', :action => 'register_report', :profile => profile.identifier}).to_json %>, | |
28 | 28 | data: $(form).serialize(), |
29 | 29 | dataType: 'json', |
30 | 30 | success: function(data, status, ajax){ | ... | ... |
app/views/profile_editor/edit.html.erb
app/views/profile_editor/index.html.erb
... | ... | @@ -28,6 +28,8 @@ |
28 | 28 | |
29 | 29 | <%= control_panel_button(_('Manage Content'), 'cms', :controller => 'cms') %> |
30 | 30 | |
31 | + <%= control_panel_button(_('Manage Roles'), 'roles', :controller => 'profile_roles') %> | |
32 | + | |
31 | 33 | <% unless profile.enterprise? %> |
32 | 34 | <%= case profile.blogs.count |
33 | 35 | when 0 | ... | ... |
app/views/profile_members/change_role.html.erb
1 | 1 | <h3> <%= _('Changing role of %s') % @member.name %> </h3> |
2 | 2 | |
3 | 3 | <%= labelled_form_for :member, :url => {:action => 'update_roles'} do |f| %> |
4 | - | |
5 | - <%= _('Roles:') %> <br> | |
4 | + | |
5 | + <h4><%= _('Roles:') %></h4> | |
6 | 6 | <% @roles.each do |r| %> |
7 | 7 | <%= labelled_check_box(r.name, 'roles[]', r.id, @associations.map(&:role).include?(r) ) %><br/> |
8 | 8 | <ul class="role-permissions"> |
... | ... | @@ -11,6 +11,17 @@ |
11 | 11 | <% end %> |
12 | 12 | </ul> |
13 | 13 | <% end %> |
14 | + <% unless @custom_roles.empty? %> | |
15 | + <h4><%= _('Custom Roles:') %></h4> | |
16 | + <% @custom_roles.each do |r| %> | |
17 | + <%= labelled_check_box(r.name, 'roles[]', r.id, @associations.map(&:role).include?(r) ) %><br/> | |
18 | + <ul class="role-permissions"> | |
19 | + <% r.permissions.each do |p| %> | |
20 | + <li> <%= permission_name(p) %> </li> | |
21 | + <% end %> | |
22 | + </ul> | |
23 | + <% end %> | |
24 | + <% end %> | |
14 | 25 | <%= hidden_field_tag 'person', @member.id %> |
15 | 26 | |
16 | 27 | <% button_bar do %> | ... | ... |
... | ... | @@ -0,0 +1,22 @@ |
1 | +<%= error_messages_for :role %> | |
2 | + | |
3 | +<%= labelled_form_for :role, :url => (mode == :edit) ? {:action => 'update', :id => role} : {:action => 'create'} do |f| %> | |
4 | + | |
5 | + <%= required_fields_message %> | |
6 | + | |
7 | + <%= required f.text_field(:name) %> | |
8 | + | |
9 | + <% permissions.each do |key| %> | |
10 | + <div class="permissions <%= key.downcase %>"> | |
11 | + <h4><%= _('%s Permissions:' % key) %></h4> | |
12 | + <% ActiveRecord::Base::PERMISSIONS[key].keys.each do |p| %> | |
13 | + <%= check_box_tag("role[permissions][]", p, role.has_permission?(p), { :id => p }) %> | |
14 | + <%= content_tag(:label, permission_name(p), { :for => p }) %><br/> | |
15 | + <% end %> | |
16 | + </div> | |
17 | + <% end %> | |
18 | + | |
19 | + <% button_bar do %> | |
20 | + <%= submit_button('save', (mode == :edit) ? _('Save changes') : _('Create role'), :cancel => {:action => 'index'} ) %> | |
21 | + <% end %> | |
22 | +<% end %> | ... | ... |
... | ... | @@ -0,0 +1,35 @@ |
1 | +<%= javascript_include_tag('assign_role.js') %> | |
2 | + | |
3 | +<h1> <%= _("Assign #{@role.name}") %> </h1> | |
4 | + | |
5 | + | |
6 | +<%= labelled_form_for :role, :url => { :action => 'define', :id => @role.id } do |f| %> | |
7 | + | |
8 | + <h2> | |
9 | + <%= _("Assign role by:") %> | |
10 | + </h2> | |
11 | + <p> | |
12 | + <%= labelled_radio_button _("Members"), :assign_role_by, "members", true, :id => "assign_role_by_members", :class => "assign_role_by" %> | |
13 | + | |
14 | + <%= labelled_radio_button _("Roles"), :assign_role_by, "roles", false, :id => "assign_role_by_roles", :class => "assign_role_by" %> | |
15 | + </p> | |
16 | + <div class="assign_by_members"> | |
17 | + <%=token_input_field_tag(:person_id, 'search-profile-members', {:action => 'assign_role_by_members'}, | |
18 | + {:focus => false, :hint_text => _('Select members to assign the role')}) %> | |
19 | + | |
20 | + <% button_bar do %> | |
21 | + <%= submit_button(:forward, _("Confirm")) %> | |
22 | + <% end %> | |
23 | + </div> | |
24 | + <div class="assign_by_roles" style="display: none;"> | |
25 | + <h6> | |
26 | + <%= _("Replace role: ") %> | |
27 | + </h6> | |
28 | + <% @roles_list.each do |role| %> | |
29 | + <%= labelled_radio_button role.name , :selected_role, role.id , false, :class => "selected_role" %> <br> | |
30 | + <% end %> | |
31 | + <% button_bar do %> | |
32 | + <%= submit_button('save',_('Confirm'), :cancel => {:action => 'index'} ) %> | |
33 | + <% end %> | |
34 | + </div> | |
35 | +<% end %> | ... | ... |
... | ... | @@ -0,0 +1,23 @@ |
1 | +<h1> <%= _("Deleting #{@role.name}") %> </h1> | |
2 | + | |
3 | +<% if @members.nil? || @members.empty? %> | |
4 | + <p><%= _('This role is not being currently used.')%></p> | |
5 | + <p><%= _('Are you sure you want to delete this role?') %></p> | |
6 | + | |
7 | + <% button_bar do %> | |
8 | + <%= button(:remove, _('Yes, I am sure'), {:action => 'remove', :id => @role.id}, :method => :post) %> | |
9 | + <%= button(:cancel, _('No, I gave up'), {:action => 'index'}) %> | |
10 | + <% end %> | |
11 | +<% else %> | |
12 | + <p><%= _('There are members currently using this role.')%></p> | |
13 | + <p><%= _('To which role do you want to change them?') %></p> | |
14 | + <%= labelled_form_for :role, :url => { :action => 'remove', :id => @role.id } do |f| %> | |
15 | + <% @roles_list.each do |role| %> | |
16 | + <%= check_box_tag("roles[]", role.id, false ,{:id => role.key}) %> | |
17 | + <%= content_tag(:label, role.name, { :for => role.key }) %><br/> | |
18 | + <% end %> | |
19 | + <% button_bar do %> | |
20 | + <%= submit_button('save',_('Delete role'), :cancel => {:action => 'index'} ) %> | |
21 | + <% end %> | |
22 | + <% end %> | |
23 | +<% end %> | ... | ... |
... | ... | @@ -0,0 +1,27 @@ |
1 | +<h1><%= _('Manage user roles') %></h1> | |
2 | + | |
3 | +<table> | |
4 | + <tr> | |
5 | + <th><%= _('Role') %></th> | |
6 | + <th><%= _('Actions') %></th> | |
7 | + </tr> | |
8 | + <% @roles.each do |role| %> | |
9 | + <tr> | |
10 | + <td> | |
11 | + <%= link_to role.name, :action => 'show', :id => role %> | |
12 | + </td> | |
13 | + <td> | |
14 | + <div style="text-align: center;"> | |
15 | + <%= button_without_text :edit, _('Edit'), :action => 'edit', :id => role %> | |
16 | + <%= button_without_text :delete, _('Delete'), :action => 'destroy', :id => role %> | |
17 | + <%= button_without_text 'vertical-toggle', _('Assign'), :action => 'assign', :id => role %> | |
18 | + </div> | |
19 | + </td> | |
20 | + </tr> | |
21 | + <% end %> | |
22 | +</table> | |
23 | + | |
24 | +<% button_bar do %> | |
25 | + <%= button :add, _('Create a new role'), :action => 'new' %> | |
26 | + <%= button :back, _('Back to control panel'), :controller => 'profile_editor' %> | |
27 | +<% end %> | ... | ... |
... | ... | @@ -0,0 +1,13 @@ |
1 | +<h1> <%= _(@role.name) %></h1> | |
2 | + | |
3 | +<h3> <%= _('Permissions') %> </h3> | |
4 | +<ul> | |
5 | + <% @role.permissions.each do |p| %> | |
6 | + <li> <%= permission_name(p) %> </li> | |
7 | + <% end %> | |
8 | +</ul> | |
9 | + | |
10 | +<% button_bar do %> | |
11 | + <%= button :edit, _('Edit'), :action => 'edit', :id => @role %> | |
12 | + <%= button :back, _('Back to roles management'), :action => 'index' %> | |
13 | +<% end %> | ... | ... |
app/views/shared/_profile_search_form.html.erb
1 | +<% search_label = _("Find in %s's content") % profile.short_name %> | |
1 | 2 | <%= form_tag( { :controller => 'profile_search', :profile => profile.identifier}, :method => 'get', :class => 'search_form' ) do %> |
2 | 3 | <div class="search-field"> |
3 | 4 | <span class="formfield"> |
4 | - <%= search_input_with_suggestions 'q', :articles, @q, :title => _("Find in %s's content") % profile.short_name %> | |
5 | + <%= search_input_with_suggestions 'q', :articles, @q, :title => search_label, :placeholder => search_label %> | |
5 | 6 | </span> |
6 | 7 | <%= submit_button(:search, _('Search')) %> |
7 | 8 | <div> | ... | ... |
app/views/spam/_suggest_article.html.erb
... | ... | @@ -7,13 +7,13 @@ |
7 | 7 | <ul class="suggest-article-details" style="display: none"> |
8 | 8 | <li><strong><%=_('Sent by')%></strong>: <%=task.name%> </li> |
9 | 9 | <li><strong><%=_('Email')%></strong>: <%=task.email%> </li> |
10 | - <li><strong><%=_('Source')%></strong>: <%=task.source_name%> </li> | |
11 | - <li><strong><%=_('Source URL')%></strong>: <%=task.source%> </li> | |
12 | - <li><strong><%=_('Folder')%></strong>: <%=(a = Article.find_by_id(task.article_parent_id))?a.name : '<em>' + s_('Folder|none') + '</em>'%> </li> | |
13 | - <li><strong><%=_('Lead')%></strong>: <%=task.article_abstract.blank? ? '<em>' + s_('Abstract|empty') + '</em>' : task.article_abstract%> </li> | |
10 | + <li><strong><%=_('Source')%></strong>: <%=task.article_object.source_name%> </li> | |
11 | + <li><strong><%=_('Source URL')%></strong>: <%=task.article_object.source%> </li> | |
12 | + <li><strong><%=_('Folder')%></strong>: <%=(a = Article.find_by_id(task.article_object.parent_id))?a.name : '<em>' + s_('Folder|none') + '</em>'%> </li> | |
13 | + <li><strong><%=_('Lead')%></strong>: <%=task.article_object.abstract.blank? ? '<em>' + s_('Abstract|empty') + '</em>' : task.article_object.abstract%> </li> | |
14 | 14 | <li><strong><%=_('Body')%></strong>: |
15 | 15 | <div class='suggest-article-body'> |
16 | - <%= task.article_body %> | |
16 | + <%= task.article_object.body %> | |
17 | 17 | </div> |
18 | 18 | </li> |
19 | 19 | </ul> | ... | ... |
app/views/tasks/_add_member_accept_details.html.erb
1 | 1 | <%= content = _("Roles:")+"<br />" |
2 | -roles = Profile::Roles.organization_member_roles(task.target.environment.id) | |
2 | +roles = Profile::Roles.organization_member_roles(task.target.environment.id) + profile.custom_roles | |
3 | 3 | roles.each do |role| |
4 | 4 | content += labelled_check_box(role.name, "tasks[#{task.id}][task][roles][]", role.id, false)+"<br />" |
5 | 5 | end |
6 | 6 | content_tag('p', content, :class => 'member-classify-suggestion') |
7 | 7 | %> |
8 | - | ... | ... |
app/views/tasks/_suggest_article_accept_details.html.erb
1 | 1 | <%= render :file => 'shared/tiny_mce' %> |
2 | 2 | |
3 | -<%= labelled_form_field(_("Sent by: "), f.text_field(:name)) %> | |
4 | -<p><%= label_tag(_("Email: %s") % task.email) %> </p> | |
5 | -<%= required labelled_form_field(_('Title'), f.text_field(:article_name, :size => 50)) %> | |
6 | -<%= labelled_form_field(_('Source'), f.text_field(:source_name)) %> | |
7 | -<%= labelled_form_field(_("Source URL"), f.text_field(:source)) %> | |
3 | +<% unless task.requestor %> | |
4 | + <%= labelled_form_field(_("Sent by: "), f.text_field(:name)) %> | |
5 | + <p><%= label_tag(_("Email: %s") % task.email) %> </p> | |
6 | +<% end %> | |
8 | 7 | |
9 | -<%= select_profile_folder(_('Select the folder where the article must be published'), "tasks[#{task.id}][task][article_parent_id]", task.target) %> | |
10 | -<%= labelled_form_field(_('Highlight this article'), f.check_box(:highlighted)) %> | |
8 | +<%= f.fields_for 'article', OpenStruct.new(task.article) do |a| %> | |
9 | + <%= required labelled_form_field(_('Title'), a.text_field(:name, :size => 50)) %> | |
10 | + <%= labelled_form_field(_('Source'), a.text_field(:source_name)) %> | |
11 | + <%= labelled_form_field(_("Source URL"), a.text_field(:source)) %> | |
11 | 12 | |
12 | -<%= render :partial => 'shared/lead_and_body', :locals => {:tiny_mce => true, :f => f, :abstract_method => 'article_abstract', :body_method => 'article_body', :lead_id => task.id} %> | |
13 | + <%= select_profile_folder(_('Select the folder where the article must be published'), "tasks[#{task.id}][task][article][parent_id]", task.target, task.article[:parent_id]) %> | |
14 | + <%= labelled_form_field(_('Highlight this article'), a.check_box(:highlighted)) %> | |
15 | + | |
16 | + <%= a.hidden_field(:type) %> | |
17 | + | |
18 | + <%= render :partial => 'shared/lead_and_body', :locals => {:tiny_mce => true, :f => a, :lead_id => task.id} %> | |
19 | +<% end %> | ... | ... |
app/views/user_mailer/profiles_suggestions_email.html.erb
... | ... | @@ -10,8 +10,8 @@ |
10 | 10 | <% @people_suggestions.each do |person| %> |
11 | 11 | <li><a href="<%= url_for(person.public_profile_url) %>"><%= person.name %></a></li> |
12 | 12 | <% end %> |
13 | - <ul> | |
14 | - <%= _("To see the full list of friends suggestions, follow the link: %s") % @people_suggestions_url %> | |
13 | + </ul> | |
14 | + <%= _("To see the full list of friends suggestions, follow the link: %s") % url_for(@people_suggestions_url) %> | |
15 | 15 | <% end %> |
16 | 16 | |
17 | 17 | <% unless @communities_suggestions.empty? %> |
... | ... | @@ -21,13 +21,15 @@ |
21 | 21 | <% @communities_suggestions.each do |community| %> |
22 | 22 | <li><a href="<%= url_for(community.public_profile_url) %>"><%= community.name %></a></li> |
23 | 23 | <% end %> |
24 | - <ul> | |
25 | - <%= _("To see the full list of communities suggestions, follow the link: %s") % @communities_suggestions_url %> | |
24 | + </ul> | |
25 | + <%= _("To see the full list of communities suggestions, follow the link: %s") % url_for(@communities_suggestions_url) %> | |
26 | 26 | <% end %> |
27 | 27 | |
28 | 28 | |
29 | 29 | <%= _("Greetings,") %> |
30 | 30 | |
31 | --- | |
32 | -<%= _('%s team.') % @environment %> | |
31 | +<p><%= _("Greetings,") %></p> | |
32 | + | |
33 | +--<br/> | |
34 | +<%= _('%s team.') % @environment %><br/> | |
33 | 35 | <%= @url %> | ... | ... |
config/environments/development.rb
config/routes.rb
... | ... | @@ -56,37 +56,37 @@ Noosfero::Application.routes.draw do |
56 | 56 | match 'search(/:action(/*category_path))', :controller => 'search' |
57 | 57 | |
58 | 58 | # events |
59 | - match 'profile/:profile/events_by_day', :controller => 'events', :action => 'events_by_day', :profile => /#{Noosfero.identifier_format}/ | |
60 | - match 'profile/:profile/events_by_month', :controller => 'events', :action => 'events_by_month', :profile => /#{Noosfero.identifier_format}/ | |
61 | - match 'profile/:profile/events/:year/:month/:day', :controller => 'events', :action => 'events', :year => /\d*/, :month => /\d*/, :day => /\d*/, :profile => /#{Noosfero.identifier_format}/ | |
62 | - match 'profile/:profile/events/:year/:month', :controller => 'events', :action => 'events', :year => /\d*/, :month => /\d*/, :profile => /#{Noosfero.identifier_format}/ | |
63 | - match 'profile/:profile/events', :controller => 'events', :action => 'events', :profile => /#{Noosfero.identifier_format}/ | |
59 | + match 'profile/:profile/events_by_day', :controller => 'events', :action => 'events_by_day', :profile => /#{Noosfero.identifier_format_in_url}/ | |
60 | + match 'profile/:profile/events_by_month', :controller => 'events', :action => 'events_by_month', :profile => /#{Noosfero.identifier_format_in_url}/ | |
61 | + match 'profile/:profile/events/:year/:month/:day', :controller => 'events', :action => 'events', :year => /\d*/, :month => /\d*/, :day => /\d*/, :profile => /#{Noosfero.identifier_format_in_url}/ | |
62 | + match 'profile/:profile/events/:year/:month', :controller => 'events', :action => 'events', :year => /\d*/, :month => /\d*/, :profile => /#{Noosfero.identifier_format_in_url}/ | |
63 | + match 'profile/:profile/events', :controller => 'events', :action => 'events', :profile => /#{Noosfero.identifier_format_in_url}/ | |
64 | 64 | |
65 | 65 | # catalog |
66 | - match 'catalog/:profile', :controller => 'catalog', :action => 'index', :profile => /#{Noosfero.identifier_format}/, :as => :catalog | |
66 | + match 'catalog/:profile', :controller => 'catalog', :action => 'index', :profile => /#{Noosfero.identifier_format_in_url}/, :as => :catalog | |
67 | 67 | |
68 | 68 | # invite |
69 | - match 'profile/:profile/invite/friends', :controller => 'invite', :action => 'invite_friends', :profile => /#{Noosfero.identifier_format}/ | |
70 | - match 'profile/:profile/invite/:action', :controller => 'invite', :profile => /#{Noosfero.identifier_format}/ | |
69 | + match 'profile/:profile/invite/friends', :controller => 'invite', :action => 'invite_friends', :profile => /#{Noosfero.identifier_format_in_url}/ | |
70 | + match 'profile/:profile/invite/:action', :controller => 'invite', :profile => /#{Noosfero.identifier_format_in_url}/ | |
71 | 71 | |
72 | 72 | # feeds per tag |
73 | - match 'profile/:profile/tags/:id/feed', :controller => 'profile', :action =>'tag_feed', :id => /.+/, :profile => /#{Noosfero.identifier_format}/, :as => :tag_feed | |
73 | + match 'profile/:profile/tags/:id/feed', :controller => 'profile', :action =>'tag_feed', :id => /.+/, :profile => /#{Noosfero.identifier_format_in_url}/, :as => :tag_feed | |
74 | 74 | |
75 | 75 | # profile tags |
76 | - match 'profile/:profile/tags/:id', :controller => 'profile', :action => 'content_tagged', :id => /.+/, :profile => /#{Noosfero.identifier_format}/ | |
77 | - match 'profile/:profile/tags(/:id)', :controller => 'profile', :action => 'tags', :profile => /#{Noosfero.identifier_format}/ | |
76 | + match 'profile/:profile/tags/:id', :controller => 'profile', :action => 'content_tagged', :id => /.+/, :profile => /#{Noosfero.identifier_format_in_url}/ | |
77 | + match 'profile/:profile/tags(/:id)', :controller => 'profile', :action => 'tags', :profile => /#{Noosfero.identifier_format_in_url}/ | |
78 | 78 | |
79 | 79 | # profile search |
80 | - match 'profile/:profile/search', :controller => 'profile_search', :action => 'index', :profile => /#{Noosfero.identifier_format}/ | |
80 | + match 'profile/:profile/search', :controller => 'profile_search', :action => 'index', :profile => /#{Noosfero.identifier_format_in_url}/ | |
81 | 81 | |
82 | 82 | # comments |
83 | - match 'profile/:profile/comment/:action/:id', :controller => 'comment', :profile => /#{Noosfero.identifier_format}/ | |
83 | + match 'profile/:profile/comment/:action/:id', :controller => 'comment', :profile => /#{Noosfero.identifier_format_in_url}/ | |
84 | 84 | |
85 | 85 | # public profile information |
86 | - match 'profile/:profile(/:action(/:id))', :controller => 'profile', :action => 'index', :id => /[^\/]*/, :profile => /#{Noosfero.identifier_format}/, :as => :profile | |
86 | + match 'profile/:profile(/:action(/:id))', :controller => 'profile', :action => 'index', :id => /[^\/]*/, :profile => /#{Noosfero.identifier_format_in_url}/, :as => :profile | |
87 | 87 | |
88 | 88 | # contact |
89 | - match 'contact/:profile/:action(/:id)', :controller => 'contact', :action => 'index', :id => /.*/, :profile => /#{Noosfero.identifier_format}/ | |
89 | + match 'contact/:profile/:action(/:id)', :controller => 'contact', :action => 'index', :id => /.*/, :profile => /#{Noosfero.identifier_format_in_url}/ | |
90 | 90 | |
91 | 91 | # map balloon |
92 | 92 | match 'map_balloon/:action/:id', :controller => 'map_balloon', :id => /.*/ |
... | ... | @@ -98,8 +98,8 @@ Noosfero::Application.routes.draw do |
98 | 98 | ## Controllers that are profile-specific (for profile admins ) |
99 | 99 | ###################################################### |
100 | 100 | # profile customization - "My profile" |
101 | - match 'myprofile/:profile', :controller => 'profile_editor', :action => 'index', :profile => /#{Noosfero.identifier_format}/ | |
102 | - match 'myprofile/:profile/:controller(/:action(/:id))', :controller => Noosfero.pattern_for_controllers_in_directory('my_profile'), :profile => /#{Noosfero.identifier_format}/, :as => :myprofile | |
101 | + match 'myprofile/:profile', :controller => 'profile_editor', :action => 'index', :profile => /#{Noosfero.identifier_format_in_url}/ | |
102 | + match 'myprofile/:profile/:controller(/:action(/:id))', :controller => Noosfero.pattern_for_controllers_in_directory('my_profile'), :profile => /#{Noosfero.identifier_format_in_url}/, :as => :myprofile | |
103 | 103 | |
104 | 104 | |
105 | 105 | ###################################################### |
... | ... | @@ -127,14 +127,14 @@ Noosfero::Application.routes.draw do |
127 | 127 | # cache stuff - hack |
128 | 128 | match 'public/:action/:id', :controller => 'public' |
129 | 129 | |
130 | - match ':profile/*page/versions', :controller => 'content_viewer', :action => 'article_versions', :profile => /#{Noosfero.identifier_format}/, :constraints => EnvironmentDomainConstraint.new | |
130 | + match ':profile/*page/versions', :controller => 'content_viewer', :action => 'article_versions', :profile => /#{Noosfero.identifier_format_in_url}/, :constraints => EnvironmentDomainConstraint.new | |
131 | 131 | match '*page/versions', :controller => 'content_viewer', :action => 'article_versions' |
132 | 132 | |
133 | - match ':profile/*page/versions_diff', :controller => 'content_viewer', :action => 'versions_diff', :profile => /#{Noosfero.identifier_format}/, :constraints => EnvironmentDomainConstraint.new | |
133 | + match ':profile/*page/versions_diff', :controller => 'content_viewer', :action => 'versions_diff', :profile => /#{Noosfero.identifier_format_in_url}/, :constraints => EnvironmentDomainConstraint.new | |
134 | 134 | match '*page/versions_diff', :controller => 'content_viewer', :action => 'versions_diff' |
135 | 135 | |
136 | 136 | # match requests for profiles that don't have a custom domain |
137 | - match ':profile(/*page)', :controller => 'content_viewer', :action => 'view_page', :profile => /#{Noosfero.identifier_format}/, :constraints => EnvironmentDomainConstraint.new | |
137 | + match ':profile(/*page)', :controller => 'content_viewer', :action => 'view_page', :profile => /#{Noosfero.identifier_format_in_url}/, :constraints => EnvironmentDomainConstraint.new | |
138 | 138 | |
139 | 139 | # match requests for content in domains hosted for profiles |
140 | 140 | match '/(*page)', :controller => 'content_viewer', :action => 'view_page' | ... | ... |
db/migrate/20150210143723_add_custom_roles_permission_to_admin_roles.rb
0 → 100644
... | ... | @@ -0,0 +1,18 @@ |
1 | +class AddCustomRolesPermissionToAdminRoles < ActiveRecord::Migration | |
2 | + def self.up | |
3 | + environment_admin = Role.find_by_key("environment_administrator") | |
4 | + profile_admin = Role.find_by_key("profile_admin") | |
5 | + environment_admin.permissions.append("manage_custom_roles") | |
6 | + profile_admin.permissions.append("manage_custom_roles") | |
7 | + environment_admin.save! | |
8 | + profile_admin.save! | |
9 | + end | |
10 | + def self.down | |
11 | + environment_admin = Role.find_by_key("environment_administrator") | |
12 | + profile_admin = Role.find_by_key("profile_admin") | |
13 | + environment_admin.permissions.delete("manage_custom_roles") | |
14 | + profile_admin.permissions.delete("manage_custom_roles") | |
15 | + environment_admin.save! | |
16 | + profile_admin.save! | |
17 | + end | |
18 | +end | ... | ... |
db/migrate/20150423144533_add_new_box_to_every_environment_and_profile.rb
0 → 100644
... | ... | @@ -0,0 +1,15 @@ |
1 | +class AddNewBoxToEveryEnvironmentAndProfile < ActiveRecord::Migration | |
2 | + def up | |
3 | + Environment.find_each do |env| | |
4 | + env.boxes << Box.new if env.boxes.count < 4 | |
5 | + end | |
6 | + | |
7 | + Profile.find_each do |profile| | |
8 | + profile.boxes << Box.new if profile.boxes.count < 4 | |
9 | + end | |
10 | + end | |
11 | + | |
12 | + def down | |
13 | + say "this migration can't be reverted" | |
14 | + end | |
15 | +end | ... | ... |
db/schema.rb
... | ... | @@ -593,6 +593,7 @@ ActiveRecord::Schema.define(:version => 20150408231524) do |
593 | 593 | t.boolean "system", :default => false |
594 | 594 | t.text "permissions" |
595 | 595 | t.integer "environment_id" |
596 | + t.integer "profile_id" | |
596 | 597 | end |
597 | 598 | |
598 | 599 | create_table "scraps", :force => true do |t| | ... | ... |
debian/changelog
1 | +noosfero (1.2~0) UNRELEASED; urgency=medium | |
2 | + | |
3 | + * Temporary version in heavy development | |
4 | + | |
5 | + -- Antonio Terceiro <terceiro@debian.org> Fri, 08 May 2015 16:08:18 -0300 | |
6 | + | |
7 | +noosfero (1.1) wheezy; urgency=low | |
8 | + | |
9 | + * Noosfero 1.1 final release | |
10 | + | |
11 | + -- Antonio Terceiro <terceiro@colivre.coop.br> Mon, 04 May 2015 18:47:35 -0300 | |
12 | + | |
1 | 13 | noosfero (1.1~rc4) wheezy; urgency=medium |
2 | 14 | |
3 | 15 | * Fourth release candidate for Noosfero 1.1 | ... | ... |
debian/control
... | ... | @@ -14,8 +14,8 @@ Build-Depends: cucumber, |
14 | 14 | ruby-database-cleaner, |
15 | 15 | ruby-gettext, |
16 | 16 | ruby-mocha, |
17 | - ruby-rspec, | |
18 | - ruby-rspec-rails, | |
17 | + ruby-rspec (>= 2.14), | |
18 | + ruby-rspec-rails (>= 2.14), | |
19 | 19 | ruby-selenium-webdriver, |
20 | 20 | ruby-sqlite3, |
21 | 21 | ruby-tidy, |
... | ... | @@ -59,7 +59,9 @@ Depends: adduser, |
59 | 59 | ruby-redcloth, |
60 | 60 | ruby-rest-client, |
61 | 61 | ruby-rmagick, |
62 | + ruby-sass-rails, | |
62 | 63 | ruby-tzinfo (>= 1.1.0-2~), |
64 | + ruby-uglifier, | |
63 | 65 | ruby-whenever, |
64 | 66 | ruby-will-paginate (>= 2.3.12-1~), |
65 | 67 | tango-icon-theme, | ... | ... |
debian/noosfero.install
... | ... | @@ -25,6 +25,7 @@ etc/init.d/noosfero etc/init.d |
25 | 25 | etc/logrotate.d/noosfero etc/logrotate.d |
26 | 26 | etc/noosfero/varnish-accept-language.vcl etc/noosfero |
27 | 27 | etc/noosfero/varnish-noosfero.vcl etc/noosfero |
28 | +etc/awstats-noosfero.conf etc/noosfero | |
28 | 29 | lib usr/share/noosfero |
29 | 30 | locale usr/share/noosfero |
30 | 31 | plugins usr/share/noosfero | ... | ... |
... | ... | @@ -0,0 +1,20 @@ |
1 | +Feature: Change appearance | |
2 | + As a user | |
3 | + I want to change the appearance of my profile page | |
4 | + | |
5 | + Background: | |
6 | + Given the following users | |
7 | + | login | name | | |
8 | + | joaosilva | Joao Silva | | |
9 | + | |
10 | + Scenario: Change appearance from default(3 boxes) to Left Top and Right(4 boxes) | |
11 | + Given I am logged in as "joaosilva" | |
12 | + And I go to joaosilva's control panel | |
13 | + And I follow "Edit sideboxes" | |
14 | + And I should not see an element ".box-4" | |
15 | + And I go to joaosilva's control panel | |
16 | + And I follow "Edit Appearance" | |
17 | + And I follow "Left Top and Right" | |
18 | + And I go to joaosilva's control panel | |
19 | + And I follow "Edit sideboxes" | |
20 | + And I should see an element ".box-4" | ... | ... |
features/signup.feature
... | ... | @@ -267,32 +267,6 @@ Feature: signup |
267 | 267 | Then I should be on the homepage |
268 | 268 | |
269 | 269 | @selenium |
270 | - Scenario: join community on signup | |
271 | - Given the following users | |
272 | - | login | name | | |
273 | - | mariasilva | Maria Silva | | |
274 | - And the following communities | |
275 | - | name | identifier | owner | | |
276 | - | Free Software | freesoftware | mariasilva | | |
277 | - And feature "skip_new_user_email_confirmation" is disabled on environment | |
278 | - And I am on /freesoftware | |
279 | - When I follow "Join" | |
280 | - And I follow "New user" | |
281 | - And I fill in the following within ".no-boxes": | |
282 | - | e-Mail | josesilva@example.com | | |
283 | - | Username | josesilva | | |
284 | - | Password | secret | | |
285 | - | Password confirmation | secret | | |
286 | - | Full name | José da Silva | | |
287 | - And wait for the captcha signup time | |
288 | - And I press "Create my account" | |
289 | - And I go to josesilva's confirmation URL | |
290 | - And I fill in "Username" with "josesilva" | |
291 | - And I fill in "Password" with "secret" | |
292 | - And I press "Log in" | |
293 | - Then "José da Silva" should be a member of "Free Software" | |
294 | - | |
295 | - @selenium | |
296 | 270 | Scenario: user registration is moderated by admin |
297 | 271 | Given feature "admin_must_approve_new_users" is enabled on environment |
298 | 272 | And feature "skip_new_user_email_confirmation" is disabled on environment | ... | ... |
features/step_definitions/noosfero_steps.rb
... | ... | @@ -94,8 +94,8 @@ Given /^the following blocks$/ do |table| |
94 | 94 | owner.boxes<< Box.new |
95 | 95 | owner.boxes.first.blocks << MainBlock.new |
96 | 96 | end |
97 | - box_id = owner.boxes.last.id | |
98 | - klass.constantize.create!(item.merge(:box_id => box_id)) | |
97 | + box = owner.boxes.where(:position => 3).first | |
98 | + klass.constantize.create!(item.merge(:box => box)) | |
99 | 99 | end |
100 | 100 | end |
101 | 101 | ... | ... |
lib/authenticated_system.rb
lib/noosfero.rb
... | ... | @@ -57,6 +57,12 @@ module Noosfero |
57 | 57 | '[a-z0-9][a-z0-9~.]*([_\-][a-z0-9~.]+)*' |
58 | 58 | end |
59 | 59 | |
60 | + # All valid identifiers, plus ~ meaning "the current user". See | |
61 | + # ApplicationController#redirect_to_current_user | |
62 | + def self.identifier_format_in_url | |
63 | + "(#{identifier_format}|~)" | |
64 | + end | |
65 | + | |
60 | 66 | def self.default_hostname |
61 | 67 | Environment.table_exists? && Environment.default ? Environment.default.default_hostname : 'localhost' |
62 | 68 | end | ... | ... |
lib/noosfero/plugin.rb
... | ... | @@ -8,6 +8,10 @@ class Noosfero::Plugin |
8 | 8 | self.context = context |
9 | 9 | end |
10 | 10 | |
11 | + def environment | |
12 | + context.environment if self.context | |
13 | + end | |
14 | + | |
11 | 15 | class << self |
12 | 16 | |
13 | 17 | attr_writer :should_load |
... | ... | @@ -35,6 +39,7 @@ class Noosfero::Plugin |
35 | 39 | # filters must be loaded after all extensions |
36 | 40 | klasses.each do |plugin| |
37 | 41 | load_plugin_filters plugin |
42 | + load_plugin_hotspots plugin | |
38 | 43 | end |
39 | 44 | end |
40 | 45 | |
... | ... | @@ -108,6 +113,23 @@ class Noosfero::Plugin |
108 | 113 | end |
109 | 114 | end |
110 | 115 | |
116 | + # This is a generic method to extend the hotspots list with plugins | |
117 | + # hotspots. This allows plugins to extend other plugins. | |
118 | + # To use this, the plugin must define its hotspots inside a module Hotspots. | |
119 | + # Its also needed to include Noosfero::Plugin::HotSpot module | |
120 | + # in order to dispatch plugins methods. | |
121 | + # | |
122 | + # Checkout FooPlugin for usage example. | |
123 | + def load_plugin_hotspots(plugin) | |
124 | + ActionDispatch::Reloader.to_prepare do | |
125 | + begin | |
126 | + module_name = "#{plugin.name}::Hotspots" | |
127 | + Noosfero::Plugin.send(:include, module_name.constantize) | |
128 | + rescue NameError | |
129 | + end | |
130 | + end | |
131 | + end | |
132 | + | |
111 | 133 | def add_controller_filters(controller_class, plugin, filters) |
112 | 134 | unless filters.is_a?(Array) |
113 | 135 | filters = [filters] | ... | ... |
lib/noosfero/version.rb
lib/tasks/backup.rake
1 | -desc "Creates a backup of the user files stored in public/" | |
2 | -task :backup do | |
3 | - dirs = Dir.glob('public/images/[0-9][0-9][0-9][0-9]') + ['public/articles', 'public/thumbnails', 'public/user_themes'].select { |d| File.exists?(d) } | |
4 | - tarball = 'backups/files-' + Time.now.strftime('%Y-%m-%d-%R') + '.tar' | |
1 | +task :load_backup_config do | |
2 | + $config = YAML.load_file('config/database.yml') | |
3 | +end | |
4 | + | |
5 | +task :check_backup_support => :load_backup_config do | |
6 | + if $config['production']['adapter'] != 'postgresql' | |
7 | + fail("Only PostgreSQL is supported for backups at the moment") | |
8 | + end | |
9 | +end | |
10 | + | |
11 | +backup_dirs = [ | |
12 | + 'public/image_uploads', | |
13 | + 'public/articles', | |
14 | + 'public/thumbnails', | |
15 | + 'public/user_themes', | |
16 | +] | |
17 | + | |
18 | +desc "Creates a backup of the database and uploaded files" | |
19 | +task :backup => :check_backup_support do | |
20 | + dirs = backup_dirs.select { |d| File.exists?(d) } | |
21 | + | |
22 | + backup_name = Time.now.strftime('%Y-%m-%d-%R') | |
23 | + backup_file = File.join('tmp/backup', backup_name) + '.tar.gz' | |
24 | + mkdir_p 'tmp/backup' | |
25 | + dump = File.join('tmp/backup', backup_name) + '.sql' | |
26 | + | |
27 | + database = $config['production']['database'] | |
28 | + host = $config['production']['host'] | |
29 | + sh "pg_dump -h #{host} #{database} > #{dump}" | |
30 | + | |
31 | + sh 'tar', 'chaf', backup_file, dump, *dirs | |
32 | + rm_f dump | |
33 | + | |
34 | + puts "****************************************************" | |
35 | + puts "Backup in #{backup_file} !" | |
36 | + puts | |
37 | + puts "To restore, use:" | |
38 | + puts "$ rake restore BACKUP=#{backup_file}" | |
39 | + puts "****************************************************" | |
40 | +end | |
41 | + | |
42 | +def invalid_backup!(message, items=[]) | |
43 | + puts "E: #{message}" | |
44 | + items.each do |i| | |
45 | + puts "E: - #{i}" | |
46 | + end | |
47 | + puts "E: Is this a backup archive created by Noosfero with \`rake backup\`?" | |
48 | + exit 1 | |
49 | +end | |
50 | + | |
51 | +desc "Restores a backup created previousy with \`rake backup\`" | |
52 | +task :restore => :check_backup_support do | |
53 | + backup = ENV["BACKUP"] | |
54 | + unless backup | |
55 | + puts "usage: rake restore BACKUP=/path/to/backup" | |
56 | + exit 1 | |
57 | + end | |
58 | + | |
59 | + files = `tar taf #{backup}`.split | |
60 | + | |
61 | + # validate files in the backup | |
62 | + invalid_files = [] | |
63 | + files.each do |f| | |
64 | + if f !~ /tmp\/backup\// && (backup_dirs.none? { |d| f =~ /^#{d}\// }) | |
65 | + invalid_files << f | |
66 | + end | |
67 | + end | |
68 | + if invalid_files.size > 0 | |
69 | + invalid_backup!("Invalid files found in the backup archive", invalid_files) | |
70 | + end | |
71 | + | |
72 | + # find database dump in the archive | |
73 | + dumps = files.select do |f| | |
74 | + File.dirname(f) == 'tmp/backup' && f =~ /\.sql$/ | |
75 | + end | |
76 | + if dumps.size == 0 | |
77 | + invalid_backup!("Could not find a database dump in the archive.") | |
78 | + elsif dumps.size > 1 | |
79 | + invalid_backup!("Multiple database dumps found in the archive:", dumps) | |
80 | + end | |
81 | + dump = dumps.first | |
82 | + | |
83 | + database = $config['production']['database'] | |
84 | + username = $config['production']['username'] | |
85 | + host = $config['production']['host'] | |
86 | + | |
87 | + puts "WARNING: backups should be restored to an empty database, otherwise" | |
88 | + puts "data from the backup may not be loaded properly." | |
89 | + puts | |
90 | + puts 'You can remove the existing database and create a new one with:' | |
91 | + puts | |
92 | + puts "$ sudo -u postgres dropdb -h #{host} #{database}" | |
93 | + puts "$ sudo -u postgres createdb -h #{host} #{database} --owner #{username}" | |
94 | + puts | |
95 | + print "Are you sure you want to continue (y/N)? " | |
96 | + response = $stdin.gets.strip | |
97 | + unless ['y', 'yes'].include?(response.downcase) | |
98 | + puts "*** ABORTED." | |
99 | + exit 1 | |
100 | + end | |
101 | + | |
102 | + sh 'tar', 'xaf', backup | |
103 | + sh "rails dbconsole production < #{dump}" | |
104 | + rm_f dump | |
5 | 105 | |
6 | - mkdir_p(File.dirname(tarball)) | |
7 | - sh('tar', 'cf', tarball, *dirs) | |
106 | + puts "****************************************************" | |
107 | + puts "Backup restored!" | |
108 | + puts "****************************************************" | |
8 | 109 | end | ... | ... |
lib/tasks/doc.rake
... | ... | @@ -12,9 +12,8 @@ namespace :noosfero do |
12 | 12 | end |
13 | 13 | end |
14 | 14 | task :unlink_plugins_textiles do |
15 | - root = Pathname.new(File.dirname(__FILE__) + '/../..').expand_path | |
16 | - rm_f Dir.glob(root.join('doc/noosfero/plugins/*.textile')) - | |
17 | - [root.join('doc/noosfero/plugins/index.textile')] | |
15 | + rm_f Dir.glob('doc/noosfero/plugins/*.textile') - | |
16 | + ['doc/noosfero/plugins/index.textile'] | |
18 | 17 | end |
19 | 18 | input = Dir.glob('doc/noosfero/**/*.textile') + plugins_textiles.map{|i| "doc/noosfero/plugins/#{File.basename(i)}"} |
20 | 19 | topics_xhtml = input.map { |item| item.sub('.textile', '.en.xhtml') }.uniq | ... | ... |
lib/tasks/error_messages.rake
... | ... | @@ -4,7 +4,7 @@ targets = [] |
4 | 4 | templates.each do |template| |
5 | 5 | target = template.gsub(/.erb$/, '') |
6 | 6 | targets << target |
7 | - file target => [:makemo, template] do | |
7 | + file target => [:makemo, template, :environment] do | |
8 | 8 | require 'erb' |
9 | 9 | erb = ERB.new(File.read(template)) |
10 | 10 | File.open(target, 'w') do |file| | ... | ... |
plugins/event/po/pt/event.po
... | ... | @@ -5,8 +5,8 @@ |
5 | 5 | # |
6 | 6 | msgid "" |
7 | 7 | msgstr "" |
8 | -"Project-Id-Version: 1.0-690-gcb6e853\n" | |
9 | -"POT-Creation-Date: 2015-03-05 12:09-0300\n" | |
8 | +"Project-Id-Version: 1.1~rc4\n" | |
9 | +"POT-Creation-Date: 2015-04-20 19:44-0300\n" | |
10 | 10 | "PO-Revision-Date: 2015-01-30 00:18-0000\n" |
11 | 11 | "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" |
12 | 12 | "Language-Team: LANGUAGE <LL@li.org>\n" |
... | ... | @@ -16,61 +16,53 @@ msgstr "" |
16 | 16 | "Content-Transfer-Encoding: 8bit\n" |
17 | 17 | "Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n" |
18 | 18 | |
19 | +#: plugins/event/lib/event_plugin.rb:4 | |
20 | +msgid "Event Extras" | |
21 | +msgstr "Extras para Eventos" | |
22 | + | |
23 | +#: plugins/event/lib/event_plugin.rb:8 | |
24 | +msgid "" | |
25 | +"Include a new block to show the environment's or profiles' events information" | |
26 | +msgstr "" | |
27 | +"Adiciona um novo bloco para apresentar as informações de eventos do ambiente " | |
28 | +"ou dos perfis" | |
29 | + | |
19 | 30 | #: plugins/event/lib/event_plugin/event_block.rb:12 |
20 | 31 | msgid "Events" |
21 | 32 | msgstr "Eventos" |
22 | 33 | |
23 | 34 | #: plugins/event/lib/event_plugin/event_block.rb:16 |
24 | 35 | msgid "Show the profile events or all environment events." |
25 | -msgstr "Mostrar todos os eventos." | |
36 | +msgstr "Mostra todos os eventos de um perfil ou do ambiente." | |
26 | 37 | |
27 | 38 | #: plugins/event/lib/event_plugin/event_block.rb:65 |
28 | -#, fuzzy | |
29 | 39 | msgid "One month ago" |
30 | 40 | msgid_plural "%d months ago" |
31 | -msgstr[0] "Iniciou a um mês atrás." | |
32 | -msgstr[1] "Iniciou a %d meses atrás." | |
41 | +msgstr[0] "Um mês atrás" | |
42 | +msgstr[1] "%d meses atrás." | |
33 | 43 | |
34 | 44 | #: plugins/event/lib/event_plugin/event_block.rb:67 |
35 | 45 | msgid "Yesterday" |
36 | 46 | msgid_plural "%d days ago" |
37 | -msgstr[0] "" | |
38 | -msgstr[1] "" | |
47 | +msgstr[0] "Ontem" | |
48 | +msgstr[1] "%d dias atrás" | |
39 | 49 | |
40 | 50 | #: plugins/event/lib/event_plugin/event_block.rb:69 |
41 | 51 | msgid "Today" |
42 | -msgstr "" | |
52 | +msgstr "Hoje" | |
43 | 53 | |
44 | 54 | #: plugins/event/lib/event_plugin/event_block.rb:71 |
45 | 55 | msgid "Tomorrow" |
46 | 56 | msgid_plural "%d days left to start" |
47 | -msgstr[0] "" | |
48 | -msgstr[1] "" | |
57 | +msgstr[0] "Amanhã" | |
58 | +msgstr[1] "%d dias para começar" | |
49 | 59 | |
50 | 60 | #: plugins/event/lib/event_plugin/event_block.rb:73 |
51 | -#, fuzzy | |
52 | 61 | msgid "One month left to start" |
53 | 62 | msgid_plural "%d months left to start" |
54 | 63 | msgstr[0] "Um mês para iniciar" |
55 | 64 | msgstr[1] "% meses para iniciar" |
56 | 65 | |
57 | -#: plugins/event/lib/event_plugin.rb:4 | |
58 | -msgid "Event Extras" | |
59 | -msgstr "Eventos" | |
60 | - | |
61 | -#: plugins/event/lib/event_plugin.rb:8 | |
62 | -msgid "" | |
63 | -"Include a new block to show the environment's or profiles' events information" | |
64 | -msgstr "" | |
65 | -"Adiciona um novo bloco para apresentar as informações de eventos do ambiente " | |
66 | -"ou de perfis" | |
67 | - | |
68 | -#: plugins/event/views/event_plugin/event_block_item.html.erb:6 | |
69 | -msgid "Duration: 1 day" | |
70 | -msgid_plural "Duration: %s days" | |
71 | -msgstr[0] "" | |
72 | -msgstr[1] "" | |
73 | - | |
74 | 66 | #: plugins/event/views/profile_design/event_plugin/_event_block.html.erb:1 |
75 | 67 | msgid "Limit of items" |
76 | 68 | msgstr "Limite de itens" |
... | ... | @@ -94,12 +86,17 @@ msgstr "Mostrar apenas eventos futuros" |
94 | 86 | |
95 | 87 | #: plugins/event/views/profile_design/event_plugin/_event_block.html.erb:22 |
96 | 88 | msgid "Limit of days to display" |
97 | -msgstr "Limite de dias de distância para mostrar eventos" | |
89 | +msgstr "Limite de dias para mostrar" | |
98 | 90 | |
99 | 91 | #: plugins/event/views/profile_design/event_plugin/_event_block.html.erb:24 |
100 | -#, fuzzy | |
101 | 92 | msgid "Only show events in this interval of days." |
102 | -msgstr "Mostar somente eventos que acontecem dentro do limite de dias" | |
93 | +msgstr "Mostar somente os eventos nesse intervalo de dias" | |
94 | + | |
95 | +#: plugins/event/views/event_plugin/event_block_item.html.erb:6 | |
96 | +msgid "Duration: 1 day" | |
97 | +msgid_plural "Duration: %s days" | |
98 | +msgstr[0] "Duração: 1 dia" | |
99 | +msgstr[1] "Duração: %s dias" | |
103 | 100 | |
104 | 101 | #~ msgid "Started one day ago." |
105 | 102 | #~ msgid_plural "Started %d days ago." | ... | ... |
plugins/foo/lib/foo_plugin.rb
1 | 1 | class FooPlugin < Noosfero::Plugin |
2 | + include Noosfero::Plugin::HotSpot | |
2 | 3 | |
3 | 4 | def self.plugin_name |
4 | 5 | "Foo" |
... | ... | @@ -8,12 +9,29 @@ class FooPlugin < Noosfero::Plugin |
8 | 9 | _("A sample plugin to test autoload craziness.") |
9 | 10 | end |
10 | 11 | |
12 | + module Hotspots | |
13 | + # -> Custom foo plugin hotspot | |
14 | + # do something to extend the FooPlugin behaviour | |
15 | + # receive params a, b and c | |
16 | + # returns = boolean or something else | |
17 | + def foo_plugin_my_hotspot(a, b, c) | |
18 | + end | |
19 | + | |
20 | + # -> Custom title for foo profiles tab | |
21 | + # returns = a string with a custom title | |
22 | + def foo_plugin_tab_title | |
23 | + end | |
24 | + end | |
25 | + | |
11 | 26 | def control_panel_buttons |
12 | 27 | {:title => 'Foo plugin button', :icon => '', :url => ''} |
13 | 28 | end |
14 | 29 | |
15 | 30 | def profile_tabs |
16 | - {:title => 'Foo plugin tab', :id => 'foo_plugin', :content => lambda {'Foo plugin random content'} } | |
31 | + title = plugins.dispatch_first(:foo_plugin_tab_title) | |
32 | + title = 'Foo plugin tab' unless title | |
33 | + | |
34 | + {:title => title, :id => 'foo_plugin', :content => lambda {'Foo plugin random content'} } | |
17 | 35 | end |
18 | 36 | |
19 | 37 | end | ... | ... |
plugins/foo/test/unit/foo_plugin_test.rb
... | ... | @@ -4,7 +4,25 @@ class FooPluginTest < ActiveSupport::TestCase |
4 | 4 | def test_foo |
5 | 5 | FooPlugin::Bar.create! |
6 | 6 | end |
7 | + | |
7 | 8 | def test_monkey_patch |
8 | 9 | Profile.new.bar |
9 | 10 | end |
11 | + | |
12 | + should "respond to new hotspots" do | |
13 | + plugin = FooPlugin.new | |
14 | + | |
15 | + assert plugin.respond_to?(:foo_plugin_my_hotspot) | |
16 | + assert plugin.respond_to?(:foo_plugin_tab_title) | |
17 | + end | |
18 | + | |
19 | + should "other plugin respond to new hotspots" do | |
20 | + class TestPlugin < Noosfero::Plugin | |
21 | + end | |
22 | + | |
23 | + plugin = TestPlugin.new | |
24 | + | |
25 | + assert plugin.respond_to?(:foo_plugin_my_hotspot) | |
26 | + assert plugin.respond_to?(:foo_plugin_tab_title) | |
27 | + end | |
10 | 28 | end | ... | ... |
plugins/google_analytics/lib/ext/profile.rb
... | ... | @@ -2,4 +2,9 @@ require_dependency 'profile' |
2 | 2 | |
3 | 3 | class Profile |
4 | 4 | settings_items :google_analytics_profile_id |
5 | + attr_accessible :google_analytics_profile_id | |
6 | + | |
7 | + descendants.each do |descendant| | |
8 | + descendant.attr_accessible :google_analytics_profile_id | |
9 | + end | |
5 | 10 | end | ... | ... |
plugins/google_analytics/lib/google_analytics_plugin.rb
... | ... | @@ -19,12 +19,15 @@ class GoogleAnalyticsPlugin < Noosfero::Plugin |
19 | 19 | |
20 | 20 | def head_ending |
21 | 21 | unless profile_id.blank? |
22 | - expanded_template('tracking-code.rhtml',{:profile_id => profile_id}) | |
22 | + expanded_template('tracking-code.html.erb',{:profile_id => profile_id}) | |
23 | 23 | end |
24 | 24 | end |
25 | 25 | |
26 | 26 | def profile_editor_extras |
27 | - expanded_template('profile-editor-extras.rhtml',{:profile_id => profile_id}) | |
27 | + analytics_id = profile_id | |
28 | + lambda { | |
29 | + render :file => 'profile-editor-extras', :locals => { :profile_id => analytics_id } | |
30 | + } | |
28 | 31 | end |
29 | 32 | |
30 | 33 | end | ... | ... |
plugins/google_analytics/test/functional/profile_editor_controller_test.rb
0 → 100644
... | ... | @@ -0,0 +1,31 @@ |
1 | +require 'test_helper' | |
2 | +require 'profile_editor_controller' | |
3 | + | |
4 | +# Re-raise errors caught by the controller. | |
5 | +class ProfileEditorController; def rescue_action(e) raise e end; end | |
6 | + | |
7 | +class ProfileEditorControllerTest < ActionController::TestCase | |
8 | + | |
9 | + def setup | |
10 | + @controller = ProfileEditorController.new | |
11 | + @request = ActionController::TestRequest.new | |
12 | + @response = ActionController::TestResponse.new | |
13 | + @profile = create_user('default_user').person | |
14 | + login_as(@profile.identifier) | |
15 | + Environment.default.enable_plugin(GoogleAnalyticsPlugin.name) | |
16 | + end | |
17 | + | |
18 | + attr_accessor :profile | |
19 | + | |
20 | + should 'add extra fields to profile editor info and settings' do | |
21 | + get :edit, :profile => profile.identifier | |
22 | + assert_tag_in_string @response.body, :tag => 'label', :content => /Google Analytics/, :attributes => { :for => 'profile_data_google_analytics_profile_id' } | |
23 | + assert_tag_in_string @response.body, :tag => 'input', :attributes => { :id => 'profile_data_google_analytics_profile_id' } | |
24 | + end | |
25 | + | |
26 | + should 'save code filled in on field' do | |
27 | + post :edit, :profile => profile.identifier, :profile_data => {:google_analytics_profile_id => 12345678} | |
28 | + assert_equal '12345678', Person.find(profile.id).google_analytics_profile_id | |
29 | + end | |
30 | + | |
31 | +end | ... | ... |
plugins/google_analytics/test/unit/google_analytics_plugin_test.rb
... | ... | @@ -27,11 +27,6 @@ class GoogleAnalyticsPluginTest < ActiveSupport::TestCase |
27 | 27 | assert_equal 'content', @plugin.head_ending |
28 | 28 | end |
29 | 29 | |
30 | - should 'add extra fields to profile editor info and settings' do | |
31 | - assert_tag_in_string @plugin.profile_editor_extras, | |
32 | - :tag => 'input', :attributes => {:id => 'profile_data_google_analytics_profile_id', :value => 10} | |
33 | - end | |
34 | - | |
35 | 30 | should 'extends Profile with attr google_analytics_profile_id' do |
36 | 31 | assert_respond_to Profile.new, :google_analytics_profile_id |
37 | 32 | end | ... | ... |
plugins/google_analytics/views/profile-editor-extras.html.erb
0 → 100644
... | ... | @@ -0,0 +1,3 @@ |
1 | +<h2><%= c_('Statistics') %></h2> | |
2 | +<%= labelled_form_field(_('Google Analytics Profile ID'), text_field(:profile_data, :google_analytics_profile_id, :value => profile_id)) %> | |
3 | +<%= link_to(_('See how to configure statistics for your profile'), '/doc/plugins/google_analytics', :target => '_blank') %> | ... | ... |
plugins/google_analytics/views/profile-editor-extras.rhtml
... | ... | @@ -1,5 +0,0 @@ |
1 | -<% extend ApplicationHelper %> | |
2 | - | |
3 | -<h2><%= c_('Statistics') %></h2> | |
4 | -<%= labelled_form_field(_('Google Analytics Profile ID'), text_field(:profile_data, :google_analytics_profile_id, :value => profile_id)) %> | |
5 | -<%= link_to(_('See how to configure statistics for your profile'), '/doc/plugins/google_analytics', :target => '_blank') %> |
... | ... | @@ -0,0 +1,9 @@ |
1 | +<script> | |
2 | + (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ | |
3 | + (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o), | |
4 | + m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) | |
5 | + })(window,document,'script','//www.google-analytics.com/analytics.js','ga'); | |
6 | + | |
7 | + ga('create', '<%= escape_javascript locals[:profile_id] %>', 'auto'); | |
8 | + ga('send', 'pageview'); | |
9 | +</script> | ... | ... |
plugins/google_analytics/views/tracking-code.rhtml
... | ... | @@ -1,10 +0,0 @@ |
1 | -<script type="text/javascript"> | |
2 | - var _gaq = _gaq || []; | |
3 | - _gaq.push(['_setAccount', '<%= escape_javascript locals[:profile_id] %>']); | |
4 | - _gaq.push(['_trackPageview']); | |
5 | - (function() { | |
6 | - var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true; | |
7 | - ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'; | |
8 | - var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s); | |
9 | - })(); | |
10 | -</script> |
plugins/ldap/lib/ldap_authentication.rb
... | ... | @@ -77,18 +77,20 @@ class LdapAuthentication |
77 | 77 | end |
78 | 78 | |
79 | 79 | def get_user_attributes_from_ldap_entry(entry) |
80 | - { | |
81 | - :dn => entry.dn, | |
82 | - :fullname => LdapAuthentication.get_attr(entry, self.attr_fullname), | |
83 | - :mail => LdapAuthentication.get_attr(entry, self.attr_mail), | |
84 | - } | |
80 | + attributes = entry.instance_values["myhash"] | |
81 | + | |
82 | + attributes[:dn] = entry.dn | |
83 | + attributes[:fullname] = LdapAuthentication.get_attr(entry, self.attr_fullname) | |
84 | + attributes[:mail] = LdapAuthentication.get_attr(entry, self.attr_mail) | |
85 | + | |
86 | + attributes | |
85 | 87 | end |
86 | 88 | |
87 | 89 | # Return the attributes needed for the LDAP search. It will only |
88 | 90 | # include the user attributes if on-the-fly registration is enabled |
89 | 91 | def search_attributes |
90 | 92 | if onthefly_register? |
91 | - ['dn', self.attr_fullname, self.attr_mail] | |
93 | + nil | |
92 | 94 | else |
93 | 95 | ['dn'] |
94 | 96 | end |
... | ... | @@ -111,6 +113,7 @@ class LdapAuthentication |
111 | 113 | end |
112 | 114 | login_filter = Net::LDAP::Filter.eq( self.attr_login, login ) |
113 | 115 | object_filter = Net::LDAP::Filter.eq( "objectClass", "*" ) |
116 | + | |
114 | 117 | attrs = {} |
115 | 118 | |
116 | 119 | search_filter = object_filter & login_filter | ... | ... |
plugins/ldap/lib/ldap_plugin.rb
1 | 1 | require File.dirname(__FILE__) + '/ldap_authentication.rb' |
2 | 2 | |
3 | 3 | class LdapPlugin < Noosfero::Plugin |
4 | + include Noosfero::Plugin::HotSpot | |
4 | 5 | |
5 | 6 | def self.plugin_name |
6 | 7 | "LdapPlugin" |
... | ... | @@ -10,6 +11,26 @@ class LdapPlugin < Noosfero::Plugin |
10 | 11 | _("A plugin that add ldap support.") |
11 | 12 | end |
12 | 13 | |
14 | + module Hotspots | |
15 | + # -> Custom ldap plugin hotspot to set profile data before user creation | |
16 | + # receive the followings params: | |
17 | + # - attrs with ldap received data | |
18 | + # - login received by ldap | |
19 | + # - params from current context | |
20 | + # returns = updated person_data hash | |
21 | + def ldap_plugin_set_profile_data(attrs, params) | |
22 | + [attrs, params] | |
23 | + end | |
24 | + | |
25 | + # -> Custom ldap plugin hotspot to update user object | |
26 | + # receive the followings params: | |
27 | + # - user: user object | |
28 | + # - attrs with ldap received data | |
29 | + # returns = none | |
30 | + def ldap_plugin_update_user(user, attrs) | |
31 | + end | |
32 | + end | |
33 | + | |
13 | 34 | def allow_user_registration |
14 | 35 | false |
15 | 36 | end |
... | ... | @@ -35,17 +56,22 @@ class LdapPlugin < Noosfero::Plugin |
35 | 56 | |
36 | 57 | if attrs |
37 | 58 | user.login = login |
38 | - user.email = attrs[:mail] | |
59 | + user.email = get_email(attrs, login) | |
39 | 60 | user.name = attrs[:fullname] |
40 | 61 | user.password = password |
41 | 62 | user.password_confirmation = password |
42 | - user.person_data = context.params[:profile_data] | |
63 | + user.person_data = plugins.pipeline(:ldap_plugin_set_profile_data, attrs, context.params).last[:profile_data] | |
43 | 64 | user.activated_at = Time.now.utc |
44 | 65 | user.activation_code = nil |
45 | 66 | |
46 | 67 | ldap = LdapAuthentication.new(context.environment.ldap_plugin_attributes) |
47 | 68 | begin |
48 | - user = nil unless user.save | |
69 | + if user.save | |
70 | + user.activate | |
71 | + plugins.dispatch(:ldap_plugin_update_user, user, attrs) | |
72 | + else | |
73 | + user = nil | |
74 | + end | |
49 | 75 | rescue |
50 | 76 | #User not saved |
51 | 77 | end |
... | ... | @@ -54,7 +80,6 @@ class LdapPlugin < Noosfero::Plugin |
54 | 80 | end |
55 | 81 | |
56 | 82 | else |
57 | - | |
58 | 83 | return nil if !user.activated? |
59 | 84 | |
60 | 85 | begin |
... | ... | @@ -69,6 +94,16 @@ class LdapPlugin < Noosfero::Plugin |
69 | 94 | user |
70 | 95 | end |
71 | 96 | |
97 | + def get_email(attrs, login) | |
98 | + return attrs[:mail] unless attrs[:mail].blank? | |
99 | + | |
100 | + if attrs[:fullname] | |
101 | + return attrs[:fullname].to_slug + "@ldap.user" | |
102 | + else | |
103 | + return login.to_slug + "@ldap.user" | |
104 | + end | |
105 | + end | |
106 | + | |
72 | 107 | def login_extra_contents |
73 | 108 | proc do |
74 | 109 | @person = Person.new(:environment => @environment) | ... | ... |
plugins/require_auth_to_comment/controllers/require_auth_to_comment_plugin_admin_controller.rb
0 → 100644
... | ... | @@ -0,0 +1,14 @@ |
1 | +class RequireAuthToCommentPluginAdminController < AdminController | |
2 | + | |
3 | + def index | |
4 | + settings = params[:settings] | |
5 | + settings ||= {} | |
6 | + @settings = Noosfero::Plugin::Settings.new(environment, RequireAuthToCommentPlugin, settings) | |
7 | + if request.post? | |
8 | + @settings.save! | |
9 | + session[:notice] = 'Settings succefully saved.' | |
10 | + redirect_to :action => 'index' | |
11 | + end | |
12 | + end | |
13 | + | |
14 | +end | ... | ... |
plugins/require_auth_to_comment/lib/require_auth_to_comment_plugin.rb
... | ... | @@ -21,11 +21,20 @@ class RequireAuthToCommentPlugin < Noosfero::Plugin |
21 | 21 | end |
22 | 22 | |
23 | 23 | def stylesheet? |
24 | - true | |
24 | + !display_login_popup? | |
25 | + end | |
26 | + | |
27 | + def display_login_popup? | |
28 | + settings = Noosfero::Plugin::Settings.new(context.environment, self.class) | |
29 | + settings.require_type == 'display_login_popup' | |
30 | + end | |
31 | + | |
32 | + def self.require_type_default_setting | |
33 | + 'hide_button' | |
25 | 34 | end |
26 | 35 | |
27 | 36 | def js_files |
28 | - ['hide_comment_form.js', 'jquery.livequery.min.js'] | |
37 | + ['hide_comment_form.js', 'jquery.livequery.min.js'] + (display_login_popup? ? ['comment_require_login.js'] : []) | |
29 | 38 | end |
30 | 39 | |
31 | 40 | def body_beginning | ... | ... |
plugins/require_auth_to_comment/public/comment_require_login.js
0 → 100644
... | ... | @@ -0,0 +1,8 @@ |
1 | +(function($) { | |
2 | + $(window).bind('userDataLoaded', function(event, data) { | |
3 | + if (!data.login && $('meta[name="profile.allow_unauthenticated_comments"]').length <= 0) { | |
4 | + $('.display-comment-form').unbind(); | |
5 | + $('.display-comment-form').addClass('require-login-popup'); | |
6 | + } | |
7 | + }); | |
8 | +})(jQuery); | ... | ... |
plugins/require_auth_to_comment/test/unit/require_auth_to_comment_plugin_test.rb
... | ... | @@ -5,9 +5,10 @@ class RequireAuthToCommentPluginTest < ActiveSupport::TestCase |
5 | 5 | def setup |
6 | 6 | @plugin = RequireAuthToCommentPlugin.new |
7 | 7 | @comment = Comment.new |
8 | + @environment = fast_create(Environment) | |
8 | 9 | end |
9 | 10 | |
10 | - attr_reader :plugin, :comment | |
11 | + attr_reader :plugin, :comment, :environment | |
11 | 12 | |
12 | 13 | should 'reject comments for unauthenticated users' do |
13 | 14 | plugin.context = logged_in(false) |
... | ... | @@ -29,6 +30,35 @@ class RequireAuthToCommentPluginTest < ActiveSupport::TestCase |
29 | 30 | assert !comment.rejected? |
30 | 31 | end |
31 | 32 | |
33 | + should 'the default require type setting be hide_button' do | |
34 | + assert_equal 'hide_button', plugin.class.require_type_default_setting | |
35 | + end | |
36 | + | |
37 | + should 'display_login_popup? be false by default' do | |
38 | + context = mock(); | |
39 | + context.expects(:environment).returns(environment) | |
40 | + plugin.expects(:context).returns(context) | |
41 | + assert !plugin.display_login_popup? | |
42 | + end | |
43 | + | |
44 | + should 'display_login_popup? be true if require_type is defined as display_login_popup' do | |
45 | + context = mock(); | |
46 | + context.expects(:environment).returns(environment) | |
47 | + environment[:settings] = {:require_auth_to_comment_plugin => {:require_type => "display_login_popup"}} | |
48 | + plugin.expects(:context).returns(context) | |
49 | + assert plugin.display_login_popup? | |
50 | + end | |
51 | + | |
52 | + should 'not display stylesheet if login popup is active' do | |
53 | + plugin.expects(:display_login_popup?).returns(true) | |
54 | + assert !plugin.stylesheet? | |
55 | + end | |
56 | + | |
57 | + should 'display stylesheet if login popup is inactive' do | |
58 | + plugin.expects(:display_login_popup?).returns(false) | |
59 | + assert plugin.stylesheet? | |
60 | + end | |
61 | + | |
32 | 62 | protected |
33 | 63 | |
34 | 64 | def logged_in(boolean) | ... | ... |
plugins/require_auth_to_comment/views/require_auth_to_comment_plugin_admin/index.html.erb
0 → 100644
... | ... | @@ -0,0 +1,20 @@ |
1 | +<h1><%= _('Require auth to comment Settings')%></h1> | |
2 | + | |
3 | +<%= form_for(:settings) do |f| %> | |
4 | + | |
5 | + <div class="require-type"> | |
6 | + <strong> | |
7 | + <div class="hide-button"> | |
8 | + <%= radio_button(:settings, :require_type, 'hide_button') %> <%= _('Hide button') %> | |
9 | + </div> | |
10 | + <div class="display-login-popup"> | |
11 | + <%= radio_button(:settings, :require_type, 'display_login_popup') %> <%= _('Display login popup') %> | |
12 | + </div> | |
13 | + </strong> | |
14 | + </div> | |
15 | + | |
16 | + <% button_bar do %> | |
17 | + <%= submit_button(:save, _('Save'), :cancel => {:controller => 'plugins', :action => 'index'}) %> | |
18 | + <% end %> | |
19 | + | |
20 | +<% end %> | ... | ... |
plugins/send_email/controllers/send_email_plugin_base_controller.rb
... | ... | @@ -11,7 +11,8 @@ module SendEmailPluginBaseController |
11 | 11 | ) |
12 | 12 | @mail.subject = params[:subject] unless params[:subject].blank? |
13 | 13 | if @mail.valid? |
14 | - SendEmailPlugin::Sender.send_message(request.referer, @context_url, @mail).deliver | |
14 | + @referer = request.referer | |
15 | + SendEmailPlugin::Sender.send_message(@referer, @context_url, @mail).deliver | |
15 | 16 | if request.xhr? |
16 | 17 | render :text => _('Message sent') |
17 | 18 | else | ... | ... |
plugins/send_email/lib/send_email_plugin.rb
... | ... | @@ -16,9 +16,9 @@ class SendEmailPlugin < Noosfero::Plugin |
16 | 16 | |
17 | 17 | def parse_content(html, source) |
18 | 18 | if context.profile |
19 | - html.gsub!(/\{sendemail\}/, "/profile/#{context.profile.identifier}/plugin/send_email/deliver") | |
19 | + html.gsub!(/({|%7[Bb])sendemail(}|%7[Dd])/, "/profile/#{context.profile.identifier}/plugin/send_email/deliver") | |
20 | 20 | else |
21 | - html.gsub!(/\{sendemail\}/, '/plugin/send_email/deliver') | |
21 | + html.gsub!(/({|%7[Bb])sendemail(}|%7[Dd])/, '/plugin/send_email/deliver') | |
22 | 22 | end |
23 | 23 | [html, source] |
24 | 24 | end | ... | ... |
plugins/send_email/lib/send_email_plugin/mail.rb
... | ... | @@ -10,12 +10,11 @@ class SendEmailPlugin::Mail |
10 | 10 | validate :recipients_format |
11 | 11 | |
12 | 12 | def initialize(attributes = {:subject => 'New mail'}) |
13 | - @environment = attributes[:environment] | |
14 | - @from = attributes[:from] | |
15 | - @to = attributes[:to] | |
16 | - @subject = attributes[:subject] | |
17 | - @message = attributes[:message] | |
18 | - @params = attributes[:params] | |
13 | + if attributes | |
14 | + attributes.each do |attr,value| | |
15 | + self.send("#{attr}=", value) | |
16 | + end | |
17 | + end | |
19 | 18 | end |
20 | 19 | |
21 | 20 | def recipients_format |
... | ... | @@ -36,7 +35,7 @@ class SendEmailPlugin::Mail |
36 | 35 | end |
37 | 36 | |
38 | 37 | def params=(value = {}) |
39 | - [:action, :controller, :to, :message, :subject, :from].each{|k| value.delete(k)} | |
38 | + [:profile, :action, :controller, :to, :message, :subject, :from, :commit].each{|k| value.delete(k)} | |
40 | 39 | @params = value |
41 | 40 | end |
42 | 41 | ... | ... |
plugins/send_email/lib/send_email_plugin/sender.rb
... | ... | @@ -7,9 +7,9 @@ class SendEmailPlugin::Sender < Noosfero::Plugin::MailerBase |
7 | 7 | @params = mail.params |
8 | 8 | |
9 | 9 | mail( |
10 | + content_type: 'text/plain', | |
10 | 11 | to: mail.to, |
11 | 12 | from: mail.from, |
12 | - body: mail.params, | |
13 | 13 | subject: "[#{mail.environment.name}] #{mail.subject}" |
14 | 14 | ) |
15 | 15 | end | ... | ... |
plugins/send_email/test/functional/send_email_plugin_base_controller_test.rb
... | ... | @@ -54,6 +54,13 @@ def run_common_tests |
54 | 54 | post :deliver, @extra_args.merge(:to => 'john@example.com', :message => 'Hi john', :subject => 'Hello john') |
55 | 55 | assert_equal '[Colivre.net] Hello john', ActionMailer::Base.deliveries.first.subject |
56 | 56 | end |
57 | + | |
58 | + should 'deliver mail with message from view' do | |
59 | + Environment.any_instance.stubs(:send_email_plugin_allow_to).returns('john@example.com') | |
60 | + post :deliver, @extra_args.merge(:to => 'john@example.com', :message => 'Hi john', :subject => 'Hello john') | |
61 | + assert_match /Contact from/, ActionMailer::Base.deliveries.first.body.to_s | |
62 | + end | |
63 | + | |
57 | 64 | end |
58 | 65 | |
59 | 66 | class SendEmailPluginProfileControllerTest < ActionController::TestCase | ... | ... |
plugins/send_email/test/unit/send_email_plugin_sender_test.rb
... | ... | @@ -15,12 +15,14 @@ class SendEmailPluginSenderTest < ActiveSupport::TestCase |
15 | 15 | end |
16 | 16 | |
17 | 17 | should 'be able to deliver mail' do |
18 | + @mail.expects(:params).returns({}) | |
18 | 19 | response = SendEmailPlugin::Sender.send_message("http://localhost/contact", 'http//profile', @mail) |
19 | 20 | assert_equal 'noreply@localhost', response.from.join |
20 | 21 | assert_equal "[Noosfero] #{@mail.subject}", response.subject |
21 | 22 | end |
22 | 23 | |
23 | 24 | should 'deliver mail to john@example.com' do |
25 | + @mail.expects(:params).returns({}) | |
24 | 26 | response = SendEmailPlugin::Sender.send_message("http://localhost/contact", 'http//profile', @mail) |
25 | 27 | assert_equal ['john@example.com'], response.to |
26 | 28 | end | ... | ... |
plugins/send_email/test/unit/send_email_plugin_test.rb
... | ... | @@ -26,4 +26,12 @@ class SendEmailPluginTest < ActiveSupport::TestCase |
26 | 26 | assert_match /profile\/#{@plugin.context.profile.identifier}\/plugin\/send_email\/deliver/, @plugin.parse_content("expand this macro {sendemail}", nil).first |
27 | 27 | end |
28 | 28 | |
29 | + should 'expand macro used on form on profile context' do | |
30 | + profile = fast_create(Community) | |
31 | + @plugin.context.stubs(:profile).returns(profile) | |
32 | + article = RawHTMLArticle.create!(:name => 'Raw HTML', :body => "<form action='{sendemail}'></form>", :profile => profile) | |
33 | + | |
34 | + assert_match /profile\/#{profile.identifier}\/plugin\/send_email\/deliver/, @plugin.parse_content(article.to_html, nil).first | |
35 | + end | |
36 | + | |
29 | 37 | end | ... | ... |
plugins/send_email/views/send_email_plugin/sender/message.html.erb
plugins/send_email/views/send_email_plugin/sender/send_message.html.erb
0 → 100644
plugins/send_email/views/send_email_plugin/success.html.erb
... | ... | @@ -2,7 +2,7 @@ |
2 | 2 | |
3 | 3 | <table class='sendemail-plugin-message-sent'> |
4 | 4 | <tr><td class='label'><strong><%= c_('Subject') %>:</strong></td><td class='value'><em><%=h @mail.subject %></em></td></tr> |
5 | - <tr><td class='label'><strong><%= c_('Message') %>:</strong></td><td class='value'><pre><%=h render :file => 'send_email_plugin/sender/message' %></pre></td></tr> | |
5 | + <tr><td class='label'><strong><%= c_('Message') %>:</strong></td><td class='value'><pre><%=h render :file => 'send_email_plugin/sender/send_message' %></pre></td></tr> | |
6 | 6 | </table> |
7 | 7 | |
8 | 8 | <p><%= button :back, c_('Back'), :back %></p> | ... | ... |
plugins/sub_organizations/db/migrate/20150508153119_add_timestamp_to_relation.rb
0 → 100644
plugins/sub_organizations/lib/sub_organizations_plugin/relation.rb
plugins/vote/public/style.css
plugins/vote/views/vote/_vote.html.erb
... | ... | @@ -5,7 +5,7 @@ reload_url = url_for(:controller => 'vote_plugin_profile', :profile => profile.i |
5 | 5 | |
6 | 6 | <span id="vote_<%= model %>_<%= target.id %>_<%= vote %>" data-reload_url=<%= reload_url %> class="vote-action action <%= action %>-action"> |
7 | 7 | |
8 | - <%= link_to_remote content_tag(:span, count, :class=>'like-action-counter') + content_tag(:span, '', :class=>"action-icon #{action}"), :url => url, :html => {:class => "#{active ? 'like-action-active':''} #{user ? '':'disabled'}"} %> | |
8 | + <%= link_to content_tag(:span, count, :class=>'like-action-counter') + content_tag(:span, '', :class=>"action-icon #{action}"), url, :class => "#{active ? 'like-action-active':''} #{user ? '':'disabled'} require-login-popup" %> | |
9 | 9 | |
10 | 10 | <% if !voters.blank? %> |
11 | 11 | <span class="vote-detail"> | ... | ... |
public/designs/templates/lefttopright/javascripts/template.js
0 → 100644
public/designs/templates/lefttopright/stylesheets/style.css
0 → 100644
... | ... | @@ -0,0 +1,42 @@ |
1 | +#boxes { | |
2 | + display: table; | |
3 | + width: 100%; | |
4 | +} | |
5 | + | |
6 | +.box-1 { | |
7 | + width: 58%; | |
8 | + float: left; | |
9 | + margin: 1% 1% 0% 1%; | |
10 | +} | |
11 | + | |
12 | + | |
13 | +.box-2 { | |
14 | + position: relative; | |
15 | + float: left; | |
16 | + width: 20%; | |
17 | +} | |
18 | + | |
19 | +.box-3 { | |
20 | + position: relative; | |
21 | + float: right; | |
22 | + width: 20%; | |
23 | + margin-top: 1%; | |
24 | +} | |
25 | + | |
26 | +.box-4 { | |
27 | + float: left; | |
28 | + width: 79%; | |
29 | + margin-left: 21%; | |
30 | +} | |
31 | + | |
32 | +#profile-activity ul, | |
33 | +#profile-network ul, | |
34 | +#profile-wall ul { | |
35 | + width: 460px; | |
36 | +} | |
37 | +#profile-activity ul.comment-replies, | |
38 | +#profile-network ul.comment-replies, | |
39 | +#profile-wall ul.comment-replies { | |
40 | + width: auto; | |
41 | +} | |
42 | + | ... | ... |
3.02 KB
... | ... | @@ -0,0 +1,434 @@ |
1 | +<?xml version="1.0" encoding="UTF-8" standalone="no"?> | |
2 | +<!-- Created with Inkscape (http://www.inkscape.org/) --> | |
3 | + | |
4 | +<svg | |
5 | + xmlns:dc="http://purl.org/dc/elements/1.1/" | |
6 | + xmlns:cc="http://creativecommons.org/ns#" | |
7 | + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" | |
8 | + xmlns:svg="http://www.w3.org/2000/svg" | |
9 | + xmlns="http://www.w3.org/2000/svg" | |
10 | + xmlns:xlink="http://www.w3.org/1999/xlink" | |
11 | + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" | |
12 | + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" | |
13 | + width="64px" | |
14 | + height="64px" | |
15 | + id="svg2383" | |
16 | + sodipodi:version="0.32" | |
17 | + inkscape:version="0.48.3.1 r9886" | |
18 | + sodipodi:docname="thumbnail.svg" | |
19 | + inkscape:output_extension="org.inkscape.output.svg.inkscape" | |
20 | + inkscape:export-filename="thumbnail.png" | |
21 | + inkscape:export-xdpi="90" | |
22 | + inkscape:export-ydpi="90" | |
23 | + version="1.1"> | |
24 | + <defs | |
25 | + id="defs2385"> | |
26 | + <linearGradient | |
27 | + id="linearGradient3263"> | |
28 | + <stop | |
29 | + id="stop3265" | |
30 | + offset="0" | |
31 | + style="stop-color:#204a87;stop-opacity:1" /> | |
32 | + <stop | |
33 | + id="stop3267" | |
34 | + offset="1" | |
35 | + style="stop-color:#729fcf;stop-opacity:1" /> | |
36 | + </linearGradient> | |
37 | + <linearGradient | |
38 | + id="linearGradient3257" | |
39 | + inkscape:collect="always"> | |
40 | + <stop | |
41 | + id="stop3259" | |
42 | + offset="0" | |
43 | + style="stop-color:#204a87;stop-opacity:1" /> | |
44 | + <stop | |
45 | + id="stop3261" | |
46 | + offset="1" | |
47 | + style="stop-color:#729fcf;stop-opacity:1" /> | |
48 | + </linearGradient> | |
49 | + <linearGradient | |
50 | + inkscape:collect="always" | |
51 | + id="linearGradient3245"> | |
52 | + <stop | |
53 | + style="stop-color:#204a87;stop-opacity:1" | |
54 | + offset="0" | |
55 | + id="stop3247" /> | |
56 | + <stop | |
57 | + style="stop-color:#729fcf;stop-opacity:1" | |
58 | + offset="1" | |
59 | + id="stop3249" /> | |
60 | + </linearGradient> | |
61 | + <inkscape:perspective | |
62 | + sodipodi:type="inkscape:persp3d" | |
63 | + inkscape:vp_x="0 : 32 : 1" | |
64 | + inkscape:vp_y="0 : 1000 : 0" | |
65 | + inkscape:vp_z="64 : 32 : 1" | |
66 | + inkscape:persp3d-origin="32 : 21.333333 : 1" | |
67 | + id="perspective2391" /> | |
68 | + <filter | |
69 | + inkscape:collect="always" | |
70 | + id="filter3241"> | |
71 | + <feGaussianBlur | |
72 | + inkscape:collect="always" | |
73 | + stdDeviation="0.9075" | |
74 | + id="feGaussianBlur3243" /> | |
75 | + </filter> | |
76 | + <linearGradient | |
77 | + inkscape:collect="always" | |
78 | + xlink:href="#linearGradient3245" | |
79 | + id="linearGradient3251" | |
80 | + x1="11.5" | |
81 | + y1="60.5" | |
82 | + x2="3.5" | |
83 | + y2="3.5" | |
84 | + gradientUnits="userSpaceOnUse" | |
85 | + gradientTransform="translate(2,0)" /> | |
86 | + <linearGradient | |
87 | + inkscape:collect="always" | |
88 | + xlink:href="#linearGradient3263" | |
89 | + id="linearGradient3253" | |
90 | + x1="49.5" | |
91 | + y1="60.5" | |
92 | + x2="23.5" | |
93 | + y2="3.5" | |
94 | + gradientUnits="userSpaceOnUse" | |
95 | + gradientTransform="translate(2,0)" /> | |
96 | + <linearGradient | |
97 | + inkscape:collect="always" | |
98 | + xlink:href="#linearGradient3257" | |
99 | + id="linearGradient3255" | |
100 | + x1="60.5" | |
101 | + y1="60.5" | |
102 | + x2="51.5" | |
103 | + y2="3.5" | |
104 | + gradientUnits="userSpaceOnUse" /> | |
105 | + <filter | |
106 | + color-interpolation-filters="sRGB" | |
107 | + inkscape:collect="always" | |
108 | + id="filter3241-2"> | |
109 | + <feGaussianBlur | |
110 | + inkscape:collect="always" | |
111 | + stdDeviation="0.9075" | |
112 | + id="feGaussianBlur3243-4" /> | |
113 | + </filter> | |
114 | + <linearGradient | |
115 | + inkscape:collect="always" | |
116 | + xlink:href="#linearGradient3245-1" | |
117 | + id="linearGradient3251-0" | |
118 | + x1="11.5" | |
119 | + y1="60.5" | |
120 | + x2="3.5" | |
121 | + y2="3.5" | |
122 | + gradientUnits="userSpaceOnUse" | |
123 | + gradientTransform="translate(249.71429,298.93361)" /> | |
124 | + <linearGradient | |
125 | + inkscape:collect="always" | |
126 | + id="linearGradient3245-1"> | |
127 | + <stop | |
128 | + style="stop-color:#204a87;stop-opacity:1" | |
129 | + offset="0" | |
130 | + id="stop3247-6" /> | |
131 | + <stop | |
132 | + style="stop-color:#729fcf;stop-opacity:1" | |
133 | + offset="1" | |
134 | + id="stop3249-5" /> | |
135 | + </linearGradient> | |
136 | + <filter | |
137 | + color-interpolation-filters="sRGB" | |
138 | + inkscape:collect="always" | |
139 | + id="filter3241-4-8"> | |
140 | + <feGaussianBlur | |
141 | + inkscape:collect="always" | |
142 | + stdDeviation="0.9075" | |
143 | + id="feGaussianBlur3243-0-7" /> | |
144 | + </filter> | |
145 | + <linearGradient | |
146 | + inkscape:collect="always" | |
147 | + xlink:href="#linearGradient3263-5-8" | |
148 | + id="linearGradient5185" | |
149 | + gradientUnits="userSpaceOnUse" | |
150 | + gradientTransform="matrix(1.4160224,0,0,0.76166072,243.22589,313.33388)" | |
151 | + x1="42.5" | |
152 | + y1="60.5" | |
153 | + x2="19.5" | |
154 | + y2="3.5" /> | |
155 | + <linearGradient | |
156 | + id="linearGradient3263-5-8"> | |
157 | + <stop | |
158 | + id="stop3265-4-3" | |
159 | + offset="0" | |
160 | + style="stop-color:#204a87;stop-opacity:1" /> | |
161 | + <stop | |
162 | + id="stop3267-2-4" | |
163 | + offset="1" | |
164 | + style="stop-color:#729fcf;stop-opacity:1" /> | |
165 | + </linearGradient> | |
166 | + <filter | |
167 | + color-interpolation-filters="sRGB" | |
168 | + inkscape:collect="always" | |
169 | + id="filter3241-0"> | |
170 | + <feGaussianBlur | |
171 | + inkscape:collect="always" | |
172 | + stdDeviation="0.9075" | |
173 | + id="feGaussianBlur3243-3" /> | |
174 | + </filter> | |
175 | + <linearGradient | |
176 | + inkscape:collect="always" | |
177 | + xlink:href="#linearGradient3245-7" | |
178 | + id="linearGradient5168" | |
179 | + gradientUnits="userSpaceOnUse" | |
180 | + gradientTransform="matrix(1.0025263,0,0,0.76423683,344.68831,300.13218)" | |
181 | + x1="11.5" | |
182 | + y1="60.5" | |
183 | + x2="3.5" | |
184 | + y2="3.5" /> | |
185 | + <linearGradient | |
186 | + inkscape:collect="always" | |
187 | + id="linearGradient3245-7"> | |
188 | + <stop | |
189 | + style="stop-color:#204a87;stop-opacity:1" | |
190 | + offset="0" | |
191 | + id="stop3247-0" /> | |
192 | + <stop | |
193 | + style="stop-color:#729fcf;stop-opacity:1" | |
194 | + offset="1" | |
195 | + id="stop3249-7" /> | |
196 | + </linearGradient> | |
197 | + <linearGradient | |
198 | + inkscape:collect="always" | |
199 | + xlink:href="#linearGradient3245-70" | |
200 | + id="linearGradient3251-55" | |
201 | + x1="11.5" | |
202 | + y1="60.5" | |
203 | + x2="3.5" | |
204 | + y2="3.5" | |
205 | + gradientUnits="userSpaceOnUse" | |
206 | + gradientTransform="matrix(1.0025263,0,0,0.76423683,344.68831,300.13218)" /> | |
207 | + <linearGradient | |
208 | + inkscape:collect="always" | |
209 | + id="linearGradient3245-70"> | |
210 | + <stop | |
211 | + style="stop-color:#204a87;stop-opacity:1" | |
212 | + offset="0" | |
213 | + id="stop3247-2" /> | |
214 | + <stop | |
215 | + style="stop-color:#729fcf;stop-opacity:1" | |
216 | + offset="1" | |
217 | + id="stop3249-87" /> | |
218 | + </linearGradient> | |
219 | + <linearGradient | |
220 | + inkscape:collect="always" | |
221 | + xlink:href="#linearGradient3245-1" | |
222 | + id="linearGradient5832" | |
223 | + gradientUnits="userSpaceOnUse" | |
224 | + gradientTransform="translate(249.71429,298.93361)" | |
225 | + x1="11.5" | |
226 | + y1="60.5" | |
227 | + x2="3.5" | |
228 | + y2="3.5" /> | |
229 | + <linearGradient | |
230 | + inkscape:collect="always" | |
231 | + xlink:href="#linearGradient3263-5-8" | |
232 | + id="linearGradient5834" | |
233 | + gradientUnits="userSpaceOnUse" | |
234 | + gradientTransform="matrix(1.4160224,0,0,0.76166072,243.22589,313.33388)" | |
235 | + x1="42.5" | |
236 | + y1="60.5" | |
237 | + x2="19.5" | |
238 | + y2="3.5" /> | |
239 | + <linearGradient | |
240 | + inkscape:collect="always" | |
241 | + xlink:href="#linearGradient3245-7" | |
242 | + id="linearGradient5836" | |
243 | + gradientUnits="userSpaceOnUse" | |
244 | + gradientTransform="matrix(1.0025263,0,0,0.76423683,344.68831,300.13218)" | |
245 | + x1="11.5" | |
246 | + y1="60.5" | |
247 | + x2="3.5" | |
248 | + y2="3.5" /> | |
249 | + <linearGradient | |
250 | + inkscape:collect="always" | |
251 | + xlink:href="#linearGradient3245-70" | |
252 | + id="linearGradient5838" | |
253 | + gradientUnits="userSpaceOnUse" | |
254 | + gradientTransform="matrix(1.0025263,0,0,0.76423683,344.68831,300.13218)" | |
255 | + x1="11.5" | |
256 | + y1="60.5" | |
257 | + x2="3.5" | |
258 | + y2="3.5" /> | |
259 | + </defs> | |
260 | + <sodipodi:namedview | |
261 | + id="base" | |
262 | + pagecolor="#ffffff" | |
263 | + bordercolor="#666666" | |
264 | + borderopacity="1.0" | |
265 | + inkscape:pageopacity="0.0" | |
266 | + inkscape:pageshadow="2" | |
267 | + inkscape:zoom="2.5351563" | |
268 | + inkscape:cx="-16.066434" | |
269 | + inkscape:cy="0.12147739" | |
270 | + inkscape:current-layer="layer1" | |
271 | + showgrid="true" | |
272 | + inkscape:document-units="px" | |
273 | + inkscape:grid-bbox="true" | |
274 | + inkscape:window-width="1364" | |
275 | + inkscape:window-height="678" | |
276 | + inkscape:window-x="0" | |
277 | + inkscape:window-y="27" | |
278 | + objecttolerance="10" | |
279 | + gridtolerance="10" | |
280 | + guidetolerance="10" | |
281 | + inkscape:window-maximized="0"> | |
282 | + <inkscape:grid | |
283 | + type="xygrid" | |
284 | + id="grid2382" | |
285 | + visible="true" | |
286 | + enabled="true" | |
287 | + originx="0.5px" | |
288 | + originy="0.5px" | |
289 | + empcolor="#0000ff" | |
290 | + empopacity="0.1254902" | |
291 | + dotted="true" /> | |
292 | + </sodipodi:namedview> | |
293 | + <metadata | |
294 | + id="metadata2388"> | |
295 | + <rdf:RDF> | |
296 | + <cc:Work | |
297 | + rdf:about=""> | |
298 | + <dc:format>image/svg+xml</dc:format> | |
299 | + <dc:type | |
300 | + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> | |
301 | + </cc:Work> | |
302 | + </rdf:RDF> | |
303 | + </metadata> | |
304 | + <g | |
305 | + id="layer1" | |
306 | + inkscape:label="Layer 1" | |
307 | + inkscape:groupmode="layer"> | |
308 | + <g | |
309 | + transform="translate(-247.62879,-298.93361)" | |
310 | + id="g5187"> | |
311 | + <g | |
312 | + id="g4846"> | |
313 | + <g | |
314 | + id="g3190-2" | |
315 | + style="opacity:0.4;filter:url(#filter3241-2)" | |
316 | + transform="translate(250.71429,299.93361)"> | |
317 | + <rect | |
318 | + y="1.5" | |
319 | + x="1.5" | |
320 | + height="59" | |
321 | + width="11" | |
322 | + id="rect3184-1" | |
323 | + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" | |
324 | + ry="2" | |
325 | + rx="2" /> | |
326 | + </g> | |
327 | + <rect | |
328 | + y="300.43362" | |
329 | + x="251.21428" | |
330 | + height="59" | |
331 | + width="11" | |
332 | + id="rect2395-8" | |
333 | + style="fill:url(#linearGradient5832);fill-opacity:1;fill-rule:nonzero;stroke:#204a87;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" | |
334 | + ry="2" | |
335 | + rx="2" /> | |
336 | + <rect | |
337 | + ry="1" | |
338 | + style="opacity:0.6;fill:none;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" | |
339 | + id="rect3158-7" | |
340 | + width="9" | |
341 | + height="57" | |
342 | + x="252.21428" | |
343 | + y="301.43362" | |
344 | + rx="1" /> | |
345 | + </g> | |
346 | + <g | |
347 | + transform="matrix(0.69260722,0,0,1,81.51265,0)" | |
348 | + id="g5180"> | |
349 | + <rect | |
350 | + rx="2" | |
351 | + ry="2" | |
352 | + style="opacity:0.4;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;filter:url(#filter3241-4-8);enable-background:accumulate" | |
353 | + id="rect3188-8" | |
354 | + width="31" | |
355 | + height="59" | |
356 | + x="16.5" | |
357 | + y="2.5" | |
358 | + transform="matrix(1.4160224,0,0,0.76166071,243.80989,314.09132)" /> | |
359 | + <rect | |
360 | + y="314.47638" | |
361 | + x="265.17426" | |
362 | + height="44.937984" | |
363 | + width="43.896694" | |
364 | + id="rect3156-3" | |
365 | + style="fill:url(#linearGradient5834);fill-opacity:1;fill-rule:nonzero;stroke:#204a87;stroke-width:1.03852236;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" | |
366 | + ry="1.5233214" /> | |
367 | + <rect | |
368 | + y="315.23804" | |
369 | + x="266.59027" | |
370 | + height="43.414661" | |
371 | + width="41.064651" | |
372 | + id="rect3162-1" | |
373 | + style="opacity:0.6;fill:none;stroke:#ffffff;stroke-width:1.03852236;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" | |
374 | + ry="0.7616607" | |
375 | + inkscape:export-xdpi="90" | |
376 | + inkscape:export-ydpi="90" /> | |
377 | + </g> | |
378 | + <g | |
379 | + transform="matrix(0.9761091,0,0,1,6.3333026,0)" | |
380 | + id="g5108"> | |
381 | + <rect | |
382 | + rx="2" | |
383 | + ry="2" | |
384 | + style="opacity:0.4;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;filter:url(#filter3241-0);enable-background:accumulate" | |
385 | + id="rect3184-5" | |
386 | + width="11" | |
387 | + height="59" | |
388 | + x="2.5" | |
389 | + y="2.5" | |
390 | + transform="matrix(0,1.0025263,-0.76423683,0,312.09322,298.92289)" /> | |
391 | + <g | |
392 | + transform="matrix(0,1,-1,0,611.46116,-45.820829)" | |
393 | + id="g4877-9"> | |
394 | + <rect | |
395 | + ry="1.5284736" | |
396 | + style="fill:url(#linearGradient5836);fill-opacity:1;fill-rule:nonzero;stroke:#204a87;stroke-width:0.87531;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" | |
397 | + id="rect2395-95" | |
398 | + width="11.02779" | |
399 | + height="45.089973" | |
400 | + x="346.19211" | |
401 | + y="301.27853" /> | |
402 | + <rect | |
403 | + y="302.04276" | |
404 | + x="347.19461" | |
405 | + height="43.561501" | |
406 | + width="9.0227375" | |
407 | + id="rect3158-2" | |
408 | + style="opacity:0.6;fill:none;stroke:#ffffff;stroke-width:0.87531;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" | |
409 | + ry="0.76423681" /> | |
410 | + </g> | |
411 | + </g> | |
412 | + <g | |
413 | + id="g4877-8" | |
414 | + transform="translate(-47.956003,13.002947)"> | |
415 | + <rect | |
416 | + y="301.27853" | |
417 | + x="346.19211" | |
418 | + height="45.089973" | |
419 | + width="11.02779" | |
420 | + id="rect2395-1" | |
421 | + style="fill:url(#linearGradient5838);fill-opacity:1;fill-rule:nonzero;stroke:#204a87;stroke-width:0.87531;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" | |
422 | + ry="1.5284736" /> | |
423 | + <rect | |
424 | + ry="0.76423681" | |
425 | + style="opacity:0.6;fill:none;stroke:#ffffff;stroke-width:0.87531;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" | |
426 | + id="rect3158-71" | |
427 | + width="9.0227375" | |
428 | + height="43.561501" | |
429 | + x="347.19461" | |
430 | + y="302.04276" /> | |
431 | + </g> | |
432 | + </g> | |
433 | + </g> | |
434 | +</svg> | ... | ... |