Commit 1c541c6f1431c436ece9fae60635390778647eea
Exists in
staging
and in
4 other branches
Merge branch 'serpro-context' of gitlab.com:participa/noosfero into serpro-context
Showing
366 changed files
with
22696 additions
and
8215 deletions
Show diff stats
Too many changes.
To preserve performance only 100 of 366 files displayed.
INSTALL.chat.md
1 | -XMPP/Chat Setup | |
2 | -=============== | |
1 | +Automatic XMPP/Chat Setup | |
2 | +========================= | |
3 | + | |
4 | +Since Noosfero 1.2, the XMPP/Chat can be installed via `noosfero-chat` Debian | |
5 | +package. So you don't need to follow the manual instructions here if you | |
6 | +already have it installed on your system. | |
7 | + | |
8 | +But if you are going to install the `noosfero-chat` package on a system that | |
9 | +already has `noosfero` older 1.2 installed then you need to check if apache's | |
10 | +configuration file `/etc/apache2/sites-available/noosfero` has this line below: | |
11 | + | |
12 | + Include /usr/share/noosfero/util/chat/apache/xmpp.conf | |
13 | + | |
14 | +Manual XMPP/Chat Setup | |
15 | +====================== | |
3 | 16 | |
4 | 17 | The samples of config file to configure a XMPP/BOSH server with ejabberd, |
5 | 18 | postgresql and apache2 can be found at util/chat directory. |
... | ... | @@ -8,7 +21,7 @@ This setup supposes that you are using Noosfero installed via Debian package |
8 | 21 | in a production environment. |
9 | 22 | |
10 | 23 | Steps |
11 | -===== | |
24 | +----- | |
12 | 25 | |
13 | 26 | This is a step-by-step guide to get a XMPP service working, in a Debian system. |
14 | 27 | |
... | ... | @@ -144,15 +157,8 @@ You should see a page with a message like that: |
144 | 157 | |
145 | 158 | ## 9. Test chat session |
146 | 159 | |
147 | -Open Noosfero console and execute: | |
148 | - | |
149 | ->> environment = Environment.default | |
150 | ->> user = Person['guest'] | |
151 | ->> password = user.user.crypted_password | |
152 | ->> login = user.jid | |
153 | ->> RubyBOSH.initialize_session(login, password, "http://#{environment.default_hostname}/http-bind", :wait => 30, :hold => 1, :window => 5 | |
154 | - | |
155 | -If you have luck, should see something like that: | |
160 | +Run `./script/noosfero-test-chat-session`. If you have luck, should see | |
161 | +something like that: | |
156 | 162 | |
157 | 163 | Ruby-BOSH - SEND |
158 | 164 | <body window="5" rid="60265" xmlns="http://jabber.org/protocol/httpbind" xmlns:xmpp="urn:xmpp:xbosh" to="vagrant-debian-squeeze.vagrantup.com" wait="30" xmpp:version="1.0" hold="1"/> | ... | ... |
INSTALL.https.md
... | ... | @@ -11,8 +11,8 @@ as below: |
11 | 11 | |
12 | 12 | # mkdir /etc/noosfero/ssl |
13 | 13 | # cd /etc/noosfero/ssl |
14 | - # openssl genrsa 1024 > noosfero.key | |
15 | - # openssl req -new -x509 -nodes -sha1 -days $[10*365] -key noosfero.key > noosfero.cert | |
14 | + # openssl genrsa 2048 > noosfero.key | |
15 | + # openssl req -new -x509 -sha256 -nodes -days $[10*365] -key noosfero.key > noosfero.cert | |
16 | 16 | # cat noosfero.key noosfero.cert > noosfero.pem |
17 | 17 | |
18 | 18 | ## Web server configuration | ... | ... |
INSTALL.md
... | ... | @@ -74,7 +74,7 @@ downloading from git |
74 | 74 | |
75 | 75 | Here we are cloning the noosfero repository from git. Note: you will need to install git before. |
76 | 76 | |
77 | - $ git clone git://gitorious.org/noosfero/noosfero.git current | |
77 | + $ git clone https://gitlab.com/noosfero/noosfero.git current | |
78 | 78 | $ cd current |
79 | 79 | $ git checkout -b stable origin/stable |
80 | 80 | ... | ... |
app/controllers/admin/admin_panel_controller.rb
... | ... | @@ -71,22 +71,4 @@ class AdminPanelController < AdminController |
71 | 71 | end |
72 | 72 | end |
73 | 73 | end |
74 | - | |
75 | - def manage_organizations_status | |
76 | - scope = environment.organizations | |
77 | - @filter = params[:filter] || 'any' | |
78 | - @title = "Organization profiles" | |
79 | - @title = @title+" - "+@filter if @filter != 'any' | |
80 | - | |
81 | - if @filter == 'enabled' | |
82 | - scope = scope.visible | |
83 | - elsif @filter == 'disabled' | |
84 | - scope = scope.disabled | |
85 | - end | |
86 | - | |
87 | - scope = scope.order('name ASC') | |
88 | - | |
89 | - @q = params[:q] | |
90 | - @collection = find_by_contents(:organizations, environment, scope, @q, {:per_page => 10, :page => params[:npage]})[:results] | |
91 | - end | |
92 | 74 | end | ... | ... |
... | ... | @@ -0,0 +1,66 @@ |
1 | +class OrganizationsController < AdminController | |
2 | + | |
3 | + protect 'manage_environment_organizations', :environment | |
4 | + | |
5 | + def index | |
6 | + @filter = params[:filter] || 'any' | |
7 | + @title = _('Organization profiles') | |
8 | + @type = params[:type] || "any" | |
9 | + @types_filter = [[_('All'), 'any'], [_('Community'), 'Community'], [_('Enterprise'), 'Enterprise']] | |
10 | + @types_filter = @types_filter | @plugins.dispatch(:organization_types_filter_options) | |
11 | + | |
12 | + scope = @plugins.dispatch_first(:filter_manage_organization_scope, @type) | |
13 | + if scope.blank? | |
14 | + scope = environment.organizations | |
15 | + scope = scope.where(:type => @type) if @type != 'any' | |
16 | + end | |
17 | + | |
18 | + if @filter == 'enabled' | |
19 | + scope = scope.visible | |
20 | + elsif @filter == 'disabled' | |
21 | + scope = scope.disabled | |
22 | + end | |
23 | + | |
24 | + scope = scope.order('name ASC') | |
25 | + | |
26 | + @q = params[:q] | |
27 | + @collection = find_by_contents(:organizations, environment, scope, @q, {:per_page => per_page, :page => params[:npage]})[:results] | |
28 | + end | |
29 | + | |
30 | + def activate | |
31 | + organization = environment.organizations.find(params[:id]) | |
32 | + if organization.enable | |
33 | + render :text => (_('%s enabled') % organization.name).to_json | |
34 | + else | |
35 | + render :text => (_('%s could not be enabled') % organization.name).to_json | |
36 | + end | |
37 | + end | |
38 | + | |
39 | + def deactivate | |
40 | + organization = environment.organizations.find(params[:id]) | |
41 | + if organization.disable | |
42 | + render :text => (_('%s disabled') % organization.name).to_json | |
43 | + else | |
44 | + render :text => (_('%s could not be disable') % organization.name).to_json | |
45 | + end | |
46 | + end | |
47 | + | |
48 | + def destroy | |
49 | + if request.post? | |
50 | + organization = environment.organizations.find(params[:id]) | |
51 | + if organization && organization.destroy | |
52 | + render :text => (_('%s removed') % organization.name).to_json | |
53 | + else | |
54 | + render :text => (_('%s could not be removed') % organization.name).to_json | |
55 | + end | |
56 | + else | |
57 | + render :nothing => true | |
58 | + end | |
59 | + end | |
60 | + | |
61 | + private | |
62 | + | |
63 | + def per_page | |
64 | + 10 | |
65 | + end | |
66 | +end | ... | ... |
app/controllers/my_profile/cms_controller.rb
... | ... | @@ -112,6 +112,11 @@ class CmsController < MyProfileController |
112 | 112 | end |
113 | 113 | end |
114 | 114 | end |
115 | + | |
116 | + unless @article.kind_of?(RssFeed) | |
117 | + @escaped_body = CGI::escapeHTML(@article.body || '') | |
118 | + @escaped_abstract = CGI::escapeHTML(@article.abstract || '') | |
119 | + end | |
115 | 120 | end |
116 | 121 | |
117 | 122 | def new |
... | ... | @@ -144,7 +149,13 @@ class CmsController < MyProfileController |
144 | 149 | article_data = environment.enabled?('articles_dont_accept_comments_by_default') ? { :accept_comments => false } : {} |
145 | 150 | article_data.merge!(params[:article]) if params[:article] |
146 | 151 | article_data.merge!(:profile => profile) if profile |
147 | - @article = klass.new(article_data) | |
152 | + | |
153 | + @article = if params[:clone] | |
154 | + current_article = profile.articles.find(params[:id]) | |
155 | + current_article.copy_without_save | |
156 | + else | |
157 | + klass.new(article_data) | |
158 | + end | |
148 | 159 | |
149 | 160 | parent = check_parent(params[:parent_id]) |
150 | 161 | if parent | ... | ... |
app/controllers/my_profile/friends_controller.rb
1 | 1 | class FriendsController < MyProfileController |
2 | - | |
2 | + | |
3 | 3 | protect 'manage_friends', :profile |
4 | - | |
4 | + | |
5 | 5 | def index |
6 | - @suggestions = profile.profile_suggestions.of_person.enabled.includes(:suggestion).limit(per_page) | |
6 | + @suggestions = profile.suggested_profiles.of_person.enabled.includes(:suggestion).limit(per_page) | |
7 | 7 | if is_cache_expired?(profile.manage_friends_cache_key(params)) |
8 | 8 | @friends = profile.friends.paginate(:per_page => per_page, :page => params[:npage]) |
9 | 9 | end |
... | ... | @@ -18,7 +18,7 @@ class FriendsController < MyProfileController |
18 | 18 | end |
19 | 19 | |
20 | 20 | def suggest |
21 | - @suggestions = profile.profile_suggestions.of_person.enabled.includes(:suggestion).limit(per_page) | |
21 | + @suggestions = profile.suggested_profiles.of_person.enabled.includes(:suggestion).limit(per_page) | |
22 | 22 | end |
23 | 23 | |
24 | 24 | def remove_suggestion |
... | ... | @@ -26,13 +26,13 @@ class FriendsController < MyProfileController |
26 | 26 | redirect_to :action => 'suggest' unless @person |
27 | 27 | if @person && request.post? |
28 | 28 | profile.remove_suggestion(@person) |
29 | - @suggestions = profile.profile_suggestions.of_person.enabled.includes(:suggestion).limit(per_page) | |
29 | + @suggestions = profile.suggested_profiles.of_person.enabled.includes(:suggestion).limit(per_page) | |
30 | 30 | render :partial => 'shared/profile_suggestions_list', :locals => { :suggestions => @suggestions, :collection => :friends_suggestions, :per_page => params[:per_page] || per_page } |
31 | 31 | end |
32 | 32 | end |
33 | 33 | |
34 | 34 | def connections |
35 | - @suggestion = profile.profile_suggestions.of_person.enabled.find_by_suggestion_id(params[:id]) | |
35 | + @suggestion = profile.suggested_profiles.of_person.enabled.find_by_suggestion_id(params[:id]) | |
36 | 36 | if @suggestion |
37 | 37 | @tags = @suggestion.tag_connections |
38 | 38 | @profiles = @suggestion.profile_connections | ... | ... |
app/controllers/my_profile/memberships_controller.rb
... | ... | @@ -40,7 +40,7 @@ class MembershipsController < MyProfileController |
40 | 40 | end |
41 | 41 | |
42 | 42 | def suggest |
43 | - @suggestions = profile.profile_suggestions.of_community.enabled.includes(:suggestion).limit(per_page) | |
43 | + @suggestions = profile.suggested_profiles.of_community.enabled.includes(:suggestion).limit(per_page) | |
44 | 44 | end |
45 | 45 | |
46 | 46 | def remove_suggestion |
... | ... | @@ -49,13 +49,13 @@ class MembershipsController < MyProfileController |
49 | 49 | redirect_to :action => 'suggest' unless @community |
50 | 50 | if @community && request.post? |
51 | 51 | profile.remove_suggestion(@community) |
52 | - @suggestions = profile.profile_suggestions.of_community.enabled.includes(:suggestion).limit(custom_per_page) | |
52 | + @suggestions = profile.suggested_profiles.of_community.enabled.includes(:suggestion).limit(custom_per_page) | |
53 | 53 | render :partial => 'shared/profile_suggestions_list', :locals => { :suggestions => @suggestions, :collection => :communities_suggestions, :per_page => custom_per_page} |
54 | 54 | end |
55 | 55 | end |
56 | 56 | |
57 | 57 | def connections |
58 | - @suggestion = profile.profile_suggestions.of_community.enabled.find_by_suggestion_id(params[:id]) | |
58 | + @suggestion = profile.suggested_profiles.of_community.enabled.find_by_suggestion_id(params[:id]) | |
59 | 59 | if @suggestion |
60 | 60 | @tags = @suggestion.tag_connections |
61 | 61 | @profiles = @suggestion.profile_connections | ... | ... |
app/controllers/my_profile/tasks_controller.rb
1 | 1 | class TasksController < MyProfileController |
2 | 2 | |
3 | - protect 'perform_task', :profile | |
4 | - | |
3 | + protect [:perform_task, :view_tasks], :profile, :only => [:index] | |
4 | + protect :perform_task, :profile, :except => [:index] | |
5 | + | |
5 | 6 | def index |
6 | - @filter = params[:filter_type].blank? ? nil : params[:filter_type] | |
7 | + @filter_type = params[:filter_type].presence | |
8 | + @filter_text = params[:filter_text].presence | |
9 | + @filter_responsible = params[:filter_responsible] | |
7 | 10 | @task_types = Task.pending_types_for(profile) |
8 | - @tasks = Task.to(profile).without_spam.pending.of(@filter).order_by('created_at', 'asc').paginate(:per_page => Task.per_page, :page => params[:page]) | |
11 | + | |
12 | + @tasks = Task.pending_all(profile, @filter_type, @filter_text).order_by('created_at', 'asc') | |
13 | + @tasks = @tasks.where(:responsible_id => @filter_responsible.to_i != -1 ? @filter_responsible : nil) if @filter_responsible.present? | |
14 | + @tasks = @tasks.paginate(:per_page => Task.per_page, :page => params[:page]) | |
15 | + | |
9 | 16 | @failed = params ? params[:failed] : {} |
17 | + | |
18 | + @responsible_candidates = profile.members.by_role(profile.roles.reject {|r| !r.has_permission?('perform_task')}) if profile.organization? | |
19 | + | |
20 | + @view_only = !current_person.has_permission?(:perform_task, profile) | |
10 | 21 | end |
11 | 22 | |
12 | 23 | def processed |
13 | 24 | @tasks = Task.to(profile).without_spam.closed.sort_by(&:created_at) |
14 | 25 | end |
15 | 26 | |
27 | + def change_responsible | |
28 | + task = profile.tasks.find(params[:task_id]) | |
29 | + | |
30 | + if task.responsible.present? && task.responsible.id != params[:old_responsible_id].to_i | |
31 | + return render :json => {:notice => _('Task already assigned!'), :success => false, :current_responsible => task.responsible.id} | |
32 | + end | |
33 | + | |
34 | + responsible = profile.members.find(params[:responsible_id]) if params[:responsible_id].present? | |
35 | + task.responsible = responsible | |
36 | + task.save! | |
37 | + render :json => {:notice => _('Task responsible successfully updated!'), :success => true, :new_responsible => {:id => responsible.present? ? responsible.id : nil}} | |
38 | + end | |
39 | + | |
16 | 40 | VALID_DECISIONS = [ 'finish', 'cancel', 'skip' ] |
17 | 41 | |
18 | 42 | def close |
... | ... | @@ -25,7 +49,7 @@ class TasksController < MyProfileController |
25 | 49 | task = profile.find_in_all_tasks(id) |
26 | 50 | begin |
27 | 51 | task.update_attributes(value[:task]) |
28 | - task.send(decision) | |
52 | + task.send(decision, current_person) | |
29 | 53 | rescue Exception => ex |
30 | 54 | message = "#{task.title} (#{task.requestor ? task.requestor.name : task.author_name})" |
31 | 55 | failed[ex.message] ? failed[ex.message] << message : failed[ex.message] = [message] | ... | ... |
app/controllers/public/chat_controller.rb
... | ... | @@ -2,6 +2,7 @@ class ChatController < PublicController |
2 | 2 | |
3 | 3 | before_filter :login_required |
4 | 4 | before_filter :check_environment_feature |
5 | + before_filter :can_send_message, :only => :register_message | |
5 | 6 | |
6 | 7 | def start_session |
7 | 8 | login = user.jid |
... | ... | @@ -54,6 +55,16 @@ class ChatController < PublicController |
54 | 55 | end |
55 | 56 | end |
56 | 57 | |
58 | + def avatars | |
59 | + profiles = environment.profiles.where(:identifier => params[:profiles]) | |
60 | + avatar_map = profiles.inject({}) do |result, profile| | |
61 | + result[profile.identifier] = profile_icon(profile, :minor) | |
62 | + result | |
63 | + end | |
64 | + | |
65 | + render_json avatar_map | |
66 | + end | |
67 | + | |
57 | 68 | def update_presence_status |
58 | 69 | if request.xhr? |
59 | 70 | current_user.update_attributes({:chat_status_at => DateTime.now}.merge(params[:status] || {})) |
... | ... | @@ -62,11 +73,17 @@ class ChatController < PublicController |
62 | 73 | end |
63 | 74 | |
64 | 75 | def save_message |
65 | - to = environment.profiles.find_by_identifier(params[:to]) | |
66 | - body = params[:body] | |
67 | - | |
68 | - ChatMessage.create!(:to => to, :from => user, :body => body) | |
69 | - render :text => 'ok' | |
76 | + if request.post? | |
77 | + to = environment.profiles.where(:identifier => params[:to]).first | |
78 | + body = params[:body] | |
79 | + | |
80 | + begin | |
81 | + ChatMessage.create!(:to => to, :from => user, :body => body) | |
82 | + return render_json({:status => 0}) | |
83 | + rescue Exception => exception | |
84 | + return render_json({:status => 3, :message => exception.to_s, :backtrace => exception.backtrace}) | |
85 | + end | |
86 | + end | |
70 | 87 | end |
71 | 88 | |
72 | 89 | def recent_messages |
... | ... | @@ -90,8 +107,9 @@ class ChatController < PublicController |
90 | 107 | end |
91 | 108 | |
92 | 109 | def recent_conversations |
93 | - conversations_order = ActiveRecord::Base.connection.execute("select profiles.identifier from profiles inner join (select distinct r.id as id, MAX(r.created_at) as created_at from (select from_id, to_id, created_at, (case when from_id=#{user.id} then to_id else from_id end) as id from chat_messages where from_id=#{user.id} or to_id=#{user.id}) as r group by id order by created_at desc, id) as t on profiles.id=t.id order by t.created_at desc").entries.map {|e| e['identifier']} | |
94 | - render :json => {:order => conversations_order.reverse, :domain => environment.default_hostname.gsub('.','-')}.to_json | |
110 | + profiles = Profile.find_by_sql("select profiles.* from profiles inner join (select distinct r.id as id, MAX(r.created_at) as created_at from (select from_id, to_id, created_at, (case when from_id=#{user.id} then to_id else from_id end) as id from chat_messages where from_id=#{user.id} or to_id=#{user.id}) as r group by id order by created_at desc, id) as t on profiles.id=t.id order by t.created_at desc") | |
111 | + jids = profiles.map(&:jid).reverse | |
112 | + render :json => jids.to_json | |
95 | 113 | end |
96 | 114 | |
97 | 115 | #TODO Ideally this is done through roster table on ejabberd. |
... | ... | @@ -108,4 +126,14 @@ class ChatController < PublicController |
108 | 126 | end |
109 | 127 | end |
110 | 128 | |
129 | + def can_send_message | |
130 | + return render_json({:status => 1, :message => 'Missing parameters!'}) if params[:from].nil? || params[:to].nil? || params[:message].nil? | |
131 | + return render_json({:status => 2, :message => 'You can not send message as another user!'}) if params[:from] != user.jid | |
132 | + # TODO Maybe register the jid in a table someday to avoid this below | |
133 | + return render_json({:status => 3, :messsage => 'You can not send messages to strangers!'}) if user.friends.where(:identifier => params[:to].split('@').first).blank? | |
134 | + end | |
135 | + | |
136 | + def render_json(result) | |
137 | + render :text => result.to_json | |
138 | + end | |
111 | 139 | end | ... | ... |
app/controllers/public/content_viewer_controller.rb
... | ... | @@ -11,6 +11,7 @@ class ContentViewerController < ApplicationController |
11 | 11 | path = get_path(params[:page], params[:format]) |
12 | 12 | |
13 | 13 | @version = params[:version].to_i |
14 | + @npage = params[:npage] || '1' | |
14 | 15 | |
15 | 16 | if path.blank? |
16 | 17 | @page = profile.home_page |
... | ... | @@ -127,7 +128,7 @@ class ContentViewerController < ApplicationController |
127 | 128 | end |
128 | 129 | |
129 | 130 | unless @page.display_to?(user) |
130 | - if !profile.visible? || profile.secret? || (user && user.follows?(profile)) | |
131 | + if !profile.visible? || profile.secret? || (user && user.follows?(profile)) || user.blank? | |
131 | 132 | render_access_denied |
132 | 133 | else #!profile.public? |
133 | 134 | private_profile_partial_parameters | ... | ... |
app/helpers/application_helper.rb
... | ... | @@ -871,7 +871,7 @@ module ApplicationHelper |
871 | 871 | field_html += capture(&block) |
872 | 872 | end |
873 | 873 | |
874 | - if controller.action_name == 'signup' || controller.action_name == 'new_community' || (controller.controller_name == "enterprise_registration" && controller.action_name == 'index') | |
874 | + if controller.action_name == 'signup' || controller.action_name == 'new_community' || (controller.controller_name == "enterprise_registration" && controller.action_name == 'index') || (controller.controller_name == 'home' && controller.action_name == 'index' && user.nil?) | |
875 | 875 | if profile.signup_fields.include?(name) |
876 | 876 | result = field_html |
877 | 877 | end |
... | ... | @@ -931,6 +931,19 @@ module ApplicationHelper |
931 | 931 | article_helper.cms_label_for_edit |
932 | 932 | end |
933 | 933 | |
934 | + def label_for_clone_article(article) | |
935 | + translated_types = { | |
936 | + Folder => _('Folder'), | |
937 | + Blog => _('Blog'), | |
938 | + Event => _('Event'), | |
939 | + Forum => _('Forum') | |
940 | + } | |
941 | + | |
942 | + translated_type = translated_types[article.class] || _('Article') | |
943 | + | |
944 | + _('Clone %s') % translated_type | |
945 | + end | |
946 | + | |
934 | 947 | def add_rss_feed_to_head(title, url) |
935 | 948 | content_for :feeds do |
936 | 949 | tag(:link, :rel => 'alternate', :type => 'application/rss+xml', :title => title, :href => url_for(url)) |
... | ... | @@ -1202,35 +1215,6 @@ module ApplicationHelper |
1202 | 1215 | list.sort.inject(Hash.new(0)){|h,i| h[i] += 1; h }.collect{ |x, n| [n, connector, x].join(" ") }.sort |
1203 | 1216 | end |
1204 | 1217 | |
1205 | - #FIXME Use time_ago_in_words instead of this method if you're using Rails 2.2+ | |
1206 | - def time_ago_as_sentence(from_time, include_seconds = false) | |
1207 | - to_time = Time.now | |
1208 | - from_time = Time.parse(from_time.to_s) | |
1209 | - from_time = from_time.to_time if from_time.respond_to?(:to_time) | |
1210 | - to_time = to_time.to_time if to_time.respond_to?(:to_time) | |
1211 | - distance_in_minutes = (((to_time - from_time).abs)/60).round | |
1212 | - distance_in_seconds = ((to_time - from_time).abs).round | |
1213 | - case distance_in_minutes | |
1214 | - when 0..1 | |
1215 | - return (distance_in_minutes == 0) ? _('less than a minute') : _('1 minute') unless include_seconds | |
1216 | - case distance_in_seconds | |
1217 | - when 0..4 then _('less than 5 seconds') | |
1218 | - when 5..9 then _('less than 10 seconds') | |
1219 | - when 10..19 then _('less than 20 seconds') | |
1220 | - when 20..39 then _('half a minute') | |
1221 | - when 40..59 then _('less than a minute') | |
1222 | - else _('1 minute') | |
1223 | - end | |
1224 | - | |
1225 | - when 2..44 then _('%{distance} minutes ago') % { :distance => distance_in_minutes } | |
1226 | - when 45..89 then _('about 1 hour ago') | |
1227 | - when 90..1439 then _('about %{distance} hours ago') % { :distance => (distance_in_minutes.to_f / 60.0).round } | |
1228 | - when 1440..2879 then _('1 day ago') | |
1229 | - when 2880..10079 then _('%{distance} days ago') % { :distance => (distance_in_minutes / 1440).round } | |
1230 | - else show_time(from_time) | |
1231 | - end | |
1232 | - end | |
1233 | - | |
1234 | 1218 | def comment_balloon(options = {}, &block) |
1235 | 1219 | wrapper = content_tag(:div, capture(&block), :class => 'comment-balloon-content') |
1236 | 1220 | (1..8).to_a.reverse.each { |i| wrapper = content_tag(:div, wrapper, :class => "comment-wrapper-#{i}") } |
... | ... | @@ -1498,4 +1482,26 @@ module ApplicationHelper |
1498 | 1482 | text_field(object_name, method, options.merge(:class => 'colorpicker_field')) |
1499 | 1483 | end |
1500 | 1484 | |
1485 | + def fullscreen_buttons(itemId) | |
1486 | + content=" | |
1487 | + <script>fullscreenPageLoad('#{itemId}')</script> | |
1488 | + " | |
1489 | + content+=content_tag('a', content_tag('span',_("Full screen")), | |
1490 | + { :id=>"fullscreen-btn", | |
1491 | + :onClick=>"toggle_fullwidth('#{itemId}')", | |
1492 | + :class=>"button with-text icon-fullscreen", | |
1493 | + :href=>"#", | |
1494 | + :title=>_("Go to full screen mode") | |
1495 | + }) | |
1496 | + | |
1497 | + content+=content_tag('a', content_tag('span',_("Exit full screen")), | |
1498 | + { :style=>"display: none;", | |
1499 | + :id=>"exit-fullscreen-btn", | |
1500 | + :onClick=>"toggle_fullwidth('#{itemId}')", | |
1501 | + :class=>"button with-text icon-fullscreen", | |
1502 | + :href=>"#", | |
1503 | + :title=>_("Exit full screen mode") | |
1504 | + }) | |
1505 | + end | |
1506 | + | |
1501 | 1507 | end | ... | ... |
app/helpers/article_helper.rb
... | ... | @@ -12,6 +12,7 @@ module ArticleHelper |
12 | 12 | @article = article |
13 | 13 | |
14 | 14 | visibility_options(@article, tokenized_children) + |
15 | + topic_creation(@article) + | |
15 | 16 | content_tag('h4', _('Options')) + |
16 | 17 | content_tag('div', |
17 | 18 | (article.profile.has_members? ? |
... | ... | @@ -55,14 +56,7 @@ module ArticleHelper |
55 | 56 | 'div', |
56 | 57 | check_box(:article, :display_versions) + |
57 | 58 | content_tag('label', _('I want this article to display a link to older versions'), :for => 'article_display_versions') |
58 | - ) : '') + | |
59 | - | |
60 | - (article.forum? && article.profile.community? ? | |
61 | - content_tag( | |
62 | - 'div', | |
63 | - check_box(:article, :allows_members_to_create_topics) + | |
64 | - content_tag('label', _('Allow members to create topics'), :for => 'article_allows_members_to_create_topics') | |
65 | - ) : '') | |
59 | + ) : '') | |
66 | 60 | ) |
67 | 61 | end |
68 | 62 | |
... | ... | @@ -81,6 +75,22 @@ module ArticleHelper |
81 | 75 | ) |
82 | 76 | end |
83 | 77 | |
78 | + def topic_creation(article) | |
79 | + return '' unless article.forum? | |
80 | + | |
81 | + general_options = Forum::TopicCreation.general_options(article) | |
82 | + slider_options = {:id => 'topic-creation-slider'} | |
83 | + slider_options = general_options.keys.inject(slider_options) do |result, option| | |
84 | + result.merge!({'data-'+option => general_options[option]}) | |
85 | + end | |
86 | + | |
87 | + content_tag('h4', _('Topic creation')) + | |
88 | + content_tag( 'small', _('Who will be able to create new topics on this forum?')) + | |
89 | + content_tag('div', '', slider_options) + | |
90 | + hidden_field_tag('article[topic_creation]', article.topic_creation) + | |
91 | + javascript_include_tag('topic-creation-config') | |
92 | + end | |
93 | + | |
84 | 94 | def privacity_exceptions(article, tokenized_children) |
85 | 95 | content_tag('div', |
86 | 96 | content_tag('div', | ... | ... |
app/helpers/blog_helper.rb
... | ... | @@ -22,7 +22,9 @@ module BlogHelper |
22 | 22 | :param_name => 'npage', |
23 | 23 | :previous_label => _('« Newer posts'), |
24 | 24 | :next_label => _('Older posts »'), |
25 | - :params => {:action=>"view_page", :page=>articles.first.parent.path.split('/'), :controller=>"content_viewer"} | |
25 | + :params => {:action=>"view_page", | |
26 | + :page=>articles.first.parent.path.split('/'), | |
27 | + :controller=>"content_viewer"} | |
26 | 28 | }) if articles.present? && conf[:paginate] |
27 | 29 | content = [] |
28 | 30 | artic_len = articles.length |
... | ... | @@ -44,7 +46,7 @@ module BlogHelper |
44 | 46 | end |
45 | 47 | |
46 | 48 | def display_post(article, format = 'full') |
47 | - no_comments = (format == 'full') ? false : true | |
49 | + no_comments = (format == 'full' || format == 'compact' ) ? false : true | |
48 | 50 | title = article_title(article, :no_comments => no_comments) |
49 | 51 | method = "display_#{format.split('+')[0]}_format" |
50 | 52 | html = send(method, FilePresenter.for(article)).html_safe |
... | ... | @@ -55,8 +57,12 @@ module BlogHelper |
55 | 57 | else |
56 | 58 | '<div class="post-pic" style="background-image:url('+img+')"></div>' |
57 | 59 | end |
58 | - end.to_s + | |
59 | - title + html | |
60 | + end.to_s + title + html | |
61 | + end | |
62 | + | |
63 | + def display_compact_format(article) | |
64 | + render :file => 'content_viewer/_display_compact_format', | |
65 | + :locals => { :article => article, :format => "compact" } | |
60 | 66 | end |
61 | 67 | |
62 | 68 | def display_full_format(article) | ... | ... |
app/helpers/boxes_helper.rb
... | ... | @@ -122,7 +122,7 @@ module BoxesHelper |
122 | 122 | end |
123 | 123 | |
124 | 124 | def wrap_main_content(content) |
125 | - (1..8).to_a.reverse.inject(content) { |acc,n| content_tag('div', acc, :id => 'main-content-wrapper-' + n.to_s) } | |
125 | + content_tag('div', content, :class => 'main-content') | |
126 | 126 | end |
127 | 127 | |
128 | 128 | def extract_block_content(content) | ... | ... |
app/helpers/chat_helper.rb
... | ... | @@ -9,12 +9,12 @@ module ChatHelper |
9 | 9 | avatar = profile_image(user, :portrait, :class => 'avatar') |
10 | 10 | content_tag('span', |
11 | 11 | link_to(avatar + content_tag('span', user.name) + ui_icon('ui-icon-triangle-1-s'), |
12 | - '#', | |
12 | + '', | |
13 | 13 | :onclick => 'toggleMenu(this); return false', |
14 | 14 | :class => icon_class + ' simplemenu-trigger' |
15 | 15 | ) + |
16 | 16 | content_tag('ul', |
17 | - links.map{|link| content_tag('li', link_to(link[1], '#', :class => link[0], :id => link[2], 'data-jid' => user.jid), :class => 'simplemenu-item') }.join("\n"), | |
17 | + links.map{|link| content_tag('li', link_to(link[1], '', :class => link[0], :id => link[2], 'data-jid' => user.jid), :class => 'simplemenu-item') }.join("\n"), | |
18 | 18 | :style => 'display: none; z-index: 100', |
19 | 19 | :class => 'simplemenu-submenu' |
20 | 20 | ), | ... | ... |
app/helpers/comment_helper.rb
app/helpers/content_viewer_helper.rb
... | ... | @@ -2,6 +2,7 @@ module ContentViewerHelper |
2 | 2 | |
3 | 3 | include BlogHelper |
4 | 4 | include ForumHelper |
5 | + include DatesHelper | |
5 | 6 | |
6 | 7 | def display_number_of_comments(n) |
7 | 8 | base_str = "<span class='comment-count hide'>#{n}</span>" |
... | ... | @@ -24,8 +25,9 @@ module ContentViewerHelper |
24 | 25 | unless args[:no_comments] || !article.accept_comments |
25 | 26 | comments = (" - %s") % link_to_comments(article) |
26 | 27 | end |
28 | + date_format = show_with_right_format_date article | |
27 | 29 | title << content_tag('span', |
28 | - content_tag('span', show_date(article.published_at), :class => 'date') + | |
30 | + date_format + | |
29 | 31 | content_tag('span', _(", by %s") % (article.author ? link_to(article.author_name, article.author_url) : article.author_name), :class => 'author') + |
30 | 32 | content_tag('span', comments, :class => 'comments'), |
31 | 33 | :class => 'created-at' |
... | ... | @@ -34,6 +36,24 @@ module ContentViewerHelper |
34 | 36 | title |
35 | 37 | end |
36 | 38 | |
39 | + def show_with_right_format_date article | |
40 | + date_format = article.environment.date_format | |
41 | + use_numbers = false | |
42 | + year = true | |
43 | + left_time = false | |
44 | + if date_format == 'numbers_with_year' | |
45 | + use_numbers = true | |
46 | + elsif date_format == 'numbers' | |
47 | + use_numbers = true | |
48 | + year = false | |
49 | + elsif date_format == 'month_name' | |
50 | + year = false | |
51 | + elsif date_format == 'past_time' | |
52 | + left_time = true | |
53 | + end | |
54 | + content_tag('span', show_date(article.published_at, use_numbers , year, left_time), :class => 'date') | |
55 | + end | |
56 | + | |
37 | 57 | def link_to_comments(article, args = {}) |
38 | 58 | return '' unless article.accept_comments? |
39 | 59 | reference_to_article number_of_comments(article), article, 'comments_list' | ... | ... |
app/helpers/dates_helper.rb
... | ... | @@ -2,6 +2,7 @@ require 'noosfero/i18n' |
2 | 2 | |
3 | 3 | module DatesHelper |
4 | 4 | |
5 | + include ActionView::Helpers::DateHelper | |
5 | 6 | def months |
6 | 7 | I18n.t('date.month_names') |
7 | 8 | end |
... | ... | @@ -15,10 +16,12 @@ module DatesHelper |
15 | 16 | end |
16 | 17 | |
17 | 18 | # formats a date for displaying. |
18 | - def show_date(date, use_numbers = false, year=true) | |
19 | + def show_date(date, use_numbers = false, year = true, left_time = false) | |
19 | 20 | if date && use_numbers |
20 | 21 | date_format = year ? _('%{month}/%{day}/%{year}') : _('%{month}/%{day}') |
21 | 22 | date_format % { :day => date.day, :month => date.month, :year => date.year } |
23 | + elsif date && left_time | |
24 | + date_format = time_ago_in_words(date) | |
22 | 25 | elsif date |
23 | 26 | date_format = year ? _('%{month_name} %{day}, %{year}') : _('%{month_name} %{day}') |
24 | 27 | date_format % { :day => date.day, :month_name => month_name(date.month), :year => date.year } | ... | ... |
app/helpers/events_helper.rb
app/helpers/folder_helper.rb
... | ... | @@ -25,49 +25,32 @@ module FolderHelper |
25 | 25 | articles.select {|article| article.display_to?(user)} |
26 | 26 | end |
27 | 27 | |
28 | - def display_content_in_listing(configure={}) | |
29 | - recursive = configure[:recursive] || false | |
30 | - list_type = configure[:list_type] || :folder | |
31 | - level = configure[:level] || 0 | |
32 | - content = FilePresenter.for configure[:content] | |
28 | + def display_content_icon(content_item) | |
29 | + content = FilePresenter.for content_item | |
33 | 30 | content_link = if content.image? |
34 | - link_to(' ' * (level * 4) + | |
35 | - image_tag(icon_for_article(content)) + short_filename(content.name), | |
31 | + link_to( | |
32 | + image_tag(icon_for_article(content, :bigicon)), | |
36 | 33 | content.url.merge(:view => true) |
37 | 34 | ) |
38 | 35 | else |
39 | - link_to(' ' * (level * 4) + | |
40 | - short_filename(content.name), | |
41 | - content.url.merge(:view => true), :class => icon_for_article(content) | |
36 | + link_to('', | |
37 | + content.url.merge(:view => true), | |
38 | + :class => icon_for_article(content, :bigicon) | |
42 | 39 | ) |
43 | 40 | end |
44 | - result = content_tag( | |
45 | - 'tr', | |
46 | - content_tag('td', content_link ) + | |
47 | - content_tag('td', show_date(content.updated_at), :class => 'last-update'), | |
48 | - :class => "#{list_type}-item" | |
49 | - ) | |
50 | - if recursive | |
51 | - result + content.children.map {|item| | |
52 | - display_content_in_listing :content=>item, :recursive=>recursive, | |
53 | - :list_type=>list_type, :level=>level+1 | |
54 | - }.join("\n") | |
55 | - else | |
56 | - result | |
57 | - end | |
58 | 41 | end |
59 | 42 | |
60 | - def icon_for_article(article) | |
43 | + def icon_for_article(article, size = 'icon') | |
61 | 44 | article = FilePresenter.for article |
62 | - icon = article.respond_to?(:icon_name) ? | |
63 | - article.icon_name : | |
64 | - article.class.icon_name(article) | |
65 | - if (icon =~ /\//) | |
66 | - icon | |
45 | + if article.respond_to?(:sized_icon) | |
46 | + article.sized_icon(size) | |
67 | 47 | else |
68 | - klasses = 'icon ' + [icon].flatten.map{|name| 'icon-'+name}.join(' ') | |
48 | + icon = article.respond_to?(:icon_name) ? | |
49 | + article.icon_name : | |
50 | + article.class.icon_name(article) | |
51 | + klasses = "#{size} " + [icon].flatten.map{|name| "#{size}-"+name}.join(' ') | |
69 | 52 | if article.kind_of?(UploadedFile) || article.kind_of?(FilePresenter) |
70 | - klasses += ' icon-upload-file' | |
53 | + klasses += " #{size}-upload-file" | |
71 | 54 | end |
72 | 55 | klasses |
73 | 56 | end | ... | ... |
app/helpers/forum_helper.rb
1 | 1 | module ForumHelper |
2 | + include ActionView::Helpers::DateHelper | |
2 | 3 | |
3 | 4 | def cms_label_for_new_children |
4 | 5 | _('New discussion topic') |
... | ... | @@ -42,9 +43,9 @@ module ForumHelper |
42 | 43 | def last_topic_update(article) |
43 | 44 | info = article.info_from_last_update |
44 | 45 | if info[:author_url] |
45 | - time_ago_as_sentence(info[:date]) + ' ' + _('by') + ' ' + link_to(info[:author_name], info[:author_url]) | |
46 | + time_ago_in_words(info[:date]) + ' ' + _('by') + ' ' + link_to(info[:author_name], info[:author_url]) | |
46 | 47 | else |
47 | - time_ago_as_sentence(info[:date]) + ' ' + _('by') + ' ' + info[:author_name] | |
48 | + time_ago_in_words(info[:date]) + ' ' + _('by') + ' ' + info[:author_name] | |
48 | 49 | end |
49 | 50 | end |
50 | 51 | ... | ... |
app/helpers/profile_editor_helper.rb
... | ... | @@ -141,8 +141,9 @@ module ProfileEditorHelper |
141 | 141 | ) |
142 | 142 | end |
143 | 143 | |
144 | - def control_panel_button(title, icon, url) | |
145 | - link_to title, url, :class => 'control-panel-%s' % icon | |
144 | + def control_panel_button(title, icon, url, html_options = {}) | |
145 | + html_options ||= {} | |
146 | + link_to title, url, html_options.merge(:class => 'control-panel-%s' % icon) | |
146 | 147 | end |
147 | 148 | |
148 | 149 | def unchangeable_privacy_field(profile) | ... | ... |
app/helpers/search_helper.rb
... | ... | @@ -106,6 +106,10 @@ module SearchHelper |
106 | 106 | end |
107 | 107 | end |
108 | 108 | |
109 | + def city_with_state_for_profile(p) | |
110 | + city_with_state(p.region) || [p.city, p.state].compact.reject(&:blank?).join(', ') | |
111 | + end | |
112 | + | |
109 | 113 | def display_selector(asset, display, float = 'right') |
110 | 114 | display = nil if display.blank? |
111 | 115 | display ||= asset_class(asset).default_search_display | ... | ... |
app/helpers/tinymce_helper.rb
... | ... | @@ -20,7 +20,7 @@ module TinymceHelper |
20 | 20 | :image_advtab => true, |
21 | 21 | :language => tinymce_language |
22 | 22 | |
23 | - options[:toolbar1] = "insertfile undo redo | copy paste | bold italic underline | styleselect fontsizeselect | forecolor backcolor | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link image" | |
23 | + options[:toolbar1] = "fullscreen | insertfile undo redo | copy paste | bold italic underline | styleselect fontsizeselect | forecolor backcolor | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link image" | |
24 | 24 | if options[:mode] == 'simple' |
25 | 25 | options[:menubar] = false |
26 | 26 | else | ... | ... |
app/helpers/users_helper.rb
... | ... | @@ -14,7 +14,7 @@ module UsersHelper |
14 | 14 | select_field = select_tag(:filter, options, :onchange => onchange) |
15 | 15 | content_tag('div', |
16 | 16 | content_tag('strong', _('Filter')) + ': ' + select_field, |
17 | - :class => "environment-users-customize-search" | |
17 | + :class => "environment-profiles-customize-search" | |
18 | 18 | ) |
19 | 19 | end |
20 | 20 | ... | ... |
app/models/add_friend.rb
... | ... | @@ -54,7 +54,7 @@ class AddFriend < Task |
54 | 54 | end |
55 | 55 | |
56 | 56 | def remove_from_suggestion_list(task) |
57 | - suggestion = task.requestor.profile_suggestions.find_by_suggestion_id task.target.id | |
57 | + suggestion = task.requestor.suggested_profiles.find_by_suggestion_id task.target.id | |
58 | 58 | suggestion.disable if suggestion |
59 | 59 | end |
60 | 60 | end | ... | ... |
app/models/article.rb
... | ... | @@ -28,7 +28,7 @@ class Article < ActiveRecord::Base |
28 | 28 | def initialize(*params) |
29 | 29 | super |
30 | 30 | |
31 | - if !params.blank? && params.first.has_key?(:profile) | |
31 | + if !params.blank? && params.first.has_key?(:profile) && !params.first[:profile].blank? | |
32 | 32 | profile = params.first[:profile] |
33 | 33 | self.published = false unless profile.public? |
34 | 34 | end |
... | ... | @@ -96,6 +96,8 @@ class Article < ActiveRecord::Base |
96 | 96 | belongs_to :translation_of, :class_name => 'Article', :foreign_key => :translation_of_id |
97 | 97 | before_destroy :rotate_translations |
98 | 98 | |
99 | + acts_as_voteable | |
100 | + | |
99 | 101 | before_create do |article| |
100 | 102 | article.published_at ||= Time.now |
101 | 103 | if article.reference_article && !article.parent |
... | ... | @@ -498,13 +500,13 @@ class Article < ActiveRecord::Base |
498 | 500 | |
499 | 501 | scope :display_filter, lambda {|user, profile| |
500 | 502 | return published if (user.nil? && profile && profile.public?) |
501 | - return [] if user.nil? || profile.nil? || (profile && !profile.public? && !user.follows?(profile)) | |
503 | + return [] if user.nil? || (profile && !profile.public? && !user.follows?(profile)) | |
502 | 504 | where( |
503 | 505 | [ |
504 | 506 | "published = ? OR last_changed_by_id = ? OR profile_id = ? OR ? |
505 | 507 | OR (show_to_followers = ? AND ? AND profile_id = ?)", true, user.id, user.id, |
506 | 508 | profile.nil? ? false : user.has_permission?(:view_private_content, profile), |
507 | - true, user.follows?(profile), profile.id | |
509 | + true, user.follows?(profile), (profile.nil? ? nil : profile.id) | |
508 | 510 | ] |
509 | 511 | ) |
510 | 512 | } |
... | ... | @@ -577,25 +579,24 @@ class Article < ActiveRecord::Base |
577 | 579 | profile.visible? && profile.public? && published? |
578 | 580 | end |
579 | 581 | |
580 | - | |
581 | - def copy(options = {}) | |
582 | + def copy_without_save(options = {}) | |
582 | 583 | attrs = attributes.reject! { |key, value| ATTRIBUTES_NOT_COPIED.include?(key.to_sym) } |
583 | 584 | attrs.merge!(options) |
584 | 585 | object = self.class.new |
585 | 586 | attrs.each do |key, value| |
586 | 587 | object.send(key.to_s+'=', value) |
587 | 588 | end |
589 | + object | |
590 | + end | |
591 | + | |
592 | + def copy(options = {}) | |
593 | + object = copy_without_save(options) | |
588 | 594 | object.save |
589 | 595 | object |
590 | 596 | end |
591 | 597 | |
592 | 598 | def copy!(options = {}) |
593 | - attrs = attributes.reject! { |key, value| ATTRIBUTES_NOT_COPIED.include?(key.to_sym) } | |
594 | - attrs.merge!(options) | |
595 | - object = self.class.new | |
596 | - attrs.each do |key, value| | |
597 | - object.send(key.to_s+'=', value) | |
598 | - end | |
599 | + object = copy_without_save(options) | |
599 | 600 | object.save! |
600 | 601 | object |
601 | 602 | end | ... | ... |
app/models/block.rb
... | ... | @@ -2,7 +2,7 @@ class Block < ActiveRecord::Base |
2 | 2 | |
3 | 3 | attr_accessible :title, :display, :limit, :box_id, :posts_per_page, |
4 | 4 | :visualization_format, :language, :display_user, |
5 | - :box, :edit_modes, :move_modes | |
5 | + :box, :edit_modes, :move_modes, :mirror | |
6 | 6 | |
7 | 7 | # to be able to generate HTML |
8 | 8 | include ActionView::Helpers::UrlHelper |
... | ... | @@ -15,11 +15,23 @@ class Block < ActiveRecord::Base |
15 | 15 | |
16 | 16 | acts_as_list :scope => :box |
17 | 17 | belongs_to :box |
18 | + belongs_to :mirror_block, :class_name => "Block" | |
19 | + has_many :observers, :class_name => "Block", :foreign_key => "mirror_block_id" | |
18 | 20 | |
19 | 21 | acts_as_having_settings |
20 | 22 | |
21 | 23 | scope :enabled, :conditions => { :enabled => true } |
22 | 24 | |
25 | + after_save do |block| | |
26 | + if block.owner.kind_of?(Profile) && block.owner.is_template? && block.mirror? | |
27 | + block.observers.each do |observer| | |
28 | + observer.copy_from(block) | |
29 | + observer.title = block.title | |
30 | + observer.save | |
31 | + end | |
32 | + end | |
33 | + end | |
34 | + | |
23 | 35 | def embedable? |
24 | 36 | false |
25 | 37 | end |
... | ... | @@ -269,6 +281,10 @@ class Block < ActiveRecord::Base |
269 | 281 | self.position = block.position |
270 | 282 | end |
271 | 283 | |
284 | + def add_observer(block) | |
285 | + self.observers << block | |
286 | + end | |
287 | + | |
272 | 288 | private |
273 | 289 | |
274 | 290 | def home_page_path | ... | ... |
app/models/blog.rb
... | ... | @@ -76,9 +76,12 @@ class Blog < Folder |
76 | 76 | end |
77 | 77 | |
78 | 78 | settings_items :visualization_format, :type => :string, :default => 'full' |
79 | - validates_inclusion_of :visualization_format, :in => [ 'full', 'short', 'short+pic' ], :if => :visualization_format | |
79 | + validates_inclusion_of :visualization_format, | |
80 | + :in => [ 'full', 'short', 'short+pic', 'compact'], | |
81 | + :if => :visualization_format | |
80 | 82 | |
81 | - settings_items :display_posts_in_current_language, :type => :boolean, :default => false | |
83 | + settings_items :display_posts_in_current_language, | |
84 | + :type => :boolean, :default => false | |
82 | 85 | |
83 | 86 | alias :display_posts_in_current_language? :display_posts_in_current_language |
84 | 87 | ... | ... |
app/models/chat_message.rb
app/models/comment.rb
app/models/environment.rb
... | ... | @@ -3,7 +3,17 @@ |
3 | 3 | # domains. |
4 | 4 | class Environment < ActiveRecord::Base |
5 | 5 | |
6 | - attr_accessible :name, :is_default, :signup_welcome_text_subject, :signup_welcome_text_body, :terms_of_use, :message_for_disabled_enterprise, :news_amount_by_folder, :default_language, :languages, :description, :organization_approval_method, :enabled_plugins, :enabled_features, :redirection_after_login, :redirection_after_signup, :contact_email, :theme, :reports_lower_bound, :noreply_email, :signup_welcome_screen_body, :members_whitelist_enabled, :members_whitelist, :highlighted_news_amount, :portal_news_amount | |
6 | + attr_accessible :name, :is_default, :signup_welcome_text_subject, | |
7 | + :signup_welcome_text_body, :terms_of_use, | |
8 | + :message_for_disabled_enterprise, :news_amount_by_folder, | |
9 | + :default_language, :languages, :description, | |
10 | + :organization_approval_method, :enabled_plugins, | |
11 | + :enabled_features, :redirection_after_login, | |
12 | + :redirection_after_signup, :contact_email, :theme, | |
13 | + :reports_lower_bound, :noreply_email, | |
14 | + :signup_welcome_screen_body, :members_whitelist_enabled, | |
15 | + :members_whitelist, :highlighted_news_amount, | |
16 | + :portal_news_amount, :date_format | |
7 | 17 | |
8 | 18 | has_many :users |
9 | 19 | |
... | ... | @@ -14,6 +24,12 @@ class Environment < ActiveRecord::Base |
14 | 24 | |
15 | 25 | IDENTIFY_SCRIPTS = /(php[0-9s]?|[sp]htm[l]?|pl|py|cgi|rb)/ |
16 | 26 | |
27 | + validates_inclusion_of :date_format, | |
28 | + :in => [ 'numbers_with_year', 'numbers', | |
29 | + 'month_name_with_year', 'month_name', | |
30 | + 'past_time'], | |
31 | + :if => :date_format | |
32 | + | |
17 | 33 | def self.verify_filename(filename) |
18 | 34 | filename += '.txt' if File.extname(filename) =~ IDENTIFY_SCRIPTS |
19 | 35 | filename |
... | ... | @@ -29,6 +45,7 @@ class Environment < ActiveRecord::Base |
29 | 45 | 'manage_environment_roles' => N_('Manage environment roles'), |
30 | 46 | 'manage_environment_validators' => N_('Manage environment validators'), |
31 | 47 | 'manage_environment_users' => N_('Manage environment users'), |
48 | + 'manage_environment_organizations' => N_('Manage environment organizations'), | |
32 | 49 | 'manage_environment_templates' => N_('Manage environment templates'), |
33 | 50 | 'manage_environment_licenses' => N_('Manage environment licenses'), |
34 | 51 | 'manage_environment_trusted_sites' => N_('Manage environment trusted sites'), |
... | ... | @@ -74,7 +91,8 @@ class Environment < ActiveRecord::Base |
74 | 91 | 'edit_profile_design', |
75 | 92 | 'manage_products', |
76 | 93 | 'manage_friends', |
77 | - 'perform_task' | |
94 | + 'perform_task', | |
95 | + 'view_tasks' | |
78 | 96 | ] |
79 | 97 | ) |
80 | 98 | end |
... | ... | @@ -339,6 +357,16 @@ class Environment < ActiveRecord::Base |
339 | 357 | self.save! |
340 | 358 | end |
341 | 359 | |
360 | + def enable_all_plugins | |
361 | + Noosfero::Plugin.available_plugin_names.each do |plugin| | |
362 | + plugin_name = plugin.to_s + "Plugin" | |
363 | + unless self.enabled_plugins.include?(plugin_name) | |
364 | + self.enabled_plugins += [plugin_name] | |
365 | + end | |
366 | + end | |
367 | + self.save! | |
368 | + end | |
369 | + | |
342 | 370 | # Disables a feature identified by its name |
343 | 371 | def disable(feature, must_save=true) |
344 | 372 | self.settings["#{feature}_enabled".to_sym] = false | ... | ... |
app/models/forum.rb
... | ... | @@ -3,11 +3,11 @@ class Forum < Folder |
3 | 3 | acts_as_having_posts :order => 'updated_at DESC' |
4 | 4 | include PostsLimit |
5 | 5 | |
6 | - attr_accessible :has_terms_of_use, :terms_of_use, :allows_members_to_create_topics | |
6 | + attr_accessible :has_terms_of_use, :terms_of_use, :topic_creation | |
7 | 7 | |
8 | 8 | settings_items :terms_of_use, :type => :string, :default => "" |
9 | 9 | settings_items :has_terms_of_use, :type => :boolean, :default => false |
10 | - settings_items :allows_members_to_create_topics, :type => :boolean, :default => false | |
10 | + settings_items :topic_creation, :type => :string, :default => 'self' | |
11 | 11 | has_and_belongs_to_many :users_with_agreement, :class_name => 'Person', :join_table => 'terms_forum_people' |
12 | 12 | |
13 | 13 | before_save do |forum| |
... | ... | @@ -33,6 +33,23 @@ class Forum < Folder |
33 | 33 | _('An internet forum, also called message board, where discussions can be held.') |
34 | 34 | end |
35 | 35 | |
36 | + module TopicCreation | |
37 | + BASE = ActiveSupport::OrderedHash.new | |
38 | + BASE['users'] = _('Logged users') | |
39 | + | |
40 | + PERSON = ActiveSupport::OrderedHash.new | |
41 | + PERSON['self'] = _('Me') | |
42 | + PERSON['related'] = _('Friends') | |
43 | + | |
44 | + GROUP = ActiveSupport::OrderedHash.new | |
45 | + GROUP['self'] = _('Administrators') | |
46 | + GROUP['related'] = _('Members') | |
47 | + | |
48 | + def self.general_options(forum) | |
49 | + forum.profile.person? ? PERSON.merge(BASE) : GROUP.merge(BASE) | |
50 | + end | |
51 | + end | |
52 | + | |
36 | 53 | include ActionView::Helpers::TagHelper |
37 | 54 | def to_html(options = {}) |
38 | 55 | proc do |
... | ... | @@ -69,11 +86,17 @@ class Forum < Folder |
69 | 86 | self.users_with_agreement.exists? user |
70 | 87 | end |
71 | 88 | |
72 | - def can_create_topic?(user, profile) | |
73 | - return profile.community? && profile.members.include?(user) && self.allows_members_to_create_topics | |
89 | + def can_create_topic?(user) | |
90 | + return true if user == profile || profile.admins.include?(user) || profile.environment.admins.include?(user) | |
91 | + case topic_creation | |
92 | + when 'related' | |
93 | + profile.person? ? profile.friends.include?(user) : profile.members.include?(user) | |
94 | + when 'users' | |
95 | + user.present? | |
96 | + end | |
74 | 97 | end |
75 | 98 | |
76 | 99 | def allow_create?(user) |
77 | - super || can_create_topic?(user, profile) | |
100 | + super || can_create_topic?(user) | |
78 | 101 | end |
79 | 102 | end | ... | ... |
app/models/person.rb
... | ... | @@ -84,9 +84,9 @@ roles] } |
84 | 84 | has_and_belongs_to_many :acepted_forums, :class_name => 'Forum', :join_table => 'terms_forum_people' |
85 | 85 | has_and_belongs_to_many :articles_with_access, :class_name => 'Article', :join_table => 'article_privacy_exceptions' |
86 | 86 | |
87 | - has_many :profile_suggestions, :foreign_key => :person_id, :order => 'score DESC', :dependent => :destroy | |
88 | - has_many :suggested_people, :through => :profile_suggestions, :source => :suggestion, :conditions => ['profile_suggestions.suggestion_type = ? AND profile_suggestions.enabled = ?', 'Person', true] | |
89 | - has_many :suggested_communities, :through => :profile_suggestions, :source => :suggestion, :conditions => ['profile_suggestions.suggestion_type = ? AND profile_suggestions.enabled = ?', 'Community', true] | |
87 | + has_many :suggested_profiles, :class_name => 'ProfileSuggestion', :foreign_key => :person_id, :order => 'score DESC', :dependent => :destroy | |
88 | + has_many :suggested_people, :through => :suggested_profiles, :source => :suggestion, :conditions => ['profile_suggestions.suggestion_type = ? AND profile_suggestions.enabled = ?', 'Person', true] | |
89 | + has_many :suggested_communities, :through => :suggested_profiles, :source => :suggestion, :conditions => ['profile_suggestions.suggestion_type = ? AND profile_suggestions.enabled = ?', 'Community', true] | |
90 | 90 | |
91 | 91 | scope :more_popular, :order => 'friends_count DESC' |
92 | 92 | |
... | ... | @@ -103,6 +103,8 @@ roles] } |
103 | 103 | |
104 | 104 | belongs_to :user, :dependent => :delete |
105 | 105 | |
106 | + acts_as_voter | |
107 | + | |
106 | 108 | def can_change_homepage? |
107 | 109 | !environment.enabled?('cant_change_homepage') || is_admin? |
108 | 110 | end |
... | ... | @@ -522,7 +524,7 @@ roles] } |
522 | 524 | end |
523 | 525 | |
524 | 526 | def remove_suggestion(profile) |
525 | - suggestion = profile_suggestions.find_by_suggestion_id profile.id | |
527 | + suggestion = suggested_profiles.find_by_suggestion_id profile.id | |
526 | 528 | suggestion.disable if suggestion |
527 | 529 | end |
528 | 530 | ... | ... |
app/models/product_category.rb
... | ... | @@ -10,6 +10,9 @@ class ProductCategory < Category |
10 | 10 | :joins => :products, |
11 | 11 | :conditions => ['products.profile_id = ?', enterprise.id] |
12 | 12 | }} |
13 | + scope :by_environment, lambda { |environment| { | |
14 | + :conditions => ['environment_id = ?', environment.id] | |
15 | + }} | |
13 | 16 | scope :unique_by_level, lambda { |level| { |
14 | 17 | :select => "DISTINCT ON (filtered_category) split_part(path, '/', #{level}) AS filtered_category, categories.*" |
15 | 18 | }} | ... | ... |
app/models/profile.rb
... | ... | @@ -71,6 +71,7 @@ class Profile < ActiveRecord::Base |
71 | 71 | 'manage_friends' => N_('Manage friends'), |
72 | 72 | 'validate_enterprise' => N_('Validate enterprise'), |
73 | 73 | 'perform_task' => N_('Perform task'), |
74 | + 'view_tasks' => N_('View tasks'), | |
74 | 75 | 'moderate_comments' => N_('Moderate comments'), |
75 | 76 | 'edit_appearance' => N_('Edit appearance'), |
76 | 77 | 'view_private_content' => N_('View private content'), |
... | ... | @@ -392,6 +393,9 @@ class Profile < ActiveRecord::Base |
392 | 393 | new_block = block.class.new(:title => block[:title]) |
393 | 394 | new_block.copy_from(block) |
394 | 395 | new_box.blocks << new_block |
396 | + if block.mirror? | |
397 | + block.add_observer(new_block) | |
398 | + end | |
395 | 399 | end |
396 | 400 | end |
397 | 401 | end |
... | ... | @@ -1021,7 +1025,7 @@ private :generate_url, :url_options |
1021 | 1025 | end |
1022 | 1026 | |
1023 | 1027 | def remove_from_suggestion_list(person) |
1024 | - suggestion = person.profile_suggestions.find_by_suggestion_id self.id | |
1028 | + suggestion = person.suggested_profiles.find_by_suggestion_id self.id | |
1025 | 1029 | suggestion.disable if suggestion |
1026 | 1030 | end |
1027 | 1031 | ... | ... |
app/models/profile_suggestion.rb
... | ... | @@ -113,14 +113,14 @@ class ProfileSuggestion < ActiveRecord::Base |
113 | 113 | suggested_profiles = all_suggestions(person) |
114 | 114 | return if suggested_profiles.nil? |
115 | 115 | |
116 | - already_suggested_profiles = person.profile_suggestions.map(&:suggestion_id).join(',') | |
116 | + already_suggested_profiles = person.suggested_profiles.map(&:suggestion_id).join(',') | |
117 | 117 | suggested_profiles = suggested_profiles.where("profiles.id NOT IN (#{already_suggested_profiles})") if already_suggested_profiles.present? |
118 | 118 | #TODO suggested_profiles = suggested_profiles.order('score DESC') |
119 | 119 | suggested_profiles = suggested_profiles.limit(N_SUGGESTIONS) |
120 | 120 | return if suggested_profiles.blank? |
121 | 121 | |
122 | 122 | suggested_profiles.each do |suggested_profile| |
123 | - suggestion = person.profile_suggestions.find_or_initialize_by_suggestion_id(suggested_profile.id) | |
123 | + suggestion = person.suggested_profiles.find_or_initialize_by_suggestion_id(suggested_profile.id) | |
124 | 124 | RULES.each do |rule, options| |
125 | 125 | begin |
126 | 126 | value = suggested_profile.send("#{rule}_count").to_i |
... | ... | @@ -273,7 +273,7 @@ class ProfileSuggestion < ActiveRecord::Base |
273 | 273 | end |
274 | 274 | |
275 | 275 | def self.generate_profile_suggestions(person, force = false) |
276 | - return if person.profile_suggestions.enabled.count >= MIN_LIMIT && !force | |
276 | + return if person.suggested_profiles.enabled.count >= MIN_LIMIT && !force | |
277 | 277 | Delayed::Job.enqueue ProfileSuggestionsJob.new(person.id) unless ProfileSuggestionsJob.exists?(person.id) |
278 | 278 | end |
279 | 279 | ... | ... |
app/models/suggest_article.rb
... | ... | @@ -25,7 +25,7 @@ class SuggestArticle < Task |
25 | 25 | |
26 | 26 | def article_object |
27 | 27 | if @article_object.nil? |
28 | - @article_object = article_type.new(article.merge({:profile => target}).except(:type)) | |
28 | + @article_object = article_type.new(article.merge(target.present? ? {:profile => target} : {}).except(:type)) | |
29 | 29 | if requestor.present? |
30 | 30 | @article_object.author = requestor |
31 | 31 | else | ... | ... |
app/models/task.rb
... | ... | @@ -33,6 +33,8 @@ class Task < ActiveRecord::Base |
33 | 33 | |
34 | 34 | belongs_to :requestor, :class_name => 'Profile', :foreign_key => :requestor_id |
35 | 35 | belongs_to :target, :foreign_key => :target_id, :polymorphic => true |
36 | + belongs_to :responsible, :class_name => 'Person', :foreign_key => :responsible_id | |
37 | + belongs_to :closed_by, :class_name => 'Person', :foreign_key => :closed_by_id | |
36 | 38 | |
37 | 39 | validates_uniqueness_of :code, :on => :create |
38 | 40 | validates_presence_of :code |
... | ... | @@ -76,11 +78,9 @@ class Task < ActiveRecord::Base |
76 | 78 | # this method finished the task. It calls #perform, which must be overriden |
77 | 79 | # by subclasses. At the end a message (as returned by #finish_message) is |
78 | 80 | # sent to the requestor with #notify_requestor. |
79 | - def finish | |
81 | + def finish(closed_by=nil) | |
80 | 82 | transaction do |
81 | - self.status = Task::Status::FINISHED | |
82 | - self.end_date = Time.now | |
83 | - self.save! | |
83 | + close(Task::Status::FINISHED, closed_by) | |
84 | 84 | self.perform |
85 | 85 | begin |
86 | 86 | send_notification(:finished) |
... | ... | @@ -105,11 +105,9 @@ class Task < ActiveRecord::Base |
105 | 105 | |
106 | 106 | # this method cancels the task. At the end a message (as returned by |
107 | 107 | # #cancel_message) is sent to the requestor with #notify_requestor. |
108 | - def cancel | |
108 | + def cancel(closed_by=nil) | |
109 | 109 | transaction do |
110 | - self.status = Task::Status::CANCELLED | |
111 | - self.end_date = Time.now | |
112 | - self.save! | |
110 | + close(Task::Status::CANCELLED, closed_by) | |
113 | 111 | begin |
114 | 112 | send_notification(:cancelled) |
115 | 113 | rescue NotImplementedError => ex |
... | ... | @@ -118,6 +116,13 @@ class Task < ActiveRecord::Base |
118 | 116 | end |
119 | 117 | end |
120 | 118 | |
119 | + def close(status, closed_by) | |
120 | + self.status = status | |
121 | + self.end_date = Time.now | |
122 | + self.closed_by = closed_by | |
123 | + self.save! | |
124 | + end | |
125 | + | |
121 | 126 | # Here are the tasks customizable options. |
122 | 127 | |
123 | 128 | def title |
... | ... | @@ -239,6 +244,10 @@ class Task < ActiveRecord::Base |
239 | 244 | scope :opened, :conditions => { :status => [Task::Status::ACTIVE, Task::Status::HIDDEN] } |
240 | 245 | scope :of, lambda { |type| conditions = type ? "type LIKE '#{type}'" : "1=1"; {:conditions => [conditions]} } |
241 | 246 | scope :order_by, lambda { |attribute, ord| {:order => "#{attribute} #{ord}"} } |
247 | + scope :like, lambda { |field, value| where("LOWER(#{field}) LIKE ?", "%#{value.downcase}%") if value} | |
248 | + scope :pending_all, lambda { |profile, filter_type, filter_text| | |
249 | + self.to(profile).without_spam.pending.of(filter_type).like('data', filter_text) | |
250 | + } | |
242 | 251 | |
243 | 252 | scope :to, lambda { |profile| |
244 | 253 | environment_condition = nil | ... | ... |
app/models/uploaded_file.rb
... | ... | @@ -65,7 +65,7 @@ class UploadedFile < Article |
65 | 65 | # :min_size => 2.megabytes |
66 | 66 | # :max_size => 5.megabytes |
67 | 67 | has_attachment :storage => :file_system, |
68 | - :thumbnails => { :icon => [24,24], :thumb => '130x130>', :slideshow => '320x240>', :display => '640X480>' }, | |
68 | + :thumbnails => { :icon => [24,24], :bigicon => [50,50], :thumb => '130x130>', :slideshow => '320x240>', :display => '640X480>' }, | |
69 | 69 | :thumbnail_class => Thumbnail, |
70 | 70 | :max_size => self.max_size |
71 | 71 | ... | ... |
app/presenters/image.rb
app/views/admin_panel/_site_info.html.erb
... | ... | @@ -3,6 +3,21 @@ |
3 | 3 | <%= labelled_form_field(_('No reply email'), text_field(:environment, :noreply_email)) %> |
4 | 4 | <% themes_options = Theme.system_themes.map {|theme| [theme.name, theme.id] }.sort %> |
5 | 5 | <%= labelled_form_field(_('Theme'), select(:environment, :theme, options_for_select(themes_options, environment.theme))) %> |
6 | + | |
7 | +<%= labelled_form_field( | |
8 | + _("Article's date format"), | |
9 | + select(:environment, :date_format, | |
10 | + options_for_select([ | |
11 | + [ _('mm/dd/yyyy'), 'numbers_with_year'], | |
12 | + [ _('mm/dd'), 'numbers'], | |
13 | + [ _('Month dd, yyyy'), 'month_name_with_year'], | |
14 | + [ _('Month dd'), 'month_name'], | |
15 | + [ _('X minutes/hours/days/months/years ago'), 'past_time'] | |
16 | + ], environment.date_format | |
17 | + ) | |
18 | + ) | |
19 | +) %> | |
20 | + | |
6 | 21 | <%= required f.text_field(:reports_lower_bound, :size => 3) %> |
7 | 22 | <%= labelled_form_field(_('Default language'), select(:environment, :default_language, environment.locales.invert, { :selected => environment.default_locale, :include_blank => true })) %> |
8 | 23 | <%= label_tag :languages, _('Available languages') %> | ... | ... |
app/views/admin_panel/index.html.erb
... | ... | @@ -18,9 +18,9 @@ |
18 | 18 | <table> |
19 | 19 | <tr><td><%= link_to _('User roles'), :controller => 'role' %></td></tr> |
20 | 20 | <tr><td><%= link_to _('Users'), :controller => 'users' %></td></tr> |
21 | + <tr><td><%= link_to _('Organizations'), :controller => 'organizations' %></td></tr> | |
21 | 22 | <tr><td><%= link_to _('Profile templates'), :controller => 'templates' %></td></tr> |
22 | 23 | <tr><td><%= link_to _('Fields'), :controller => 'features', :action => 'manage_fields' %></td></tr> |
23 | - <tr><td><%= link_to _('Manage organizations status'), :action => 'manage_organizations_status' %></td></tr> | |
24 | 24 | </table> |
25 | 25 | |
26 | 26 | ... | ... |
app/views/admin_panel/manage_organizations_status.html.erb
... | ... | @@ -1,69 +0,0 @@ |
1 | -<h1><%= _('Manage organizations') %></h1> | |
2 | - | |
3 | -<%= form_tag( { :action => 'manage_organizations_status' }, :method => 'get', :class => 'users-search' ) do %> | |
4 | - | |
5 | - <div class="search-field"> | |
6 | - <span class="formfield"> | |
7 | - <%= text_field_tag 'q', @q, :title => _("Find profiles"), :style=>"width:85%" %> | |
8 | - </span> | |
9 | - | |
10 | - <%= submit_button(:search, _('Search')) %> | |
11 | - </div> | |
12 | - | |
13 | - <div class="environment-users-results-header"> | |
14 | - <div id='environment-users-filter-title'><%= @title %></div> | |
15 | - | |
16 | - <div id="environment-users-filter-filter"> | |
17 | - <strong><%= _("Filter by: ") %></strong> | |
18 | - | |
19 | - <select id="profile_filter_select"> | |
20 | - <%= options_for_select([['Any', 'any'],["Disabled profiles", "disabled"], ["Enabled profiles", "enabled"]], @filter) %> | |
21 | - </select> | |
22 | - </div> | |
23 | - <div style="clear: both"></div> | |
24 | - </div> | |
25 | - | |
26 | - <table> | |
27 | - <colgroup> | |
28 | - <col width="80%"> | |
29 | - <col width="20%"> | |
30 | - </colgroup> | |
31 | - | |
32 | - <tr> | |
33 | - <th><%= _('Member') %></th> | |
34 | - <th><%= _('Actions') %></th> | |
35 | - </tr> | |
36 | - | |
37 | - <% @collection.each do |p| %> | |
38 | - <tr title="<%= p.name %>"> | |
39 | - <td><%= link_to_profile p.short_name, p.identifier, :title => p.name %> </td> | |
40 | - | |
41 | - <td class='actions'> | |
42 | - <div class="members-buttons-cell"> | |
43 | - <% if p.visible %> | |
44 | - <%= button_without_text :'deactivate-user', _('Deactivate'), {:controller => "profile_editor", :action => 'deactivate_profile', :profile => p.identifier, :id => p.id}, :confirm => _("Do you want to deactivate this profile ?") %> | |
45 | - <% else %> | |
46 | - <%= button_without_text :'activate-user', _('Activate'), {:controller => "profile_editor", :action => 'activate_profile', :profile => p.identifier, :id => p.id}, :confirm => _("Do you want to activate this profile ?") %> | |
47 | - <% end %> | |
48 | - <%= button_without_text :'delete', _('Remove'), {:controller => "profile_editor", :action => 'destroy_profile', :profile => p.identifier, :id => p.id, :return_to => "/admin/admin_panel/manage_organizations_status"}, :method => :post, :confirm => _("Do you want to deactivate this profile ?") %> | |
49 | - </div> | |
50 | - </td> | |
51 | - </tr> | |
52 | - <% end %> | |
53 | - </table> | |
54 | - | |
55 | -<% end %> | |
56 | - | |
57 | -<%= pagination_links @collection, {:param_name => 'npage', :page_links => true} %> | |
58 | - | |
59 | -<% button_bar do %> | |
60 | - <%= button :back, _('Back'), :controller => 'admin_panel' %> | |
61 | -<% end %> | |
62 | - | |
63 | -<script type="text/javascript"> | |
64 | - jQuery(document).ready(function(){ | |
65 | - jQuery("#profile_filter_select").change(function(){ | |
66 | - document.location.href = '/admin/admin_panel/manage_organizations_status?filter='+this.value; | |
67 | - }); | |
68 | - }); | |
69 | -</script> | |
70 | 0 | \ No newline at end of file |
app/views/blocks/profile_info_actions/_community.html.erb
app/views/blocks/profile_info_actions/_enterprise.html.erb
... | ... | @@ -8,5 +8,5 @@ |
8 | 8 | <li><%= button(:'menu-mail', _('Send an e-mail'), {:profile => profile.identifier, :controller => 'contact', :action => 'new'}, {:id => 'enterprise-contact-button'} ) %></li> |
9 | 9 | <% end %> |
10 | 10 | |
11 | - <li><%= report_abuse(profile, :button) %></li> | |
11 | + <%= render :partial => 'blocks/profile_info_actions/common' %> | |
12 | 12 | </ul> | ... | ... |
app/views/blocks/profile_info_actions/_person.html.erb
... | ... | @@ -11,6 +11,6 @@ |
11 | 11 | <li><%= button(:back, _('Send an e-mail'), {:profile => profile.identifier, :controller => 'contact', :action => 'new'}) %></li> |
12 | 12 | <% end %> |
13 | 13 | |
14 | - <li><%= report_abuse(profile, :button) %></li> | |
14 | + <%= render :partial => 'blocks/profile_info_actions/common' %> | |
15 | 15 | <% end %> |
16 | 16 | </ul> | ... | ... |
app/views/box_organizer/edit.html.erb
... | ... | @@ -28,6 +28,12 @@ |
28 | 28 | </div> |
29 | 29 | <% end %> |
30 | 30 | |
31 | + <% if @block.owner.kind_of?(Profile) && @block.owner.is_template? %> | |
32 | + <div class="mirror_block"> | |
33 | + <%= labelled_check_box(_("Mirror"), "block[mirror]", value = "1", checked = @block.mirror) %> | |
34 | + </div> | |
35 | + <% end %> | |
36 | + | |
31 | 37 | <% button_bar do %> |
32 | 38 | <%= submit_button(:save, _('Save')) %> |
33 | 39 | <%= modal_close_button(_('Cancel')) %> | ... | ... |
app/views/chat/start_session_error.html.erb
1 | 1 | <p> |
2 | 2 | <%= ui_icon('ui-icon-alert') %> |
3 | -<%= _('Could not connect to chat') %>, <a id='chat-retry' href='#' data-jid='<%= user.jid %>'><%= _('try again') %></a>. | |
3 | +<%= _('Could not connect to chat') %>, <a id='chat-retry' href='' data-jid='<%= user.jid %>'><%= _('try again') %></a>. | |
4 | 4 | </p> | ... | ... |
app/views/cms/_blog.html.erb
... | ... | @@ -67,7 +67,8 @@ |
67 | 67 | <%= labelled_form_field(_('How to display posts:'), f.select(:visualization_format, [ |
68 | 68 | [ _('Full post'), 'full'], |
69 | 69 | [ _('First paragraph'), 'short'], |
70 | - [ _('First paragraph, with post picture'), 'short+pic'] | |
70 | + [ _('First paragraph, with post picture'), 'short+pic'], | |
71 | + [ _("Title, Image, Lead"), 'compact'] | |
71 | 72 | ])) %> |
72 | 73 | |
73 | 74 | <%= labelled_form_field(_('Posts per page:'), f.select(:posts_per_page, Blog.posts_per_page_options)) %> | ... | ... |
app/views/cms/_forum.html.erb
app/views/content_viewer/_article_toolbar.html.erb
1 | 1 | <div<%= user && " class='logged-in'" %>> |
2 | 2 | <div id="article-actions"> |
3 | 3 | |
4 | + <%= fullscreen_buttons('#article') %> | |
4 | 5 | |
5 | 6 | <% if @page.allow_edit?(user) && !remove_content_button(:edit, @page) %> |
6 | 7 | <% content = content_tag('span', label_for_edit_article(@page)) %> |
... | ... | @@ -29,6 +30,10 @@ |
29 | 30 | <% end %> |
30 | 31 | |
31 | 32 | <%= modal_button(:new, label_for_new_article(@page), profile.admin_url.merge(:controller => 'cms', :action => 'new', :parent_id => (@page.folder? ? @page : (@page.parent.nil? ? nil : @page.parent)))) unless remove_content_button(:new, @page) %> |
33 | + | |
34 | + <% content = content_tag('span', label_for_clone_article(@page)) %> | |
35 | + <% url = profile.admin_url.merge({ :controller => 'cms', :action => 'new', :id => @page.id, :clone => true, :type => @page.class }) %> | |
36 | + <%= expirable_button @page, :clone, content, url %> | |
32 | 37 | <% end %> |
33 | 38 | |
34 | 39 | <% if @page.accept_uploads? && @page.allow_create?(user) %> |
... | ... | @@ -57,7 +62,7 @@ |
57 | 62 | <% if @page.blog? and !@page.image.nil? %> |
58 | 63 | <div class="blog-cover"><%= image_tag(@page.image.public_filename())%></div> |
59 | 64 | <% end %> |
60 | - <%= link_to(image_tag('icons-mime/rss-feed.png'), @page.feed.url, :class => 'blog-feed-link') if @page.has_posts? && @page.feed %> | |
65 | + <%= link_to(image_tag('/images/icons-mime/rss-feed.png'), @page.feed.url, :class => 'blog-feed-link') if @page.has_posts? && @page.feed %> | |
61 | 66 | <%= @plugins.dispatch(:article_header_extra_contents, @page).collect { |content| instance_exec(&content) }.join("") %> |
62 | 67 | <%= article_title(@page, :no_link => true) %> |
63 | 68 | <%= article_translations(@page) %> | ... | ... |
app/views/content_viewer/_display_compact_format.html.erb
0 → 100644
... | ... | @@ -0,0 +1,21 @@ |
1 | +<% if article.image %> | |
2 | + <% className = "article-compact-abstract-with-image" %> | |
3 | + <% if article.image.thumbnails_processed? %> | |
4 | + <% image_file = article.image.public_filename(:big) %> | |
5 | + <% else %> | |
6 | + <% image_file = "/images/icons-app/image-loading-thumb.png" %> | |
7 | + <% end %> | |
8 | +<% else %> | |
9 | + <% className = "article-compact-abstract" %> | |
10 | +<% end %> | |
11 | + | |
12 | +<div> | |
13 | + <% if article.image %> | |
14 | + <div class = "article-compact-image"> | |
15 | + <%= image_tag(image_file) %> | |
16 | + </div> | |
17 | + <% end %> | |
18 | + <div class = <%= className %> > | |
19 | + <%= article.abstract.truncate(400) %> | |
20 | + </div> | |
21 | +</div> | ... | ... |
app/views/content_viewer/blog_page.html.erb
app/views/content_viewer/folder.html.erb
... | ... | @@ -0,0 +1,41 @@ |
1 | +<div class='results'> | |
2 | + <table id='organizations-list'> | |
3 | + <colgroup> | |
4 | + <col width="60%"> | |
5 | + <col width="20%"> | |
6 | + <col width="20%"> | |
7 | + </colgroup> | |
8 | + | |
9 | + <tr> | |
10 | + <th><%= _('Profile') %></th> | |
11 | + <th><%= _('Actions') %></th> | |
12 | + <th><%= _('Type') %> | |
13 | + | |
14 | + <%= select_tag(:type, options_for_select(@types_filter, @type)) %> | |
15 | + </th> | |
16 | + </tr> | |
17 | + | |
18 | + <% @collection.each do |p| %> | |
19 | + <tr title="<%= p.name %>"> | |
20 | + <td><%= link_to_profile p.short_name, p.identifier, :title => p.name %> </td> | |
21 | + | |
22 | + <td class='actions'> | |
23 | + <div class="members-buttons-cell"> | |
24 | + <% if p.visible %> | |
25 | + <%= button_without_text :'deactivate-user', _('Deactivate'), {:action => 'deactivate', :id => p.id}, :class => 'action', 'data-confirm' => _("Do you want to deactivate this organization?") %> | |
26 | + <% else %> | |
27 | + <%= button_without_text :'activate-user', _('Activate'), {:action => 'activate', :id => p.id}, :class => 'action', 'data-confirm' => _("Do you want to activate this organization?") %> | |
28 | + <% end %> | |
29 | + <%= button_without_text :'delete', _('Remove'), {:action => 'destroy', :id => p.id}, :class => 'action', 'data-method' => :post, 'data-confirm' => _("Do you want to destroy this organization?") %> | |
30 | + </div> | |
31 | + </td> | |
32 | + | |
33 | + <td> <%= _("#{p.type}") %> </td> | |
34 | + </tr> | |
35 | + <% end %> | |
36 | + </table> | |
37 | + | |
38 | + <div> | |
39 | + <%= pagination_links @collection, {:param_name => 'npage', :page_links => true} %> | |
40 | + </div> | |
41 | +</div> | ... | ... |
... | ... | @@ -0,0 +1,30 @@ |
1 | +<h1><%= _('Organizations') %></h1> | |
2 | + | |
3 | +<%= form_tag( { :action => 'index' }, :method => 'get', :id => 'manage-profiles' ) do %> | |
4 | + | |
5 | + <div class="search-field"> | |
6 | + <span class="formfield"> | |
7 | + <%= text_field_tag 'q', @q, :title => _('Find organizations'), :style=>"width:85%" %> | |
8 | + </span> | |
9 | + | |
10 | + <%= submit_button(:search, _('Search')) %> | |
11 | + </div> | |
12 | + | |
13 | + <div class="environment-profiles-results-header"> | |
14 | + <div id='environment-profiles-filter-title'><%= @title %></div> | |
15 | + | |
16 | + <div id="environment-profiles-filter-filter"> | |
17 | + <strong><%= _("Filter by: ") %></strong> | |
18 | + <%= select_tag(:filter, options_for_select([[_('Any'), 'any'],[_('Disabled'), "disabled"], [_('Enabled') , "enabled"]], @filter)) %> | |
19 | + </div> | |
20 | + <div style="clear: both"></div> | |
21 | + </div> | |
22 | + | |
23 | + <%= render :partial => 'results' %> | |
24 | + | |
25 | + <% button_bar do %> | |
26 | + <%= button :back, _('Back'), :controller => 'admin_panel' %> | |
27 | + <% end %> | |
28 | +<% end %> | |
29 | + | |
30 | +<%= javascript_include_tag 'manage-organizations' %> | ... | ... |
app/views/person_notifier/mailer/_comment.html.erb
... | ... | @@ -19,7 +19,7 @@ |
19 | 19 | <span style="font-size: 12px;"><%= comment.title %></span><br/> |
20 | 20 | <% end %> |
21 | 21 | <span style="font-size: 10px;"><%= txt2html comment.body %></span><br/> |
22 | - <span style="font-size: 8px; color: #929292"><%= time_ago_as_sentence(comment.created_at) %></span> | |
22 | + <span style="font-size: 8px; color: #929292"><%= time_ago_in_words(comment.created_at) %></span> | |
23 | 23 | <br style="clear: both;" /> |
24 | 24 | |
25 | 25 | <% unless comment.replies.blank? %> | ... | ... |
app/views/person_notifier/mailer/_create_article.html.erb
... | ... | @@ -6,7 +6,7 @@ |
6 | 6 | <p> |
7 | 7 | <span style="font-size: 14px;"><%= link_to activity.user.short_name(20), activity.user.url %></span> |
8 | 8 | <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> |
9 | - <span style="font-size: 10px; color: #929292; float:right;"><%= time_ago_as_sentence(activity.created_at) %></span> | |
9 | + <span style="font-size: 10px; color: #929292; float:right;"><%= time_ago_in_words(activity.created_at) %></span> | |
10 | 10 | </p> |
11 | 11 | <p> |
12 | 12 | <span style="font-size: 14px;"><%= link_to(activity.params['name'], activity.params['url'], :style => "color: #333; font-weight: bold; text-decoration: none;") %></span> | ... | ... |
app/views/person_notifier/mailer/_default_activity.html.erb
... | ... | @@ -5,7 +5,7 @@ |
5 | 5 | <td> |
6 | 6 | <p> |
7 | 7 | <span style="font-size: 14px;"><%= link_to activity.user.name, activity.user.url %> <%= describe activity %></span> |
8 | - <span style="font-size: 10px; color: #929292; float: right;"><%= time_ago_as_sentence(activity.created_at) %></span> | |
8 | + <span style="font-size: 10px; color: #929292; float: right;"><%= time_ago_in_words(activity.created_at) %></span> | |
9 | 9 | </p> |
10 | 10 | </td> |
11 | 11 | </tr> | ... | ... |
app/views/person_notifier/mailer/_task.html.erb
... | ... | @@ -12,7 +12,7 @@ |
12 | 12 | <span style="font-size: 14px"> |
13 | 13 | <%= task_information(task) %> |
14 | 14 | </span> |
15 | - <span style="font-size: 10px; color: #929292; float: right;"><%= time_ago_as_sentence(task.created_at) %></span> | |
15 | + <span style="font-size: 10px; color: #929292; float: right;"><%= time_ago_in_words(task.created_at) %></span> | |
16 | 16 | </div> |
17 | 17 | </td> |
18 | 18 | </tr> | ... | ... |
app/views/person_notifier/mailer/_upload_image.html.erb
... | ... | @@ -5,7 +5,7 @@ |
5 | 5 | <td> |
6 | 6 | <p> |
7 | 7 | <span style="font-size: 14px;"><%= link_to activity.user.name, activity.user.url %> <%= describe activity %></span> |
8 | - <span style="font-size: 10px; color: #929292; float:right;"><%= time_ago_as_sentence(activity.created_at) %></span> | |
8 | + <span style="font-size: 10px; color: #929292; float:right;"><%= time_ago_in_words(activity.created_at) %></span> | |
9 | 9 | </p> |
10 | 10 | </td> |
11 | 11 | </tr> | ... | ... |
app/views/profile/_comment.html.erb
app/views/profile/_create_article.html.erb
... | ... | @@ -12,7 +12,7 @@ |
12 | 12 | <%= 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+/, '') unless activity.params['lead'].blank? %> <small><%= link_to(_('See more'), activity.params['url']) unless activity.get_lead.blank? %></small> |
13 | 13 | </div> |
14 | 14 | <%= content_tag(:p, link_to(_('See complete forum'), activity.get_url), :class => 'see-forum') if activity.target.is_a?(Forum) %> |
15 | - <p class='profile-activity-time'><%= time_ago_as_sentence(activity.created_at) %></p> | |
15 | + <p class='profile-activity-time'><%= time_ago_in_words(activity.created_at) %></p> | |
16 | 16 | <div class='profile-wall-actions'> |
17 | 17 | <%= link_to s_('profile|Comment'), '#', { :class => 'focus-on-comment'} %> |
18 | 18 | <%= link_to_function(_('Remove'), 'remove_item_wall(this, \'%s\', \'%s\', \'%s\'); return false ;' % [".profile-activity-item", url_for(:profile => params[:profile], :action => :remove_activity, :activity_id => activity.id, :only_hide => true, :view => params[:view]), _('Are you sure you want to remove this activity and all its replies?')]) if logged_in? && current_person == @profile %> | ... | ... |
app/views/profile/_default_activity.html.erb
... | ... | @@ -3,7 +3,7 @@ |
3 | 3 | </div> |
4 | 4 | <div class='profile-activity-description'> |
5 | 5 | <p class='profile-activity-text'><%= link_to activity.user.name, activity.user.url %> <%= describe activity %></p> |
6 | - <p class='profile-activity-time'><%= time_ago_as_sentence(activity.created_at) %></p> | |
6 | + <p class='profile-activity-time'><%= time_ago_in_words(activity.created_at) %></p> | |
7 | 7 | <div class='profile-wall-actions'> |
8 | 8 | <%= link_to s_('profile|Comment'), '#', { :class => 'focus-on-comment'} %> |
9 | 9 | <%= link_to_function(_('Remove'), 'remove_item_wall(this, \'%s\', \'%s\', \'%s\'); return false ;' % [".profile-activity-item", url_for(:profile => params[:profile], :action => :remove_activity, :activity_id => activity.id, :view => params[:view]), _('Are you sure you want to remove this activity and all its replies?')]) if logged_in? && current_person == @profile %> | ... | ... |
app/views/profile/_leave_scrap.html.erb
... | ... | @@ -3,7 +3,7 @@ |
3 | 3 | </div> |
4 | 4 | <div class='profile-activity-description'> |
5 | 5 | <p class='profile-activity-text'><%= link_to activity.user.name, activity.user.url %> <%= describe activity %></p> |
6 | - <p class='profile-activity-time'><%= time_ago_as_sentence(activity.created_at) %></p> | |
6 | + <p class='profile-activity-time'><%= time_ago_in_words(activity.created_at) %></p> | |
7 | 7 | <div class='profile-wall-actions'> |
8 | 8 | <%= link_to_function(_('Remove'), 'remove_item_wall(this, \'%s\', \'%s\', \'%s\'); return false ;' % [".profile-activity-item", url_for(:profile => params[:profile], :action => :remove_activity, :activity_id => activity.id, :view => params[:view]), _('Are you sure you want to remove this activity and all its replies?')]) if logged_in? && current_person == @profile %> |
9 | 9 | </div> | ... | ... |
app/views/profile/_profile_scrap.html.erb
... | ... | @@ -5,7 +5,7 @@ |
5 | 5 | <div class='profile-activity-description'> |
6 | 6 | <p class='profile-activity-sender'><%= link_to scrap.sender.name, scrap.sender.url %></p> |
7 | 7 | <p class='profile-activity-text'><%= txt2html scrap.content %></p> |
8 | - <p class='profile-activity-time'><%= time_ago_as_sentence(scrap.created_at) %></p> | |
8 | + <p class='profile-activity-time'><%= time_ago_in_words(scrap.created_at) %></p> | |
9 | 9 | <div class='profile-wall-actions'> |
10 | 10 | <% if logged_in? && current_person.follows?(scrap.sender) %> |
11 | 11 | <span class='profile-activity-send-reply'> |
... | ... | @@ -22,5 +22,5 @@ |
22 | 22 | <% end %> |
23 | 23 | </ul> |
24 | 24 | <%= render :partial => 'profile_scrap_reply_form', :locals => { :scrap => scrap } %> |
25 | - <hr /> | |
25 | + <hr /> | |
26 | 26 | </li> | ... | ... |
app/views/profile/_profile_scraps.html.erb
... | ... | @@ -5,7 +5,7 @@ |
5 | 5 | <div class='profile-activity-description'> |
6 | 6 | <p class='profile-activity-sender'><%= link_to scrap.sender.name, scrap.sender.url %></p> |
7 | 7 | <p class='profile-activity-text'><%= txt2html scrap.content %></p> |
8 | - <p class='profile-activity-time'><%= time_ago_as_sentence(scrap.created_at) %></p> | |
8 | + <p class='profile-activity-time'><%= time_ago_in_words(scrap.created_at) %></p> | |
9 | 9 | <div class='profile-wall-actions'> |
10 | 10 | <% if logged_in? && current_person.follows?(scrap.sender) %> |
11 | 11 | <span class='profile-activity-send-reply'> | ... | ... |
app/views/profile/_upload_image.html.erb
... | ... | @@ -4,7 +4,7 @@ |
4 | 4 | </div> |
5 | 5 | <div class='profile-activity-description'> |
6 | 6 | <p class='profile-activity-text'><%= link_to activity.user.name, activity.user.url %> <%= describe activity %></p> |
7 | - <p class='profile-activity-time'><%= time_ago_as_sentence(activity.created_at) %></p> | |
7 | + <p class='profile-activity-time'><%= time_ago_in_words(activity.created_at) %></p> | |
8 | 8 | <div class='profile-wall-actions'> |
9 | 9 | <%= link_to_function(_('Remove'), 'remove_item_wall(this, \'%s\', \'%s\', \'%s\'); return false ;' % [".profile-activity-item", url_for(:profile => params[:profile], :action => :remove_activity, :activity_id => activity.id, :view => params[:view]), _('Are you sure you want to remove this activity and all its replies?')]) if logged_in? && current_person == @profile %> |
10 | 10 | </div> | ... | ... |
app/views/profile/content_tagged.html.erb
... | ... | @@ -5,7 +5,7 @@ |
5 | 5 | <h1><%= _('Content tagged with "%s"') % escaped_tag %></h1> |
6 | 6 | |
7 | 7 | <p> |
8 | -<%= link_to image_tag('icons-mime/rss-feed.png', :alt => _('Feed for this tag'), :title => _('Feed for this tag')), tag_feed_path, :class => 'blog-feed-link'%> | |
8 | +<%= link_to image_tag('/images/icons-mime/rss-feed.png', :alt => _('Feed for this tag'), :title => _('Feed for this tag')), tag_feed_path, :class => 'blog-feed-link'%> | |
9 | 9 | </p> |
10 | 10 | |
11 | 11 | <% cache_timeout(@tag_cache_key, 4.hour) do %> | ... | ... |
app/views/profile_editor/index.html.erb
... | ... | @@ -73,7 +73,7 @@ |
73 | 73 | <%= control_panel_button(_('Edit welcome page'), 'welcome-page', :action => 'welcome_page') if has_welcome_page %> |
74 | 74 | |
75 | 75 | <% @plugins.dispatch(:control_panel_buttons).each do |button| %> |
76 | - <%= control_panel_button(button[:title], button[:icon], button[:url]) %> | |
76 | + <%= control_panel_button(button[:title], button[:icon], button[:url], button[:html_options]) %> | |
77 | 77 | <% end %> |
78 | 78 | |
79 | 79 | <% end %> | ... | ... |
... | ... | @@ -0,0 +1,11 @@ |
1 | +<div id="list-item"> | |
2 | + <div class="item-info"> | |
3 | + <div class="item-icon" > | |
4 | + <%= display_content_icon(content) %> | |
5 | + </div> | |
6 | + <span class="item-description"> | |
7 | + <%= link_to(short_filename_upper_ext(content.name), content.url) %> | |
8 | + </span> | |
9 | + <span class="item-date"><%= _("Published at: #{show_date(content.updated_at)}") %></span> | |
10 | + </div> | |
11 | +</div> | |
0 | 12 | \ No newline at end of file | ... | ... |
app/views/shared/_lead_and_body.html.erb
... | ... | @@ -19,17 +19,27 @@ |
19 | 19 | |
20 | 20 | <div class='article-lead' id="article-lead-<%=lead_id.to_s%>"> |
21 | 21 | |
22 | + <% abstract_options = {:style => 'width: 100%; height: 200px;', :class => editor_type} %> | |
22 | 23 | <% if f %> |
23 | - <%= labelled_form_field(_(abstract_label), f.text_area(abstract_method, :style => 'width: 100%; height: 200px;', :class => editor_type)) %> | |
24 | + <%= labelled_form_field(_(abstract_label), f.text_area(abstract_method, abstract_options)) %> | |
24 | 25 | <% else %> |
25 | - <%= labelled_form_field(_(abstract_label), text_area(object, abstract_method, :style => 'width: 100%; height: 200px;', :class => editor_type)) %> | |
26 | + <% if @article.kind_of?(Article) %> | |
27 | + <%= labelled_form_field(_(abstract_label), text_area_tag("article[abstract]", @escaped_abstract, abstract_options)) %> | |
28 | + <% else %> | |
29 | + <%= labelled_form_field(_(abstract_label), text_area(object, abstract_method, abstract_options)) %> | |
30 | + <% end %> | |
26 | 31 | <% end %> |
27 | 32 | </div> |
28 | 33 | <div style="margin-top: 10px;"> |
34 | + <% body_options = {:style => 'width: 100%; height: 400px;', :class => editor_type} %> | |
29 | 35 | <% if f %> |
30 | - <%= labelled_form_field(_(body_label), f.text_area(body_method, :style => 'width: 100%; height: 400px;', :class => editor_type)) %> | |
36 | + <%= labelled_form_field(_(body_label), f.text_area(body_method, body_options)) %> | |
31 | 37 | <% else %> |
32 | - <%= labelled_form_field(_(body_label), text_area(object, body_method, :style => 'width: 100%; height: 400px;', :class => editor_type)) %> | |
38 | + <% if @article.kind_of?(Article) %> | |
39 | + <%= labelled_form_field(_(body_label), text_area_tag("article[body]", @escaped_body, body_options)) %> | |
40 | + <% else %> | |
41 | + <%= labelled_form_field(_(body_label), text_area(object, body_method, body_options)) %> | |
42 | + <% end %> | |
33 | 43 | <% end %> |
34 | 44 | </div> |
35 | 45 | ... | ... |
... | ... | @@ -0,0 +1 @@ |
1 | +jQuery('#manage-profiles .results').replaceWith('<%= escape_javascript(render 'results') %>'); | ... | ... |
app/views/shared/content_list.html.erb
1 | -<table class="<%= list_type %>-content"> | |
2 | - <tr> | |
3 | - <th><%= _('Title') %></th> | |
4 | - <th><%= _('Last update') %></th> | |
5 | - </tr> | |
1 | +<ul class="<%= list_type %>-content"> | |
6 | 2 | <% contents.each do |content| %> |
7 | - <% if content.display_to?(user) %> | |
8 | - <%= display_content_in_listing :content=>content, :list_type=>list_type, :recursive=>recursive %> | |
9 | - <% end %> | |
3 | + <li class="<%= list_type %>-item"> | |
4 | + <% if content.display_to?(user) %> | |
5 | + <%= render :partial => 'shared/content_item', :locals => { :content => content } %> | |
6 | + <% end %> | |
7 | + </li> | |
10 | 8 | <% end %> |
11 | -</table> | |
9 | +</ul> | |
12 | 10 | |
13 | 11 | <p><%= pagination_links contents, :param_name => 'npage', :page_links => true %></p> | ... | ... |
app/views/shared/logged_in/xmpp_chat.html.erb
... | ... | @@ -7,13 +7,13 @@ |
7 | 7 | var $own_name = '<%= user.name %>'; |
8 | 8 | var $muc_domain = '<%= "conference.#{environment.default_hostname}" %>'; |
9 | 9 | var $bosh_service = '//<%= environment.default_hostname %>/http-bind'; |
10 | - var $user_unavailable_error = '<%= _("<strong>ooops!</strong> The message could not be sent because the user is not online") %>'; | |
10 | + var $user_unavailable_error = '<%= _("The user is not online now. He/She will receive these messages as soon as he/she gets online.") %>'; | |
11 | 11 | var $update_presence_status_every = <%= User.expires_chat_status_every.minutes %>; |
12 | 12 | var $presence = '<%= current_user.last_chat_status %>'; |
13 | 13 | </script> |
14 | 14 | |
15 | - | |
16 | 15 | <div id="chat-label"> |
16 | + <span id="unread-messages"></span> | |
17 | 17 | <span class="right-arrow">▶</span> |
18 | 18 | <span class="title"><%= _('Chat') %></span> |
19 | 19 | </div> |
... | ... | @@ -98,10 +98,5 @@ |
98 | 98 | </div> |
99 | 99 | </div> |
100 | 100 | </div> |
101 | - | |
102 | - <div class="error-message"> | |
103 | - <span class='error'>%{text}</span> | |
104 | - </div> | |
105 | - | |
106 | 101 | </div> |
107 | 102 | </div> | ... | ... |
... | ... | @@ -0,0 +1,8 @@ |
1 | +<% label_name = profile.person? ? _('Open chat') : _('Join chat room') %> | |
2 | +<% display = profile.person? ? profile.friends.include?(user) : profile.members.include?(user) %> | |
3 | + | |
4 | +<% if display %> | |
5 | + <li> | |
6 | + <%= button(:chat, label_name , {}, :class => 'open-conversation', 'data-jid' => profile.jid) %> | |
7 | + </li> | |
8 | +<% end %> | ... | ... |
app/views/tasks/_abuse_complaint_accept_details.html.erb
... | ... | @@ -2,7 +2,7 @@ |
2 | 2 | <% task.abuse_reports.each do |abuse_report| %> |
3 | 3 | <div> |
4 | 4 | <strong style="word-wrap: break-word; display: block; padding-right: 40px">"<%= abuse_report.reason %>"</strong> <br /> |
5 | - <i><%= _('Reported by %{reporter} %{time}.') % {:reporter => abuse_report.reporter.name, :time => time_ago_as_sentence(abuse_report.created_at) }%></i> <br /> | |
5 | + <i><%= _('Reported by %{reporter} %{time}.') % {:reporter => abuse_report.reporter.name, :time => time_ago_in_words(abuse_report.created_at) }%></i> <br /> | |
6 | 6 | <% if !abuse_report.content.blank? %> |
7 | 7 | <button class="display-abuse-report-details" data-report="<%=abuse_report.id%>"><%=_('View details')%></button> |
8 | 8 | <div style='display: none' id=<%= 'abuse-report-details-'+abuse_report.id.to_s %> class="abuse-report-details"> | ... | ... |
app/views/tasks/_task.html.erb
... | ... | @@ -2,8 +2,26 @@ |
2 | 2 | |
3 | 3 | <%= render :partial => 'task_icon', :locals => {:task => task} %> |
4 | 4 | |
5 | + <% if !@view_only && profile.organization? && @responsible_candidates.present? %> | |
6 | + <div class="task_responsible"> | |
7 | + <span class="label"><%= _('Assign to:') %></span> | |
8 | + <span> | |
9 | + <% change_responsible_url = url_for :action => :change_responsible, :controller => :tasks %> | |
10 | + <%= select_tag "tasks[#{task.id}][responsible]", options_from_collection_for_select(@responsible_candidates, :id, :name, task.responsible.present? ? task.responsible.id : nil), :include_blank => true, :onchange => "change_task_responsible(this);", 'data-old-responsible' => task.responsible.present? ? task.responsible.id : nil, 'data-task' => task.id, 'data-url' => change_responsible_url %> | |
11 | + </span> | |
12 | + </div> | |
13 | + <% end %> | |
14 | + | |
15 | + <% if @view_only && task.responsible.present? %> | |
16 | + <div class="task_responsible"> | |
17 | + <span class="label"><%= _('Assigned to:') %></span> | |
18 | + <span class="value"><%= task.responsible.name %></span> | |
19 | + </div> | |
20 | + <% end %> | |
21 | + | |
5 | 22 | <div class="task_decisions"> |
6 | - <%= | |
23 | + <% unless @view_only %> | |
24 | + <%= | |
7 | 25 | labelled_radio_button(_("Accept"), "tasks[#{task.id}][decision]", 'finish', task.default_decision == 'accept', |
8 | 26 | :id => "decision-finish-#{task.id}", |
9 | 27 | :class => 'task_accept_radio', |
... | ... | @@ -19,9 +37,12 @@ |
19 | 37 | :class => 'task_skip_radio', |
20 | 38 | :disabled => task.skip_disabled?, |
21 | 39 | :task_id => "#{task.id}") |
22 | - %> | |
40 | + %> | |
41 | + <% end %> | |
23 | 42 | </div><!-- class="task_decisions" --> |
24 | 43 | |
44 | + <div class="task_date"><%= show_time(task.created_at) %></div> | |
45 | + | |
25 | 46 | <%= render :partial => 'task_title', :locals => {:task => task} %> |
26 | 47 | |
27 | 48 | <div class="task_information"> | ... | ... |
app/views/tasks/index.html.erb
... | ... | @@ -21,45 +21,66 @@ |
21 | 21 | </div> |
22 | 22 | <% end %> |
23 | 23 | |
24 | +<%= form_tag '#', :method => 'get' do %> | |
25 | + <%= field_set_tag _('Filter'), :class => 'filter_fields' do %> | |
26 | + <p> | |
27 | + <%= labelled_select(_('Type of task')+': ', :filter_type, :first, :last, @filter_type, type_collection, {:id => 'filter-type'}) %> | |
28 | + </p> | |
29 | + <p> | |
30 | + <%= labelled_text_field(_("Text filter")+': ', :filter_text, nil, {:id => 'filter-text',:value => @filter_text}) %> | |
31 | + </p> | |
32 | + <% if profile.organization? %> | |
33 | + <p> | |
34 | + <%= labelled_select(_('Assigned to')+': ', :filter_responsible, :id, :name, @filter_responsible, [OpenStruct.new(:name => _('All'), :id => nil), OpenStruct.new(:name => _('Unassigned'), :id => -1)] + @responsible_candidates, :class => 'filter_responsible') %> | |
35 | + </p> | |
36 | + <% end %> | |
37 | + <p> | |
38 | + <%= submit_button(:search, _('Search')) %> | |
39 | + </p> | |
40 | + <% end %> | |
41 | +<% end %> | |
42 | + | |
24 | 43 | <% if @tasks.empty? %> |
25 | 44 | <p> |
26 | - <%= labelled_select(_('Filter')+': ', :filter_type, :first, :last, @filter, type_collection, :onchange => "document.location.href = '?filter_type='+this.value")%> | |
45 | + <em><%= _('No pending tasks for %s') % profile.name %></em> | |
27 | 46 | </p> |
28 | - <em><%= _('No pending tasks for %s') % profile.name %></em> | |
29 | 47 | <% else %> |
30 | 48 | <%= form_tag :action => 'close' do%> |
31 | - <% button_bar do %> | |
49 | + <% button_bar(:class => 'task-actions') do %> | |
32 | 50 | <%# FiXME button(:edit, _('View my requests'), :action => 'list_requested') %> |
33 | 51 | <%# FIXME button('menu-mail', _('Send request'), :action => 'new') %> |
34 | 52 | <%= submit_button :save, _("Apply!") %> |
35 | 53 | <%= button(:edit, _('View processed tasks'), :action => 'processed') %> |
36 | 54 | <%= button(:back, _('Back to control panel'), :controller => 'profile_editor') %> |
37 | - <% end %> | |
55 | + <% end unless @view_only %> | |
38 | 56 | |
39 | 57 | <ul class='task-list'> |
40 | - <p> | |
41 | - <%= labelled_select(_('Filter')+': ', :filter_type, :first, :last, @filter, type_collection, :onchange => "document.location.href = '?filter_type='+this.value") %> | |
42 | - </p> | |
43 | - <p> | |
44 | - <%= labelled_select(_("Set all to: "), 'set-decisions', 'first', 'last', nil, [['',""],['accept',_("Accept")],['reject',_("Reject")],['skip',_("Skip")]], :id => "up-set-all-tasks-to") %> | |
45 | - </p> | |
46 | - <% @tasks.each do |task| %> | |
47 | - <%= render :partial => 'task', :locals => { :task => task } %> | |
58 | + <% unless @view_only %> | |
59 | + <p> | |
60 | + <%= labelled_select(_("Set all to: "), 'set-decisions', 'first', 'last', nil, [['',""],['accept',_("Accept")],['reject',_("Reject")],['skip',_("Skip")]], :id => "up-set-all-tasks-to") %> | |
61 | + </p> | |
62 | + <% end %> | |
63 | + | |
64 | + <div class="task_boxes"> | |
65 | + <%= render :partial => 'task', :collection => @tasks %> | |
66 | + </div> | |
67 | + | |
68 | + <% unless @view_only %> | |
69 | + <p> | |
70 | + <%= labelled_select(_("Set all to: "), 'set-decisions', 'first', 'last', nil, [['',""],['accept',_("Accept")],['reject',_("Reject")],['skip',_("Skip")]], :id => "down-set-all-tasks-to") %> | |
71 | + </p> | |
48 | 72 | <% end %> |
49 | - <p> | |
50 | - <%= labelled_select(_("Set all to: "), 'set-decisions', 'first', 'last', nil, [['',""],['accept',_("Accept")],['reject',_("Reject")],['skip',_("Skip")]], :id => "down-set-all-tasks-to") %> | |
51 | - </p> | |
52 | 73 | </ul> |
53 | 74 | |
54 | 75 | <%= pagination_links(@tasks)%> |
55 | 76 | |
56 | - <% button_bar do %> | |
77 | + <% button_bar(:class => 'task-actions') do %> | |
57 | 78 | <%# FiXME button(:edit, _('View my requests'), :action => 'list_requested') %> |
58 | 79 | <%# FIXME button('menu-mail', _('Send request'), :action => 'new') %> |
59 | 80 | <%= submit_button :save, _("Apply!") %> |
60 | 81 | <%= button(:edit, _('View processed tasks'), :action => 'processed') %> |
61 | 82 | <%= button(:back, _('Back to control panel'), :controller => 'profile_editor') %> |
62 | - <% end %> | |
83 | + <% end unless @view_only %> | |
63 | 84 | <% end %> |
64 | 85 | <% end %> |
65 | 86 | </p> | ... | ... |
app/views/users/_users_list.html.erb
1 | -<div class="environment-users-results-header"> | |
2 | - <div id='environment-users-filter-title'><%= users_filter_title(@filter) %></div> | |
1 | +<div class="environment-profiles-results-header"> | |
2 | + <div id='environment-profiles-filter-title'><%= users_filter_title(@filter) %></div> | |
3 | 3 | <%= filter_selector(@filter) %> |
4 | 4 | <div style="clear: both"></div> |
5 | 5 | </div> | ... | ... |
config/initializers/delayed_job_config.rb
... | ... | @@ -23,3 +23,13 @@ end |
23 | 23 | # end |
24 | 24 | # alias_method_chain :handle_failed_job, :loggin |
25 | 25 | #end |
26 | + | |
27 | +# Chain delayed job's handle_failed_job method to do exception notification | |
28 | +Delayed::Worker.class_eval do | |
29 | + def handle_failed_job_with_notification job, error | |
30 | + handle_failed_job_without_notification job, error | |
31 | + ExceptionNotifier.notify_exception error, exception_recipients: NOOSFERO_CONF['exception_recipients'], | |
32 | + data: {job: job, handler: job.handler} rescue nil | |
33 | + end | |
34 | + alias_method_chain :handle_failed_job, :notification | |
35 | +end | ... | ... |
config/initializers/noosfero_extensions.rb
... | ... | @@ -0,0 +1,13 @@ |
1 | +# Be sure to restart your server when you modify this file. | |
2 | +# This file contains settings for ActionController::ParamsWrapper which | |
3 | +# is enabled by default. | |
4 | + | |
5 | +# Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array. | |
6 | +ActiveSupport.on_load(:action_controller) do | |
7 | + wrap_parameters :format => [] | |
8 | +end | |
9 | + | |
10 | +# Disable root element in JSON by default. | |
11 | +ActiveSupport.on_load(:active_record) do | |
12 | + self.include_root_in_json = false | |
13 | +end | ... | ... |
db/migrate/20140820173129_create_chat_messages.rb
1 | 1 | class CreateChatMessages < ActiveRecord::Migration |
2 | - def change | |
2 | + def up | |
3 | 3 | create_table :chat_messages do |t| |
4 | 4 | t.integer :to_id |
5 | 5 | t.integer :from_id |
... | ... | @@ -8,4 +8,8 @@ class CreateChatMessages < ActiveRecord::Migration |
8 | 8 | t.timestamps |
9 | 9 | end |
10 | 10 | end |
11 | + | |
12 | + def down | |
13 | + drop_table :chat_messages | |
14 | + end | |
11 | 15 | end | ... | ... |
db/migrate/20141014205254_change_chat_messages_columns_and_add_indexes.rb
0 → 100644
... | ... | @@ -0,0 +1,23 @@ |
1 | +class ChangeChatMessagesColumnsAndAddIndexes < ActiveRecord::Migration | |
2 | + def up | |
3 | + change_table :chat_messages do |t| | |
4 | + t.change :from_id, :integer, :null => false | |
5 | + t.change :to_id, :integer, :null => false | |
6 | + t.change :body, :text | |
7 | + end | |
8 | + add_index :chat_messages, :from_id | |
9 | + add_index :chat_messages, :to_id | |
10 | + add_index :chat_messages, :created_at | |
11 | + end | |
12 | + | |
13 | + def down | |
14 | + remove_index :chat_messages, :from_id | |
15 | + remove_index :chat_messages, :to_id | |
16 | + remove_index :chat_messages, :created_at | |
17 | + change_table :chat_messages do |t| | |
18 | + t.change :from_id, :integer, :null => true | |
19 | + t.change :to_id, :integer, :null => true | |
20 | + t.change :body, :string | |
21 | + end | |
22 | + end | |
23 | +end | ... | ... |
... | ... | @@ -0,0 +1,19 @@ |
1 | +class FixTagsCaseDifferences < ActiveRecord::Migration | |
2 | + def up | |
3 | + tags = ActsAsTaggableOn::Tag.joins('LEFT JOIN tags as b on LOWER(tags.name) = b.name').where('b.id is null') | |
4 | + tags.find_each do |tag| | |
5 | + unless ActsAsTaggableOn::Tag.exists?(:name => tag.name.mb_chars.downcase) | |
6 | + ActsAsTaggableOn::Tag.create(:name => tag.name.mb_chars.downcase) | |
7 | + end | |
8 | + end | |
9 | + | |
10 | + execute("UPDATE taggings SET tag_id = new.id FROM taggings AS t INNER JOIN tags AS old ON t.tag_id = old.id INNER JOIN tags AS new ON LOWER(old.name) = new.name WHERE old.id != new.id AND taggings.id = t.id") | |
11 | + | |
12 | + execute("UPDATE tags SET taggings_count = (SELECT COUNT(*) FROM taggings WHERE taggings.tag_id = tags.id)") | |
13 | + execute("DELETE FROM tags WHERE taggings_count = 0") | |
14 | + end | |
15 | + | |
16 | + def down | |
17 | + say 'This migration is irreversible.' | |
18 | + end | |
19 | +end | ... | ... |
... | ... | @@ -0,0 +1,15 @@ |
1 | +class AddMirrorToBlock < ActiveRecord::Migration | |
2 | + def up | |
3 | + change_table :blocks do |t| | |
4 | + t.boolean :mirror, :default => false | |
5 | + t.references :mirror_block | |
6 | + t.references :observers | |
7 | + end | |
8 | + end | |
9 | + | |
10 | + def down | |
11 | + remove_column :blocks, :mirror | |
12 | + remove_column :blocks, :mirror_block_id | |
13 | + remove_column :blocks, :observers_id | |
14 | + end | |
15 | +end | ... | ... |
db/migrate/20150507204849_remove_broken_profile_suggestions.rb
0 → 100644
db/migrate/20150513213939_update_topic_creation_configuration.rb
0 → 100644
... | ... | @@ -0,0 +1,13 @@ |
1 | +class UpdateTopicCreationConfiguration < ActiveRecord::Migration | |
2 | + def up | |
3 | + Forum.where("setting LIKE '%:allows_members_to_create_topics: true%'").find_each do |forum| | |
4 | + forum.setting.delete(:allows_members_to_create_topics) | |
5 | + forum.setting.merge!(:topic_creation => 'related') | |
6 | + forum.save | |
7 | + end | |
8 | + end | |
9 | + | |
10 | + def down | |
11 | + say "this migration can't be reverted" | |
12 | + end | |
13 | +end | ... | ... |
db/migrate/20150529180110_add_date_format_to_environment.rb
0 → 100644
db/schema.rb
... | ... | @@ -11,7 +11,7 @@ |
11 | 11 | # |
12 | 12 | # It's strongly recommended to check this file into your version control system. |
13 | 13 | |
14 | -ActiveRecord::Schema.define(:version => 20150408231524) do | |
14 | +ActiveRecord::Schema.define(:version => 20150602142030) do | |
15 | 15 | |
16 | 16 | create_table "abuse_reports", :force => true do |t| |
17 | 17 | t.integer "reporter_id" |
... | ... | @@ -183,10 +183,13 @@ ActiveRecord::Schema.define(:version => 20150408231524) do |
183 | 183 | t.string "type" |
184 | 184 | t.text "settings" |
185 | 185 | t.integer "position" |
186 | - t.boolean "enabled", :default => true | |
186 | + t.boolean "enabled", :default => true | |
187 | 187 | t.datetime "created_at" |
188 | 188 | t.datetime "updated_at" |
189 | 189 | t.datetime "fetched_at" |
190 | + t.boolean "mirror", :default => false | |
191 | + t.integer "mirror_block_id" | |
192 | + t.integer "observers_id" | |
190 | 193 | end |
191 | 194 | |
192 | 195 | add_index "blocks", ["box_id"], :name => "index_blocks_on_box_id" |
... | ... | @@ -242,13 +245,17 @@ ActiveRecord::Schema.define(:version => 20150408231524) do |
242 | 245 | end |
243 | 246 | |
244 | 247 | create_table "chat_messages", :force => true do |t| |
245 | - t.integer "to_id" | |
246 | - t.integer "from_id" | |
247 | - t.string "body" | |
248 | + t.integer "from_id", :null => false | |
249 | + t.integer "to_id", :null => false | |
250 | + t.text "body" | |
248 | 251 | t.datetime "created_at", :null => false |
249 | 252 | t.datetime "updated_at", :null => false |
250 | 253 | end |
251 | 254 | |
255 | + add_index "chat_messages", ["created_at"], :name => "index_chat_messages_on_created_at" | |
256 | + add_index "chat_messages", ["from_id"], :name => "index_chat_messages_on_from_id" | |
257 | + add_index "chat_messages", ["to_id"], :name => "index_chat_messages_on_to_id" | |
258 | + | |
252 | 259 | create_table "comments", :force => true do |t| |
253 | 260 | t.string "title" |
254 | 261 | t.text "body" |
... | ... | @@ -313,17 +320,18 @@ ActiveRecord::Schema.define(:version => 20150408231524) do |
313 | 320 | t.text "design_data" |
314 | 321 | t.text "custom_header" |
315 | 322 | t.text "custom_footer" |
316 | - t.string "theme", :default => "default", :null => false | |
323 | + t.string "theme", :default => "default", :null => false | |
317 | 324 | t.text "terms_of_use_acceptance_text" |
318 | 325 | t.datetime "created_at" |
319 | 326 | t.datetime "updated_at" |
320 | - t.integer "reports_lower_bound", :default => 0, :null => false | |
327 | + t.integer "reports_lower_bound", :default => 0, :null => false | |
321 | 328 | t.string "redirection_after_login", :default => "keep_on_same_page" |
322 | 329 | t.text "signup_welcome_text" |
323 | 330 | t.string "languages" |
324 | 331 | t.string "default_language" |
325 | 332 | t.string "noreply_email" |
326 | 333 | t.string "redirection_after_signup", :default => "keep_on_same_page" |
334 | + t.string "date_format", :default => "month_name_with_year" | |
327 | 335 | end |
328 | 336 | |
329 | 337 | create_table "external_feeds", :force => true do |t| |
... | ... | @@ -677,12 +685,14 @@ ActiveRecord::Schema.define(:version => 20150408231524) do |
677 | 685 | t.date "end_date" |
678 | 686 | t.integer "requestor_id" |
679 | 687 | t.integer "target_id" |
680 | - t.string "code", :limit => 40 | |
688 | + t.string "code", :limit => 40 | |
681 | 689 | t.string "type" |
682 | 690 | t.datetime "created_at" |
683 | 691 | t.string "target_type" |
684 | 692 | t.integer "image_id" |
685 | - t.boolean "spam", :default => false | |
693 | + t.boolean "spam", :default => false | |
694 | + t.integer "responsible_id" | |
695 | + t.integer "closed_by_id" | |
686 | 696 | end |
687 | 697 | |
688 | 698 | add_index "tasks", ["requestor_id"], :name => "index_tasks_on_requestor_id" | ... | ... |
debian/changelog
1 | -noosfero (1.2~0) UNRELEASED; urgency=medium | |
1 | +noosfero (1.2~1) UNRELEASED; urgency=medium | |
2 | 2 | |
3 | + [ Antonio Terceiro ] | |
3 | 4 | * Temporary version in heavy development |
4 | 5 | |
5 | - -- Antonio Terceiro <terceiro@debian.org> Fri, 08 May 2015 16:08:18 -0300 | |
6 | + [ Joenio Costa ] | |
7 | + * Build noosfero-chat package | |
8 | + | |
9 | + -- Joenio Costa <joenio@colivre.coop.br> Mon, 18 May 2015 14:32:21 -0300 | |
6 | 10 | |
7 | 11 | noosfero (1.1) wheezy; urgency=low |
8 | 12 | ... | ... |
debian/control
... | ... | @@ -85,3 +85,14 @@ Description: free web-based platform for social networks (apache frontend) |
85 | 85 | . |
86 | 86 | This package contains the configuration files needed to run Noosfero with the |
87 | 87 | Apache HTTPD server as frontend. |
88 | + | |
89 | +Package: noosfero-chat | |
90 | +Architecture: all | |
91 | +Depends: noosfero (>= 1.2), ejabberd, odbc-postgresql, pidgin-data | |
92 | +Description: free web-based platform for social networks (ejabberd based chat) | |
93 | + Noosfero is a web platform for social and solidarity economy networks with | |
94 | + blog, e-Porfolios, CMS, RSS, thematic discussion, events agenda and collective | |
95 | + inteligence for solidarity economy in the same system. | |
96 | + . | |
97 | + This package contains the configuration files needed to run Noosfero with the | |
98 | + Ejabberd XMPP chat server. | ... | ... |