Commit d08608afec164fe6dd991f8a0bbc487825b94600
Exists in
master
and in
29 other branches
Merge remote-tracking branch 'origin' into stable
Conflicts: app/views/content_viewer/view_page.rhtml app/views/profile_editor/index.rhtml debian/changelog lib/noosfero.rb plugins/comment_group/test/functional/comment_group_plugin_profile_controller_test.rb
Showing
411 changed files
with
25827 additions
and
10014 deletions
Show diff stats
Too many changes.
To preserve performance only 100 of 411 files displayed.
AUTHORS
... | ... | @@ -7,6 +7,7 @@ Developers |
7 | 7 | ========== |
8 | 8 | |
9 | 9 | Alan Freihof Tygel <alantygel@gmail.com> |
10 | +alcampelo <alcampelo@alcampelo.(none)> | |
10 | 11 | Alessandro Palmeira <alessandro.palmeira@gmail.com> |
11 | 12 | Alessandro Palmeira + Caio C. Salgado <alessandro.palmeira@gmail.com> |
12 | 13 | Alessandro Palmeira + Caio Salgado <alessandro.palmeira@gmail.com> |
... | ... | @@ -38,6 +39,7 @@ Alessandro Palmeira + João M. M. Silva <alessandro.palmeira@gmail.com> |
38 | 39 | Alessandro Palmeira + Paulo Meirelles <alessandro.palmeira@gmail.com> |
39 | 40 | Alessandro Palmeira + Paulo Meirelles + João M. M. da Silva <alessandro.palmeira@gmail.com> |
40 | 41 | Alessandro Palmeira + Rafael Manzo <alessandro.palmeira@gmail.com> |
42 | +Ana Losnak <analosnak@gmail.com> | |
41 | 43 | Antonio Terceiro + Carlos Morais <terceiro@colivre.coop.br> |
42 | 44 | Antonio Terceiro + Paulo Meirelles <terceiro@colivre.coop.br> |
43 | 45 | Antonio Terceiro <terceiro@colivre.coop.br> |
... | ... | @@ -85,6 +87,7 @@ Daniel Alves + Rafael Manzo <rr.manzo@gmail.com> |
85 | 87 | Daniela Soares Feitosa <danielafeitosa@colivre.coop.br> |
86 | 88 | Daniel Bucher <daniel.bucher88@gmail.com> |
87 | 89 | Daniel Cunha <daniel@colivre.coop.br> |
90 | +David Carlos <ddavidcarlos1392@gmail.com> | |
88 | 91 | diegoamc <diegoamc90@gmail.com> |
89 | 92 | Diego Araújo + Alessandro Palmeira <diegoamc90@gmail.com> |
90 | 93 | Diego Araújo + Alessandro Palmeira + João M. M. da Silva <diegoamc90@gmail.com> |
... | ... | @@ -114,12 +117,16 @@ Diego Martinez <diegoamc90@gmail.com> |
114 | 117 | Diego Martinez <diego@diego-K55A.(none)> |
115 | 118 | Diego + Renan <renanteruoc@gmail.com> |
116 | 119 | Eduardo Tourinho Edington <eduardo.edington@serpro.gov.br> |
120 | +Fabio Teixeira <fabio1079@gmail.com> | |
117 | 121 | Fernanda Lopes <nanda.listas+psl@gmail.com> |
118 | 122 | Francisco Marcelo A. Lima Júnior <francisco.lima-junior@serpro.gov.br> |
119 | 123 | Francisco Marcelo de Araujo Lima Junior <79350259591@serpro-1457614.(none)> |
120 | 124 | Francisco Marcelo de Araújo Lima Júnior <francisco.lima-junior@serpro.gov.br> |
121 | 125 | Francisco Marcelo de Araújo Lima Júnior <maljunior@gmail.com> |
126 | +Gabriela Navarro <navarro1703@gmail.com> | |
122 | 127 | Grazieno Pellegrino <grazieno@gmail.com> |
128 | +Gust <darksshades@hotmail.com> | |
129 | +Hugo Melo <hugo@riseup.net> | |
123 | 130 | Isaac Canan <isaac@intelletto.com.br> |
124 | 131 | Italo Valcy <italo@dcc.ufba.br> |
125 | 132 | Jefferson Fernandes + Diego Araujo + Rafael Manzo <jeffs.fernandes@gmail.com> |
... | ... | @@ -155,6 +162,7 @@ João M. M. Silva + Rafael Manzo <jaodsilv@linux.ime.usp.br> |
155 | 162 | João M. M. Silva + Renan Teruo <jaodsilv@linux.ime.usp.br> |
156 | 163 | Joenio Costa <joenio@colivre.coop.br> |
157 | 164 | Josef Spillner <josef.spillner@tu-dresden.de> |
165 | +Junior Silva <junior@bajor.localhost.localdomain> | |
158 | 166 | Junior Silva <juniorsilva1001@gmail.com> |
159 | 167 | Junior Silva <juniorsilva7@juniorsilva-Aspire-5750Z.(none)> |
160 | 168 | Junior Silva <juniorsilva@colivre.coop.br> |
... | ... | @@ -202,6 +210,7 @@ Renan Teruo + Diego Araujo <renanteruoc@gmail.com> |
202 | 210 | Renan Teruo + Diego Araújo <renanteruoc@gmail.com> |
203 | 211 | Renan Teruo + Paulo Meirelles <renanteruoc@gmail.com> |
204 | 212 | Renan Teruo + Rafael Manzo <renanteruoc@gmail.com> |
213 | +Rodrigo Souto + Ana Losnak + Daniel Bucher + Caio Almeida + Leandro Nunes + Daniela Feitosa + Mariel Zasso <noosfero-br@listas.softwarelivre.org> | |
205 | 214 | Rodrigo Souto <diguliu@gmail.com> |
206 | 215 | Rodrigo Souto <rodrigo@colivre.coop.br> |
207 | 216 | Ronny Kursawe <kursawe.ronny@googlemail.com> | ... | ... |
INSTALL.md
... | ... | @@ -110,7 +110,7 @@ Setup Noosfero log and tmp directories: |
110 | 110 | # cd /var/lib/noosfero/current |
111 | 111 | # ./etc/init.d/noosfero setup |
112 | 112 | |
113 | -Now it's time to setup the database. In this example we are using PostgreSQL, so if you are planning to use a different database this steps won't apply. | |
113 | +Now it's time to setup the database. In this example we are using PostgreSQL, so if you are planning to use a different database this steps won't apply. Pay special attention to the default collation defined on your setup by the environment variable LC_COLLATE because it might interfere in some sorting operations on your database. For more information checkout `man locale`. | |
114 | 114 | |
115 | 115 | # apt-get install postgresql libpgsql-ruby |
116 | 116 | # su postgres -c 'createuser noosfero -S -d -R' | ... | ... |
README.md
1 | +[](https://codeclimate.com/github/Noosfero/noosfero) | |
2 | + | |
1 | 3 | Noosfero - a web-based social platform |
2 | 4 | ====================================== |
3 | 5 | |
... | ... | @@ -30,4 +32,4 @@ Authorship and copyright information is available in the files listed below. |
30 | 32 | -------------------- ----------------------------------------- |
31 | 33 | AUTHORS.md list of authors (updated at each release) |
32 | 34 | COPYRIGHT Copyright statement for the project |
33 | 35 | - COPYING Full text of the project license |
36 | + COPYING Full text of the project license | |
34 | 37 | \ No newline at end of file | ... | ... |
app/controllers/admin/environment_design_controller.rb
... | ... | @@ -3,6 +3,8 @@ class EnvironmentDesignController < BoxOrganizerController |
3 | 3 | protect 'edit_environment_design', :environment |
4 | 4 | |
5 | 5 | def available_blocks |
6 | + # TODO EnvironmentStatisticsBlock is DEPRECATED and will be removed from | |
7 | + # the Noosfero core soon, see ActionItem3045 | |
6 | 8 | @available_blocks ||= [ ArticleBlock, LoginBlock, EnvironmentStatisticsBlock, RecentDocumentsBlock, EnterprisesBlock, CommunitiesBlock, PeopleBlock, SellersSearchBlock, LinkListBlock, FeedReaderBlock, SlideshowBlock, HighlightsBlock, FeaturedProductsBlock, CategoriesBlock, RawHTMLBlock, TagsBlock ] |
7 | 9 | @available_blocks += plugins.dispatch(:extra_blocks, :type => Environment) |
8 | 10 | end | ... | ... |
app/controllers/admin/users_controller.rb
... | ... | @@ -45,6 +45,20 @@ class UsersController < AdminController |
45 | 45 | redirect_to :action => :index, :q => params[:q], :filter => params[:filter] |
46 | 46 | end |
47 | 47 | |
48 | + | |
49 | + def destroy_user | |
50 | + if request.post? | |
51 | + person = environment.people.find_by_id(params[:id]) | |
52 | + if person && person.destroy | |
53 | + session[:notice] = _('The profile was deleted.') | |
54 | + else | |
55 | + session[:notice] = _('Could not remove profile') | |
56 | + end | |
57 | + end | |
58 | + redirect_to :action => :index, :q => params[:q], :filter => params[:filter] | |
59 | + end | |
60 | + | |
61 | + | |
48 | 62 | def download |
49 | 63 | respond_to do |format| |
50 | 64 | format.html | ... | ... |
app/controllers/my_profile/cms_controller.rb
... | ... | @@ -24,10 +24,16 @@ class CmsController < MyProfileController |
24 | 24 | (user && (user.has_permission?('post_content', profile) || user.has_permission?('publish_content', profile))) |
25 | 25 | end |
26 | 26 | |
27 | - protect_if :except => [:suggest_an_article, :set_home_page, :edit, :destroy, :publish, :upload_files] do |c, user, profile| | |
27 | + protect_if :except => [:suggest_an_article, :set_home_page, :edit, :destroy, :publish, :upload_files, :new] do |c, user, profile| | |
28 | 28 | user && (user.has_permission?('post_content', profile) || user.has_permission?('publish_content', profile)) |
29 | 29 | end |
30 | 30 | |
31 | + protect_if :only => :new do |c, user, profile| | |
32 | + article = profile.articles.find_by_id(c.params[:parent_id]) | |
33 | + (!article.nil? && (article.allow_create?(user) || article.parent.allow_create?(user))) || | |
34 | + (user && (user.has_permission?('post_content', profile) || user.has_permission?('publish_content', profile))) | |
35 | + end | |
36 | + | |
31 | 37 | protect_if :only => [:destroy, :publish] do |c, user, profile| |
32 | 38 | profile.articles.find(c.params[:id]).allow_post_content?(user) |
33 | 39 | end |
... | ... | @@ -68,6 +74,9 @@ class CmsController < MyProfileController |
68 | 74 | def edit |
69 | 75 | @success_back_to = params[:success_back_to] |
70 | 76 | @article = profile.articles.find(params[:id]) |
77 | + version = params[:version] | |
78 | + @article.revert_to(version) if version | |
79 | + | |
71 | 80 | @parent_id = params[:parent_id] |
72 | 81 | @type = params[:type] || @article.class.to_s |
73 | 82 | translations if @article.translatable? |
... | ... | @@ -202,7 +211,7 @@ class CmsController < MyProfileController |
202 | 211 | @article.destroy |
203 | 212 | session[:notice] = _("\"#{@article.name}\" was removed.") |
204 | 213 | referer = ActionController::Routing::Routes.recognize_path URI.parse(request.referer).path rescue nil |
205 | - if referer and referer[:controller] == 'cms' | |
214 | + if referer and referer[:controller] == 'cms' and referer[:action] != 'edit' | |
206 | 215 | redirect_to referer |
207 | 216 | elsif @article.parent |
208 | 217 | redirect_to @article.parent.url |
... | ... | @@ -218,11 +227,10 @@ class CmsController < MyProfileController |
218 | 227 | |
219 | 228 | def update_categories |
220 | 229 | @object = params[:id] ? @profile.articles.find(params[:id]) : Article.new |
230 | + @categories = @toplevel_categories = environment.top_level_categories | |
221 | 231 | if params[:category_id] |
222 | 232 | @current_category = Category.find(params[:category_id]) |
223 | 233 | @categories = @current_category.children |
224 | - else | |
225 | - @categories = environment.top_level_categories.select{|i| !i.children.empty?} | |
226 | 234 | end |
227 | 235 | render :partial => 'shared/select_categories', :locals => {:object_name => 'article', :multiple => true}, :layout => false |
228 | 236 | end | ... | ... |
app/controllers/my_profile/profile_design_controller.rb
... | ... | @@ -32,6 +32,7 @@ class ProfileDesignController < BoxOrganizerController |
32 | 32 | if profile.enterprise? |
33 | 33 | blocks << DisabledEnterpriseMessageBlock |
34 | 34 | blocks << HighlightsBlock |
35 | + blocks << ProductCategoriesBlock | |
35 | 36 | blocks << FeaturedProductsBlock |
36 | 37 | blocks << FansBlock |
37 | 38 | blocks += plugins.dispatch(:extra_blocks, :type => Enterprise) |
... | ... | @@ -54,4 +55,10 @@ class ProfileDesignController < BoxOrganizerController |
54 | 55 | blocks |
55 | 56 | end |
56 | 57 | |
58 | + def clone | |
59 | + block = Block.find(params[:id]) | |
60 | + block.duplicate | |
61 | + redirect_to :action => 'index' | |
62 | + end | |
63 | + | |
57 | 64 | end | ... | ... |
app/controllers/my_profile/profile_editor_controller.rb
... | ... | @@ -55,11 +55,10 @@ class ProfileEditorController < MyProfileController |
55 | 55 | |
56 | 56 | def update_categories |
57 | 57 | @object = profile |
58 | + @categories = @toplevel_categories = environment.top_level_categories | |
58 | 59 | if params[:category_id] |
59 | 60 | @current_category = Category.find(params[:category_id]) |
60 | 61 | @categories = @current_category.children |
61 | - else | |
62 | - @categories = environment.top_level_categories.select{|i| !i.children.empty?} | |
63 | 62 | end |
64 | 63 | render :partial => 'shared/select_categories', :locals => {:object_name => 'profile_data', :multiple => true}, :layout => false |
65 | 64 | end | ... | ... |
app/controllers/my_profile/profile_members_controller.rb
... | ... | @@ -0,0 +1,75 @@ |
1 | +class ProfileThemesController < ThemesController | |
2 | + | |
3 | + needs_profile | |
4 | + | |
5 | + protect 'edit_appearance', :profile | |
6 | + | |
7 | + no_design_blocks | |
8 | + | |
9 | + def target | |
10 | + @target = profile | |
11 | + end | |
12 | + | |
13 | + def new | |
14 | + if !request.xhr? | |
15 | + id = params[:name] ? params[:name].to_slug : 'my-theme' | |
16 | + t = Theme.new(id, :name => params[:name], :owner => profile, :public => false) | |
17 | + t.save | |
18 | + redirect_to :action => 'index' | |
19 | + else | |
20 | + render :action => 'new', :layout => false | |
21 | + end | |
22 | + end | |
23 | + | |
24 | + def edit | |
25 | + @theme = profile.find_theme(params[:id]) | |
26 | + @css_files = @theme.css_files | |
27 | + @image_files = @theme.image_files | |
28 | + end | |
29 | + | |
30 | + def add_css | |
31 | + @theme = profile.find_theme(params[:id]) | |
32 | + if request.xhr? | |
33 | + render :action => 'add_css', :layout => false | |
34 | + else | |
35 | + @theme.add_css(params[:css]) | |
36 | + redirect_to :action => 'edit', :id => @theme.id | |
37 | + end | |
38 | + end | |
39 | + | |
40 | + def css_editor | |
41 | + @theme = profile.find_theme(params[:id]) | |
42 | + @css = params[:css] | |
43 | + | |
44 | + @code = @theme.read_css(@css) | |
45 | + render :action => 'css_editor', :layout => false | |
46 | + end | |
47 | + | |
48 | + post_only :update_css | |
49 | + def update_css | |
50 | + @theme = profile.find_theme(params[:id]) | |
51 | + @theme.update_css(params[:css], params[:csscode]) | |
52 | + redirect_to :action => 'edit', :id => @theme.id | |
53 | + end | |
54 | + | |
55 | + def add_image | |
56 | + @theme = profile.find_theme(params[:id]) | |
57 | + if request.xhr? | |
58 | + render :action => 'add_image', :layout => false | |
59 | + else | |
60 | + @theme.add_image(params[:image].original_filename, params[:image].read) | |
61 | + redirect_to :action => 'edit', :id => @theme.id | |
62 | + end | |
63 | + end | |
64 | + | |
65 | + def start_test | |
66 | + session[:theme] = params[:id] | |
67 | + redirect_to :controller => 'content_viewer', :profile => profile.identifier, :action => 'view_page' | |
68 | + end | |
69 | + | |
70 | + def stop_test | |
71 | + session[:theme] = nil | |
72 | + redirect_to :action => 'index' | |
73 | + end | |
74 | + | |
75 | +end | ... | ... |
app/controllers/my_profile/themes_controller.rb
... | ... | @@ -1,91 +0,0 @@ |
1 | -class ThemesController < MyProfileController | |
2 | - | |
3 | - protect 'edit_appearance', :profile | |
4 | - no_design_blocks | |
5 | - | |
6 | - def set | |
7 | - profile.update_theme(params[:id]) | |
8 | - redirect_to :action => 'index' | |
9 | - end | |
10 | - | |
11 | - def unset | |
12 | - profile.update_theme(nil) | |
13 | - redirect_to :action => 'index' | |
14 | - end | |
15 | - | |
16 | - def index | |
17 | - @themes = (profile.environment.themes + Theme.approved_themes(profile)).uniq_by{ |t| t.id }.sort_by{ |t| t.name } | |
18 | - @current_theme = profile.theme | |
19 | - | |
20 | - @layout_templates = LayoutTemplate.all | |
21 | - @current_template = profile.layout_template | |
22 | - end | |
23 | - | |
24 | - def new | |
25 | - if !request.xhr? | |
26 | - id = params[:name] ? params[:name].to_slug : 'my-theme' | |
27 | - t = Theme.new(id, :name => params[:name], :owner => profile, :public => false) | |
28 | - t.save | |
29 | - redirect_to :action => 'index' | |
30 | - else | |
31 | - render :action => 'new', :layout => false | |
32 | - end | |
33 | - end | |
34 | - | |
35 | - def edit | |
36 | - @theme = profile.find_theme(params[:id]) | |
37 | - @css_files = @theme.css_files | |
38 | - @image_files = @theme.image_files | |
39 | - end | |
40 | - | |
41 | - def add_css | |
42 | - @theme = profile.find_theme(params[:id]) | |
43 | - if request.xhr? | |
44 | - render :action => 'add_css', :layout => false | |
45 | - else | |
46 | - @theme.add_css(params[:css]) | |
47 | - redirect_to :action => 'edit', :id => @theme.id | |
48 | - end | |
49 | - end | |
50 | - | |
51 | - def css_editor | |
52 | - @theme = profile.find_theme(params[:id]) | |
53 | - @css = params[:css] | |
54 | - | |
55 | - @code = @theme.read_css(@css) | |
56 | - render :action => 'css_editor', :layout => false | |
57 | - end | |
58 | - | |
59 | - post_only :update_css | |
60 | - def update_css | |
61 | - @theme = profile.find_theme(params[:id]) | |
62 | - @theme.update_css(params[:css], params[:csscode]) | |
63 | - redirect_to :action => 'edit', :id => @theme.id | |
64 | - end | |
65 | - | |
66 | - def add_image | |
67 | - @theme = profile.find_theme(params[:id]) | |
68 | - if request.xhr? | |
69 | - render :action => 'add_image', :layout => false | |
70 | - else | |
71 | - @theme.add_image(params[:image].original_filename, params[:image].read) | |
72 | - redirect_to :action => 'edit', :id => @theme.id | |
73 | - end | |
74 | - end | |
75 | - | |
76 | - def start_test | |
77 | - session[:theme] = params[:id] | |
78 | - redirect_to :controller => 'content_viewer', :profile => profile.identifier, :action => 'view_page' | |
79 | - end | |
80 | - | |
81 | - def stop_test | |
82 | - session[:theme] = nil | |
83 | - redirect_to :action => 'index' | |
84 | - end | |
85 | - | |
86 | - def set_layout_template | |
87 | - profile.update_layout_template(params[:id]) | |
88 | - redirect_to :action => 'index' | |
89 | - end | |
90 | - | |
91 | -end |
app/controllers/public/account_controller.rb
... | ... | @@ -69,6 +69,8 @@ class AccountController < ApplicationController |
69 | 69 | session[:notice] = _("This environment doesn't allow user registration.") |
70 | 70 | end |
71 | 71 | |
72 | + store_location(request.referer) unless params[:return_to] or session[:return_to] | |
73 | + | |
72 | 74 | @block_bot = !!session[:may_be_a_bot] |
73 | 75 | @invitation_code = params[:invitation_code] |
74 | 76 | begin |
... | ... | @@ -77,6 +79,7 @@ class AccountController < ApplicationController |
77 | 79 | @user.environment = environment |
78 | 80 | @terms_of_use = environment.terms_of_use |
79 | 81 | @user.person_data = params[:profile_data] |
82 | + @user.return_to = session[:return_to] | |
80 | 83 | @person = Person.new(params[:profile_data]) |
81 | 84 | @person.environment = @user.environment |
82 | 85 | if request.post? |
... | ... | @@ -98,7 +101,7 @@ class AccountController < ApplicationController |
98 | 101 | end |
99 | 102 | if @user.activated? |
100 | 103 | self.current_user = @user |
101 | - redirect_to '/' | |
104 | + go_to_signup_initial_page | |
102 | 105 | else |
103 | 106 | @register_pending = true |
104 | 107 | end |
... | ... | @@ -368,32 +371,29 @@ class AccountController < ApplicationController |
368 | 371 | end |
369 | 372 | |
370 | 373 | def go_to_initial_page |
374 | + if params[:redirection] | |
375 | + session[:return_to] = @user.return_to | |
376 | + @user.return_to = nil | |
377 | + @user.save | |
378 | + end | |
379 | + | |
371 | 380 | if params[:return_to] |
372 | 381 | redirect_to params[:return_to] |
373 | 382 | elsif environment.enabled?('allow_change_of_redirection_after_login') |
374 | - case user.preferred_login_redirection | |
375 | - when 'keep_on_same_page' | |
376 | - redirect_back_or_default(user.admin_url) | |
377 | - when 'site_homepage' | |
378 | - redirect_to :controller => :home | |
379 | - when 'user_profile_page' | |
380 | - redirect_to user.public_profile_url | |
381 | - when 'user_homepage' | |
382 | - redirect_to user.url | |
383 | - when 'user_control_panel' | |
384 | - redirect_to user.admin_url | |
385 | - else | |
386 | - redirect_back_or_default(user.admin_url) | |
387 | - end | |
383 | + check_redirection_options(user, user.preferred_login_redirection, user.admin_url) | |
388 | 384 | else |
389 | 385 | if environment == current_user.environment |
390 | - redirect_back_or_default(user.admin_url) | |
386 | + check_redirection_options(user, environment.redirection_after_login, user.admin_url) | |
391 | 387 | else |
392 | 388 | redirect_back_or_default(:controller => 'home') |
393 | 389 | end |
394 | 390 | end |
395 | 391 | end |
396 | 392 | |
393 | + def go_to_signup_initial_page | |
394 | + check_redirection_options(user, user.environment.redirection_after_signup, user.url) | |
395 | + end | |
396 | + | |
397 | 397 | def redirect_if_logged_in |
398 | 398 | if logged_in? |
399 | 399 | go_to_initial_page |
... | ... | @@ -409,4 +409,22 @@ class AccountController < ApplicationController |
409 | 409 | user |
410 | 410 | end |
411 | 411 | |
412 | + protected | |
413 | + | |
414 | + def check_redirection_options(user, condition, default) | |
415 | + case condition | |
416 | + when 'keep_on_same_page' | |
417 | + redirect_back_or_default(user.admin_url) | |
418 | + when 'site_homepage' | |
419 | + redirect_to :controller => :home | |
420 | + when 'user_profile_page' | |
421 | + redirect_to user.public_profile_url | |
422 | + when 'user_homepage' | |
423 | + redirect_to user.url | |
424 | + when 'user_control_panel' | |
425 | + redirect_to user.admin_url | |
426 | + else | |
427 | + redirect_back_or_default(default) | |
428 | + end | |
429 | + end | |
412 | 430 | end | ... | ... |
app/controllers/public/catalog_controller.rb
app/controllers/public/comment_controller.rb
... | ... | @@ -71,7 +71,9 @@ class CommentController < ApplicationController |
71 | 71 | return |
72 | 72 | end |
73 | 73 | |
74 | - @comment.save | |
74 | + if @comment.save | |
75 | + @plugins.dispatch(:process_extra_comment_params, [@comment,params]) | |
76 | + end | |
75 | 77 | |
76 | 78 | respond_to do |format| |
77 | 79 | format.js do |
... | ... | @@ -113,6 +115,8 @@ class CommentController < ApplicationController |
113 | 115 | |
114 | 116 | def update |
115 | 117 | if @comment.update_attributes(params[:comment]) |
118 | + @plugins.dispatch(:process_extra_comment_params, [@comment,params]) | |
119 | + | |
116 | 120 | respond_to do |format| |
117 | 121 | format.js do |
118 | 122 | comment_to_render = @comment.comment_root | ... | ... |
app/controllers/public/content_viewer_controller.rb
1 | +require 'diffy' | |
2 | + | |
1 | 3 | class ContentViewerController < ApplicationController |
2 | 4 | |
3 | 5 | needs_profile |
... | ... | @@ -7,6 +9,7 @@ class ContentViewerController < ApplicationController |
7 | 9 | |
8 | 10 | def view_page |
9 | 11 | path = params[:page].join('/') |
12 | + @version = params[:version].to_i | |
10 | 13 | |
11 | 14 | if path.blank? |
12 | 15 | @page = profile.home_page |
... | ... | @@ -25,27 +28,15 @@ class ContentViewerController < ApplicationController |
25 | 28 | end |
26 | 29 | end |
27 | 30 | |
28 | - if !@page.nil? && !@page.display_to?(user) | |
29 | - if !profile.public? | |
30 | - private_profile_partial_parameters | |
31 | - render :template => 'profile/_private_profile.rhtml', :status => 403 | |
32 | - else #if !profile.visible? | |
33 | - message = _('You are not allowed to view this content.') | |
34 | - message += ' ' + _('You can contact the owner of this profile to request access then.') | |
35 | - render_access_denied(message) | |
36 | - end | |
37 | - return | |
38 | - end | |
31 | + return unless allow_access_to_page(path) | |
39 | 32 | |
40 | - # page not found, give error | |
41 | - if @page.nil? | |
42 | - render_not_found(@path) | |
43 | - return | |
44 | - end | |
45 | - | |
46 | - if request.xhr? && params[:toolbar] | |
47 | - render :partial => 'article_toolbar' | |
48 | - return | |
33 | + if @version > 0 | |
34 | + return render_access_denied unless @page.display_versions? | |
35 | + @versioned_article = @page.versions.find_by_version(@version) | |
36 | + if @versioned_article && @page.versions.latest.version != @versioned_article.version | |
37 | + render :template => 'content_viewer/versioned_article.rhtml' | |
38 | + return | |
39 | + end | |
49 | 40 | end |
50 | 41 | |
51 | 42 | redirect_to_translation if @page.profile.redirect_l10n |
... | ... | @@ -128,6 +119,21 @@ class ContentViewerController < ApplicationController |
128 | 119 | end |
129 | 120 | end |
130 | 121 | |
122 | + def versions_diff | |
123 | + path = params[:page].join('/') | |
124 | + @page = profile.articles.find_by_path(path) | |
125 | + @v1, @v2 = @page.versions.find_by_version(params[:v1]), @page.versions.find_by_version(params[:v2]) | |
126 | + end | |
127 | + | |
128 | + def article_versions | |
129 | + path = params[:page].join('/') | |
130 | + @page = profile.articles.find_by_path(path) | |
131 | + return unless allow_access_to_page(path) | |
132 | + | |
133 | + render_access_denied unless @page.display_versions? | |
134 | + @versions = @page.versions.paginate(:per_page => per_page, :page => params[:npage]) | |
135 | + end | |
136 | + | |
131 | 137 | protected |
132 | 138 | |
133 | 139 | def per_page |
... | ... | @@ -158,6 +164,24 @@ class ContentViewerController < ApplicationController |
158 | 164 | end |
159 | 165 | helper_method :pass_without_comment_captcha? |
160 | 166 | |
167 | + def allow_access_to_page(path) | |
168 | + allowed = true | |
169 | + if @page.nil? # page not found, give error | |
170 | + render_not_found(path) | |
171 | + allowed = false | |
172 | + elsif !@page.display_to?(user) | |
173 | + if !profile.public? | |
174 | + private_profile_partial_parameters | |
175 | + render :template => 'profile/_private_profile.rhtml', :status => 403 | |
176 | + allowed = false | |
177 | + else #if !profile.visible? | |
178 | + render_access_denied | |
179 | + allowed = false | |
180 | + end | |
181 | + end | |
182 | + allowed | |
183 | + end | |
184 | + | |
161 | 185 | def user_is_a_bot? |
162 | 186 | user_agent= request.env["HTTP_USER_AGENT"] |
163 | 187 | user_agent.blank? || |
... | ... | @@ -166,5 +190,4 @@ class ContentViewerController < ApplicationController |
166 | 190 | user_agent.match(/crawler/) || |
167 | 191 | user_agent.match(/\(.*https?:\/\/.*\)/) |
168 | 192 | end |
169 | - | |
170 | 193 | end | ... | ... |
app/controllers/public/profile_controller.rb
... | ... | @@ -67,7 +67,7 @@ class ProfileController < PublicController |
67 | 67 | |
68 | 68 | def members |
69 | 69 | if is_cache_expired?(profile.members_cache_key(params)) |
70 | - @members = profile.members.includes(relations_to_include).paginate(:per_page => members_per_page, :page => params[:npage]) | |
70 | + @members = profile.members_by_name.includes(relations_to_include).paginate(:per_page => members_per_page, :page => params[:npage]) | |
71 | 71 | end |
72 | 72 | end |
73 | 73 | |
... | ... | @@ -304,14 +304,6 @@ class ProfileController < PublicController |
304 | 304 | end |
305 | 305 | end |
306 | 306 | |
307 | - def profile_info | |
308 | - begin | |
309 | - @block = profile.blocks.find(params[:block_id]) | |
310 | - rescue | |
311 | - render :text => _('Profile information could not be loaded') | |
312 | - end | |
313 | - end | |
314 | - | |
315 | 307 | def report_abuse |
316 | 308 | @abuse_report = AbuseReport.new |
317 | 309 | render :layout => false | ... | ... |
app/controllers/public/search_controller.rb
... | ... | @@ -0,0 +1,42 @@ |
1 | +class ThemesController < ApplicationController | |
2 | + | |
3 | + before_filter :login_required | |
4 | + | |
5 | + no_design_blocks | |
6 | + | |
7 | + # attr_reader :target | |
8 | + | |
9 | + def target | |
10 | + @target | |
11 | + end | |
12 | + | |
13 | + def index | |
14 | + @environment = environment | |
15 | + @themes = (environment.themes + Theme.approved_themes(target)).sort_by { |t| t.name } | |
16 | + | |
17 | + @current_theme = target.theme | |
18 | + | |
19 | + @layout_templates = LayoutTemplate.all | |
20 | + @current_template = target.layout_template | |
21 | + end | |
22 | + | |
23 | + def set | |
24 | + target.update_theme(params[:id]) | |
25 | + redirect_to :action => 'index' | |
26 | + end | |
27 | + | |
28 | + def unset | |
29 | + if target.kind_of?(Environment) | |
30 | + target.update_theme('default') | |
31 | + else | |
32 | + target.update_theme(nil) | |
33 | + end | |
34 | + redirect_to :action => 'index' | |
35 | + end | |
36 | + | |
37 | + def set_layout_template | |
38 | + target.update_layout_template(params[:id]) | |
39 | + redirect_to :action => 'index' | |
40 | + end | |
41 | + | |
42 | +end | ... | ... |
app/helpers/application_helper.rb
... | ... | @@ -42,6 +42,8 @@ module ApplicationHelper |
42 | 42 | |
43 | 43 | include TokenHelper |
44 | 44 | |
45 | + include CatalogHelper | |
46 | + | |
45 | 47 | def locale |
46 | 48 | (@page && !@page.language.blank?) ? @page.language : FastGettext.locale |
47 | 49 | end |
... | ... | @@ -512,24 +514,25 @@ module ApplicationHelper |
512 | 514 | |
513 | 515 | def profile_cat_icons( profile ) |
514 | 516 | if profile.class == Enterprise |
515 | - icons = profile.product_categories.map{ |c| c.size > 1 ? c[1] : nil }. | |
516 | - compact.uniq.map do |c| | |
517 | - cat_name = c.gsub( /[-_\s,.;'"]+/, '_' ) | |
518 | - cat_icon = "/images/icons-cat/#{cat_name}.png" | |
519 | - if ! File.exists? RAILS_ROOT.to_s() + '/public/' + cat_icon | |
520 | - cat_icon = '/images/icons-cat/undefined.png' | |
521 | - end | |
522 | - content_tag('span', | |
523 | - content_tag( 'span', c ), | |
524 | - :title => c, | |
525 | - :class => 'product-cat-icon cat_icon_' + cat_name, | |
526 | - :style => "background-image:url(#{cat_icon})" | |
527 | - ) | |
528 | - end.join("\n").html_safe | |
529 | - content_tag('div', | |
530 | - content_tag( 'span', _('Principal Product Categories'), :class => 'header' ) +"\n"+ icons, | |
531 | - :class => 'product-category-icons' | |
517 | + icons = profile.product_categories.unique_by_level(2).limit(3).map do |c| | |
518 | + filtered_category = c.filtered_category.blank? ? c.path.split('/').last : c.filtered_category | |
519 | + category_title = filtered_category.split(/[-_\s,.;'"]+/).map(&:capitalize).join(' ') | |
520 | + category_name = category_title.gsub(' ', '_' ) | |
521 | + category_icon = "/images/icons-cat/#{category_name}.png" | |
522 | + if ! File.exists? RAILS_ROOT.to_s() + '/public/' + category_icon | |
523 | + category_icon = '/images/icons-cat/undefined.png' | |
524 | + end | |
525 | + content_tag('span', | |
526 | + content_tag( 'span', category_title ), | |
527 | + :title => category_title, | |
528 | + :class => 'product-cat-icon cat_icon_' + category_name, | |
529 | + :style => "background-image:url(#{category_icon})" | |
532 | 530 | ) |
531 | + end.join("\n").html_safe | |
532 | + content_tag('div', | |
533 | + content_tag( 'span', _('Principal Product Categories'), :class => 'header' ) +"\n"+ icons, | |
534 | + :class => 'product-category-icons' | |
535 | + ) | |
533 | 536 | else |
534 | 537 | '' |
535 | 538 | end |
... | ... | @@ -606,49 +609,18 @@ module ApplicationHelper |
606 | 609 | end |
607 | 610 | |
608 | 611 | attr_reader :environment |
612 | + | |
609 | 613 | def select_categories(object_name, title=nil, title_size=4) |
610 | 614 | return nil if environment.enabled?(:disable_categories) |
611 | 615 | if title.nil? |
612 | 616 | title = _('Categories') |
613 | 617 | end |
614 | 618 | |
615 | - object = instance_variable_get("@#{object_name}") | |
616 | - | |
617 | - result = content_tag 'h'+title_size.to_s(), title | |
618 | - result << javascript_tag( 'function open_close_cat( link ) { | |
619 | - var div = link.parentNode.getElementsByTagName("div")[0]; | |
620 | - var end = function(){ | |
621 | - if ( div.style.display == "none" ) { | |
622 | - this.link.className="button icon-button icon-down" | |
623 | - } else { | |
624 | - this.link.className="button icon-button icon-up-red" | |
625 | - } | |
626 | - } | |
627 | - Effect.toggle( div, "slide", { link:link, div:div, afterFinish:end } ) | |
628 | - }') | |
629 | - environment.top_level_categories.select{|i| !i.children.empty?}.each do |toplevel| | |
630 | - next unless object.accept_category?(toplevel) | |
631 | - # FIXME | |
632 | - ([toplevel] + toplevel.children_for_menu).each do |cat| | |
633 | - if cat.top_level? | |
634 | - result << '<div class="categorie_box">'.html_safe | |
635 | - result << icon_button( :down, _('open'), '#', :onclick => 'open_close_cat(this); return false' ) | |
636 | - result << content_tag('h5', toplevel.name) | |
637 | - result << '<div style="display:none"><ul class="categories">'.html_safe | |
638 | - else | |
639 | - checkbox_id = "#{object_name}_#{cat.full_name.downcase.gsub(/\s+|\//, '_')}" | |
640 | - result << content_tag('li', labelled_check_box( | |
641 | - cat.full_name_without_leading(1, " → "), | |
642 | - "#{object_name}[category_ids][]", cat.id, | |
643 | - object.category_ids.include?(cat.id), :id => checkbox_id, | |
644 | - :onchange => 'this.parentNode.className=(this.checked?"cat_checked":"")' ), | |
645 | - :class => ( object.category_ids.include?(cat.id) ? 'cat_checked' : '' ) ) + "\n" | |
646 | - end | |
647 | - end | |
648 | - result << '</ul></div></div>'.html_safe | |
649 | - end | |
619 | + @object = instance_variable_get("@#{object_name}") | |
620 | + @categories = environment.top_level_categories | |
650 | 621 | |
651 | - content_tag('div', result) | |
622 | + @current_categories = environment.top_level_categories.select{|i| !i.children.empty?} | |
623 | + render :partial => 'shared/select_categories_top', :locals => {:object_name => object_name, :title => title, :title_size => title_size, :multiple => true, :categories_selected => @object.categories }, :layout => false | |
652 | 624 | end |
653 | 625 | |
654 | 626 | def theme_option(opt = nil) |
... | ... | @@ -918,12 +890,11 @@ module ApplicationHelper |
918 | 890 | |
919 | 891 | def page_title |
920 | 892 | (@page ? @page.title + ' - ' : '') + |
921 | - (profile ? profile.short_name + ' - ' : '') + | |
922 | 893 | (@topic ? @topic.title + ' - ' : '') + |
923 | 894 | (@section ? @section.title + ' - ' : '') + |
924 | 895 | (@toc ? _('Online Manual') + ' - ' : '') + |
925 | 896 | (@controller.controller_name == 'chat' ? _('Chat') + ' - ' : '') + |
926 | - environment.name + | |
897 | + (profile ? profile.short_name : environment.name) + | |
927 | 898 | (@category ? " - #{@category.full_name}" : '') |
928 | 899 | end |
929 | 900 | |
... | ... | @@ -1178,6 +1149,7 @@ module ApplicationHelper |
1178 | 1149 | #FIXME Use time_ago_in_words instead of this method if you're using Rails 2.2+ |
1179 | 1150 | def time_ago_as_sentence(from_time, include_seconds = false) |
1180 | 1151 | to_time = Time.now |
1152 | + from_time = Time.parse(from_time.to_s) | |
1181 | 1153 | from_time = from_time.to_time if from_time.respond_to?(:to_time) |
1182 | 1154 | to_time = to_time.to_time if to_time.respond_to?(:to_time) |
1183 | 1155 | distance_in_minutes = (((to_time - from_time).abs)/60).round |
... | ... | @@ -1402,4 +1374,8 @@ module ApplicationHelper |
1402 | 1374 | content.nil? ? '' : content.id.to_s |
1403 | 1375 | end |
1404 | 1376 | |
1377 | + def display_article_versions(article, version = nil) | |
1378 | + content_tag('ul', article.versions.map {|v| link_to("r#{v.version}", @page.url.merge(:version => v.version))}) | |
1379 | + end | |
1380 | + | |
1405 | 1381 | end | ... | ... |
app/helpers/article_helper.rb
... | ... | @@ -28,7 +28,7 @@ module ArticleHelper |
28 | 28 | 'div', |
29 | 29 | check_box(:article, :notify_comments) + |
30 | 30 | content_tag('label', _('I want to receive a notification of each comment written by e-mail'), :for => 'article_notify_comments') + |
31 | - observe_field(:article_accept_comments, :function => "$('article_notify_comments').disabled = ! $('article_accept_comments').checked;$('article_moderate_comments').disabled = ! $('article_accept_comments').checked") | |
31 | + observe_field(:article_accept_comments, :function => "$('article_notify_comments').disabled = ! $('article_accept_comments').checked;$('article_moderate_comments').disabled = ! $('article_accept_comments').checked") | |
32 | 32 | ) + |
33 | 33 | |
34 | 34 | content_tag( |
... | ... | @@ -42,7 +42,21 @@ module ArticleHelper |
42 | 42 | 'div', |
43 | 43 | check_box(:article, :display_hits) + |
44 | 44 | content_tag('label', _('I want this article to display the number of hits it received'), :for => 'article_display_hits') |
45 | - ) : '') | |
45 | + ) : '') + | |
46 | + | |
47 | + (article.can_display_versions? ? | |
48 | + content_tag( | |
49 | + 'div', | |
50 | + check_box(:article, :display_versions) + | |
51 | + content_tag('label', _('I want this article to display a link to older versions'), :for => 'article_display_versions') | |
52 | + ) : '') + | |
53 | + | |
54 | + (article.forum? && article.profile.community? ? | |
55 | + content_tag( | |
56 | + 'div', | |
57 | + check_box(:article, :allows_members_to_create_topics) + | |
58 | + content_tag('label', _('Allow members to create topics'), :for => 'article_allows_members_to_create_topics') | |
59 | + ) : '') | |
46 | 60 | ) |
47 | 61 | end |
48 | 62 | ... | ... |
app/helpers/boxes_helper.rb
... | ... | @@ -65,7 +65,7 @@ module BoxesHelper |
65 | 65 | end |
66 | 66 | |
67 | 67 | def display_box_content(box, main_content) |
68 | - context = { :article => @page, :request_path => request.path, :locale => locale } | |
68 | + context = { :article => @page, :request_path => request.path, :locale => locale, :params => request.params } | |
69 | 69 | box_decorator.select_blocks(box.blocks.includes(:box), context).map { |item| display_block(item, main_content) }.join("\n") + box_decorator.block_target(box) |
70 | 70 | end |
71 | 71 | |
... | ... | @@ -212,6 +212,7 @@ module BoxesHelper |
212 | 212 | |
213 | 213 | if !block.main? |
214 | 214 | buttons << icon_button(:delete, _('Remove block'), { :action => 'remove', :id => block.id }, { :method => 'post', :confirm => _('Are you sure you want to remove this block?')}) |
215 | + buttons << icon_button(:clone, _('Clone'), { :action => 'clone', :id => block.id }, { :method => 'post' }) | |
215 | 216 | end |
216 | 217 | |
217 | 218 | if block.respond_to?(:help) | ... | ... |
app/helpers/catalog_helper.rb
... | ... | @@ -9,7 +9,11 @@ module CatalogHelper |
9 | 9 | @categories = ProductCategory.on_level(params[:level]).order(:name) |
10 | 10 | end |
11 | 11 | |
12 | - @products = profile.products.from_category(@category).paginate(:order => 'available desc, highlighted desc, name asc', :per_page => 9, :page => options[:page]) | |
12 | + @products = profile.products.from_category(@category).paginate( | |
13 | + :order => 'available desc, highlighted desc, name asc', | |
14 | + :per_page => @profile.products_per_catalog_page, | |
15 | + :page => options[:page] | |
16 | + ) | |
13 | 17 | end |
14 | 18 | |
15 | 19 | def breadcrumb(category) |
... | ... | @@ -20,20 +24,24 @@ module CatalogHelper |
20 | 24 | content_tag('div', all_items.join(' → '), :id => 'breadcrumb') |
21 | 25 | end |
22 | 26 | |
23 | - def category_link(category, sub = false) | |
27 | + def category_link(category) | |
24 | 28 | count = profile.products.from_category(category).count |
25 | 29 | name = truncate(category.name, :length => 22 - count.to_s.size) |
26 | - link_name = sub ? name : content_tag('strong', name) | |
27 | - link = link_to(link_name, {:controller => :catalog, :action => 'index', :level => category.id}, :title => category.name) | |
28 | - content_tag('li', "#{link} (#{count})") if count > 0 | |
30 | + link = link_to(name, {:controller => 'catalog', :action => 'index', :level => category.id}, :title => category.name) | |
31 | + content_tag('div', "#{link} <span class=\"count\">#{count}</span>") if count > 0 | |
29 | 32 | end |
30 | 33 | |
31 | - def category_sub_links(category) | |
34 | + def category_with_sub_list(category) | |
35 | + content_tag 'li', "#{category_link(category)}\n#{sub_category_list(category)}" | |
36 | + end | |
37 | + | |
38 | + def sub_category_list(category) | |
32 | 39 | sub_categories = [] |
33 | 40 | category.children.order(:name).each do |sub_category| |
34 | - sub_categories << category_link(sub_category, true) | |
41 | + cat_link = category_link sub_category | |
42 | + sub_categories << content_tag('li', cat_link) unless cat_link.nil? | |
35 | 43 | end |
36 | - content_tag('ul', sub_categories) if sub_categories.size > 1 | |
44 | + content_tag('ul', sub_categories) if sub_categories.size > 0 | |
37 | 45 | end |
38 | 46 | |
39 | 47 | end | ... | ... |
app/helpers/categories_helper.rb
... | ... | @@ -48,4 +48,12 @@ module CategoriesHelper |
48 | 48 | labelled_form_field(_('Type of category'), select_tag('type', options_for_select(TYPES, value))) |
49 | 49 | end |
50 | 50 | |
51 | + #FIXME make this test | |
52 | + def selected_category_link(cat) | |
53 | + content_tag('div', button_to_function_without_text(:remove, _('Remove'), nil) {|page| page["selected-category-#{cat.id}"].remove} + | |
54 | + link_to_function(cat.full_name(' → '), nil, :id => "remove-selected-category-#{cat.id}-button", :class => 'select-subcategory-link') {|page| page["selected-category-#{cat.id}"].remove}, | |
55 | + :class => 'selected-category' | |
56 | + ) | |
57 | + end | |
58 | + | |
51 | 59 | end | ... | ... |
app/helpers/comment_helper.rb
... | ... | @@ -21,10 +21,19 @@ module CommentHelper |
21 | 21 | title |
22 | 22 | end |
23 | 23 | |
24 | + def comment_extra_contents(comment) | |
25 | + @plugins.dispatch(:comment_extra_contents, comment).collect do |extra_content| | |
26 | + extra_content.kind_of?(Proc) ? self.instance_eval(&extra_content) : extra_content | |
27 | + end.join('\n') | |
28 | + end | |
29 | + | |
24 | 30 | def comment_actions(comment) |
25 | 31 | url = url_for(:profile => profile.identifier, :controller => :comment, :action => :check_actions, :id => comment.id) |
26 | 32 | links = links_for_comment_actions(comment) |
27 | - content_tag(:li, link_to(content_tag(:span, _('Contents menu')), '#', :onclick => "toggleSubmenu(this,'',#{links.to_json}); return false", :class => 'menu-submenu-trigger comment-trigger', :url => url), :class=> 'vcard') unless links.empty? | |
33 | + links_submenu = links.select{|link| link[:action_bar].blank?} | |
34 | + links_action_bar = links - links_submenu | |
35 | + links_submenu = links_submenu.collect {|link| link.slice(:link)} | |
36 | + render :partial => 'comment/comment_actions', :locals => {:links_submenu => links_submenu, :links_action_bar => links_action_bar, :url => url, :comment => comment} | |
28 | 37 | end |
29 | 38 | |
30 | 39 | private | ... | ... |
app/helpers/content_viewer_helper.rb
... | ... | @@ -51,15 +51,6 @@ module ContentViewerHelper |
51 | 51 | end |
52 | 52 | end |
53 | 53 | |
54 | - def addthis_facebook_url(article) | |
55 | - "http://www.facebook.com/sharer.php?s=100&p[title]=%{title}&p[summary]=%{summary}&p[url]=%{url}&p[images][0]=%{image}" % { | |
56 | - :title => CGI.escape(article.title), | |
57 | - :url => CGI.escape(url_for(article.url)), | |
58 | - :summary => CGI.escape(truncate(strip_tags(article.body.to_s), :length => 300)), | |
59 | - :image => CGI.escape(article.body_images_paths.first.to_s) | |
60 | - } | |
61 | - end | |
62 | - | |
63 | 54 | def addthis_image_tag |
64 | 55 | if File.exists?(File.join(Rails.root, 'public', theme_path, 'images', 'addthis.gif')) |
65 | 56 | image_tag(File.join(theme_path, 'images', 'addthis.gif'), :border => 0, :alt => '') | ... | ... |
app/helpers/layout_helper.rb
app/helpers/profile_helper.rb
... | ... | @@ -16,14 +16,17 @@ module ProfileHelper |
16 | 16 | end |
17 | 17 | |
18 | 18 | def display_contact(profile) |
19 | - address = display_field(_('Address:'), profile, :address) | |
20 | - zip = display_field(_('ZIP code:'), profile, :zip_code) | |
21 | - phone = display_field(_('Contact phone:'), profile, :contact_phone) | |
22 | - email = display_field(_('e-Mail:'), profile, :email) { |email| link_to_email(email) } | |
23 | - if address.blank? && zip.blank? && phone.blank? && email.blank? | |
19 | + fields = [] | |
20 | + fields << display_field(_('Address:'), profile, :address).html_safe | |
21 | + fields << display_field(_('ZIP code:'), profile, :zip_code).html_safe | |
22 | + fields << display_field(_('Contact phone:'), profile, :contact_phone).html_safe | |
23 | + fields << display_field(_('e-Mail:'), profile, :email) { |email| link_to_email(email) }.html_safe | |
24 | + fields << display_field(_('Personal website:'), profile, :personal_website).html_safe | |
25 | + fields << display_field(_('Jabber:'), profile, :jabber_id).html_safe | |
26 | + if fields.reject!(&:blank?).empty? | |
24 | 27 | '' |
25 | 28 | else |
26 | - content_tag('tr', content_tag('th', _('Contact'), { :colspan => 2 })) + address + zip + phone + email | |
29 | + content_tag('tr', content_tag('th', _('Contact'), { :colspan => 2 })) + fields.join.html_safe | |
27 | 30 | end |
28 | 31 | end |
29 | 32 | ... | ... |
app/models/article.rb
... | ... | @@ -201,6 +201,7 @@ class Article < ActiveRecord::Base |
201 | 201 | acts_as_filesystem |
202 | 202 | |
203 | 203 | acts_as_versioned |
204 | + self.non_versioned_columns << 'setting' | |
204 | 205 | |
205 | 206 | def comment_data |
206 | 207 | comments.map {|item| [item.title, item.body].join(' ') }.join(' ') |
... | ... | @@ -604,25 +605,49 @@ class Article < ActiveRecord::Base |
604 | 605 | false |
605 | 606 | end |
606 | 607 | |
607 | - def author | |
608 | - if versions.empty? | |
609 | - last_changed_by | |
610 | - else | |
611 | - author_id = versions.first.last_changed_by_id | |
608 | + settings_items :display_versions, :type => :boolean, :default => false | |
609 | + | |
610 | + def can_display_versions? | |
611 | + false | |
612 | + end | |
613 | + | |
614 | + def display_versions? | |
615 | + can_display_versions? && display_versions | |
616 | + end | |
617 | + | |
618 | + def author(version_number = nil) | |
619 | + if version_number | |
620 | + version = versions.find_by_version(version_number) | |
621 | + author_id = version.last_changed_by_id if version | |
612 | 622 | Person.exists?(author_id) ? Person.find(author_id) : nil |
623 | + else | |
624 | + if versions.empty? | |
625 | + last_changed_by | |
626 | + else | |
627 | + author_id = versions.first.last_changed_by_id | |
628 | + Person.exists?(author_id) ? Person.find(author_id) : nil | |
629 | + end | |
613 | 630 | end |
614 | 631 | end |
615 | 632 | |
616 | - def author_name | |
617 | - author ? author.name : (setting[:author_name] || _('Unknown')) | |
633 | + def author_name(version_number = nil) | |
634 | + person = author(version_number) | |
635 | + person ? person.name : (setting[:author_name] || _('Unknown')) | |
618 | 636 | end |
619 | 637 | |
620 | - def author_url | |
621 | - author ? author.url : nil | |
638 | + def author_url(version_number = nil) | |
639 | + person = author(version_number) | |
640 | + person ? person.url : nil | |
622 | 641 | end |
623 | 642 | |
624 | - def author_id | |
625 | - author ? author.id : nil | |
643 | + def author_id(version_number = nil) | |
644 | + person = author(version_number) | |
645 | + person ? person.id : nil | |
646 | + end | |
647 | + | |
648 | + def version_license(version_number = nil) | |
649 | + return license if version_number.nil? | |
650 | + profile.environment.licenses.find_by_id(versions.find_by_version(version_number).license_id) | |
626 | 651 | end |
627 | 652 | |
628 | 653 | alias :active_record_cache_key :cache_key |
... | ... | @@ -631,7 +656,9 @@ class Article < ActiveRecord::Base |
631 | 656 | (allow_post_content?(the_profile) ? "-owner" : '') + |
632 | 657 | (params[:npage] ? "-npage-#{params[:npage]}" : '') + |
633 | 658 | (params[:year] ? "-year-#{params[:year]}" : '') + |
634 | - (params[:month] ? "-month-#{params[:month]}" : '') | |
659 | + (params[:month] ? "-month-#{params[:month]}" : '') + | |
660 | + (params[:version] ? "-version-#{params[:version]}" : '') | |
661 | + | |
635 | 662 | end |
636 | 663 | |
637 | 664 | def first_paragraph | ... | ... |
app/models/block.rb
... | ... | @@ -23,30 +23,41 @@ class Block < ActiveRecord::Base |
23 | 23 | # * <tt>:article</tt>: the article being viewed currently |
24 | 24 | # * <tt>:language</tt>: in which language the block will be displayed |
25 | 25 | def visible?(context = nil) |
26 | - if display == 'never' | |
27 | - return false | |
28 | - end | |
26 | + return false if display == 'never' | |
27 | + | |
29 | 28 | if context |
30 | - if language != 'all' && language != context[:locale] | |
31 | - return false | |
32 | - end | |
33 | - if display == 'home_page_only' | |
34 | - if context[:article] | |
35 | - return context[:article] == owner.home_page | |
36 | - else | |
37 | - return context[:request_path] == '/' | |
38 | - end | |
39 | - elsif display == 'except_home_page' | |
40 | - if context[:article] | |
41 | - return context[:article] != owner.home_page | |
42 | - else | |
43 | - return context[:request_path] != '/' + (owner.kind_of?(Profile) ? owner.identifier : '') | |
44 | - end | |
29 | + return false if language != 'all' && language != context[:locale] | |
30 | + | |
31 | + begin | |
32 | + return self.send("display_#{display}", context) | |
33 | + rescue NoMethodError => exception | |
34 | + raise "Display '#{display}' is not a valid value." | |
45 | 35 | end |
46 | 36 | end |
37 | + | |
47 | 38 | true |
48 | 39 | end |
49 | 40 | |
41 | + def display_always(context) | |
42 | + true | |
43 | + end | |
44 | + | |
45 | + def display_home_page_only(context) | |
46 | + if context[:article] | |
47 | + return context[:article] == owner.home_page | |
48 | + else | |
49 | + return context[:request_path] == '/' | |
50 | + end | |
51 | + end | |
52 | + | |
53 | + def display_except_home_page(context) | |
54 | + if context[:article] | |
55 | + return context[:article] != owner.home_page | |
56 | + else | |
57 | + return context[:request_path] != '/' + (owner.kind_of?(Profile) ? owner.identifier : '') | |
58 | + end | |
59 | + end | |
60 | + | |
50 | 61 | # The condition for displaying a block. It can assume the following values: |
51 | 62 | # |
52 | 63 | # * <tt>'always'</tt>: the block is always displayed |
... | ... | @@ -168,4 +179,14 @@ class Block < ActiveRecord::Base |
168 | 179 | DISPLAY_OPTIONS[option] |
169 | 180 | end |
170 | 181 | |
182 | + def duplicate | |
183 | + duplicated_block = self.clone | |
184 | + duplicated_block.display = 'never' | |
185 | + duplicated_block.created_at = nil | |
186 | + duplicated_block.updated_at = nil | |
187 | + duplicated_block.save! | |
188 | + duplicated_block.insert_at(self.position + 1) | |
189 | + duplicated_block | |
190 | + end | |
191 | + | |
171 | 192 | end | ... | ... |
app/models/box.rb
... | ... | @@ -26,6 +26,8 @@ class Box < ActiveRecord::Base |
26 | 26 | CategoriesBlock, |
27 | 27 | CommunitiesBlock, |
28 | 28 | EnterprisesBlock, |
29 | + # TODO EnvironmentStatisticsBlock is DEPRECATED and will be removed from | |
30 | + # the Noosfero core soon, see ActionItem3045 | |
29 | 31 | EnvironmentStatisticsBlock, |
30 | 32 | FansBlock, |
31 | 33 | FavoriteEnterprisesBlock, |
... | ... | @@ -52,6 +54,8 @@ class Box < ActiveRecord::Base |
52 | 54 | CommunitiesBlock, |
53 | 55 | DisabledEnterpriseMessageBlock, |
54 | 56 | EnterprisesBlock, |
57 | + # TODO EnvironmentStatisticsBlock is DEPRECATED and will be removed from | |
58 | + # the Noosfero core soon, see ActionItem3045 | |
55 | 59 | EnvironmentStatisticsBlock, |
56 | 60 | FansBlock, |
57 | 61 | FavoriteEnterprisesBlock, |
... | ... | @@ -66,6 +70,7 @@ class Box < ActiveRecord::Base |
66 | 70 | MyNetworkBlock, |
67 | 71 | PeopleBlock, |
68 | 72 | ProductsBlock, |
73 | + ProductCategoriesBlock, | |
69 | 74 | ProfileImageBlock, |
70 | 75 | ProfileInfoBlock, |
71 | 76 | ProfileSearchBlock, | ... | ... |
app/models/enterprise.rb
... | ... | @@ -10,19 +10,20 @@ class Enterprise < Organization |
10 | 10 | |
11 | 11 | N_('Enterprise') |
12 | 12 | |
13 | - has_many :products, :dependent => :destroy, :order => 'name ASC' | |
13 | + has_many :products, :foreign_key => :profile_id, :dependent => :destroy, :order => 'name ASC' | |
14 | 14 | has_many :inputs, :through => :products |
15 | 15 | has_many :production_costs, :as => :owner |
16 | 16 | |
17 | 17 | has_and_belongs_to_many :fans, :class_name => 'Person', :join_table => 'favorite_enteprises_people' |
18 | 18 | |
19 | 19 | def product_categories |
20 | - products.includes(:product_category).map{|p| p.category_full_name}.compact | |
20 | + ProductCategory.by_enterprise(self) | |
21 | 21 | end |
22 | 22 | |
23 | 23 | N_('Organization website'); N_('Historic and current context'); N_('Activities short description'); N_('City'); N_('State'); N_('Country'); N_('ZIP code') |
24 | 24 | |
25 | 25 | settings_items :organization_website, :historic_and_current_context, :activities_short_description, :zip_code, :city, :state, :country |
26 | + settings_items :products_per_catalog_page, :type => :integer, :default => 6 | |
26 | 27 | |
27 | 28 | extend SetProfileRegionFromCityState::ClassMethods |
28 | 29 | set_profile_region_from_city_state |
... | ... | @@ -135,8 +136,11 @@ class Enterprise < Organization |
135 | 136 | ] |
136 | 137 | blocks = [ |
137 | 138 | [MainBlock.new], |
138 | - [ProfileImageBlock.new, LinkListBlock.new(:links => links)], | |
139 | - [] | |
139 | + [ ProfileImageBlock.new, | |
140 | + LinkListBlock.new(:links => links), | |
141 | + ProductCategoriesBlock.new | |
142 | + ], | |
143 | + [LocationBlock.new] | |
140 | 144 | ] |
141 | 145 | if environment.enabled?('products_for_enterprises') |
142 | 146 | blocks[2].unshift ProductsBlock.new | ... | ... |
app/models/environment.rb
... | ... | @@ -26,7 +26,8 @@ class Environment < ActiveRecord::Base |
26 | 26 | 'manage_environment_users' => N_('Manage environment users'), |
27 | 27 | 'manage_environment_templates' => N_('Manage environment templates'), |
28 | 28 | 'manage_environment_licenses' => N_('Manage environment licenses'), |
29 | - 'manage_environment_trusted_sites' => N_('Manage environment trusted sites') | |
29 | + 'manage_environment_trusted_sites' => N_('Manage environment trusted sites'), | |
30 | + 'edit_appearance' => N_('Edit appearance'), | |
30 | 31 | } |
31 | 32 | |
32 | 33 | module Roles |
... | ... | @@ -144,6 +145,18 @@ class Environment < ActiveRecord::Base |
144 | 145 | end |
145 | 146 | validates_inclusion_of :redirection_after_login, :in => Environment.login_redirection_options.keys, :allow_nil => true |
146 | 147 | |
148 | + def self.signup_redirection_options | |
149 | + { | |
150 | + 'keep_on_same_page' => _('Stays on the same page the user was before signup.'), | |
151 | + 'site_homepage' => _('Redirects the user to the environment homepage.'), | |
152 | + 'user_profile_page' => _('Redirects the user to his profile page.'), | |
153 | + 'user_homepage' => _('Redirects the user to his homepage.'), | |
154 | + 'user_control_panel' => _('Redirects the user to his control panel.') | |
155 | + } | |
156 | + end | |
157 | + validates_inclusion_of :redirection_after_signup, :in => Environment.signup_redirection_options.keys, :allow_nil => true | |
158 | + | |
159 | + | |
147 | 160 | # ################################################# |
148 | 161 | # Relationships and applied behaviour |
149 | 162 | # ################################################# |
... | ... | @@ -160,6 +173,8 @@ class Environment < ActiveRecord::Base |
160 | 173 | |
161 | 174 | # "left" area |
162 | 175 | env.boxes[1].blocks << LoginBlock.new |
176 | + # TODO EnvironmentStatisticsBlock is DEPRECATED and will be removed from | |
177 | + # the Noosfero core soon, see ActionItem3045 | |
163 | 178 | env.boxes[1].blocks << EnvironmentStatisticsBlock.new |
164 | 179 | env.boxes[1].blocks << RecentDocumentsBlock.new |
165 | 180 | |
... | ... | @@ -680,6 +695,16 @@ class Environment < ActiveRecord::Base |
680 | 695 | end |
681 | 696 | end |
682 | 697 | |
698 | + def update_theme(theme) | |
699 | + self.theme = theme | |
700 | + self.save! | |
701 | + end | |
702 | + | |
703 | + def update_layout_template(template) | |
704 | + self.layout_template = template | |
705 | + self.save! | |
706 | + end | |
707 | + | |
683 | 708 | before_create do |env| |
684 | 709 | env.settings[:themes] ||= %w[ |
685 | 710 | aluminium |
... | ... | @@ -695,7 +720,8 @@ class Environment < ActiveRecord::Base |
695 | 720 | end |
696 | 721 | |
697 | 722 | def community_template |
698 | - Community.find_by_id settings[:community_template_id] | |
723 | + template = Community.find_by_id settings[:community_template_id] | |
724 | + template if template && template.is_template | |
699 | 725 | end |
700 | 726 | |
701 | 727 | def community_template=(value) |
... | ... | @@ -703,7 +729,8 @@ class Environment < ActiveRecord::Base |
703 | 729 | end |
704 | 730 | |
705 | 731 | def person_template |
706 | - Person.find_by_id settings[:person_template_id] | |
732 | + template = Person.find_by_id settings[:person_template_id] | |
733 | + template if template && template.is_template | |
707 | 734 | end |
708 | 735 | |
709 | 736 | def person_template=(value) |
... | ... | @@ -711,7 +738,8 @@ class Environment < ActiveRecord::Base |
711 | 738 | end |
712 | 739 | |
713 | 740 | def enterprise_template |
714 | - Enterprise.find_by_id settings[:enterprise_template_id] | |
741 | + template = Enterprise.find_by_id settings[:enterprise_template_id] | |
742 | + template if template && template.is_template | |
715 | 743 | end |
716 | 744 | |
717 | 745 | def enterprise_template=(value) |
... | ... | @@ -719,7 +747,8 @@ class Environment < ActiveRecord::Base |
719 | 747 | end |
720 | 748 | |
721 | 749 | def inactive_enterprise_template |
722 | - Enterprise.find_by_id settings[:inactive_enterprise_template_id] | |
750 | + template = Enterprise.find_by_id settings[:inactive_enterprise_template_id] | |
751 | + template if template && template.is_template | |
723 | 752 | end |
724 | 753 | |
725 | 754 | def inactive_enterprise_template=(value) |
... | ... | @@ -801,7 +830,7 @@ class Environment < ActiveRecord::Base |
801 | 830 | end |
802 | 831 | |
803 | 832 | def highlighted_products_with_image(options = {}) |
804 | - Product.find(:all, {:conditions => {:highlighted => true, :enterprise_id => self.enterprises.find(:all, :select => :id) }, :joins => :image}.merge(options)) | |
833 | + Product.find(:all, {:conditions => {:highlighted => true, :profile_id => self.enterprises.find(:all, :select => :id) }, :joins => :image}.merge(options)) | |
805 | 834 | end |
806 | 835 | |
807 | 836 | settings_items :home_cache_in_minutes, :type => :integer, :default => 5 | ... | ... |
app/models/environment_statistics_block.rb
1 | +# TODO EnvironmentStatisticsBlock is DEPRECATED and will be removed from | |
2 | +# the Noosfero core soon, see ActionItem3045 | |
3 | + | |
1 | 4 | class EnvironmentStatisticsBlock < Block |
2 | 5 | |
3 | 6 | def self.description |
4 | - _('Environment stastistics') | |
7 | + _('Environment stastistics (DEPRECATED)') | |
5 | 8 | end |
6 | 9 | |
7 | 10 | def default_title | ... | ... |
app/models/forum.rb
... | ... | @@ -5,6 +5,7 @@ class Forum < Folder |
5 | 5 | |
6 | 6 | settings_items :terms_of_use, :type => :string, :default => "" |
7 | 7 | settings_items :has_terms_of_use, :type => :boolean, :default => false |
8 | + settings_items :allows_members_to_create_topics, :type => :boolean, :default => false | |
8 | 9 | has_and_belongs_to_many :users_with_agreement, :class_name => 'Person', :join_table => 'terms_forum_people' |
9 | 10 | |
10 | 11 | before_save do |forum| |
... | ... | @@ -66,4 +67,11 @@ class Forum < Folder |
66 | 67 | self.users_with_agreement.exists? user |
67 | 68 | end |
68 | 69 | |
70 | + def can_create_topic?(user, profile) | |
71 | + return profile.community? && profile.members.include?(user) && self.allows_members_to_create_topics | |
72 | + end | |
73 | + | |
74 | + def allow_create?(user) | |
75 | + super || can_create_topic?(user, profile) | |
76 | + end | |
69 | 77 | end | ... | ... |
app/models/link_list_block.rb
... | ... | @@ -63,7 +63,7 @@ class LinkListBlock < Block |
63 | 63 | def link_html(link) |
64 | 64 | klass = 'icon-' + link[:icon] if link[:icon] |
65 | 65 | sanitize_link( |
66 | - link_to(link[:name], expand_address(link[:address]), :target => link[:target], :class => klass) | |
66 | + link_to(link[:name], expand_address(link[:address]), :target => link[:target], :class => klass, :title => link[:title]) | |
67 | 67 | ) |
68 | 68 | end |
69 | 69 | ... | ... |
app/models/person.rb
... | ... | @@ -43,7 +43,12 @@ class Person < Profile |
43 | 43 | alias_method_chain :has_permission?, :plugins |
44 | 44 | |
45 | 45 | def memberships |
46 | - Profile.memberships_of(self) | |
46 | + scopes = [] | |
47 | + plugins_scopes = plugins.dispatch_scopes(:person_memberships, self) | |
48 | + scopes = plugins_scopes unless plugins_scopes.first.blank? | |
49 | + scopes << Profile.memberships_of(self) | |
50 | + return scopes.first if scopes.size == 1 | |
51 | + ScopeTool.union *scopes | |
47 | 52 | end |
48 | 53 | |
49 | 54 | def memberships_by_role(role) |
... | ... | @@ -129,32 +134,34 @@ class Person < Profile |
129 | 134 | end |
130 | 135 | |
131 | 136 | FIELDS = %w[ |
137 | + description | |
138 | + image | |
132 | 139 | preferred_domain |
133 | 140 | nickname |
134 | 141 | sex |
135 | - address | |
136 | - zip_code | |
137 | - city | |
138 | - state | |
139 | - country | |
140 | - nationality | |
141 | 142 | birth_date |
143 | + nationality | |
144 | + country | |
145 | + state | |
146 | + city | |
147 | + district | |
148 | + zip_code | |
149 | + address | |
150 | + address_reference | |
142 | 151 | cell_phone |
143 | 152 | comercial_phone |
153 | + personal_website | |
154 | + jabber_id | |
144 | 155 | schooling |
156 | + formation | |
157 | + custom_formation | |
158 | + area_of_study | |
159 | + custom_area_of_study | |
145 | 160 | professional_activity |
146 | 161 | organization |
147 | 162 | organization_website |
148 | - area_of_study | |
149 | - custom_area_of_study | |
150 | - formation | |
151 | - custom_formation | |
152 | 163 | contact_phone |
153 | 164 | contact_information |
154 | - description | |
155 | - image | |
156 | - district | |
157 | - address_reference | |
158 | 165 | ] |
159 | 166 | |
160 | 167 | validates_multiparameter_assignments |
... | ... | @@ -483,6 +490,17 @@ class Person < Profile |
483 | 490 | gravatar_profile_image_url(self.email, :size=>20, :d => gravatar_default) |
484 | 491 | end |
485 | 492 | |
493 | + settings_items :last_notification, :type => DateTime | |
494 | + settings_items :notification_time, :type => :integer, :default => 0 | |
495 | + | |
496 | + def notifier | |
497 | + @notifier ||= PersonNotifier.new(self) | |
498 | + end | |
499 | + | |
500 | + after_update do |person| | |
501 | + person.notifier.reschedule_next_notification_mail | |
502 | + end | |
503 | + | |
486 | 504 | protected |
487 | 505 | |
488 | 506 | def followed_by?(profile) | ... | ... |
... | ... | @@ -0,0 +1,89 @@ |
1 | +class PersonNotifier | |
2 | + | |
3 | + def initialize(person) | |
4 | + @person = person | |
5 | + end | |
6 | + | |
7 | + def self.schedule_all_next_notification_mail | |
8 | + Delayed::Job.enqueue(NotifyAllJob.new) unless NotifyAllJob.exists? | |
9 | + end | |
10 | + | |
11 | + def schedule_next_notification_mail | |
12 | + dispatch_notification_mail if !NotifyJob.exists?(@person.id) | |
13 | + end | |
14 | + | |
15 | + def dispatch_notification_mail | |
16 | + Delayed::Job.enqueue(NotifyJob.new(@person.id), nil, @person.notification_time.hours.from_now) if @person.notification_time>0 | |
17 | + end | |
18 | + | |
19 | + def reschedule_next_notification_mail | |
20 | + return nil unless @person.setting_changed?(:notification_time) || @person.setting_changed?(:last_notification) | |
21 | + NotifyJob.find(@person.id).delete_all | |
22 | + schedule_next_notification_mail | |
23 | + end | |
24 | + | |
25 | + def notify | |
26 | + if @person.notification_time && @person.notification_time > 0 | |
27 | + from = @person.last_notification || DateTime.now - @person.notification_time.hours | |
28 | + notifications = @person.tracked_notifications.find(:all, :conditions => ["created_at > ?", from]) | |
29 | + Noosfero.with_locale @person.environment.default_language do | |
30 | + Mailer::deliver_content_summary(@person, notifications) unless notifications.empty? | |
31 | + end | |
32 | + @person.settings[:last_notification] = DateTime.now | |
33 | + @person.save! | |
34 | + end | |
35 | + end | |
36 | + | |
37 | + class NotifyAllJob | |
38 | + def self.exists? | |
39 | + Delayed::Job.where(:handler => "--- !ruby/object:PersonNotifier::NotifyAllJob {}\n\n").count > 0 | |
40 | + end | |
41 | + | |
42 | + def perform | |
43 | + Person.find_each {|person| person.notifier.schedule_next_notification_mail } | |
44 | + end | |
45 | + end | |
46 | + | |
47 | + class NotifyJob < Struct.new(:person_id) | |
48 | + | |
49 | + def self.exists?(person_id) | |
50 | + !find(person_id).empty? | |
51 | + end | |
52 | + | |
53 | + def self.find(person_id) | |
54 | + Delayed::Job.where(:handler => "--- !ruby/struct:PersonNotifier::NotifyJob \nperson_id: #{person_id}\n") | |
55 | + end | |
56 | + | |
57 | + def perform | |
58 | + Person.find(person_id).notifier.notify | |
59 | + end | |
60 | + | |
61 | + def on_permanent_failure | |
62 | + person = Person.find(person_id) | |
63 | + person.notifier.dispatch_notification_mail | |
64 | + end | |
65 | + | |
66 | + end | |
67 | + | |
68 | + class Mailer < ActionMailer::Base | |
69 | + | |
70 | + add_template_helper(PersonNotifierHelper) | |
71 | + | |
72 | + def session | |
73 | + {:theme => nil} | |
74 | + end | |
75 | + | |
76 | + def content_summary(person, notifications) | |
77 | + @current_theme = 'default' | |
78 | + @profile = person | |
79 | + recipients person.email | |
80 | + from "#{@profile.environment.name} <#{@profile.environment.contact_email}>" | |
81 | + subject _("[%s] Network Activity") % [@profile.environment.name] | |
82 | + body :recipient => @profile.nickname || @profile.name, | |
83 | + :environment => @profile.environment.name, | |
84 | + :url => @profile.environment.top_url, | |
85 | + :notifications => notifications | |
86 | + content_type "text/html" | |
87 | + end | |
88 | + end | |
89 | +end | ... | ... |
app/models/product.rb
... | ... | @@ -15,7 +15,11 @@ class Product < ActiveRecord::Base |
15 | 15 | 'full' |
16 | 16 | end |
17 | 17 | |
18 | - belongs_to :enterprise | |
18 | + belongs_to :enterprise, :foreign_key => :profile_id, :class_name => 'Profile' | |
19 | + belongs_to :profile | |
20 | + alias_method :enterprise=, :profile= | |
21 | + alias_method :enterprise, :profile | |
22 | + | |
19 | 23 | has_one :region, :through => :enterprise |
20 | 24 | validates_presence_of :enterprise |
21 | 25 | |
... | ... | @@ -29,7 +33,10 @@ class Product < ActiveRecord::Base |
29 | 33 | has_many :qualifiers, :through => :product_qualifiers |
30 | 34 | has_many :certifiers, :through => :product_qualifiers |
31 | 35 | |
32 | - validates_uniqueness_of :name, :scope => :enterprise_id, :allow_nil => true | |
36 | + acts_as_having_settings :field => :data | |
37 | + | |
38 | + validates_uniqueness_of :name, :scope => :profile_id, :allow_nil => true, :if => :validate_uniqueness_of_column_name? | |
39 | + | |
33 | 40 | validates_presence_of :product_category_id |
34 | 41 | validates_associated :product_category |
35 | 42 | |
... | ... | @@ -81,10 +88,6 @@ class Product < ActiveRecord::Base |
81 | 88 | image ? image.public_filename(size) : '/images/icons-app/product-default-pic-%s.png' % size |
82 | 89 | end |
83 | 90 | |
84 | - def category_full_name | |
85 | - product_category ? product_category.full_name.split('/') : nil | |
86 | - end | |
87 | - | |
88 | 91 | acts_as_having_image |
89 | 92 | |
90 | 93 | def save_image |
... | ... | @@ -234,4 +237,10 @@ class Product < ActiveRecord::Base |
234 | 237 | |
235 | 238 | delegate :enabled, :region, :region_id, :environment, :environment_id, :to => :enterprise |
236 | 239 | |
240 | + protected | |
241 | + | |
242 | + def validate_uniqueness_of_column_name? | |
243 | + true | |
244 | + end | |
245 | + | |
237 | 246 | end | ... | ... |
... | ... | @@ -0,0 +1,50 @@ |
1 | +class ProductCategoriesBlock < Block | |
2 | + | |
3 | + def self.description | |
4 | + _('Product category menu') | |
5 | + end | |
6 | + | |
7 | + # the title of the block. Probably will be overriden in subclasses. | |
8 | + def default_title | |
9 | + _('Catalog') | |
10 | + end | |
11 | + | |
12 | + def help | |
13 | + _('Helps to filter the products catalog.') | |
14 | + end | |
15 | + | |
16 | + def content(args={}) | |
17 | + profile = owner | |
18 | + lambda do | |
19 | + if @categories.nil? or @categories.length == 0 | |
20 | + categories = ProductCategory.on_level().order(:name) | |
21 | + if @categories and @categories.length == 0 | |
22 | + notice = _('There are no sub-categories for %s') % @category.name | |
23 | + end | |
24 | + else | |
25 | + categories = @categories | |
26 | + end | |
27 | + render :file => 'blocks/product_categories', | |
28 | + :locals => { | |
29 | + :profile => profile, | |
30 | + :categories => categories, | |
31 | + :notice => notice | |
32 | + } | |
33 | + end | |
34 | + end | |
35 | + | |
36 | + DISPLAY_OPTIONS['catalog_only'] = __('Only on the catalog') | |
37 | + | |
38 | + def display | |
39 | + settings[:display].nil? ? 'catalog_only' : super | |
40 | + end | |
41 | + | |
42 | + def display_catalog_only(context) | |
43 | + context[:params][:controller] == 'catalog' | |
44 | + end | |
45 | + | |
46 | + def visible?(*args) | |
47 | + box.environment.enabled?('products_for_enterprises') ? super(*args) : false | |
48 | + end | |
49 | + | |
50 | +end | ... | ... |
app/models/product_category.rb
... | ... | @@ -3,6 +3,15 @@ class ProductCategory < Category |
3 | 3 | has_many :products |
4 | 4 | has_many :inputs |
5 | 5 | |
6 | + named_scope :unique, :select => 'DISTINCT ON (path) categories.*' | |
7 | + named_scope :by_enterprise, lambda { |enterprise| { | |
8 | + :joins => :products, | |
9 | + :conditions => ['products.profile_id = ?', enterprise.id] | |
10 | + }} | |
11 | + named_scope :unique_by_level, lambda { |level| { | |
12 | + :select => "DISTINCT ON (filtered_category) split_part(path, '/', #{level}) AS filtered_category, categories.*" | |
13 | + }} | |
14 | + | |
6 | 15 | def all_products |
7 | 16 | Product.find(:all, :conditions => { :product_category_id => (all_children << self).map(&:id) }) |
8 | 17 | end | ... | ... |
app/models/profile.rb
... | ... | @@ -84,7 +84,12 @@ class Profile < ActiveRecord::Base |
84 | 84 | def members |
85 | 85 | scopes = plugins.dispatch_scopes(:organization_members, self) |
86 | 86 | scopes << Person.members_of(self) |
87 | - scopes.size == 1 ? scopes.first : Person.or_scope(scopes) | |
87 | + return scopes.first if scopes.size == 1 | |
88 | + ScopeTool.union *scopes | |
89 | + end | |
90 | + | |
91 | + def members_by_name | |
92 | + members.order(:name) | |
88 | 93 | end |
89 | 94 | |
90 | 95 | class << self | ... | ... |
app/models/text_article.rb
app/models/user.rb
... | ... | @@ -71,7 +71,8 @@ class User < ActiveRecord::Base |
71 | 71 | body :recipient => user.name, |
72 | 72 | :activation_code => user.activation_code, |
73 | 73 | :environment => user.environment.name, |
74 | - :url => user.environment.top_url | |
74 | + :url => user.environment.top_url, | |
75 | + :redirection => (true if user.return_to) | |
75 | 76 | end |
76 | 77 | |
77 | 78 | def signup_welcome_email(user) | ... | ... |
app/sweepers/profile_sweeper.rb
... | ... | @@ -8,6 +8,8 @@ class ProfileSweeper # < ActiveRecord::Observer |
8 | 8 | end |
9 | 9 | |
10 | 10 | def after_create(profile) |
11 | + # TODO EnvironmentStatisticsBlock is DEPRECATED and will be removed from | |
12 | + # the Noosfero core soon, see ActionItem3045 | |
11 | 13 | expire_statistics_block_cache(profile) |
12 | 14 | end |
13 | 15 | |
... | ... | @@ -29,6 +31,8 @@ protected |
29 | 31 | expire_blogs(profile) if profile.organization? |
30 | 32 | end |
31 | 33 | |
34 | + # TODO EnvironmentStatisticsBlock is DEPRECATED and will be removed from | |
35 | + # the Noosfero core soon, see ActionItem3045 | |
32 | 36 | def expire_statistics_block_cache(profile) |
33 | 37 | blocks = profile.environment.blocks.select { |b| b.kind_of?(EnvironmentStatisticsBlock) } |
34 | 38 | BlockSweeper.expire_blocks(blocks) | ... | ... |
app/views/admin_panel/index.rhtml
... | ... | @@ -6,6 +6,7 @@ |
6 | 6 | <tr><td><%= link_to _('Environment settings'), :action => 'site_info' %></td></tr> |
7 | 7 | <tr><td><%= link_to _('Features'), :controller => 'features' %></td></tr> |
8 | 8 | <tr><td><%= link_to _('Plugins'), :controller => 'plugins' %></td></tr> |
9 | + <tr><td><%= link_to _('Appearance'), :controller =>'environment_themes' %></td></tr> | |
9 | 10 | <tr><td><%= link_to _('Sideboxes'), :controller => 'environment_design'%></td></tr> |
10 | 11 | <tr><td><%= link_to _('Homepage'), :action => 'set_portal_community' %></td></tr> |
11 | 12 | <tr><td><%= link_to _('Licenses'), :controller =>'licenses' %></td></tr> | ... | ... |
... | ... | @@ -0,0 +1,9 @@ |
1 | +<%= link_to _('Catalog start'), profile.catalog_url, :class=>'catalog-home-link' %> | |
2 | +<ul class="catalog-categories-list"> | |
3 | + <% categories.each do |category| %> | |
4 | + <%= category_with_sub_list(category) %> | |
5 | + <% end %> | |
6 | +</ul> | |
7 | +<% if notice %> | |
8 | + <div class="catalog-categories-notice"><%= notice %></div> | |
9 | +<% end %> | ... | ... |
app/views/blocks/profile_image.rhtml
... | ... | @@ -16,11 +16,13 @@ |
16 | 16 | <p><%= h block.owner.short_name %></p> |
17 | 17 | <% end %> |
18 | 18 | |
19 | -<div style="text-align: center; font-size: 75%; clear: both" id="profile-admin-url-<%= block.id %>"></div> | |
20 | - | |
21 | -<div class="profile-info-options" id="profile-info-options-<%= block.id %>"></div> | |
19 | +<% if !user.nil? and user.has_permission?('edit_profile', profile) %> | |
20 | + <div class='admin-link'> | |
21 | + <%= link_to _('Control panel'), block.owner.admin_url %> | |
22 | + </div> | |
23 | +<% end %> | |
22 | 24 | |
25 | +<div class="profile-info-options"> | |
26 | + <%= render :file => view_for_profile_actions(block.owner.class) %> | |
27 | +</div> | |
23 | 28 | </div><!-- end class="vcard" --> |
24 | -<script type="text/javascript"> | |
25 | - <%= remote_function :url => { :controller => 'profile', :profile => profile.identifier, :action => 'profile_info', :block_id => block.id } %> | |
26 | -</script> | ... | ... |
app/views/blocks/profile_info.rhtml
... | ... | @@ -14,13 +14,15 @@ |
14 | 14 | </div> |
15 | 15 | </div> |
16 | 16 | |
17 | -<ul class="profile-info-data" id="profile-info-data-<%= block.id %>"> | |
17 | +<ul class="profile-info-data"> | |
18 | 18 | <li><%= link_to __('Homepage'), block.owner.url, :class => 'url' %></li> |
19 | 19 | <li><%= link_to _('View profile'), block.owner.public_profile_url %></li> |
20 | 20 | <% if block.owner.enterprise? && block.owner.environment.enabled?('products_for_enterprises') %> |
21 | 21 | <li><%= link_to(_('Products/Services'), :controller => 'catalog', :profile => block.owner.identifier) %></li> |
22 | 22 | <% end %> |
23 | - <li id="profile-admin-url-<%= block.id %>"></li> | |
23 | + <% if !user.nil? and user.has_permission?('edit_profile', profile) %> | |
24 | + <li><%= link_to _('Control panel'), block.owner.admin_url %></li> | |
25 | + <% end %> | |
24 | 26 | <% if profile.person? %> |
25 | 27 | <li><%= _('Since %{year}/%{month}') % { :year => block.owner.created_at.year, :month => block.owner.created_at.month } %></li> |
26 | 28 | <% end %> |
... | ... | @@ -37,9 +39,8 @@ |
37 | 39 | </div> |
38 | 40 | <% end %> |
39 | 41 | |
40 | -<div class="profile-info-options" id="profile-info-options-<%= block.id %>"></div> | |
42 | +<div class="profile-info-options"> | |
43 | + <%= render :file => view_for_profile_actions(block.owner.class) %> | |
44 | +</div> | |
41 | 45 | |
42 | 46 | </div><!-- end class="vcard" --> |
43 | -<script type="text/javascript"> | |
44 | - <%= remote_function :url => { :controller => 'profile', :profile => profile.identifier, :action => 'profile_info', :block_id => block.id } %> | |
45 | -</script> | ... | ... |
app/views/box_organizer/_link_list_block.rhtml
1 | 1 | <strong><%= _('Links') %></strong> |
2 | 2 | <div id='edit-link-list-block'> |
3 | 3 | <table id='links' class='noborder'> |
4 | - <tr><th><%= _('Icon') %></th><th><%= _('Name') %></th><th><%= _('Address') %></th><th><%= _('Target') %></th></tr> | |
4 | + <tr> | |
5 | + <th><%= _('Icon') %></th> | |
6 | + <th><%= _('Name') %></th> | |
7 | + <th><%= _('Address') %></th> | |
8 | + <th><%= _('Title') %></th> | |
9 | + <th><%= _('Target') %></th> | |
10 | + </tr> | |
5 | 11 | <% for link in @block.links do %> |
6 | - <tr> | |
7 | - <td> | |
8 | - <%= icon_selector(link['icon']) %> | |
9 | - </td> | |
10 | - <td><%= text_field_tag 'block[links][][name]', link[:name], :class => 'link-name', :maxlength => 20 %></td> | |
11 | - <td class='cel-address'><%= text_field_tag 'block[links][][address]', link[:address], :class => 'link-address' %></td> | |
12 | - <td> | |
13 | - <%= select_tag('block[links][][target]', options_for_select(LinkListBlock::TARGET_OPTIONS, link[:target])) %> | |
14 | - </td> | |
15 | - </tr> | |
12 | + <tr> | |
13 | + <td><%= icon_selector(link['icon']) %></td> | |
14 | + <td><%= text_field_tag 'block[links][][name]', link[:name], :class => 'link-name', :maxlength => 20 %></td> | |
15 | + <td class='cel-address'><%= text_field_tag 'block[links][][address]', link[:address], :class => 'link-address' %></td> | |
16 | + <td><%= text_field_tag 'block[links][][title]', link[:title], :class => 'link-title' %></td> | |
17 | + <td><%= select_tag('block[links][][target]', options_for_select(LinkListBlock::TARGET_OPTIONS, link[:target])) %></td> | |
18 | + </tr> | |
16 | 19 | <% end %> |
17 | 20 | </table> |
18 | 21 | </div> |
... | ... | @@ -22,8 +25,8 @@ |
22 | 25 | content_tag('td', icon_selector('ok')) + |
23 | 26 | content_tag('td', text_field_tag('block[links][][name]', '', :maxlength => 20)) + |
24 | 27 | content_tag('td', text_field_tag('block[links][][address]', nil, :class => 'link-address'), :class => 'cel-address') + |
25 | - content_tag('td', select_tag('block[links][][target]', | |
26 | -options_for_select(LinkListBlock::TARGET_OPTIONS, '_self'))) | |
28 | + content_tag('td', text_field_tag('block[links][][title]', '', :class => 'link-title')) + | |
29 | + content_tag('td', select_tag('block[links][][target]', options_for_select(LinkListBlock::TARGET_OPTIONS, '_self'))) | |
27 | 30 | ) + |
28 | 31 | javascript_tag("$('edit-link-list-block').scrollTop = $('edit-link-list-block').scrollHeight") |
29 | 32 | end %> | ... | ... |
app/views/catalog/index.rhtml
1 | 1 | <% extra_content = [] %> |
2 | 2 | <% extra_content_list = [] %> |
3 | 3 | |
4 | -<h1><%= _('Products/Services') %></h1> | |
5 | - | |
6 | -<% if @categories %> | |
7 | - <%= breadcrumb(@category) if params[:level] %> | |
8 | - | |
9 | - <div class='l-sidebar-left-bar'> | |
10 | - <ul> | |
11 | - <%= content_tag('li', link_to(_('Homepage'), profile.url), :class => 'catalog-categories-link') %> | |
12 | - <%= content_tag('li', link_to(_('Catalog start'), profile.catalog_url), :class => 'catalog-categories-link') %> | |
13 | - <% if @categories.present? %> | |
14 | - <% @categories.each do |category| %> | |
15 | - <%= category_link(category) %> | |
16 | - <%= category_sub_links(category) %> | |
17 | - <% end %> | |
18 | - <% elsif @category.present? %> | |
19 | - <%= content_tag('li', _('There are no sub-categories for %s') % @category.name, :id => 'catalog-categories-notice') %> | |
20 | - <% else %> | |
21 | - <%= content_tag('li', _('There are no categories available.'), :id => 'catalog-categories-notice') %> | |
22 | - <% end %> | |
23 | - </ul> | |
4 | +<div id="product-catalog"> | |
5 | +<% if !user.nil? && ( user.is_admin?(profile.environment) || user.is_admin?(profile) ) %> | |
6 | + <div class="product-catalog-ctrl"> | |
7 | + <%= button :product, _('Manage Products/Services'), :controller => 'manage_products' %> | |
24 | 8 | </div> |
25 | 9 | <% end %> |
26 | 10 | |
27 | -<ul id="product-list" class="<%="l-sidebar-left-content" if @categories %>"> | |
11 | +<h1><%= _('Products/Services') %></h1> | |
12 | + | |
13 | +<%= breadcrumb(@category) if params[:level] %> | |
14 | + | |
15 | +<ul id="product-list"> | |
28 | 16 | <% @products.each do |product| %> |
29 | 17 | <% extra_content = @plugins.dispatch(:catalog_item_extras, product).collect { |content| instance_eval(&content) } %> |
30 | 18 | <% extra_content_list = @plugins.dispatch(:catalog_list_item_extras, product).collect { |content| instance_eval(&content) } %> |
... | ... | @@ -132,10 +120,11 @@ |
132 | 120 | </ul> |
133 | 121 | </li> |
134 | 122 | <% end %> |
135 | -</ul> | |
123 | +</ul><!-- end id="product-list" --> | |
136 | 124 | |
137 | 125 | <%= pagination_links @products, :params => {:controller => :catalog, :action => :index, :profile => profile.identifier} %> |
138 | 126 | |
139 | 127 | <%= add_zoom_to_images %> |
140 | 128 | |
141 | 129 | <br style="clear:both"/> |
130 | +</div><!-- end id="product-catalog" --> | ... | ... |
app/views/cms/edit.rhtml
... | ... | @@ -40,6 +40,7 @@ |
40 | 40 | |
41 | 41 | <% button_bar do %> |
42 | 42 | <%= submit_button :save, _('Save') %> |
43 | + | |
43 | 44 | <% if @back_to %> |
44 | 45 | <%= button :cancel, _('Cancel'), @back_to %> |
45 | 46 | <% elsif @parent_id || @article.parent %> |
... | ... | @@ -47,6 +48,11 @@ |
47 | 48 | <% else %> |
48 | 49 | <%= button :cancel, _('Cancel'), :action => 'index' %> |
49 | 50 | <% end %> |
51 | + | |
52 | + <% unless @article.new_record? %> | |
53 | + <%= button :delete, _('Delete'), {:controller => :cms, :action => :destroy, :id => @article}, | |
54 | + :method => :post, :confirm => delete_article_message(@article) %> | |
55 | + <% end %> | |
50 | 56 | <% end %> |
51 | 57 | <% end %> |
52 | 58 | </div> | ... | ... |
app/views/comment/_comment.rhtml
... | ... | @@ -32,19 +32,7 @@ |
32 | 32 | |
33 | 33 | <div class="comment-details"> |
34 | 34 | <div class="comment-header"> |
35 | - <ul> | |
36 | - <div class="comment-actions"> | |
37 | - <%= comment_actions(comment) %> | |
38 | - </div> | |
39 | - </ul> | |
40 | - <% unless comment.spam? %> | |
41 | - <%= link_to_function '', | |
42 | - "var f = add_comment_reply_form(this, %s); f.find('comment_title, textarea').val(''); return false" % comment.id, | |
43 | - :class => 'comment-footer comment-footer-link comment-footer-hide comment-actions-reply button', | |
44 | - :id => 'comment-reply-to-' + comment.id.to_s, | |
45 | - :title => _('Reply') | |
46 | - %> | |
47 | - <% end %> | |
35 | + <%= comment_actions(comment) %> | |
48 | 36 | </div> |
49 | 37 | |
50 | 38 | <div class="comment-created-at"> |
... | ... | @@ -55,6 +43,7 @@ |
55 | 43 | <p/> |
56 | 44 | <%= txt2html comment.body %> |
57 | 45 | </div> |
46 | + <%= @plugins.dispatch(:comment_extra_contents, local_assigns).collect { |content| instance_eval(&content) }.join("") %> | |
58 | 47 | </div> |
59 | 48 | |
60 | 49 | <div class="comment_reply post_comment_box closed" id="comment_reply_to_<%= comment.id %>"> | ... | ... |
... | ... | @@ -0,0 +1,22 @@ |
1 | +<ul> | |
2 | + <% if !links_submenu.empty? %> | |
3 | + <div class="comment-actions"> | |
4 | + <li class="vcard"> | |
5 | + <%= link_to(content_tag(:span, _('Contents menu')), '#', :onclick => "toggleSubmenu(this,'',#{links_submenu.to_json}); return false", :class => 'menu-submenu-trigger comment-trigger', :url => url) %> | |
6 | + </li> | |
7 | + </div> | |
8 | + <% end %> | |
9 | +</ul> | |
10 | +<div class="comments-action-bar"> | |
11 | + <% unless comment.spam? %> | |
12 | + <%= link_to_function '', | |
13 | + "var f = add_comment_reply_form(this, %s); f.find('comment_title, textarea').val(''); return false" % comment.id, | |
14 | + :class => 'comment-footer comment-footer-link comment-footer-hide comment-actions-reply button', | |
15 | + :id => 'comment-reply-to-' + comment.id.to_s, | |
16 | + :title => _('Reply') | |
17 | + %> | |
18 | + <% end %> | |
19 | + <% links_action_bar.collect do |link| %> | |
20 | + <%= link[:link] %> | |
21 | + <% end %> | |
22 | +</div> | ... | ... |
... | ... | @@ -0,0 +1,8 @@ |
1 | +<div id="addThis"> | |
2 | + <script type="text/javascript"> | |
3 | + addthis_pub = '<%= escape_javascript( NOOSFERO_CONF['addthis_pub'] ) %>'; | |
4 | + addthis_logo = '<%= escape_javascript( NOOSFERO_CONF['addthis_logo'] ) %>'; | |
5 | + addthis_options = '<%= escape_javascript( NOOSFERO_CONF['addthis_options'] ) %>'; | |
6 | + </script> | |
7 | + <a href="http://www.addthis.com/bookmark.php" id="bt_addThis" target="_blank" onmouseover="return addthis_open(this, '', '[URL]')" onmouseout="addthis_close()" onclick="return addthis_sendto()"><%= addthis_image_tag %></a> | |
8 | +</div> | ... | ... |
app/views/content_viewer/_article_toolbar.rhtml
... | ... | @@ -26,7 +26,7 @@ |
26 | 26 | <%= expirable_button @page, :spread, content, url if url %> |
27 | 27 | <% end %> |
28 | 28 | |
29 | - <% if !@page.gallery? && @page.allow_create?(user) %> | |
29 | + <% if !@page.gallery? && (@page.allow_create?(user) || (@page.parent && @page.parent.allow_create?(user))) %> | |
30 | 30 | <% if @page.translatable? && !@page.native_translation.language.blank? && !remove_content_button(:locale) %> |
31 | 31 | <% content = _('Add translation') %> |
32 | 32 | <% parent_id = (@page.folder? ? @page : (@page.parent.nil? ? nil : @page.parent)) %> |
... | ... | @@ -48,6 +48,10 @@ |
48 | 48 | <%= expirable_button @page, :suggest, content, url, options %> |
49 | 49 | <% end %> |
50 | 50 | |
51 | + <% if @page.display_versions? %> | |
52 | + <%= button(:clock, _('All versions'), {:controller => 'content_viewer', :profile => profile.identifier, :action => 'article_versions'}, :id => 'article-versions-link') %> | |
53 | + <% end %> | |
54 | + | |
51 | 55 | <%= report_abuse(profile, :link, @page) %> |
52 | 56 | |
53 | 57 | </div> |
... | ... | @@ -56,6 +60,7 @@ |
56 | 60 | <div class="blog-cover"><%= image_tag(@page.image.public_filename())%></div> |
57 | 61 | <% end %> |
58 | 62 | <%= link_to(image_tag('icons-mime/rss-feed.png'), @page.feed.url, :class => 'blog-feed-link') if @page.has_posts? && @page.feed %> |
63 | + <%= @plugins.dispatch(:article_header_extra_contents, @page).collect { |content| instance_eval(&content) }.join("") %> | |
59 | 64 | <%= article_title(@page, :no_link => true) %> |
60 | 65 | <%= article_translations(@page) %> |
61 | 66 | </div> | ... | ... |
... | ... | @@ -0,0 +1,58 @@ |
1 | +<div class="article-versions"> | |
2 | + <%= button(:back, _('Go back to latest version'), {:action => 'view_page'}) %> | |
3 | +</div> | |
4 | + | |
5 | +<%= article_title(@page, :no_link => true) %> | |
6 | + | |
7 | +<p><%= _('This is the list of all versions of this content. Select a version to see it and then revert to it.') %>.</p> | |
8 | + | |
9 | +<% form_tag({:controller => 'content_viewer', :action => 'versions_diff', :profile => profile.identifier, :page => @page.path.split('/')}, :method => 'get') do %> | |
10 | + <ul id="article-versions"> | |
11 | + <% @versions.each do |v| %> | |
12 | + <li> | |
13 | + <%= radio_button_tag 'v1', v.version, false, :onclick => 'versionInputClicked(this)' %> | |
14 | + <%= radio_button_tag 'v2', v.version, false, :onclick => 'versionInputClicked(this)' %> | |
15 | + <%= link_to(_("Version #{v.version}"), @page.url.merge(:version => v.version)) %> | |
16 | + <%= @page.version == v.version ? _('(current)') : '' %> | |
17 | + <span class='updated-by'><%= _('by %{author}') % {:author => link_to(@page.author_name(v.version), @page.author_url(v.version))} %></span> | |
18 | + <span class='updated-on'><%= show_time(v.updated_at) %></span> | |
19 | + </li> | |
20 | + <% end %> | |
21 | + </ul> | |
22 | + | |
23 | +<script> | |
24 | + function versionInputClicked(input) { | |
25 | + var selectedColumn = input.name; | |
26 | + var sisterColumn = (selectedColumn == 'v1') ? 'v2' : 'v1'; | |
27 | + var li = input.parentNode; | |
28 | + var checkedBrotherLi = jQuery('#article-versions input[name=' + sisterColumn + ']:checked').parent()[0]; | |
29 | + updateColumn(selectedColumn, li); | |
30 | + updateColumn(sisterColumn, checkedBrotherLi); | |
31 | + } | |
32 | + | |
33 | + function updateColumn(selectedColumn, startLi){ | |
34 | + var sisterColumn = (selectedColumn == 'v1') ? 'v2' : 'v1'; | |
35 | + var walkMethod = (selectedColumn == 'v1') ? 'prev' : 'next'; | |
36 | + var li = startLi; | |
37 | + var foundCheckedBrother = false; | |
38 | + while(li = jQuery(li)[walkMethod]()[0]) { | |
39 | + li.className = ''; | |
40 | + if (!foundCheckedBrother){ | |
41 | + li.className = 'selected'; | |
42 | + foundCheckedBrother = jQuery('input[name=' + sisterColumn + ']', li)[0].checked; | |
43 | + } | |
44 | + jQuery('input[name=' + selectedColumn + ']', li)[0].disabled = foundCheckedBrother; | |
45 | + } | |
46 | + } | |
47 | + | |
48 | + var penultVersion = jQuery('#article-versions input[name=v1]')[1]; | |
49 | + var lastVersion = jQuery('#article-versions input[name=v2]')[0]; | |
50 | + jQuery('#article-versions input').attr('disabled', false); | |
51 | + if (penultVersion && lastVersion) { | |
52 | + penultVersion.checked = lastVersion.checked = true; | |
53 | + lastVersion.onclick(); | |
54 | + } | |
55 | +</script> | |
56 | + <%= submit_button(:clock, _('Show differences between selected versions')) %> | |
57 | +<% end %> | |
58 | +<%= pagination_links @versions, :param_name => 'npage' %> | ... | ... |
... | ... | @@ -0,0 +1,53 @@ |
1 | +<div class="article-versions"> | |
2 | + <%= button(:back, _('Back to the versions'), {:action => 'article_versions'}) %> | |
3 | +</div> | |
4 | + | |
5 | +<div id="article" class="<%= @page.css_class_name %>"> | |
6 | + | |
7 | + <div id="article-actions"> | |
8 | + <%= button(:clock, _('All versions'), {:controller => 'content_viewer', :profile => profile.identifier, :action => 'article_versions'}, :id => 'article-versions-link') %> | |
9 | + | |
10 | + <% if @page.allow_edit?(user) && !remove_content_button(:undo) %> | |
11 | + <% content = content_tag('span', _('Revert to this version')) %> | |
12 | + <% url = profile.admin_url.merge({ :controller => 'cms', :action => 'edit', :id => @page.id, :version => @version }) %> | |
13 | + <%= expirable_button @page, :undo, content, url, :id => 'article-revert-version-link' %> | |
14 | + <% end %> | |
15 | + | |
16 | + <%= button(:forward, _('Go to latest version'), {:action => 'view_page'}) %> | |
17 | +</div> | |
18 | + <div id="article-header"> | |
19 | + <h1 class='title'><%= @versioned_article.name %></h1> | |
20 | + <%= _("Version %{version} - %{author} on %{date}") % {:version => @version, :author => @page.author_name(@version), :date => show_time(@versioned_article.updated_at) } %> | |
21 | + </div> | |
22 | + | |
23 | + <p id="no-current-version"> | |
24 | + <%= _('This is not the latest version of this content.') %> | |
25 | + </p> | |
26 | +</div> | |
27 | + | |
28 | + <% version_license = @page.version_license(@version) %> | |
29 | + <%# This seemingly doubled verification exists because the article-sub-header | |
30 | + div must appear only if at least one content inside it will appear. | |
31 | + Although we have only one content now, we might have others in the future. | |
32 | + So we're keeping it like that to avoid mistakes. %> | |
33 | + <% if version_license.present? %> | |
34 | + <div id='article-sub-header'> | |
35 | + <% if version_license.present? %> | |
36 | + <div id="article-license"> | |
37 | + <%= _('Licensed under %s') % (version_license.url.present? ? link_to(version_license.name, version_license.url, :target => '_blank') : version_license.name) %> | |
38 | + </div> | |
39 | + <% end %> | |
40 | + </div> | |
41 | + <% end %> | |
42 | + | |
43 | + <% cache(@page.cache_key(params, user, language)) do %> | |
44 | + <div class="<%="article-body article-body-" + @page.css_class_name %>"> | |
45 | + <%= @versioned_article.body %> | |
46 | + <br style="clear:both" /> | |
47 | + </div> <!-- end class="article-body" --> | |
48 | + <% end %> | |
49 | + | |
50 | + <%= display_source_info(@page) %> | |
51 | + | |
52 | +</div><!-- end id="article" --> | |
53 | +<%= add_zoom_to_article_images %> | ... | ... |
... | ... | @@ -0,0 +1,16 @@ |
1 | +<div class="article-versions"> | |
2 | +<%= button(:back, _('Back to the versions'), {:action => 'article_versions'}) %> | |
3 | +</div> | |
4 | + | |
5 | +<h1><%= _('Changes on "%s"') % @page.title %></h1> | |
6 | + | |
7 | +<p> <%= _('Changes from %s → %s') % [show_time(@v1.updated_at), show_time(@v2.updated_at)] %> </p> | |
8 | + | |
9 | +<% diffContent = Diffy::Diff.new(@v1.body, @v2.body, :context => 1) %> | |
10 | +<% if diffContent.to_s(:text).blank? %> | |
11 | + <p id="article-versions-no-diff"> | |
12 | + <%= _('These versions range have no differences.')%> | |
13 | + </p> | |
14 | +<% else %> | |
15 | + <%= diffContent.to_s(:html) %> | |
16 | +<% end %> | ... | ... |
app/views/content_viewer/view_page.rhtml
... | ... | @@ -15,16 +15,14 @@ |
15 | 15 | </script> |
16 | 16 | |
17 | 17 | <% if @page.parent && !@page.parent.path.blank? %> |
18 | -<div id="article-parent"> | |
19 | - <%= button(:back, _('Go back to %s') % @page.parent.short_title, @page.parent.url) %> | |
20 | -</div> | |
18 | + <div id="article-parent"> | |
19 | + <%= button(:back, _('Go back to %s') % @page.parent.short_title, @page.parent.url) %> | |
20 | + </div> | |
21 | 21 | <% end %> |
22 | 22 | |
23 | -<div id="article-toolbar"></div> | |
24 | - | |
25 | -<script type="text/javascript"> | |
26 | - <%= remote_function :update => "article-toolbar", :url => @page.url.merge({ :toolbar => true, :only_path => true }) %> | |
27 | -</script> | |
23 | +<div id="article-toolbar"> | |
24 | + <%= render :partial => 'article_toolbar' %> | |
25 | +</div> | |
28 | 26 | |
29 | 27 | <% if @page.display_hits? || @page.license.present? %> |
30 | 28 | <div id='article-sub-header'> |
... | ... | @@ -42,32 +40,10 @@ |
42 | 40 | </div> |
43 | 41 | <% end %> |
44 | 42 | |
45 | -<% if !@page.tags.empty? %> | |
46 | - <div id="article-tags"> | |
47 | - <%= _("This article's tags:") %> | |
48 | - <%= @page.tags.map { |t| link_to(t, :controller => 'profile', :profile => @profile.identifier, :action => 'tags', :id => t.name ) }.join("\n") %> | |
49 | - </div> | |
50 | -<% end %> | |
51 | - | |
52 | - | |
53 | 43 | <%= render :partial => 'shared/disabled_enterprise' %> |
54 | 44 | |
55 | 45 | <% if NOOSFERO_CONF['addthis_enabled'] %> |
56 | -<div id="addThis"> | |
57 | -<script type="text/javascript"> | |
58 | - addthis_pub = '<%= escape_javascript( NOOSFERO_CONF['addthis_pub'] ) %>'; | |
59 | - addthis_logo = '<%= escape_javascript( NOOSFERO_CONF['addthis_logo'] ) %>'; | |
60 | - addthis_config = { | |
61 | - services_custom: { | |
62 | - name: 'Facebook', | |
63 | - url: '<%= addthis_facebook_url(@page) %>', | |
64 | - icon: 'http://cache.addthiscdn.com/icons/v1/thumbs/facebook.gif' | |
65 | - } | |
66 | - }; | |
67 | - addthis_options = '<%= escape_javascript( NOOSFERO_CONF['addthis_options'] ) %>'; | |
68 | -</script> | |
69 | -<a href="https://www.addthis.com/bookmark.php" id="bt_addThis" target="_blank" onmouseover="return addthis_open(this, '', '[URL]')" onmouseout="addthis_close()" onclick="return addthis_sendto()"><%= addthis_image_tag %></a> | |
70 | -</div> | |
46 | + <%= render :partial => 'addthis' %> | |
71 | 47 | <% end %> |
72 | 48 | |
73 | 49 | <% cache(@page.cache_key(params, user, language)) do %> |
... | ... | @@ -85,8 +61,17 @@ |
85 | 61 | </div> |
86 | 62 | <% end %> |
87 | 63 | |
64 | +<% if !@page.tags.empty? %> | |
65 | + <div id="article-tags"> | |
66 | + <%= _("This article's tags:") %> | |
67 | + <%= @page.tags.map { |t| link_to(t, :controller => 'profile', :profile => @profile.identifier, :action => 'tags', :id => t.name ) }.join("\n") %> | |
68 | + </div> | |
69 | +<% end %> | |
70 | + | |
88 | 71 | <%= display_source_info(@page) %> |
89 | 72 | |
73 | +<%= @plugins.dispatch(:article_extra_contents, @page).collect { |content| instance_eval(&content) }.join("") %> | |
74 | + | |
90 | 75 | <div class="comments" id="comments_list"> |
91 | 76 | |
92 | 77 | <% if @page.accept_comments? || @comments_count > 0 %> | ... | ... |
app/views/features/_manage_community_fields.rhtml
1 | -<h2><%= __('Manage community fields') %></h2> | |
2 | - | |
3 | 1 | <% labelled_form_for(:environment, @environment, :url => {:action => 'manage_community_fields'}) do |f| %> |
4 | 2 | |
5 | 3 | <table id='community_fields_conf'> |
... | ... | @@ -9,21 +7,37 @@ |
9 | 7 | <th><%= _('Required') %></th> |
10 | 8 | <th><%= _('Display on creation?') %></th> |
11 | 9 | </tr> |
10 | + | |
11 | + <tr class='manage-fields-batch-actions'> | |
12 | + <td> | |
13 | + <%= _("Check/Uncheck All")%> | |
14 | + </td> | |
15 | + <td> | |
16 | + <input type="checkbox" id="community_active" /> | |
17 | + </td> | |
18 | + <td> | |
19 | + <input type="checkbox" id="community_required" /> | |
20 | + </td> | |
21 | + <td> | |
22 | + <input type="checkbox" id="community_signup" /> | |
23 | + </td> | |
24 | + </tr> | |
25 | + | |
12 | 26 | <% @community_fields.each do |field| %> |
13 | 27 | <tr> |
14 | 28 | <td><label for="community_fields[<%= field %>][active]"><%= _(field.humanize) %></label></td> |
15 | 29 | |
16 | 30 | <td> |
17 | 31 | <%= hidden_field_tag "community_fields[#{field}][active]", false %> |
18 | - <%= check_box_tag "community_fields[#{field}][active]", true, environment.custom_community_field(field, 'active'), :onclick => "$('community_fields[#{field}][required]').disabled=$('community_fields[#{field}][signup]').disabled=!this.checked;" %> | |
32 | + <%= check_box_tag "community_fields[#{field}][active]", true, environment.custom_community_field(field, 'active'), :onclick => "active_action(this, 'community_fields[#{field}][required]', 'community_fields[#{field}][signup]')" %> | |
19 | 33 | </td> |
20 | 34 | <td> |
21 | 35 | <%= hidden_field_tag "community_fields[#{field}][required]", false %> |
22 | - <%= check_box_tag "community_fields[#{field}][required]", true, environment.custom_community_field(field, 'required'), :onclick => "if(this.checked) $('community_fields[#{field}][signup]').checked = true;" %> | |
36 | + <%= check_box_tag "community_fields[#{field}][required]", true, environment.custom_community_field(field, 'required'), :onclick => "required_action('community_fields[#{field}][active]','community_fields[#{field}][required]', 'community_fields[#{field}][signup]')" %> | |
23 | 37 | </td> |
24 | 38 | <td> |
25 | 39 | <%= hidden_field_tag "community_fields[#{field}][signup]", false %> |
26 | - <%= check_box_tag "community_fields[#{field}][signup]", true, environment.custom_community_field(field, 'signup'), :onclick => "if(!this.checked) $('community_fields[#{field}][required]').checked = false;" %> | |
40 | + <%= check_box_tag "community_fields[#{field}][signup]", true, environment.custom_community_field(field, 'signup'), :onclick => "signup_action('community_fields[#{field}][active]','community_fields[#{field}][required]', 'community_fields[#{field}][signup]')" %> | |
27 | 41 | </td> |
28 | 42 | |
29 | 43 | </tr> |
... | ... | @@ -31,18 +45,18 @@ |
31 | 45 | </table> |
32 | 46 | |
33 | 47 | <script type='text/javascript'> |
34 | - var trs = $$('#community_fields_conf tr'); | |
48 | + var trs = jQuery('#community_fields_conf tr'); | |
35 | 49 | var tr, td2; |
36 | - for ( var i=0; tr=trs[i]; i++ ) { | |
50 | + for ( var i=2; tr=trs[i]; i++ ) { | |
37 | 51 | if ( td2 = tr.getElementsByTagName('td')[1] ) { |
38 | - td2.getElementsByTagName('input')[0].onclick(); | |
52 | + td2.getElementsByTagName('input')[1].onclick(); | |
39 | 53 | } |
40 | 54 | } |
41 | 55 | </script> |
42 | 56 | |
43 | 57 | <div> |
44 | 58 | <% button_bar do %> |
45 | - <%= submit_button('save', _('Save changes')) %> | |
59 | + <%= submit_button('save', _('Save changes'), :id=>"save_community_fields") %> | |
46 | 60 | <%= button :back, _('Back to admin panel'), :controller => 'admin_panel', :action => 'index' %> |
47 | 61 | <% end %> |
48 | 62 | </div> | ... | ... |
app/views/features/_manage_enterprise_fields.rhtml
1 | -<h2><%= __('Manage enterprise fields') %></h2> | |
2 | - | |
3 | 1 | <% labelled_form_for(:environment, @environment, :url => {:action => 'manage_enterprise_fields'}) do |f| %> |
4 | 2 | |
5 | 3 | <table id='enterprise_fields_conf'> |
... | ... | @@ -9,21 +7,37 @@ |
9 | 7 | <th><%= _('Required') %></th> |
10 | 8 | <th><%= _('Display on registration?') %></th> |
11 | 9 | </tr> |
10 | + | |
11 | + <tr class='manage-fields-batch-actions'> | |
12 | + <td> | |
13 | + <%= _("Check/Uncheck All")%> | |
14 | + </td> | |
15 | + <td> | |
16 | + <input type="checkbox" id="enterprise_active" /> | |
17 | + </td> | |
18 | + <td> | |
19 | + <input type="checkbox" id="enterprise_required" /> | |
20 | + </td> | |
21 | + <td> | |
22 | + <input type="checkbox" id="enterprise_signup" /> | |
23 | + </td> | |
24 | + </tr> | |
25 | + | |
12 | 26 | <% @enterprise_fields.each do |field| %> |
13 | 27 | <tr> |
14 | 28 | |
15 | 29 | <td><label for="enterprise_fields[<%= field %>][active]"><%= _(field.humanize) %></label></td> |
16 | 30 | <td> |
17 | 31 | <%= hidden_field_tag "enterprise_fields[#{field}][active]", false %> |
18 | - <%= check_box_tag "enterprise_fields[#{field}][active]", true, environment.custom_enterprise_field(field, 'active'), :onclick => "$('enterprise_fields[#{field}][required]').disabled=$('enterprise_fields[#{field}][signup]').disabled=!this.checked;" %> | |
32 | + <%= check_box_tag "enterprise_fields[#{field}][active]", true, environment.custom_enterprise_field(field, 'active'), :onclick => "active_action(this, 'enterprise_fields[#{field}][required]', 'enterprise_fields[#{field}][signup]')" %> | |
19 | 33 | </td> |
20 | 34 | <td> |
21 | 35 | <%= hidden_field_tag "enterprise_fields[#{field}][required]", false %> |
22 | - <%= check_box_tag "enterprise_fields[#{field}][required]", true, environment.custom_enterprise_field(field, 'required'), :onclick => "if(this.checked) $('enterprise_fields[#{field}][signup]').checked = true;" %> | |
36 | + <%= check_box_tag "enterprise_fields[#{field}][required]", true, environment.custom_enterprise_field(field, 'required'), :onclick => "required_action('enterprise_fields[#{field}][active]','enterprise_fields[#{field}][required]', 'enterprise_fields[#{field}][signup]')" %> | |
23 | 37 | </td> |
24 | 38 | <td> |
25 | 39 | <%= hidden_field_tag "enterprise_fields[#{field}][signup]", false %> |
26 | - <%= check_box_tag "enterprise_fields[#{field}][signup]", true, environment.custom_enterprise_field(field, 'signup'), :onclick => "if(!this.checked) $('enterprise_fields[#{field}][required]').checked = false;" %> | |
40 | + <%= check_box_tag "enterprise_fields[#{field}][signup]", true, environment.custom_enterprise_field(field, 'signup'), :onclick => "signup_action('enterprise_fields[#{field}][active]','enterprise_fields[#{field}][required]', 'enterprise_fields[#{field}][signup]')" %> | |
27 | 41 | </td> |
28 | 42 | |
29 | 43 | </tr> |
... | ... | @@ -31,18 +45,18 @@ |
31 | 45 | </table> |
32 | 46 | |
33 | 47 | <script type='text/javascript'> |
34 | - var trs = $$('#enterprise_fields_conf tr'); | |
48 | + var trs = jQuery('#enterprise_fields_conf tr'); | |
35 | 49 | var tr, td2; |
36 | - for ( var i=0; tr=trs[i]; i++ ) { | |
50 | + for ( var i=2; tr=trs[i]; i++ ) { | |
37 | 51 | if ( td2 = tr.getElementsByTagName('td')[1] ) { |
38 | - td2.getElementsByTagName('input')[0].onclick(); | |
52 | + td2.getElementsByTagName('input')[1].onclick(); | |
39 | 53 | } |
40 | 54 | } |
41 | 55 | </script> |
42 | 56 | |
43 | 57 | <div> |
44 | 58 | <% button_bar do %> |
45 | - <%= submit_button('save', _('Save changes')) %> | |
59 | + <%= submit_button('save', _('Save changes'), :id=>"save_enterprise_fields") %> | |
46 | 60 | <%= button :back, _('Back to admin panel'), :controller => 'admin_panel', :action => 'index' %> |
47 | 61 | <% end %> |
48 | 62 | </div> | ... | ... |
app/views/features/_manage_person_fields.rhtml
1 | -<h2><%= _('Manage person fields') %></h2> | |
2 | - | |
3 | 1 | <% labelled_form_for(:environment, @environment, :url => {:action => 'manage_person_fields'}) do |f| %> |
4 | 2 | |
5 | 3 | <table id='person_fields_conf'> |
... | ... | @@ -9,31 +7,48 @@ |
9 | 7 | <th><%= _('Required') %></th> |
10 | 8 | <th><%= _('Display on signup?') %></th> |
11 | 9 | </tr> |
10 | + | |
11 | + <tr class='manage-fields-batch-actions'> | |
12 | + <td> | |
13 | + <%= _("Check/Uncheck All")%> | |
14 | + </td> | |
15 | + <td> | |
16 | + <input type="checkbox" id="person_active" /> | |
17 | + </td> | |
18 | + <td> | |
19 | + <input type="checkbox" id="person_required" /> | |
20 | + </td> | |
21 | + <td> | |
22 | + <input type="checkbox" id="person_signup" /> | |
23 | + </td> | |
24 | + </tr> | |
25 | + | |
12 | 26 | <% @person_fields.each do |field| %> |
13 | 27 | <tr> |
14 | 28 | <td><label for="person_fields[<%= field %>][active]"><%= _(field.humanize) %></label></td> |
15 | 29 | <td> |
16 | 30 | <%= hidden_field_tag "person_fields[#{field}][active]", false %> |
17 | - <%= check_box_tag "person_fields[#{field}][active]", true, environment.custom_person_field(field, 'active'), :onclick => "$('person_fields[#{field}][required]').disabled=$('person_fields[#{field}][signup]').disabled=!this.checked;" %> | |
31 | + <%= check_box_tag "person_fields[#{field}][active]", true, environment.custom_person_field(field, 'active'), :onclick => "active_action(this, 'person_fields[#{field}][required]', 'person_fields[#{field}][signup]')" %> | |
18 | 32 | </td> |
19 | 33 | <td> |
20 | 34 | <%= hidden_field_tag "person_fields[#{field}][required]", false %> |
21 | - <%= check_box_tag "person_fields[#{field}][required]", true, environment.custom_person_field(field, 'required'), :onclick => "if(this.checked) $('person_fields[#{field}][signup]').checked = true;" %> | |
35 | + <%= check_box_tag "person_fields[#{field}][required]", true, environment.custom_person_field(field, 'required'), :onclick => "required_action('person_fields[#{field}][active]','person_fields[#{field}][required]', 'person_fields[#{field}][signup]')" %> | |
22 | 36 | </td> |
23 | 37 | <td> |
24 | 38 | <%= hidden_field_tag "person_fields[#{field}][signup]", false %> |
25 | - <%= check_box_tag "person_fields[#{field}][signup]", true, environment.custom_person_field(field, 'signup'), :onclick => "if(!this.checked) $('person_fields[#{field}][required]').checked = false;" %> | |
39 | + <%= check_box_tag "person_fields[#{field}][signup]", true, environment.custom_person_field(field, 'signup'), :onclick => "signup_action('person_fields[#{field}][active]','person_fields[#{field}][required]', 'person_fields[#{field}][signup]')" %> | |
26 | 40 | </td> |
27 | 41 | </tr> |
28 | 42 | <% end %> |
29 | 43 | </table> |
30 | 44 | |
31 | 45 | <script type='text/javascript'>// <!-- |
32 | - var trs = $$('#person_fields_conf tr'); | |
46 | + var trs = jQuery('#person_fields_conf tr'); | |
47 | + | |
33 | 48 | var tr, td2; |
34 | - for ( var i=0; tr=trs[i]; i++ ) { | |
49 | + for ( var i=2; tr=trs[i]; i++ ) { | |
35 | 50 | if ( td2 = tr.getElementsByTagName('td')[1] ) { |
36 | - td2.getElementsByTagName('input')[0].onclick(); | |
51 | + td2.getElementsByTagName('input')[1].onclick(); | |
37 | 52 | } |
38 | 53 | } |
39 | 54 | // --> |
... | ... | @@ -41,7 +56,7 @@ |
41 | 56 | |
42 | 57 | <div> |
43 | 58 | <% button_bar do %> |
44 | - <%= submit_button('save', _('Save changes')) %> | |
59 | + <%= submit_button('save', _('Save changes'), :id=>"save_person_fields") %> | |
45 | 60 | <%= button :back, _('Back to admin panel'), :controller => 'admin_panel', :action => 'index' %> |
46 | 61 | <% end %> |
47 | 62 | </div> | ... | ... |
app/views/features/index.rhtml
... | ... | @@ -26,9 +26,13 @@ Check all the features you want to enable for your environment, uncheck all the |
26 | 26 | |
27 | 27 | <h2><%= _('Configure features') %></h2> |
28 | 28 | |
29 | +<h3><%= _('Page to redirect after signup') %></h3> | |
30 | + <%= select 'environment', 'redirection_after_signup', Environment.signup_redirection_options.map{|key,value|[value,key]} %> | |
31 | +<hr/> | |
29 | 32 | <h3><%= _('Page to redirect after login') %></h3> |
30 | 33 | <%= select 'environment', 'redirection_after_login', Environment.login_redirection_options.map{|key,value|[value,key]} %> |
31 | 34 | <hr/> |
35 | + | |
32 | 36 | <h3><%= _('Organization Approval Method') %></h3> |
33 | 37 | <%= select_organization_approval_method('environment', 'organization_approval_method') %> |
34 | 38 | <hr/> | ... | ... |
app/views/features/manage_fields.rhtml
1 | -<%= render :partial => 'manage_person_fields' %> | |
1 | +<h1><%= _('Manage fields displayed for profiles') %></h1> | |
2 | 2 | |
3 | -<% if !environment.enabled?('disable_asset_enterprises') %> | |
4 | - <%= render :partial => 'manage_enterprise_fields' %> | |
3 | +<% tabs = [] %> | |
4 | +<% tabs << {:title => _("Person's fields"), :id => 'person-fields', | |
5 | + :content => (render :partial => 'manage_person_fields')} %> | |
6 | +<% tabs << {:title => _("Community's fields"), :id => 'community-fields', | |
7 | + :content => (render :partial => 'manage_community_fields')} %> | |
8 | +<% unless environment.enabled?('disable_asset_enterprises') %> | |
9 | + <% tabs << {:title => _("Enterprise's fields"), :id => 'enterprise-fields', | |
10 | + :content => (render :partial => 'manage_enterprise_fields')} %> | |
5 | 11 | <% end %> |
6 | 12 | |
7 | -<%= render :partial => 'manage_community_fields' %> | |
13 | +<%= render_tabs(tabs) %> | |
14 | + | |
15 | +<%= javascript_include_tag "manage-fields.js" %> | ... | ... |
app/views/layouts/application-ng.rhtml
... | ... | @@ -6,6 +6,27 @@ |
6 | 6 | <!--<meta http-equiv="refresh" content="1"/>--> |
7 | 7 | <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> |
8 | 8 | <meta name="description" content="<%= @environment.name %>" /> |
9 | + | |
10 | + <!-- Twitter Card --> | |
11 | + <meta name="twitter:card" value="summary"> | |
12 | + <meta name="twitter:title" content="<%= h page_title %>"> | |
13 | + <meta name="twitter:description" content="<%= meta_description_tag(@page) %>"> | |
14 | + | |
15 | + <!-- Open Graph --> | |
16 | + <meta property="og:type" content="<%= @page ? 'article' : 'website' %>"> | |
17 | + <meta property="og:url" content="<%= @page ? url_for(@page.url) : @environment.top_url %>"> | |
18 | + <meta property="og:title" content="<%= h page_title %>"> | |
19 | + <meta property="og:site_name" content="<%= profile ? profile.name : @environment.name %>"> | |
20 | + <meta property="og:description" content="<%= @page ? truncate(strip_tags(@page.body.to_s), :length => 200) : @environment.name %>"> | |
21 | + | |
22 | + <% if @page %> | |
23 | + <meta property="article:published_time" content="<%= show_date(@page.published_at) %>"> | |
24 | + <% @page.body_images_paths.each do |img| %> | |
25 | + <meta name="twitter:image" content="<%= img.to_s %>"> | |
26 | + <meta property="og:image" content="<%= img.to_s %>"> | |
27 | + <% end %> | |
28 | + <% end %> | |
29 | + | |
9 | 30 | <link rel="shortcut icon" href="<%= image_path(theme_favicon) %>" type="image/x-icon" /> |
10 | 31 | <%= noosfero_javascript %> |
11 | 32 | <%= noosfero_stylesheets %> | ... | ... |
app/views/person_notifier/mailer/_add_member_in_community.rhtml
0 → 100644
... | ... | @@ -0,0 +1 @@ |
1 | +<%= render :partial => 'default_activity', :locals => { :activity => activity } %> | ... | ... |
... | ... | @@ -0,0 +1,33 @@ |
1 | +<% Comment %> | |
2 | +<% Profile %> | |
3 | +<% Person %> | |
4 | + | |
5 | +<table style="background: #f0f0f1;border-bottom: 1px solid #d2d2d2 !important;border-top: 1px solid #fff;margin-bottom: 0;"> | |
6 | +<tr> | |
7 | + <td> | |
8 | + <% if comment.author %> | |
9 | + <%= link_to profile_image(comment.author, :minor), | |
10 | + comment.author_url, | |
11 | + :class => 'comment-picture', | |
12 | + :title => comment.author_name | |
13 | + %> | |
14 | + <% end %> | |
15 | + </td> | |
16 | + <td> | |
17 | + <%= comment.author.present? ? link_to(comment.author_name, comment.author.url, :style => "font-size: 12px; color: #333; font-weight: bold; text-decoration: none;") : content_tag('strong', comment.author_name) %> | |
18 | + <% unless comment.title.blank? %> | |
19 | + <span style="font-size: 12px;"><%= comment.title %></span><br/> | |
20 | + <% end %> | |
21 | + <span style="font-size: 10px;"><%= txt2html comment.body %></span><br/> | |
22 | + <span style="font-size: 8px; color: #444444"><%= time_ago_as_sentence(comment.created_at) %></span> | |
23 | + <br style="clear: both;" /> | |
24 | + | |
25 | + <% unless comment.replies.blank? %> | |
26 | + <ul class="comment-replies"> | |
27 | + <% comment.replies.each do |reply| %> | |
28 | + <%= render :partial => 'comment', :locals => { :comment => reply } %> | |
29 | + <% end %> | |
30 | + </ul> | |
31 | + <% end %> | |
32 | + </td> | |
33 | +</table> | ... | ... |
... | ... | @@ -0,0 +1,27 @@ |
1 | +<table> | |
2 | +<tr> | |
3 | + <td> | |
4 | + <%= link_to(profile_image(activity.user, :minor), activity.user.url) %> | |
5 | + </td> | |
6 | + <td> | |
7 | + <p style="width:550px"> | |
8 | + <span style="font-size: 14px;"><%= link_to activity.user.short_name(20), activity.user.url %></span> | |
9 | + <span style="font-size: 14px;"><%= _("has published on community %s") % link_to(activity.target.profile.short_name(20), activity.target.profile.url, :style => "color: #333; font-weight: bold; text-decoration: none;") if activity.target.profile.is_a?(Community) %></span> | |
10 | + <span style="font-size: 10px; color: #444444; float:right;"><%= time_ago_as_sentence(activity.created_at) %></span> | |
11 | + </p> | |
12 | + <p> | |
13 | + <span style="font-size: 14px;"><%= link_to(activity.params['name'], activity.params['url'], :style => "color: #333; font-weight: bold; text-decoration: none;") %></span> | |
14 | + <br/> | |
15 | + <span title='<%= activity.target.class.short_description %>' class='profile-activity-icon icon-new icon-new<%= activity.target.class.icon_name %>'></span> | |
16 | + <%= image_tag(activity.params['first_image']) unless activity.params['first_image'].blank? %><%= strip_tags(truncate(activity.params['lead'], :length => 1000, :ommision => '...')).gsub(/(\xC2\xA0|\s)+/, ' ').gsub(/^\s+/, '') %> | |
17 | + </p> | |
18 | + <p><%= content_tag(:p, link_to(_('See complete forum'), activity.get_url), :class => 'see-forum') if activity.target.is_a?(Forum) %></p> | |
19 | + </td> | |
20 | +</tr> | |
21 | +<tr> | |
22 | + <td></td> | |
23 | + <td> | |
24 | + <%= render :partial => 'profile_comments', :locals => { :activity => activity } %> | |
25 | + </td> | |
26 | +</tr> | |
27 | +</table> | ... | ... |
app/views/person_notifier/mailer/_default_activity.rhtml
0 → 100644
... | ... | @@ -0,0 +1,19 @@ |
1 | +<table> | |
2 | +<tr> | |
3 | + <td> | |
4 | + <%= link_to(profile_image(activity.user, :minor), activity.user.url) %> | |
5 | + </td> | |
6 | + <td> | |
7 | + <p style="width:550px"> | |
8 | + <span style="font-size: 14px;"><%= link_to activity.user.name, activity.user.url %> <%= describe activity %></span> | |
9 | + <span style="font-size: 10px; color: #444444; float: right;"><%= time_ago_as_sentence(activity.created_at) %></span> | |
10 | + </p> | |
11 | + </td> | |
12 | +</tr> | |
13 | +<tr> | |
14 | + <td></td> | |
15 | + <td> | |
16 | + <%= render :partial => 'profile_comments', :locals => { :activity => activity } %> | |
17 | + </td> | |
18 | +</tr> | |
19 | +</table> | ... | ... |
... | ... | @@ -0,0 +1 @@ |
1 | +<%= render :partial => 'default_activity', :locals => { :activity => activity } %> | ... | ... |
... | ... | @@ -0,0 +1 @@ |
1 | +<%= render :partial => 'default_activity', :locals => { :activity => activity } %> | ... | ... |
app/views/person_notifier/mailer/_leave_scrap_to_self.rhtml
0 → 120000
... | ... | @@ -0,0 +1 @@ |
1 | +<%= render :partial => 'default_activity', :locals => { :activity => activity } %> | ... | ... |
app/views/person_notifier/mailer/_profile_comments.rhtml
0 → 100644
... | ... | @@ -0,0 +1,13 @@ |
1 | +<% if activity.comments_count > 2 %> | |
2 | + <div style="font-size: 10px;"> | |
3 | + <% if activity.params['url'].blank? %> | |
4 | + <%= _("%s comments") % activity.comments_count %> | |
5 | + <% else %> | |
6 | + <%= link_to(_("View all %s comments") % activity.comments_count, activity.params['url']) %> | |
7 | + <% end %> | |
8 | + </div> | |
9 | +<% else %> | |
10 | + <ul> | |
11 | + <%= render :partial => 'comment', :collection => activity.comments %> | |
12 | + </ul> | |
13 | +<% end %> | ... | ... |
app/views/person_notifier/mailer/_reply_scrap_on_self.rhtml
0 → 120000
... | ... | @@ -0,0 +1,15 @@ |
1 | +<table> | |
2 | + <tr> | |
3 | + <td> | |
4 | + <%= link_to(profile_image(activity.user, :minor), activity.user.url) %> | |
5 | + </td> | |
6 | + <td> | |
7 | + <p style="width:550px"> | |
8 | + <span style="font-size: 14px;"><%= link_to activity.user.name, activity.user.url %> <%= describe activity %></span> | |
9 | + <span style="font-size: 10px; color: #444444; float:right;"><%= time_ago_as_sentence(activity.created_at) %></span> | |
10 | + </p> | |
11 | + </td> | |
12 | +</tr> | |
13 | +</table> | |
14 | +<div title='<%= activity.target.class.short_description %>' class='profile-activity-icon icon-new icon-newgallery'></div> | |
15 | +<br/> | ... | ... |
... | ... | @@ -0,0 +1,18 @@ |
1 | +<h3><%= _("%s's network activity") % @profile.name %></h3> | |
2 | +<br/> | |
3 | +<div> | |
4 | +<% @notifications.each do |activity| %> | |
5 | + <div style="border-left:none;border-right:none;border-top:1px solid #ccc;border-bottom:none;padding:10px;width:600px"> | |
6 | + <%= render :partial => activity.verb, :locals => { :activity => activity } rescue "cannot render notification for #{activity.verb}" %> | |
7 | + </div> | |
8 | +<% end %> | |
9 | +</div> | |
10 | + | |
11 | +<div style="color:#444444;font-size:11px;"> | |
12 | +<p><%= _("Greetings,") %></p> | |
13 | +<br/> | |
14 | +<p>--</p> | |
15 | +<p><%= _('%s team.') % @environment %></p> | |
16 | +<p><%= url_for @url %></p> | |
17 | +</div> | |
18 | +<br/> | ... | ... |
app/views/profile/_create_article.rhtml
... | ... | @@ -4,7 +4,7 @@ |
4 | 4 | <div class='profile-activity-description profile-activity-article-<%= activity.target.class.icon_name %>'> |
5 | 5 | <p class='profile-activity-text'> |
6 | 6 | <%= link_to activity.user.short_name(20), activity.user.url %> |
7 | - <%= _("on community %s") % link_to(activity.target.profile.short_name(20), activity.target.profile.url) if activity.target.profile.is_a?(Community) %> | |
7 | + <%= _("has published on community %s") % link_to(activity.target.profile.short_name(20), activity.target.profile.url) if activity.target.profile.is_a?(Community) %> | |
8 | 8 | </p> |
9 | 9 | <div class='profile-activity-lead'> |
10 | 10 | <div class='article-name'><%= link_to(activity.params['name'], activity.params['url']) %></div> | ... | ... |
app/views/profile/index.rhtml
... | ... | @@ -19,22 +19,21 @@ |
19 | 19 | <table class='profile'> |
20 | 20 | <tr> |
21 | 21 | <td colspan='2'> |
22 | - <% plugins_tabs = @plugins.dispatch(:profile_tabs). | |
23 | - map { |tab| {:title => tab[:title], :id => tab[:id], :content => instance_eval(&tab[:content]), :start => tab[:title]} }%> | |
22 | + <% plugins_tabs = @plugins.dispatch(:profile_tabs).map { |tab| {:title => tab[:title], :id => tab[:id], :content => instance_eval(&tab[:content]), :start => tab[:title]} }%> | |
24 | 23 | |
25 | 24 | <% tabs = plugins_tabs.select { |tab| tab[:start] } %> |
26 | 25 | |
27 | 26 | <% if @profile.organization? %> |
28 | - <% tabs << {:title => _('Profile'), :id => 'organization-profile', :content => (render :partial => 'organization_profile')} %> | |
29 | 27 | <% if logged_in? && current_person.follows?(@profile) %> |
30 | 28 | <% tabs << {:title => _('Wall'), :id => 'profile-wall', :content => (render :partial => 'profile_wall')} %> |
31 | 29 | <% end %> |
30 | + <% tabs << {:title => _('Profile'), :id => 'organization-profile', :content => (render :partial => 'organization_profile')} %> | |
32 | 31 | <% elsif @profile.person? %> |
33 | - <% tabs << {:title => _('Profile'), :id => 'person-profile', :content => (render :partial => 'person_profile')} %> | |
34 | 32 | <% if logged_in? && current_person.follows?(@profile) %> |
35 | 33 | <% tabs << {:title => _('Wall'), :id => 'profile-wall', :content => (render :partial => 'profile_wall')} %> |
36 | 34 | <% tabs << {:title => _('Network'), :id => 'profile-network', :content => (render :partial => 'profile_network')} %> |
37 | 35 | <% end %> |
36 | + <% tabs << {:title => _('Profile'), :id => 'person-profile', :content => (render :partial => 'person_profile')} %> | |
38 | 37 | <% end %> |
39 | 38 | |
40 | 39 | <% tabs += plugins_tabs.select { |tab| !tab[:start] } %> | ... | ... |
app/views/profile/profile_info.rjs
... | ... | @@ -1,6 +0,0 @@ |
1 | -if !user.nil? and user.has_permission?('edit_profile', profile) | |
2 | - page.replace_html "profile-admin-url-#{@block.id}", link_to(_('Control panel'), @block.owner.admin_url) | |
3 | -else | |
4 | - page.hide "profile-admin-url-#{@block.id}" | |
5 | -end | |
6 | -page.replace_html "profile-info-options-#{@block.id}", :file => view_for_profile_actions(@block.owner.class) |
app/views/profile_editor/_organization.rhtml
... | ... | @@ -65,3 +65,8 @@ |
65 | 65 | <%= labelled_check_box(_('Enable "contact us"'), 'profile_data[enable_contact_us]', "1", @profile.enable_contact_us) if @profile.enterprise? %> |
66 | 66 | |
67 | 67 | <%= render :partial => 'moderation', :locals => { :profile => @profile } %> |
68 | + | |
69 | +<% if profile.enterprise? && profile.environment.enabled?('products_for_enterprises') %> | |
70 | + <h2><%=_('Products/Services catalog')%></h2> | |
71 | + <%= labelled_form_field(_('Number of products/services displayed per page on catalog'), text_field(:profile_data, :products_per_catalog_page, :size => 3)) %> | |
72 | +<% end %> | ... | ... |
app/views/profile_editor/_person.rhtml
... | ... | @@ -19,3 +19,8 @@ |
19 | 19 | <%= @plugins.dispatch(:profile_info_extra_contents).collect { |content| instance_eval(&content) }.join("") %> |
20 | 20 | |
21 | 21 | <%= render :partial => 'person_form', :locals => {:f => f} %> |
22 | + | |
23 | + <h2><%= _('Notification options') %></h2> | |
24 | + <div> | |
25 | + <%= select_tag 'profile_data[notification_time]', options_for_select([[_('Disabled'), 0], [_('Hourly'), 1], [_('Half Day'), 12], [_('Daily'), 24]], @profile.notification_time) %> | |
26 | + </div> | ... | ... |
app/views/profile_editor/_person_form.rhtml
... | ... | @@ -13,6 +13,8 @@ |
13 | 13 | <%= optional_field(@person, 'contact_phone', labelled_form_field(_('Home phone'), text_field(:profile_data, :contact_phone, :rel => _('Contact phone')))) %> |
14 | 14 | <%= optional_field(@person, 'cell_phone', f.text_field(:cell_phone, :rel => _('Cell phone'))) %> |
15 | 15 | <%= optional_field(@person, 'comercial_phone', f.text_field(:comercial_phone, :rel => _('Comercial phone'))) %> |
16 | +<%= optional_field(@person, 'jabber_id', f.text_field(:jabber_id, :rel => _('Jabber'))) %> | |
17 | +<%= optional_field(@person, 'personal_website', f.text_field(:personal_website, :rel => _('Personal website'))) %> | |
16 | 18 | <%= optional_field(@person, 'sex', f.radio_group(:profile_data, :sex, [ ['male',_('Male')], ['female',_('Female')] ])) %> |
17 | 19 | <%= optional_field(@person, 'birth_date', labelled_form_field(_('Birth date'), '<div class="select-birth-date">' + pick_date(:profile_data, :birth_date, {:start_year => (Date.today.year - 100), :end_year => (Date.today.year - 5)}) + '</div>')) %> |
18 | 20 | <%= optional_field(@person, 'nationality', f.text_field(:nationality, :rel => _('Nationality'))) %> | ... | ... |
app/views/profile_editor/index.rhtml
... | ... | @@ -22,7 +22,7 @@ |
22 | 22 | |
23 | 23 | <%= control_panel_button(_('Edit sideboxes'), 'blocks', :controller => 'profile_design', :action => 'index') %> |
24 | 24 | |
25 | - <%= control_panel_button(_('Edit Appearance'), 'design-editor', :controller => 'themes', :action => 'index') %> | |
25 | + <%= control_panel_button(_('Edit Appearance'), 'design-editor', :controller => 'profile_themes', :action => 'index') %> | |
26 | 26 | |
27 | 27 | <%= control_panel_button(_('Edit Header and Footer'), 'header-and-footer', :controller => 'profile_editor', :action => 'header_footer') unless profile.enterprise? && environment.enabled?('disable_header_and_footer') && !user.is_admin?(environment) %> |
28 | 28 | ... | ... |
app/views/profile_members/_members_list.rhtml
1 | -<% collection = @collection == :profile_admins ? profile.admins : profile.members %> | |
1 | +<% collection = @collection == :profile_admins ? profile.admins : profile.members_by_name %> | |
2 | 2 | <% title = @title ? @title : _('Current members') %> |
3 | 3 | <% remove_action = @remove_action ? @remove_action : {:action => 'unassociate'} %> |
4 | 4 | ... | ... |
... | ... | @@ -0,0 +1,11 @@ |
1 | +<h2><%= _('Add a CSS file') %></h2> | |
2 | + | |
3 | +<% form_tag do %> | |
4 | + <%= labelled_form_field(_('File name'), text_field_tag('css')) %> | |
5 | + | |
6 | + <% button_bar do %> | |
7 | + <%= submit_button(:add, _('Add')) %> | |
8 | + <%= lightbox_close_button(_('Cancel')) %> | |
9 | + <% end %> | |
10 | + | |
11 | +<% end %> | ... | ... |
... | ... | @@ -0,0 +1,13 @@ |
1 | +<h2><%= _('CSS code: "%s"') % @css %></h2> | |
2 | + | |
3 | +<% form_tag({:action => 'update_css', :id => @theme.id }, :name => 'csscode_form') do %> | |
4 | + <%= hidden_field_tag('css', @css) %> | |
5 | + <%= text_area_tag('csscode', @code, :id => "codepressWindow", :class => 'codepress css') %> | |
6 | + <% button_bar do %> | |
7 | + <%= submit_button(:save, _('Save')) %> | |
8 | + <% end %> | |
9 | +<% end %> | |
10 | + | |
11 | +<!--<script type='text/javascript'>--> | |
12 | + <!--CodePress.run();--> | |
13 | +<!--</script>--> | ... | ... |
... | ... | @@ -0,0 +1,41 @@ |
1 | +<form> | |
2 | + <%# FIXME %> | |
3 | + <h1 id='theme-name'> | |
4 | + <%= _('Editing theme "%s"') % @theme.name %> | |
5 | + <%= button(:eyes, _('Preview this theme'), :action => 'start_test', :id => @theme.id) %> | |
6 | + <%= button(:back, _('Back'), :action => 'index') %> | |
7 | + </h1> | |
8 | +</form> | |
9 | + | |
10 | + | |
11 | +<div id='css-files-list'> | |
12 | + <h2><%= _('CSS files') %></h2> | |
13 | + <ul> | |
14 | + <% for css in @css_files %> | |
15 | + <li><%= link_to_remote(css, :url => { :action => 'css_editor', :id => @theme.id, :css => css }, :update => { :success => 'css-code' }) %></li> | |
16 | + <% end %> | |
17 | + </ul> | |
18 | + <% button_bar do %> | |
19 | + <%= lightbox_button(:add, _('New CSS'), :action => 'add_css', :id => @theme.id) %> | |
20 | + <% end %> | |
21 | +</div> | |
22 | + | |
23 | +<div id='image-files-list'> | |
24 | + <h2><%= _('Images') %></h2> | |
25 | + <ul> | |
26 | + <% for image in @image_files %> | |
27 | + <li><%= image_tag("/user_themes/#{@theme.id}/images/#{image}") %></li> | |
28 | + <% end %> | |
29 | + </ul> | |
30 | + <% button_bar do %> | |
31 | + <%= lightbox_button(:add, _('Add image'), :action => 'add_image', :id => @theme.id) %> | |
32 | + <% end %> | |
33 | +</div> | |
34 | + | |
35 | +<div id='css-code'> | |
36 | + <center style='padding-top: 5em;'> | |
37 | + <em><%= _('Select a CSS file to edit') %></em> | |
38 | + </center> | |
39 | +</div> | |
40 | + | |
41 | +<%# javascript_include_tag 'codepress/codepress' %> | ... | ... |
... | ... | @@ -0,0 +1,48 @@ |
1 | +<%= render :partial => 'themes/select_template' %> | |
2 | +<%= render :partial => 'themes/select_theme' %> | |
3 | + | |
4 | +<% if environment.enabled?('user_themes') %> | |
5 | + <div id="user-themes" class="list-options"> | |
6 | + | |
7 | + <h2><%= _('My themes') %></h2> | |
8 | + | |
9 | + <% for themes in profile.themes.in_groups_of(3) %> | |
10 | + <div class="list-group"> | |
11 | + <% for theme in themes %><%= | |
12 | + if theme | |
13 | + | |
14 | + selected = theme.id == @current_theme | |
15 | + sel_html = selected ? | |
16 | + content_tag('big', _('(current)') ) : | |
17 | + link_to(_('Use this theme'), :action => 'set', :id => theme.id) | |
18 | + | |
19 | + content_tag( 'div', | |
20 | + image_tag( | |
21 | + '/images/icons-app/design-editor.png', | |
22 | + :alt => (_('The "%s" theme.') % theme.name)) + | |
23 | + '<div class="opt-info">' + | |
24 | + content_tag('strong', theme.name, :class => 'name') + | |
25 | + ' <br/> '+ sel_html +' <br/> ' + | |
26 | + link_to(_('Edit this theme'), :action => 'edit', :id => theme.id) + | |
27 | + ' <br/> ' + | |
28 | + link_to(_('Test this theme'), :action => 'start_test', :id => theme.id) + | |
29 | + '</div>', | |
30 | + :class => 'theme-opt list-opt' + (selected ? ' selected' : '') | |
31 | + ) | |
32 | + | |
33 | + end | |
34 | + %><% end %> | |
35 | + </div> | |
36 | + <% end %> | |
37 | + | |
38 | + </div><!-- end id="user-themes" --> | |
39 | +<% end %> | |
40 | + | |
41 | +<br style="clear:both" /> | |
42 | + | |
43 | +<% button_bar do %> | |
44 | + <% if environment.enabled?('user_themes') %> | |
45 | + <%= lightbox_button(:add, _('New theme ...'), :action => 'new') %> | |
46 | + <% end %> | |
47 | + <%= button(:back, _('Back'), :controller => 'profile_editor', :action => 'index') %> | |
48 | +<% end %> | ... | ... |
... | ... | @@ -0,0 +1,10 @@ |
1 | +<h2><%= _('Create new theme') %></h2> | |
2 | + | |
3 | +<% form_tag(:action => 'new') do %> | |
4 | + | |
5 | + <%= labelled_form_field(_('Name of the new theme:'), text_field_tag(:name)) %> | |
6 | + | |
7 | + <% button_bar do %> | |
8 | + <%= submit_button(:save, _('Create')) %> | |
9 | + <% end %> | |
10 | +<% end %> | ... | ... |
app/views/shared/_select_categories.rhtml
1 | -<div id="category-ajax-selector"> | |
1 | +<% extend CategoriesHelper %> | |
2 | + | |
2 | 3 | <% if !@current_category.nil? %> |
3 | - <h3 class="box-title"><%= _('Current category:') %></h3> | |
4 | 4 | <%= hidden_field_tag "#{object_name}[#{object_name}_category_id]", @current_category.id unless multiple %> |
5 | + <%= hidden_field_tag "#{object_name}[category_ids][]", @current_category.id if multiple %> | |
6 | + <%= button_to_remote_without_text(:back, _('Back'), | |
7 | + { :update => "select-categories", | |
8 | + :url => { :action => 'update_categories', :id => @object }, | |
9 | + :loaded => visual_effect(:highlight, "select-categories") | |
10 | + }, | |
11 | + :id => 'cancel-category-button') %> | |
5 | 12 | <% |
6 | 13 | categories = [@current_category] |
7 | 14 | categories.push(@current_category) while @current_category = @current_category.parent |
8 | 15 | %> |
9 | 16 | <%= categories.compact.reverse.map{|i| |
10 | - link_to_remote(i.name, | |
17 | + link_to_remote(i.name, | |
11 | 18 | :update => "select-categories", |
12 | 19 | :url => { :action => 'update_categories', :category_id => i.id, :id => @object }, |
13 | 20 | :loaded => visual_effect(:highlight, "select-categories"), |
14 | 21 | :class => 'select-current-category-link')}.join(' → ') |
15 | 22 | %> |
16 | - <strong> | |
17 | - <%= button_to_function_without_text(:save, _('Save'), nil, :id => 'save-category-button') do |page| | |
18 | - page.insert_html :bottom, 'selected-categories', content_tag('li', categories.first.full_name + | |
23 | + <%= button_to_function_without_text(:add, _('Add'), nil, :id => 'save-category-button') do |page| | |
24 | + page.insert_html :bottom, 'selected-categories', content_tag('div', | |
19 | 25 | hidden_field_tag("#{object_name}[category_ids][]", categories.first.id) + |
20 | - button_to_function_without_text(:cancel, _('Remove'), nil, :id => "remove-selected-category-#{categories.first.id}-button") {|page| page["selected-category-#{categories.first.id}"].remove}, :id => "selected-category-#{categories.first.id}") | |
26 | + selected_category_link(categories.first), :id => "selected-category-#{categories.first.id}") | |
27 | + page.replace_html 'select-categories', :partial => 'shared/select_subcategories', | |
28 | + :locals => {:object_name => object_name, :categories => @toplevel_categories} | |
21 | 29 | end if multiple %> |
22 | - <%= button_to_remote_without_text(:cancel, _('Cancel'), | |
23 | - { :update => "select-categories", | |
24 | - :url => { :action => 'update_categories', :id => @object }, | |
25 | - :loaded => visual_effect(:highlight, "select-categories") | |
26 | - }, | |
27 | - :id => 'cancel-category-button') %> | |
28 | - </strong> | |
29 | -<% else %> | |
30 | - <h3 class="box-title"><%= _('Select a category:') %></h3> | |
31 | 30 | <% end %> |
32 | 31 | |
33 | -<% if !@categories.empty? %> | |
34 | - <h3><%= _('Categories:') %></h3> | |
35 | - <% @categories.select{|i| !@object.respond_to?(:accept_category?) || @object.accept_category?(i)}.each do |category| %> | |
36 | - <%= link_to_remote category.name, | |
37 | - { :update => "select-categories", | |
38 | - :url => { :action => "update_categories", :category_id => category.id, :id => @object}, | |
39 | - :loaded => visual_effect(:highlight, "select-categories") | |
40 | - }, | |
41 | - :class => 'select-subcategory-link', | |
42 | - :id => "select-category-#{category.id}-link" | |
43 | - %> | |
44 | - <% end %> | |
45 | -<% end %> | |
32 | +<div class="toplevel-categories"> | |
33 | + <%= render :partial => 'shared/select_subcategories', :locals => {:object_name => object_name, :categories => @categories} %> | |
46 | 34 | </div> | ... | ... |
... | ... | @@ -0,0 +1,26 @@ |
1 | +<% categories_selected ||= nil %> | |
2 | +<% title ||= nil %> | |
3 | + | |
4 | +<% extend CategoriesHelper %> | |
5 | + | |
6 | +<%= content_tag "h#{title_size}", title, :class => "box-title" %> | |
7 | + | |
8 | +<%= hidden_field_tag "#{object_name}[category_ids][]", nil %> | |
9 | + | |
10 | +<div id="category-ajax-selector"> | |
11 | +<% unless categories_selected.nil? %> | |
12 | +<div id="selected-categories"> | |
13 | + <div class="label"><%= _('Selected categories:') %></div> | |
14 | + <% categories_selected.each do |cat| %> | |
15 | + <div id="selected-category-<%= cat.id %>"> | |
16 | + <%= hidden_field_tag("#{object_name}[category_ids][]", cat.id) %> | |
17 | + <%= selected_category_link(cat) %> | |
18 | + </div> | |
19 | + <% end %> | |
20 | +</div> | |
21 | +<% end %> | |
22 | +<div id="select-categories"> | |
23 | + <%= render :partial => 'shared/select_categories', :locals => {:object_name => object_name, :multiple => true, :categories_selected => categories_selected }, :layout => false %> | |
24 | +</div> | |
25 | + | |
26 | +</div> | ... | ... |
... | ... | @@ -0,0 +1,16 @@ |
1 | +<% if !categories.nil? && !categories.empty? && !@object.nil? %> | |
2 | + <hr> | |
3 | + <div class="category-helper-label"><%= _('Click to select a category') %></div> | |
4 | + | |
5 | + <% categories.select{|i| @object.accept_category?(i)}.each do |category| %> | |
6 | + | |
7 | + <%= link_to_remote category.name, | |
8 | + { :update => "select-categories", | |
9 | + :url => { :action => "update_categories", :category_id => category.id, :id => @object}, | |
10 | + :loaded => visual_effect(:highlight, "select-categories") | |
11 | + }, | |
12 | + :class => 'select-subcategory-link', | |
13 | + :id => "select-category-#{category.id}-link" | |
14 | + %> | |
15 | + <% end %> | |
16 | +<% end %> | ... | ... |
app/views/shared/theme_test_panel.rhtml
... | ... | @@ -6,8 +6,8 @@ |
6 | 6 | <p><small><em><%= _('You can move this window away to have a better visualization of specific parts of screen.') %></em></small></p> |
7 | 7 | |
8 | 8 | <% button_bar do %> |
9 | - <%= button(:ok, _('Finished testing'), :controller => 'themes', :profile => theme_owner, :action => 'stop_test', :id => current_theme) %> | |
10 | - <%= button(:edit, _('Edit theme'), :controller => 'themes', :profile => theme_owner, :action => 'edit', :id => current_theme) %> | |
9 | + <%= button(:ok, _('Finished testing'), :controller => 'profile_themes', :profile => theme_owner, :action => 'stop_test', :id => current_theme) %> | |
10 | + <%= button(:edit, _('Edit theme'), :controller => 'profile_themes', :profile => theme_owner, :action => 'edit', :id => current_theme) %> | |
11 | 11 | <% end %> |
12 | 12 | </div> |
13 | 13 | <%= draggable_element('theme-test-panel') %> | ... | ... |
... | ... | @@ -0,0 +1,35 @@ |
1 | +<h1><%= _('Editing Appearance') %></h1> | |
2 | + | |
3 | +<div id="template-options" class="list-options"> | |
4 | + | |
5 | +<h2><%= _('Select template') %></h2> | |
6 | + | |
7 | +<% for templates in @layout_templates.in_groups_of(3) %> | |
8 | + <div class="list-group"> | |
9 | + <% for template in templates %><%= | |
10 | + if template | |
11 | + base_content = image_tag( | |
12 | + "/designs/templates/#{template.id}/thumbnail.png", | |
13 | + :alt => _('The "%s" template')) + | |
14 | + '<div class="opt-info">'.html_safe + | |
15 | + content_tag('strong', template.name, :title => template.title, :class => 'name') + | |
16 | + ' <br/> '.html_safe | |
17 | + | |
18 | + if @current_template == template.id # selected | |
19 | + content_tag( 'div', | |
20 | + base_content + content_tag('big', _('(current)') ) +'</div>'.html_safe, | |
21 | + :class => 'template-opt list-opt selected') | |
22 | + else # Not selected | |
23 | + link_to( | |
24 | + base_content +'</div>'.html_safe, | |
25 | + { :action => 'set_layout_template', :id => template.id }, | |
26 | + :class => 'template-opt list-opt') | |
27 | + end | |
28 | + | |
29 | + end | |
30 | + %><% end %> | |
31 | + </div> | |
32 | +<% end %> | |
33 | + | |
34 | +</div><!-- end id="template-options" --> | |
35 | + | ... | ... |
... | ... | @@ -0,0 +1,37 @@ |
1 | +<% if !@themes.empty? %> | |
2 | +<div id="theme-options" class="list-options"> | |
3 | + | |
4 | +<h2><%= _('Select theme') %></h2> | |
5 | +<%= button :home, _('Use the default theme'), { :action => 'unset'}, :method => 'post', :confirm => _('Are you sure you want to use the environment default theme?') %> | |
6 | + | |
7 | +<% for themes in @themes.in_groups_of(3) %> | |
8 | + <div class="list-group"> | |
9 | + <% for theme in themes %><%= | |
10 | + if theme | |
11 | + | |
12 | + base_content = image_tag( | |
13 | + "/designs/themes/#{theme.id}/preview.png", | |
14 | + :alt => (_('The "%s" theme.') % theme.name)) + | |
15 | + '<div class="opt-info">'.html_safe + | |
16 | + content_tag('strong', theme.name, :class => 'name') + | |
17 | + ' <br/> '.html_safe | |
18 | + | |
19 | + if theme.id == @current_theme # selected | |
20 | + content_tag( 'div', | |
21 | + base_content + content_tag('big', _('(current)') ) +'</div>'.html_safe, | |
22 | + :class => 'theme-opt list-opt selected') | |
23 | + else # Not selected | |
24 | + link_to( | |
25 | + base_content + '</div>'.html_safe, | |
26 | + { :action => 'set', :id => theme.id }, | |
27 | + :class => 'theme-opt list-opt') | |
28 | + end | |
29 | + | |
30 | + end | |
31 | + %><% end %> | |
32 | + </div> | |
33 | +<% end %> | |
34 | + | |
35 | +</div><!-- end id="theme-options" --> | |
36 | +<% end %> | |
37 | + | ... | ... |