Commit 4b0c7f1f71a783ac43113244044bf77a240b3d4e
Exists in
master
and in
28 other branches
Merge branch 'next' into AI2888-context_block
Conflicts: test/unit/article_test.rb
Showing
316 changed files
with
55715 additions
and
48751 deletions
Show diff stats
Too many changes.
To preserve performance only 100 of 316 files displayed.
AUTHORS
| ... | ... | @@ -111,6 +111,7 @@ Diego Martinez <diegoamc90@gmail.com> |
| 111 | 111 | Diego Martinez <diego@diego-K55A.(none)> |
| 112 | 112 | Diego + Renan <renanteruoc@gmail.com> |
| 113 | 113 | Fernanda Lopes <nanda.listas+psl@gmail.com> |
| 114 | +Francisco Marcelo A. Lima Júnior <francisco.lima-junior@serpro.gov.br> | |
| 114 | 115 | Francisco Marcelo de Araujo Lima Junior <79350259591@serpro-1457614.(none)> |
| 115 | 116 | Grazieno Pellegrino <grazieno@gmail.com> |
| 116 | 117 | Isaac Canan <isaac@intelletto.com.br> |
| ... | ... | @@ -189,12 +190,14 @@ Renan Teruo + Diego Araujo <renanteruoc@gmail.com> |
| 189 | 190 | Renan Teruo + Diego Araújo <renanteruoc@gmail.com> |
| 190 | 191 | Renan Teruo + Paulo Meirelles <renanteruoc@gmail.com> |
| 191 | 192 | Renan Teruo + Rafael Manzo <renanteruoc@gmail.com> |
| 193 | +Rodrigo Souto <diguliu@gmail.com> | |
| 192 | 194 | Rodrigo Souto <rodrigo@colivre.coop.br> |
| 193 | 195 | Ronny Kursawe <kursawe.ronny@googlemail.com> |
| 194 | 196 | root <root@debian.sdr.serpro> |
| 195 | 197 | Samuel R. C. Vale <srcvale@holoscopio.com> |
| 196 | 198 | Valessio Brito <valessio@gmail.com> |
| 197 | 199 | vfcosta <vfcosta@gmail.com> |
| 200 | +Vinicius Cubas Brand <viniciuscb@gmail.com> | |
| 198 | 201 | Visita <visita@debian.(none)> |
| 199 | 202 | Yann Lugrin <yann.lugrin@liquid-concept.ch> |
| 200 | 203 | ... | ... |
COPYRIGHT
| ... | ... | @@ -4,8 +4,9 @@ Copyright (c) 2007-2009, |
| 4 | 4 | Cáritas Brasileira <http://www.caritasbrasileira.org/> |
| 5 | 5 | Copyright (c) 2007-2009, |
| 6 | 6 | Ynternet.org Foundation <http://www.ynternet.org/> |
| 7 | -Copyright (c) 2008-2009, | |
| 7 | +Copyright (c) 2008-2013, | |
| 8 | 8 | Colivre <http://www.colivre.coop.br/> |
| 9 | +Copyright (c) the Noosfero contributors. See AUTHORS | |
| 9 | 10 | |
| 10 | 11 | This program is free software: you can redistribute it and/or modify |
| 11 | 12 | it under the terms of the GNU Affero General Public License as published by | ... | ... |
HACKING
| ... | ... | @@ -52,3 +52,12 @@ If you write such script for your own OS, *please* share it with us at the |
| 52 | 52 | development mailing list so that we can include it in the official repository. |
| 53 | 53 | This way other people using the same OS will have to put less effort to develop |
| 54 | 54 | Noosfero. |
| 55 | + | |
| 56 | +== Submitting your changes back | |
| 57 | + | |
| 58 | +For now please read: | |
| 59 | + | |
| 60 | +- Coding conventions | |
| 61 | + http://noosfero.org/Development/CodingConventions | |
| 62 | +- Patch guidelines | |
| 63 | + http://noosfero.org/Development/PatchGuidelines | ... | ... |
HACKING.rails235
| ... | ... | @@ -1,13 +0,0 @@ |
| 1 | -This is a draft of how to create a environment to Rails 2.3.5 to Noosfero | |
| 2 | -development. | |
| 3 | - | |
| 4 | -Install dependencies: | |
| 5 | - | |
| 6 | -gem install rails -v 2.3.5 | |
| 7 | -gem install i18n | |
| 8 | -gem install will_paginate -v 2.3.12 | |
| 9 | -gem install cucumber | |
| 10 | - | |
| 11 | -Creating initial environment: | |
| 12 | - | |
| 13 | -rake db:schema:load |
INSTALL.chat
| ... | ... | @@ -6,7 +6,7 @@ To configure XMPP/BOSH in Noosfero you need: |
| 6 | 6 | * SystemTimer - http://ph7spot.com/musings/system-timer |
| 7 | 7 | * Pidgin data files - http://www.pidgin.im/ |
| 8 | 8 | |
| 9 | -If you use Debian Wheezy: | |
| 9 | +If you use Debian 6.0 (squeeze): | |
| 10 | 10 | |
| 11 | 11 | # apt-get install librestclient-ruby pidgin-data ruby1.8-dev |
| 12 | 12 | # gem install SystemTimer | ... | ... |
README
| 1 | -noosfero - a web-based social platform | |
| 1 | +Noosfero - a web-based social platform | |
| 2 | 2 | ====================================== |
| 3 | 3 | |
| 4 | -:: About the project | |
| 4 | +http://www.noosfero.org/ | |
| 5 | 5 | |
| 6 | -Homepage: http://www.noosfero.org/ | |
| 6 | +Documentation | |
| 7 | +------------- | |
| 7 | 8 | |
| 8 | -:: Authors and copyright | |
| 9 | +The following documentation is available: | |
| 9 | 10 | |
| 10 | -Authors: see file AUTHORS | |
| 11 | -Copyright information: see file COPYRIGHT | |
| 12 | -Full license text; see file COPYING | |
| 11 | +File Purpose | |
| 12 | +~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
| 13 | +INSTALL install instructions | |
| 14 | +INSTALL.awstats install instructions - access statistics service | |
| 15 | +INSTALL.chat install instructions - chat service | |
| 16 | +INSTALL.email install instructions - email service | |
| 17 | +INSTALL.multitenancy install instructions - multiple sites | |
| 18 | +INSTALL.varnish install instructions - varnish HTTP caching (recommended) | |
| 19 | +HACKING development instruction | |
| 20 | +RELEASING instructions for doing releases | |
| 21 | +doc/noosfero/* user documentation (available through the app itself) | |
| 22 | + | |
| 23 | + | |
| 24 | +Authors and copyright | |
| 25 | +--------------------- | |
| 26 | + | |
| 27 | +Authorship and copyright information is available in the files listed below. | |
| 28 | + | |
| 29 | +File Purpose | |
| 30 | +~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
| 31 | +AUTHORS list of authors (updated at each release) | |
| 32 | +COPYRIGHT Copyright statement for the project | |
| 33 | +COPYING Full text of the project license | ... | ... |
app/controllers/application_controller.rb
| ... | ... | @@ -174,8 +174,6 @@ class ApplicationController < ActionController::Base |
| 174 | 174 | end |
| 175 | 175 | |
| 176 | 176 | def find_by_contents(asset, scope, query, paginate_options={:page => 1}, options={}) |
| 177 | - scope = scope.send(options[:filter]) if options[:filter] | |
| 178 | - | |
| 179 | 177 | @plugins.dispatch_first(:find_by_contents, asset, scope, query, paginate_options, options) || |
| 180 | 178 | fallback_find_by_contents(asset, scope, query, paginate_options, options) |
| 181 | 179 | end |
| ... | ... | @@ -183,8 +181,9 @@ class ApplicationController < ActionController::Base |
| 183 | 181 | private |
| 184 | 182 | |
| 185 | 183 | def fallback_find_by_contents(asset, scope, query, paginate_options, options) |
| 186 | - return {:results => scope.paginate(paginate_options)} if query.blank? | |
| 187 | - {:results => scope.like_search(query).paginate(paginate_options)} | |
| 184 | + scope = scope.like_search(query) unless query.blank? | |
| 185 | + scope = scope.send(options[:filter]) unless options[:filter].blank? | |
| 186 | + {:results => scope.paginate(paginate_options)} | |
| 188 | 187 | end |
| 189 | 188 | |
| 190 | 189 | end | ... | ... |
app/controllers/my_profile/cms_controller.rb
| ... | ... | @@ -73,6 +73,7 @@ class CmsController < MyProfileController |
| 73 | 73 | refuse_blocks |
| 74 | 74 | record_coming |
| 75 | 75 | if request.post? |
| 76 | + @article.image = nil if params[:remove_image] == 'true' | |
| 76 | 77 | @article.last_changed_by = user |
| 77 | 78 | if @article.update_attributes(params[:article]) |
| 78 | 79 | if !continue |
| ... | ... | @@ -144,10 +145,15 @@ class CmsController < MyProfileController |
| 144 | 145 | |
| 145 | 146 | post_only :set_home_page |
| 146 | 147 | def set_home_page |
| 147 | - @article = profile.articles.find(params[:id]) | |
| 148 | - profile.home_page = @article | |
| 149 | - profile.save(false) | |
| 150 | - session[:notice] = _('"%s" configured as home page.') % @article.name | |
| 148 | + article = params[:id].nil? ? nil : profile.articles.find(params[:id]) | |
| 149 | + profile.update_attribute(:home_page, article) | |
| 150 | + | |
| 151 | + if article.nil? | |
| 152 | + session[:notice] = _('Homepage reseted.') | |
| 153 | + else | |
| 154 | + session[:notice] = _('"%s" configured as homepage.') % article.name | |
| 155 | + end | |
| 156 | + | |
| 151 | 157 | redirect_to (request.referer || profile.url) |
| 152 | 158 | end |
| 153 | 159 | |
| ... | ... | @@ -267,7 +273,10 @@ class CmsController < MyProfileController |
| 267 | 273 | @back_to = params[:back_to] || request.referer || url_for(profile.public_profile_url) |
| 268 | 274 | @task = SuggestArticle.new(params[:task]) |
| 269 | 275 | if request.post? |
| 270 | - @task.target = profile | |
| 276 | + @task.target = profile | |
| 277 | + @task.ip_address = request.remote_ip | |
| 278 | + @task.user_agent = request.user_agent | |
| 279 | + @task.referrer = request.referrer | |
| 271 | 280 | if verify_recaptcha(:model => @task, :message => _('Please type the words correctly')) && @task.save |
| 272 | 281 | session[:notice] = _('Thanks for your suggestion. The community administrators were notified.') |
| 273 | 282 | redirect_to @back_to | ... | ... |
app/controllers/my_profile/memberships_controller.rb
| ... | ... | @@ -9,9 +9,10 @@ class MembershipsController < MyProfileController |
| 9 | 9 | def new_community |
| 10 | 10 | @community = Community.new(params[:community]) |
| 11 | 11 | @community.environment = environment |
| 12 | + @back_to = params[:back_to] || url_for(:action => 'index') | |
| 12 | 13 | if request.post? && @community.valid? |
| 13 | 14 | @community = Community.create_after_moderation(user, {:environment => environment}.merge(params[:community])) |
| 14 | - redirect_to :action => 'index' | |
| 15 | + redirect_to @back_to | |
| 15 | 16 | return |
| 16 | 17 | end |
| 17 | 18 | end | ... | ... |
app/controllers/my_profile/profile_editor_controller.rb
| ... | ... | @@ -4,7 +4,7 @@ class ProfileEditorController < MyProfileController |
| 4 | 4 | protect 'destroy_profile', :profile, :only => [:destroy_profile] |
| 5 | 5 | |
| 6 | 6 | def index |
| 7 | - @pending_tasks = Task.to(profile).pending.select{|i| user.has_permission?(i.permission, profile)} | |
| 7 | + @pending_tasks = Task.to(profile).pending.without_spam.select{|i| user.has_permission?(i.permission, profile)} | |
| 8 | 8 | end |
| 9 | 9 | |
| 10 | 10 | helper :profile | ... | ... |
app/controllers/my_profile/spam_controller.rb
| ... | ... | @@ -14,9 +14,15 @@ class SpamController < MyProfileController |
| 14 | 14 | if params[:remove_comment] |
| 15 | 15 | profile.comments_received.find(params[:remove_comment]).destroy |
| 16 | 16 | end |
| 17 | + if params[:remove_task] | |
| 18 | + Task.to(profile).find_by_id(params[:remove_task]).destroy | |
| 19 | + end | |
| 17 | 20 | if params[:mark_comment_as_ham] |
| 18 | 21 | profile.comments_received.find(params[:mark_comment_as_ham]).ham! |
| 19 | 22 | end |
| 23 | + if params[:mark_task_as_ham] && (t = Task.to(profile).find_by_id(params[:mark_task_as_ham])) | |
| 24 | + t.ham! | |
| 25 | + end | |
| 20 | 26 | if request.xhr? |
| 21 | 27 | json_response(true) |
| 22 | 28 | else |
| ... | ... | @@ -28,7 +34,8 @@ class SpamController < MyProfileController |
| 28 | 34 | return |
| 29 | 35 | end |
| 30 | 36 | |
| 31 | - @spam = profile.comments_received.spam.paginate({:page => params[:page]}) | |
| 37 | + @comment_spam = profile.comments_received.spam.paginate({:page => params[:comments_page]}) | |
| 38 | + @task_spam = Task.to(profile).spam.paginate({:page => params[:tasks_page]}) | |
| 32 | 39 | end |
| 33 | 40 | |
| 34 | 41 | protected | ... | ... |
app/controllers/my_profile/tasks_controller.rb
| ... | ... | @@ -4,12 +4,12 @@ class TasksController < MyProfileController |
| 4 | 4 | |
| 5 | 5 | def index |
| 6 | 6 | @filter = params[:filter_type].blank? ? nil : params[:filter_type] |
| 7 | - @tasks = Task.to(profile).pending.of(@filter).order_by('created_at', 'asc').paginate(:per_page => Task.per_page, :page => params[:page]) | |
| 7 | + @tasks = Task.to(profile).without_spam.pending.of(@filter).order_by('created_at', 'asc').paginate(:per_page => Task.per_page, :page => params[:page]) | |
| 8 | 8 | @failed = params ? params[:failed] : {} |
| 9 | 9 | end |
| 10 | 10 | |
| 11 | 11 | def processed |
| 12 | - @tasks = Task.to(profile).closed.sort_by(&:created_at) | |
| 12 | + @tasks = Task.to(profile).without_spam.closed.sort_by(&:created_at) | |
| 13 | 13 | end |
| 14 | 14 | |
| 15 | 15 | VALID_DECISIONS = [ 'finish', 'cancel', 'skip' ] |
| ... | ... | @@ -57,7 +57,7 @@ class TasksController < MyProfileController |
| 57 | 57 | end |
| 58 | 58 | |
| 59 | 59 | def list_requested |
| 60 | - @tasks = Task.find_all_by_requestor_id(profile.id) | |
| 60 | + @tasks = Task.without_spam.find_all_by_requestor_id(profile.id) | |
| 61 | 61 | end |
| 62 | 62 | |
| 63 | 63 | def ticket_details | ... | ... |
app/controllers/public/content_viewer_controller.rb
| ... | ... | @@ -53,8 +53,11 @@ class ContentViewerController < ApplicationController |
| 53 | 53 | # At this point the page will be showed |
| 54 | 54 | @page.hit |
| 55 | 55 | |
| 56 | - unless @page.mime_type == 'text/html' || (@page.image? && params[:view]) | |
| 56 | + @page = FilePresenter.for @page | |
| 57 | + | |
| 58 | + if @page.download? params[:view] | |
| 57 | 59 | headers['Content-Type'] = @page.mime_type |
| 60 | + headers.merge! @page.download_headers | |
| 58 | 61 | data = @page.data |
| 59 | 62 | |
| 60 | 63 | # TODO test the condition |
| ... | ... | @@ -70,7 +73,7 @@ class ContentViewerController < ApplicationController |
| 70 | 73 | |
| 71 | 74 | #FIXME see a better way to do this. It's not need to pass this variable anymore |
| 72 | 75 | @comment = Comment.new |
| 73 | - | |
| 76 | + | |
| 74 | 77 | if @page.has_posts? |
| 75 | 78 | posts = if params[:year] and params[:month] |
| 76 | 79 | filter_date = DateTime.parse("#{params[:year]}-#{params[:month]}-01") | ... | ... |
app/controllers/public/events_controller.rb
| 1 | 1 | class EventsController < PublicController |
| 2 | 2 | |
| 3 | 3 | needs_profile |
| 4 | - no_design_blocks | |
| 5 | 4 | |
| 6 | 5 | def events |
| 7 | - @selected_day = nil | |
| 8 | - @events_of_the_day = [] | |
| 9 | - date = build_date(params[:year], params[:month], params[:day]) | |
| 6 | + @events = [] | |
| 7 | + @date = build_date(params[:year], params[:month], params[:day]) | |
| 10 | 8 | |
| 11 | - if params[:day] || !params[:year] && !params[:month] | |
| 12 | - @selected_day = date | |
| 13 | - @events_of_the_day = profile.events.by_day(@selected_day) | |
| 9 | + if !params[:year] && !params[:month] && !params[:day] | |
| 10 | + @events = profile.events.next_events_from_month(@date) | |
| 14 | 11 | end |
| 15 | 12 | |
| 16 | - events = profile.events.by_range((date - 1.month).at_beginning_of_month..(date + 1.month).at_end_of_month) | |
| 13 | + if params[:year] || params[:month] | |
| 14 | + @events = profile.events.by_month(@date) | |
| 15 | + end | |
| 16 | + | |
| 17 | + events_in_range = profile.events.by_range((@date - 1.month).at_beginning_of_month .. (@date + 1.month).at_end_of_month) | |
| 17 | 18 | |
| 18 | - @calendar = populate_calendar(date, events) | |
| 19 | - @previous_calendar = populate_calendar(date - 1.month, events) | |
| 20 | - @next_calendar = populate_calendar(date + 1.month, events) | |
| 19 | + @calendar = populate_calendar(@date, events_in_range) | |
| 21 | 20 | end |
| 22 | 21 | |
| 23 | 22 | def events_by_day |
| 24 | - @selected_day = build_date(params[:year], params[:month], params[:day]) | |
| 25 | - @events_of_the_day = profile.events.by_day(@selected_day) | |
| 26 | - render :partial => 'events_by_day' | |
| 23 | + @date = build_date(params[:year], params[:month], params[:day]) | |
| 24 | + @events = profile.events.by_day(@date) | |
| 25 | + render :partial => 'events' | |
| 27 | 26 | end |
| 28 | 27 | |
| 29 | 28 | protected | ... | ... |
app/controllers/public/profile_controller.rb
| ... | ... | @@ -206,10 +206,50 @@ class ProfileController < PublicController |
| 206 | 206 | end |
| 207 | 207 | |
| 208 | 208 | def view_more_network_activities |
| 209 | - @activities = @profile.tracked_notifications.paginate(:per_page => 10, :page => params[:page]) | |
| 209 | + @activities = @profile.tracked_notifications.paginate(:per_page => 10, :page => params[:page]) | |
| 210 | 210 | render :partial => 'profile_network_activities', :locals => {:network_activities => @activities} |
| 211 | 211 | end |
| 212 | 212 | |
| 213 | + def more_comments | |
| 214 | + activity = ActionTracker::Record.find(:first, :conditions => {:id => params[:activity], :user_id => @profile}) | |
| 215 | + comments_count = activity.comments.count | |
| 216 | + comment_page = (params[:comment_page] || 1).to_i | |
| 217 | + comments_per_page = 5 | |
| 218 | + no_more_pages = comments_count <= comment_page * comments_per_page | |
| 219 | + | |
| 220 | + render :update do |page| | |
| 221 | + page.insert_html :bottom, 'profile-wall-activities-comments-'+params[:activity], | |
| 222 | + :partial => 'comment', :collection => activity.comments.paginate(:per_page => comments_per_page, :page => comment_page) | |
| 223 | + | |
| 224 | + if no_more_pages | |
| 225 | + page.remove 'profile-wall-activities-comments-more-'+params[:activity] | |
| 226 | + else | |
| 227 | + page.replace_html 'profile-wall-activities-comments-more-'+params[:activity], | |
| 228 | + :partial => 'more_comments', :locals => {:activity => activity, :comment_page => comment_page} | |
| 229 | + end | |
| 230 | + end | |
| 231 | + end | |
| 232 | + | |
| 233 | + def more_replies | |
| 234 | + activity = Scrap.find(:first, :conditions => {:id => params[:activity], :receiver_id => @profile, :scrap_id => nil}) | |
| 235 | + comments_count = activity.replies.count | |
| 236 | + comment_page = (params[:comment_page] || 1).to_i | |
| 237 | + comments_per_page = 5 | |
| 238 | + no_more_pages = comments_count <= comment_page * comments_per_page | |
| 239 | + | |
| 240 | + render :update do |page| | |
| 241 | + page.insert_html :bottom, 'profile-wall-activities-comments-'+params[:activity], | |
| 242 | + :partial => 'profile_scrap', :collection => activity.replies.paginate(:per_page => comments_per_page, :page => comment_page), :as => :scrap | |
| 243 | + | |
| 244 | + if no_more_pages | |
| 245 | + page.remove 'profile-wall-activities-comments-more-'+params[:activity] | |
| 246 | + else | |
| 247 | + page.replace_html 'profile-wall-activities-comments-more-'+params[:activity], | |
| 248 | + :partial => 'more_replies', :locals => {:activity => activity, :comment_page => comment_page} | |
| 249 | + end | |
| 250 | + end | |
| 251 | + end | |
| 252 | + | |
| 213 | 253 | def remove_scrap |
| 214 | 254 | begin |
| 215 | 255 | scrap = current_user.person.scraps(params[:scrap_id]) |
| ... | ... | @@ -343,6 +383,7 @@ class ProfileController < PublicController |
| 343 | 383 | end |
| 344 | 384 | end |
| 345 | 385 | |
| 386 | + | |
| 346 | 387 | protected |
| 347 | 388 | |
| 348 | 389 | def check_access_to_profile |
| ... | ... | @@ -393,4 +434,5 @@ class ProfileController < PublicController |
| 393 | 434 | def relations_to_include |
| 394 | 435 | [:image, :domains, :preferred_domain, :environment] |
| 395 | 436 | end |
| 437 | + | |
| 396 | 438 | end | ... | ... |
app/controllers/public/search_controller.rb
| ... | ... | @@ -93,25 +93,27 @@ class SearchController < PublicController |
| 93 | 93 | year = (params[:year] ? params[:year].to_i : Date.today.year) |
| 94 | 94 | month = (params[:month] ? params[:month].to_i : Date.today.month) |
| 95 | 95 | day = (params[:day] ? params[:day].to_i : Date.today.day) |
| 96 | - date = build_date(params[:year], params[:month], params[:day]) | |
| 97 | - date_range = (date - 1.month).at_beginning_of_month..(date + 1.month).at_end_of_month | |
| 96 | + @date = build_date(year, month, day) | |
| 97 | + date_range = (@date - 1.month).at_beginning_of_month..(@date + 1.month).at_end_of_month | |
| 98 | 98 | |
| 99 | - @selected_day = nil | |
| 100 | - @events_of_the_day = [] | |
| 99 | + @events = [] | |
| 101 | 100 | if params[:day] || !params[:year] && !params[:month] |
| 102 | - @selected_day = date | |
| 103 | - @events_of_the_day = @category ? | |
| 104 | - environment.events.by_day(@selected_day).in_category(Category.find(@category_id)) : | |
| 105 | - environment.events.by_day(@selected_day) | |
| 101 | + @events = @category ? | |
| 102 | + environment.events.by_day(@date).in_category(Category.find(@category_id)) : | |
| 103 | + environment.events.by_day(@date) | |
| 104 | + end | |
| 105 | + | |
| 106 | + if params[:year] || params[:month] | |
| 107 | + @events = @category ? | |
| 108 | + environment.events.by_month(@date).in_category(Category.find(@category_id)) : | |
| 109 | + environment.events.by_month(@date) | |
| 106 | 110 | end |
| 107 | 111 | |
| 108 | 112 | @scope = date_range && params[:action] == 'events' ? environment.events.by_range(date_range) : environment.events |
| 109 | 113 | full_text_search |
| 110 | 114 | |
| 111 | 115 | events = @searches[@asset][:results] |
| 112 | - @calendar = populate_calendar(date, events) | |
| 113 | - @previous_calendar = populate_calendar(date - 1.month, events) | |
| 114 | - @next_calendar = populate_calendar(date + 1.month, events) | |
| 116 | + @calendar = populate_calendar(@date, events) | |
| 115 | 117 | end |
| 116 | 118 | |
| 117 | 119 | # keep old URLs workings |
| ... | ... | @@ -136,9 +138,9 @@ class SearchController < PublicController |
| 136 | 138 | end |
| 137 | 139 | |
| 138 | 140 | def events_by_day |
| 139 | - @selected_day = build_date(params[:year], params[:month], params[:day]) | |
| 140 | - @events_of_the_day = environment.events.by_day(@selected_day) | |
| 141 | - render :partial => 'events/events_by_day' | |
| 141 | + @date = build_date(params[:year], params[:month], params[:day]) | |
| 142 | + @events = environment.events.by_day(@date) | |
| 143 | + render :partial => 'events/events' | |
| 142 | 144 | end |
| 143 | 145 | |
| 144 | 146 | ####################################################### | ... | ... |
app/helpers/application_helper.rb
| ... | ... | @@ -558,6 +558,9 @@ module ApplicationHelper |
| 558 | 558 | # displays a link to the profile homepage with its image (as generated by |
| 559 | 559 | # #profile_image) and its name below it. |
| 560 | 560 | def profile_image_link( profile, size=:portrait, tag='li', extra_info = nil ) |
| 561 | + if content = @plugins.dispatch_first(:profile_image_link, profile, size, tag, extra_info) | |
| 562 | + return instance_eval(&content) | |
| 563 | + end | |
| 561 | 564 | name = profile.short_name |
| 562 | 565 | if profile.person? |
| 563 | 566 | url = url_for(profile.check_friendship_url) |
| ... | ... | @@ -574,16 +577,16 @@ module ApplicationHelper |
| 574 | 577 | extra_info = extra_info.nil? ? '' : content_tag( 'span', extra_info, :class => 'extra_info' ) |
| 575 | 578 | links = links_for_balloon(profile) |
| 576 | 579 | content_tag('div', content_tag(tag, |
| 577 | - (environment.enabled?(:show_balloon_with_profile_links_when_clicked) ? link_to( content_tag( 'span', _('Profile links')), '#', :onclick => "toggleSubmenu(this, '#{profile.short_name}', #{links.to_json}); return false", :class => "menu-submenu-trigger #{trigger_class}", :url => url) : "") + | |
| 578 | - link_to( | |
| 579 | - content_tag( 'span', profile_image( profile, size ), :class => 'profile-image' ) + | |
| 580 | - content_tag( 'span', h(name), :class => ( profile.class == Person ? 'fn' : 'org' ) ) + | |
| 581 | - extra_info + profile_sex_icon( profile ) + profile_cat_icons( profile ), | |
| 582 | - profile.url, | |
| 583 | - :class => 'profile_link url', | |
| 584 | - :help => _('Click on this icon to go to the <b>%s</b>\'s home page') % profile.name, | |
| 585 | - :title => profile.name ), | |
| 586 | - :class => 'vcard'), :class => 'common-profile-list-block') | |
| 580 | + (environment.enabled?(:show_balloon_with_profile_links_when_clicked) ? link_to( content_tag( 'span', _('Profile links')), '#', :onclick => "toggleSubmenu(this, '#{profile.short_name}', #{links.to_json}); return false", :class => "menu-submenu-trigger #{trigger_class}", :url => url) : "") + | |
| 581 | + link_to( | |
| 582 | + content_tag( 'span', profile_image( profile, size ), :class => 'profile-image' ) + | |
| 583 | + content_tag( 'span', h(name), :class => ( profile.class == Person ? 'fn' : 'org' ) ) + | |
| 584 | + extra_info + profile_sex_icon( profile ) + profile_cat_icons( profile ), | |
| 585 | + profile.url, | |
| 586 | + :class => 'profile_link url', | |
| 587 | + :help => _('Click on this icon to go to the <b>%s</b>\'s home page') % profile.name, | |
| 588 | + :title => profile.name ), | |
| 589 | + :class => 'vcard'), :class => 'common-profile-list-block') | |
| 587 | 590 | end |
| 588 | 591 | |
| 589 | 592 | def gravatar_url_for(email, options = {}) |
| ... | ... | @@ -727,8 +730,15 @@ module ApplicationHelper |
| 727 | 730 | end |
| 728 | 731 | |
| 729 | 732 | def rolename_for(profile, resource) |
| 730 | - role = profile.role_assignments.find_by_resource_id(resource.id).role | |
| 731 | - content_tag('span', role.name, :style => "color: #{role_color(role, resource.environment.id)}") | |
| 733 | + roles = profile.role_assignments. | |
| 734 | + where(:resource_id => resource.id). | |
| 735 | + sort_by{ |role_assignment| role_assignment.role_id }. | |
| 736 | + map(&:role) | |
| 737 | + names = [] | |
| 738 | + roles.each do |role| | |
| 739 | + names << content_tag('span', role.name, :style => "color: #{role_color(role, resource.environment.id)}") | |
| 740 | + end | |
| 741 | + names.join(', ') | |
| 732 | 742 | end |
| 733 | 743 | |
| 734 | 744 | def role_color(role, env_id) |
| ... | ... | @@ -1113,15 +1123,34 @@ module ApplicationHelper |
| 1113 | 1123 | result |
| 1114 | 1124 | end |
| 1115 | 1125 | |
| 1116 | - def manage_enterprises | |
| 1117 | - if user && !user.enterprises.empty? | |
| 1118 | - enterprises_link = user.enterprises.map do |enterprise| | |
| 1119 | - link_to(content_tag('strong', [_('<span>Manage</span> %s') % enterprise.short_name(25)]), @environment.top_url + "/myprofile/#{enterprise.identifier}", :class => "icon-menu-"+enterprise.class.identification.underscore, :title => [_('Manage %s') % enterprise.short_name]) | |
| 1126 | + def manage_link(list, kind) | |
| 1127 | + if list.present? | |
| 1128 | + link_to_all = nil | |
| 1129 | + if list.count > 5 | |
| 1130 | + list = list.first(5) | |
| 1131 | + link_to_all = link_to(content_tag('strong', _('See all')), :controller => 'memberships', :profile => current_user.login) | |
| 1132 | + end | |
| 1133 | + link = list.map do |element| | |
| 1134 | + link_to(content_tag('strong', [_('<span>Manage</span> %s') % element.short_name(25)]), @environment.top_url + "/myprofile/#{element.identifier}", :class => "icon-menu-"+element.class.identification.underscore, :title => [_('Manage %s') % element.short_name]) | |
| 1135 | + end | |
| 1136 | + if link_to_all | |
| 1137 | + link << link_to_all | |
| 1120 | 1138 | end |
| 1121 | - render :partial => 'shared/manage_enterprises', :locals => {:enterprises_link => enterprises_link} | |
| 1139 | + render :partial => "shared/manage_link", :locals => {:link => link, :kind => kind.to_s} | |
| 1122 | 1140 | end |
| 1123 | 1141 | end |
| 1124 | 1142 | |
| 1143 | + def manage_enterprises | |
| 1144 | + return unless user && user.environment.enabled?(:display_my_enterprises_on_user_menu) | |
| 1145 | + manage_link(user.enterprises, :enterprises) | |
| 1146 | + end | |
| 1147 | + | |
| 1148 | + def manage_communities | |
| 1149 | + return unless user && user.environment.enabled?(:display_my_communities_on_user_menu) | |
| 1150 | + administered_communities = user.communities.more_popular.select {|c| c.admins.include? user} | |
| 1151 | + manage_link(administered_communities, :communities) | |
| 1152 | + end | |
| 1153 | + | |
| 1125 | 1154 | def usermenu_logged_in |
| 1126 | 1155 | pending_tasks_count = '' |
| 1127 | 1156 | count = user ? Task.to(user).pending.count : -1 |
| ... | ... | @@ -1133,6 +1162,7 @@ module ApplicationHelper |
| 1133 | 1162 | render_environment_features(:usermenu) + |
| 1134 | 1163 | link_to('<i class="icon-menu-admin"></i><strong>' + _('Administration') + '</strong>', @environment.top_url + '/admin', :id => "controlpanel", :title => _("Configure the environment"), :class => 'admin-link', :style => 'display: none') + |
| 1135 | 1164 | manage_enterprises.to_s + |
| 1165 | + manage_communities.to_s + | |
| 1136 | 1166 | link_to('<i class="icon-menu-ctrl-panel"></i><strong>' + _('Control panel') + '</strong>', @environment.top_url + '/myprofile/{login}', :id => "controlpanel", :title => _("Configure your personal account and content")) + |
| 1137 | 1167 | pending_tasks_count + |
| 1138 | 1168 | link_to('<i class="icon-menu-logout"></i><strong>' + _('Logout') + '</strong>', { :controller => 'account', :action => 'logout'} , :id => "logout", :title => _("Leave the system")) |
| ... | ... | @@ -1401,8 +1431,8 @@ module ApplicationHelper |
| 1401 | 1431 | end |
| 1402 | 1432 | |
| 1403 | 1433 | def filter_html(html, source) |
| 1404 | - if @plugins && source.has_macro? | |
| 1405 | - html = convert_macro(html, source) | |
| 1434 | + if @plugins && source && source.has_macro? | |
| 1435 | + html = convert_macro(html, source) unless @plugins.enabled_macros.blank? | |
| 1406 | 1436 | #TODO This parse should be done through the macro infra, but since there |
| 1407 | 1437 | # are old things that do not support it we are keeping this hot spot. |
| 1408 | 1438 | html = @plugins.pipeline(:parse_content, html, source).first | ... | ... |
app/helpers/blog_helper.rb
| ... | ... | @@ -42,7 +42,7 @@ module BlogHelper |
| 42 | 42 | |
| 43 | 43 | def display_post(article, format = 'full') |
| 44 | 44 | no_comments = (format == 'full') ? false : true |
| 45 | - html = send("display_#{format}_format", article).html_safe | |
| 45 | + html = send("display_#{format}_format", FilePresenter.for(article)).html_safe | |
| 46 | 46 | |
| 47 | 47 | article_title(article, :no_comments => no_comments) + html |
| 48 | 48 | end | ... | ... |
app/helpers/categories_helper.rb
| ... | ... | @@ -3,10 +3,21 @@ module CategoriesHelper |
| 3 | 3 | |
| 4 | 4 | COLORS = [ |
| 5 | 5 | [ N_('Do not display at the menu'), nil ], |
| 6 | - [ N_('Orange'), 1 ], | |
| 7 | - [ N_('Green'), 2 ], | |
| 8 | - [ N_('Purple'), 3 ], | |
| 9 | - [ N_('Red'), 4 ], | |
| 6 | + [ N_('Orange'), 1], | |
| 7 | + [ N_('Green'), 2], | |
| 8 | + [ N_('Purple'), 3], | |
| 9 | + [ N_('Red'), 4], | |
| 10 | + [ N_('Dark Green'), 5], | |
| 11 | + [ N_('Blue Oil'), 6], | |
| 12 | + [ N_('Blue'), 7], | |
| 13 | + [ N_('Brown'), 8], | |
| 14 | + [ N_('Light Green'), 9], | |
| 15 | + [ N_('Light Blue'), 10], | |
| 16 | + [ N_('Dark Blue'), 11], | |
| 17 | + [ N_('Blue Pool'), 12], | |
| 18 | + [ N_('Beige'), 13], | |
| 19 | + [ N_('Yellow'), 14], | |
| 20 | + [ N_('Light Brown'), 15] | |
| 10 | 21 | ] |
| 11 | 22 | |
| 12 | 23 | TYPES = [ | ... | ... |
app/helpers/cms_helper.rb
| ... | ... | @@ -33,7 +33,7 @@ module CmsHelper |
| 33 | 33 | link_to article_name, {:action => 'view', :id => article.id}, :class => icon_for_article(article) |
| 34 | 34 | else |
| 35 | 35 | if article.image? |
| 36 | - image_tag(icon_for_article(article)) + link_to(article_name, article.url) | |
| 36 | + image_tag(icon_for_article(article)) + link_to(article_name, article.url) | |
| 37 | 37 | else |
| 38 | 38 | link_to article_name, article.url, :class => icon_for_article(article) |
| 39 | 39 | end | ... | ... |
app/helpers/content_viewer_helper.rb
| ... | ... | @@ -17,7 +17,7 @@ module ContentViewerHelper |
| 17 | 17 | title = article.display_title if article.kind_of?(UploadedFile) && article.image? |
| 18 | 18 | title = article.title if title.blank? |
| 19 | 19 | title = content_tag('h1', h(title), :class => 'title') |
| 20 | - if article.belongs_to_blog? | |
| 20 | + if article.belongs_to_blog? || article.belongs_to_forum? | |
| 21 | 21 | unless args[:no_link] |
| 22 | 22 | title = content_tag('h1', link_to(article.name, article.url), :class => 'title') |
| 23 | 23 | end | ... | ... |
app/helpers/dates_helper.rb
| ... | ... | @@ -35,6 +35,18 @@ module DatesHelper |
| 35 | 35 | end |
| 36 | 36 | end |
| 37 | 37 | |
| 38 | + def show_date_month(date, use_numbers = false, year=true) | |
| 39 | + if date && use_numbers | |
| 40 | + date_format = year ? _('%{month}/%{year}') : _('%{month}/%{day}') | |
| 41 | + date_format % { :month => date.month, :year => date.year } | |
| 42 | + elsif date | |
| 43 | + date_format = year ? _('%{month_name}, %{year}') : _('%{month_name}') | |
| 44 | + date_format % { :month_name => month_name(date.month), :year => date.year } | |
| 45 | + else | |
| 46 | + '' | |
| 47 | + end | |
| 48 | + end | |
| 49 | + | |
| 38 | 50 | # formats a datetime for displaying. |
| 39 | 51 | def show_time(time) |
| 40 | 52 | if time |
| ... | ... | @@ -98,7 +110,11 @@ module DatesHelper |
| 98 | 110 | elsif opts[:previous] |
| 99 | 111 | date = date << 1 |
| 100 | 112 | end |
| 101 | - _('%{month} %{year}') % { :year => date.year, :month => month_name(date.month.to_i) } | |
| 113 | + if opts[:only_month] | |
| 114 | + _('%{month}') % {:month => month_name(date.month.to_i) } | |
| 115 | + else | |
| 116 | + _('%{month} %{year}') % { :year => date.year, :month => month_name(date.month.to_i) } | |
| 117 | + end | |
| 102 | 118 | end |
| 103 | 119 | |
| 104 | 120 | def build_date(year, month, day = 1) |
| ... | ... | @@ -123,7 +139,7 @@ module DatesHelper |
| 123 | 139 | previous_month_date = date - 1.month |
| 124 | 140 | |
| 125 | 141 | label ||= show_month(previous_month_date.year, previous_month_date.month) |
| 126 | - link_to label, :year => previous_month_date.year, :month => previous_month_date.month | |
| 142 | + button(:back, label, {:year => previous_month_date.year, :month => previous_month_date.month}) | |
| 127 | 143 | end |
| 128 | 144 | |
| 129 | 145 | def link_to_next_month(year, month, label = nil) |
| ... | ... | @@ -131,7 +147,7 @@ module DatesHelper |
| 131 | 147 | next_month_date = date + 1.month |
| 132 | 148 | |
| 133 | 149 | label ||= show_month(next_month_date.year, next_month_date.month) |
| 134 | - link_to label, :year => next_month_date.year, :month => next_month_date.month | |
| 150 | + button(:next, label, {:year => next_month_date.year, :month => next_month_date.month}) | |
| 135 | 151 | end |
| 136 | 152 | |
| 137 | 153 | def pick_date(object, method, options = {}, html_options = {}) | ... | ... |
app/helpers/events_helper.rb
| 1 | 1 | module EventsHelper |
| 2 | 2 | |
| 3 | 3 | def list_events(date, events) |
| 4 | - return content_tag('em', _("Select a day on the left to display it's events here"), :class => 'select-a-day') unless date | |
| 5 | - title = _('Events for %s') % show_date(date) | |
| 4 | + title = _('Events for %s') % show_date_month(date) | |
| 6 | 5 | content_tag('h2', title) + |
| 7 | 6 | content_tag('div', |
| 8 | 7 | (events.any? ? |
| 9 | 8 | content_tag('table', events.select { |item| item.display_to?(user) }.map {|item| display_event_in_listing(item)}.join('')) : |
| 10 | - content_tag('em', _('No events for this date'), :class => 'no-events') | |
| 9 | + content_tag('em', _('No events for this month'), :class => 'no-events') | |
| 11 | 10 | ), :id => 'agenda-items' |
| 12 | 11 | ) |
| 13 | 12 | end |
| 14 | 13 | |
| 15 | 14 | def display_event_in_listing(article) |
| 16 | - content_tag( | |
| 17 | - 'tr', | |
| 18 | - content_tag('td', link_to(article.name, article.url, :class => icon_for_article(article))), | |
| 19 | - :class => 'agenda-item' | |
| 15 | + | |
| 16 | + content_tag( 'tr', | |
| 17 | + content_tag('td', | |
| 18 | + content_tag('div', show_date(article.start_date) + ( article.end_date.nil? ? '' : (_(" to ") + show_date(article.end_date))),:class => 'event-date' ) + | |
| 19 | + content_tag('div',link_to(article.name,article.url),:class => 'event-title') + | |
| 20 | + content_tag('div',(article.address.nil? or article.address == '') ? '' : (_('Place: ') + article.address),:class => 'event-place') | |
| 21 | + ) | |
| 20 | 22 | ) |
| 21 | 23 | end |
| 22 | 24 | ... | ... |
app/helpers/folder_helper.rb
| ... | ... | @@ -21,6 +21,7 @@ module FolderHelper |
| 21 | 21 | end |
| 22 | 22 | |
| 23 | 23 | def display_article_in_listing(article, recursive = false, level = 0) |
| 24 | + article = FilePresenter.for article | |
| 24 | 25 | article_link = if article.image? |
| 25 | 26 | link_to(' ' * (level * 4) + image_tag(icon_for_article(article)) + short_filename(article.name), article.url.merge(:view => true)) |
| 26 | 27 | else |
| ... | ... | @@ -40,12 +41,15 @@ module FolderHelper |
| 40 | 41 | end |
| 41 | 42 | |
| 42 | 43 | def icon_for_article(article) |
| 43 | - icon = article.class.icon_name(article) | |
| 44 | + article = FilePresenter.for article | |
| 45 | + icon = article.respond_to?(:icon_name) ? | |
| 46 | + article.icon_name : | |
| 47 | + article.class.icon_name(article) | |
| 44 | 48 | if (icon =~ /\//) |
| 45 | 49 | icon |
| 46 | 50 | else |
| 47 | - klasses = 'icon icon-' + icon | |
| 48 | - if article.kind_of?(UploadedFile) | |
| 51 | + klasses = 'icon ' + [icon].flatten.map{|name| 'icon-'+name}.join(' ') | |
| 52 | + if article.kind_of?(UploadedFile) || article.kind_of?(FilePresenter) | |
| 49 | 53 | klasses += ' icon-upload-file' |
| 50 | 54 | end |
| 51 | 55 | klasses | ... | ... |
app/helpers/sweeper_helper.rb
| ... | ... | @@ -44,4 +44,30 @@ module SweeperHelper |
| 44 | 44 | def expire_profile_index(profile) |
| 45 | 45 | expire_timeout_fragment(profile.relationships_cache_key) |
| 46 | 46 | end |
| 47 | + | |
| 48 | + def expire_blocks_cache(context, causes) | |
| 49 | + if context.kind_of?(Profile) | |
| 50 | + profile = context | |
| 51 | + environment = profile.environment | |
| 52 | + else | |
| 53 | + environment = context | |
| 54 | + profile = nil | |
| 55 | + end | |
| 56 | + | |
| 57 | + blocks_to_expire = [] | |
| 58 | + if profile | |
| 59 | + profile.blocks.each {|block| | |
| 60 | + conditions = block.class.expire_on | |
| 61 | + blocks_to_expire << block unless (conditions[:profile] & causes).empty? | |
| 62 | + } | |
| 63 | + end | |
| 64 | + environment.blocks.each {|block| | |
| 65 | + conditions = block.class.expire_on | |
| 66 | + blocks_to_expire << block unless (conditions[:environment] & causes).empty? | |
| 67 | + } | |
| 68 | + | |
| 69 | + blocks_to_expire.uniq! | |
| 70 | + BlockSweeper.expire_blocks(blocks_to_expire) | |
| 71 | + end | |
| 72 | + | |
| 47 | 73 | end | ... | ... |
app/models/article.rb
| ... | ... | @@ -2,6 +2,8 @@ require 'hpricot' |
| 2 | 2 | |
| 3 | 3 | class Article < ActiveRecord::Base |
| 4 | 4 | |
| 5 | + acts_as_having_image | |
| 6 | + | |
| 5 | 7 | SEARCHABLE_FIELDS = { |
| 6 | 8 | :name => 10, |
| 7 | 9 | :abstract => 3, |
| ... | ... | @@ -154,8 +156,12 @@ class Article < ActiveRecord::Base |
| 154 | 156 | end |
| 155 | 157 | end |
| 156 | 158 | |
| 159 | + def css_class_list | |
| 160 | + [self.class.name.underscore.dasherize] | |
| 161 | + end | |
| 162 | + | |
| 157 | 163 | def css_class_name |
| 158 | - self.class.name.underscore.dasherize | |
| 164 | + [css_class_list].flatten.compact.join(' ') | |
| 159 | 165 | end |
| 160 | 166 | |
| 161 | 167 | def pending_categorizations |
| ... | ... | @@ -188,7 +194,7 @@ class Article < ActiveRecord::Base |
| 188 | 194 | pending_categorizations.clear |
| 189 | 195 | end |
| 190 | 196 | |
| 191 | - acts_as_taggable | |
| 197 | + acts_as_taggable | |
| 192 | 198 | N_('Tag list') |
| 193 | 199 | |
| 194 | 200 | acts_as_filesystem |
| ... | ... | @@ -268,7 +274,7 @@ class Article < ActiveRecord::Base |
| 268 | 274 | end |
| 269 | 275 | |
| 270 | 276 | # returns the data of the article. Must be overriden in each subclass to |
| 271 | - # provide the correct content for the article. | |
| 277 | + # provide the correct content for the article. | |
| 272 | 278 | def data |
| 273 | 279 | body |
| 274 | 280 | end |
| ... | ... | @@ -310,6 +316,10 @@ class Article < ActiveRecord::Base |
| 310 | 316 | def belongs_to_blog? |
| 311 | 317 | self.parent and self.parent.blog? |
| 312 | 318 | end |
| 319 | + | |
| 320 | + def belongs_to_forum? | |
| 321 | + self.parent and self.parent.forum? | |
| 322 | + end | |
| 313 | 323 | |
| 314 | 324 | def info_from_last_update |
| 315 | 325 | last_comment = comments.last |
| ... | ... | @@ -325,7 +335,7 @@ class Article < ActiveRecord::Base |
| 325 | 335 | end |
| 326 | 336 | |
| 327 | 337 | def view_url |
| 328 | - @view_url ||= image? ? url.merge(:view => true) : url | |
| 338 | + @view_url ||= is_a?(UploadedFile) ? url.merge(:view => true) : url | |
| 329 | 339 | end |
| 330 | 340 | |
| 331 | 341 | def comment_url_structure(comment, action = :edit) |
| ... | ... | @@ -360,6 +370,16 @@ class Article < ActiveRecord::Base |
| 360 | 370 | false |
| 361 | 371 | end |
| 362 | 372 | |
| 373 | + def download? view = nil | |
| 374 | + (self.uploaded_file? and not self.image?) or | |
| 375 | + (self.image? and view.blank?) or | |
| 376 | + (not self.uploaded_file? and self.mime_type != 'text/html') | |
| 377 | + end | |
| 378 | + | |
| 379 | + def download_headers | |
| 380 | + {} | |
| 381 | + end | |
| 382 | + | |
| 363 | 383 | named_scope :native_translations, :conditions => { :translation_of_id => nil } |
| 364 | 384 | |
| 365 | 385 | def translatable? | ... | ... |
app/models/article_block.rb
| ... | ... | @@ -12,7 +12,7 @@ class ArticleBlock < Block |
| 12 | 12 | block = self |
| 13 | 13 | lambda do |
| 14 | 14 | block_title(block.title) + |
| 15 | - (block.article ? article_to_html(block.article, | |
| 15 | + (block.article ? article_to_html(FilePresenter.for(block.article), | |
| 16 | 16 | :gallery_view => false, |
| 17 | 17 | :inside_block => block, # For Blogs and folders |
| 18 | 18 | :format => block.visualization_format # For Articles and contents |
| ... | ... | @@ -23,7 +23,7 @@ class ArticleBlock < Block |
| 23 | 23 | def article_id |
| 24 | 24 | self.settings[:article_id] |
| 25 | 25 | end |
| 26 | - | |
| 26 | + | |
| 27 | 27 | def article_id= value |
| 28 | 28 | self.settings[:article_id] = value.blank? ? nil : value.to_i |
| 29 | 29 | end |
| ... | ... | @@ -63,4 +63,9 @@ class ArticleBlock < Block |
| 63 | 63 | end |
| 64 | 64 | |
| 65 | 65 | settings_items :visualization_format, :type => :string, :default => 'short' |
| 66 | + | |
| 67 | + def self.expire_on | |
| 68 | + { :profile => [:article], :environment => [:article] } | |
| 69 | + end | |
| 70 | + | |
| 66 | 71 | end | ... | ... |
app/models/block.rb
| ... | ... | @@ -142,4 +142,15 @@ class Block < ActiveRecord::Base |
| 142 | 142 | false |
| 143 | 143 | end |
| 144 | 144 | |
| 145 | + # Override in your subclasses. | |
| 146 | + # Define which events and context should cause the block cache to expire | |
| 147 | + # Possible events are: :article, :profile, :friendship, :category | |
| 148 | + # Possible contexts are: :profile, :environment | |
| 149 | + def self.expire_on | |
| 150 | + { | |
| 151 | + :profile => [], | |
| 152 | + :environment => [] | |
| 153 | + } | |
| 154 | + end | |
| 155 | + | |
| 145 | 156 | end | ... | ... |
app/models/blog_archives_block.rb
app/models/categories_block.rb
app/models/category.rb
| ... | ... | @@ -7,13 +7,13 @@ class Category < ActiveRecord::Base |
| 7 | 7 | :slug => 1, |
| 8 | 8 | } |
| 9 | 9 | |
| 10 | - validates_exclusion_of :slug, :in => [ 'index' ], :message => N_('%{fn} cannot be like that.').fix_i18n | |
| 10 | + validates_exclusion_of :slug, :in => [ 'index' ], :message => N_('{fn} cannot be like that.').fix_i18n | |
| 11 | 11 | validates_presence_of :name, :environment_id |
| 12 | - validates_uniqueness_of :slug,:scope => [ :environment_id, :parent_id ], :message => N_('%{fn} is already being used by another category.').fix_i18n | |
| 12 | + validates_uniqueness_of :slug,:scope => [ :environment_id, :parent_id ], :message => N_('{fn} is already being used by another category.').fix_i18n | |
| 13 | 13 | belongs_to :environment |
| 14 | 14 | |
| 15 | - validates_inclusion_of :display_color, :in => [ 1, 2, 3, 4, nil ] | |
| 16 | - validates_uniqueness_of :display_color, :scope => :environment_id, :if => (lambda { |cat| ! cat.display_color.nil? }), :message => N_('%{fn} was already assigned to another category.').fix_i18n | |
| 15 | + validates_inclusion_of :display_color, :in => 1..15, :allow_nil => true | |
| 16 | + validates_uniqueness_of :display_color, :scope => :environment_id, :if => (lambda { |cat| ! cat.display_color.nil? }), :message => N_('{fn} was already assigned to another category.').fix_i18n | |
| 17 | 17 | |
| 18 | 18 | # Finds all top level categories for a given environment. |
| 19 | 19 | named_scope :top_level_for, lambda { |environment| | ... | ... |
app/models/comment.rb
| ... | ... | @@ -16,9 +16,7 @@ class Comment < ActiveRecord::Base |
| 16 | 16 | has_many :children, :class_name => 'Comment', :foreign_key => 'reply_of_id', :dependent => :destroy |
| 17 | 17 | belongs_to :reply_of, :class_name => 'Comment', :foreign_key => 'reply_of_id' |
| 18 | 18 | |
| 19 | - named_scope :without_spam, :conditions => ['spam IS NULL OR spam = ?', false] | |
| 20 | 19 | named_scope :without_reply, :conditions => ['reply_of_id IS NULL'] |
| 21 | - named_scope :spam, :conditions => ['spam = ?', true] | |
| 22 | 20 | |
| 23 | 21 | # unauthenticated authors: |
| 24 | 22 | validates_presence_of :name, :if => (lambda { |record| !record.email.blank? }) |
| ... | ... | @@ -29,7 +27,7 @@ class Comment < ActiveRecord::Base |
| 29 | 27 | validates_presence_of :author_id, :if => (lambda { |rec| rec.name.blank? && rec.email.blank? }) |
| 30 | 28 | validates_each :name do |rec,attribute,value| |
| 31 | 29 | if rec.author_id && (!rec.name.blank? || !rec.email.blank?) |
| 32 | - rec.errors.add(:name, _('%{fn} can only be informed for unauthenticated authors').fix_i18n) | |
| 30 | + rec.errors.add(:name, _('{fn} can only be informed for unauthenticated authors').fix_i18n) | |
| 33 | 31 | end |
| 34 | 32 | end |
| 35 | 33 | |
| ... | ... | @@ -108,6 +106,17 @@ class Comment < ActiveRecord::Base |
| 108 | 106 | |
| 109 | 107 | include Noosfero::Plugin::HotSpot |
| 110 | 108 | |
| 109 | + include Spammable | |
| 110 | + | |
| 111 | + def after_spam! | |
| 112 | + SpammerLogger.log(ip_address, self) | |
| 113 | + Delayed::Job.enqueue(CommentHandler.new(self.id, :marked_as_spam)) | |
| 114 | + end | |
| 115 | + | |
| 116 | + def after_ham! | |
| 117 | + Delayed::Job.enqueue(CommentHandler.new(self.id, :marked_as_ham)) | |
| 118 | + end | |
| 119 | + | |
| 111 | 120 | def verify_and_notify |
| 112 | 121 | check_for_spam |
| 113 | 122 | unless spam? |
| ... | ... | @@ -115,10 +124,6 @@ class Comment < ActiveRecord::Base |
| 115 | 124 | end |
| 116 | 125 | end |
| 117 | 126 | |
| 118 | - def check_for_spam | |
| 119 | - plugins.dispatch(:check_comment_for_spam, self) | |
| 120 | - end | |
| 121 | - | |
| 122 | 127 | def notify_by_mail |
| 123 | 128 | if source.kind_of?(Article) && article.notify_comments? |
| 124 | 129 | if !notification_emails.empty? |
| ... | ... | @@ -205,37 +210,6 @@ class Comment < ActiveRecord::Base |
| 205 | 210 | @rejected = true |
| 206 | 211 | end |
| 207 | 212 | |
| 208 | - def spam? | |
| 209 | - !spam.nil? && spam | |
| 210 | - end | |
| 211 | - | |
| 212 | - def ham? | |
| 213 | - !spam.nil? && !spam | |
| 214 | - end | |
| 215 | - | |
| 216 | - def spam! | |
| 217 | - self.spam = true | |
| 218 | - self.save! | |
| 219 | - SpammerLogger.log(ip_address, self) | |
| 220 | - Delayed::Job.enqueue(CommentHandler.new(self.id, :marked_as_spam)) | |
| 221 | - self | |
| 222 | - end | |
| 223 | - | |
| 224 | - def ham! | |
| 225 | - self.spam = false | |
| 226 | - self.save! | |
| 227 | - Delayed::Job.enqueue(CommentHandler.new(self.id, :marked_as_ham)) | |
| 228 | - self | |
| 229 | - end | |
| 230 | - | |
| 231 | - def marked_as_spam | |
| 232 | - plugins.dispatch(:comment_marked_as_spam, self) | |
| 233 | - end | |
| 234 | - | |
| 235 | - def marked_as_ham | |
| 236 | - plugins.dispatch(:comment_marked_as_ham, self) | |
| 237 | - end | |
| 238 | - | |
| 239 | 213 | def need_moderation? |
| 240 | 214 | article.moderate_comments? && (author.nil? || article.author != author) |
| 241 | 215 | end | ... | ... |
app/models/create_enterprise.rb
| ... | ... | @@ -40,12 +40,12 @@ class CreateEnterprise < Task |
| 40 | 40 | |
| 41 | 41 | if self.region && self.target |
| 42 | 42 | unless self.region.validators.include?(self.target) || self.target_type == "Environment" |
| 43 | - self.errors.add(:target, _('%{fn} is not a validator for the chosen region').fix_i18n) | |
| 43 | + self.errors.add(:target, _('{fn} is not a validator for the chosen region').fix_i18n) | |
| 44 | 44 | end |
| 45 | 45 | end |
| 46 | 46 | |
| 47 | 47 | if self.status != Task::Status::CANCELLED && self.identifier && Profile.exists?(:identifier => self.identifier) |
| 48 | - self.errors.add(:identifier, _('%{fn} is already being as identifier by another enterprise, organization or person.').fix_i18n) | |
| 48 | + self.errors.add(:identifier, _('{fn} is already being as identifier by another enterprise, organization or person.').fix_i18n) | |
| 49 | 49 | end |
| 50 | 50 | end |
| 51 | 51 | ... | ... |
app/models/domain.rb
| ... | ... | @@ -10,14 +10,14 @@ class Domain < ActiveRecord::Base |
| 10 | 10 | |
| 11 | 11 | # <tt>name</tt> must be sequences of alphanumeric characters (a to z, |
| 12 | 12 | # 0 to 9), plus '_' or '-', separated by dots. Letters must be lowercase. |
| 13 | - validates_format_of :name, :with => /^([a-z0-9_-]+\.)+[a-z0-9_-]+$/, :message => N_('%{fn} must be composed of sequences of lowercase letters (a to z), numbers (0 to 9), "_" and "-", separated by dots.').fix_i18n | |
| 13 | + validates_format_of :name, :with => /^([a-z0-9_-]+\.)+[a-z0-9_-]+$/, :message => N_('{fn} must be composed of sequences of lowercase letters (a to z), numbers (0 to 9), "_" and "-", separated by dots.').fix_i18n | |
| 14 | 14 | |
| 15 | 15 | # checks validations that could not be expressed using Rails' predefined |
| 16 | 16 | # validations. In particular: |
| 17 | 17 | # * <tt>name</tt> must not start with 'www.' |
| 18 | 18 | def validate |
| 19 | 19 | if self.name =~ /^www\./ |
| 20 | - self.errors.add(:name, _('%{fn} must not start with www.').fix_i18n) | |
| 20 | + self.errors.add(:name, _('{fn} must not start with www.').fix_i18n) | |
| 21 | 21 | end |
| 22 | 22 | end |
| 23 | 23 | ... | ... |
app/models/environment.rb
| ... | ... | @@ -127,7 +127,9 @@ class Environment < ActiveRecord::Base |
| 127 | 127 | 'captcha_for_logged_users' => _('Ask captcha when a logged user comments too'), |
| 128 | 128 | 'skip_new_user_email_confirmation' => _('Skip e-mail confirmation for new users'), |
| 129 | 129 | 'send_welcome_email_to_new_users' => _('Send welcome e-mail to new users'), |
| 130 | - 'allow_change_of_redirection_after_login' => _('Allow users to set the page to redirect after login') | |
| 130 | + 'allow_change_of_redirection_after_login' => _('Allow users to set the page to redirect after login'), | |
| 131 | + 'display_my_communities_on_user_menu' => _('Display on menu the list of communities the user can manage'), | |
| 132 | + 'display_my_enterprises_on_user_menu' => _('Display on menu the list of enterprises the user can manage') | |
| 131 | 133 | } |
| 132 | 134 | end |
| 133 | 135 | |
| ... | ... | @@ -168,7 +170,7 @@ class Environment < ActiveRecord::Base |
| 168 | 170 | |
| 169 | 171 | # One Environment can be reached by many domains |
| 170 | 172 | has_many :domains, :as => :owner |
| 171 | - has_many :profiles | |
| 173 | + has_many :profiles, :dependent => :destroy | |
| 172 | 174 | |
| 173 | 175 | has_many :organizations |
| 174 | 176 | has_many :enterprises |
| ... | ... | @@ -783,13 +785,6 @@ class Environment < ActiveRecord::Base |
| 783 | 785 | self.save! |
| 784 | 786 | end |
| 785 | 787 | |
| 786 | - after_destroy :destroy_templates | |
| 787 | - def destroy_templates | |
| 788 | - [enterprise_template, inactive_enterprise_template, community_template, person_template].compact.each do |template| | |
| 789 | - template.destroy | |
| 790 | - end | |
| 791 | - end | |
| 792 | - | |
| 793 | 788 | after_create :create_default_licenses |
| 794 | 789 | def create_default_licenses |
| 795 | 790 | License.create!(:name => 'CC (by)', :url => 'http://creativecommons.org/licenses/by/3.0/legalcode', :environment => self) | ... | ... |
app/models/event.rb
| ... | ... | @@ -25,12 +25,30 @@ class Event < Article |
| 25 | 25 | |
| 26 | 26 | validates_each :start_date do |event,field,value| |
| 27 | 27 | if event.end_date && event.start_date && event.start_date > event.end_date |
| 28 | - event.errors.add(:start_date, _('%{fn} cannot come before end date.').fix_i18n) | |
| 28 | + event.errors.add(:start_date, _('{fn} cannot come before end date.').fix_i18n) | |
| 29 | 29 | end |
| 30 | 30 | end |
| 31 | 31 | |
| 32 | 32 | named_scope :by_day, lambda { |date| |
| 33 | - {:conditions => ['start_date = :date AND end_date IS NULL OR (start_date <= :date AND end_date >= :date)', {:date => date}]} | |
| 33 | + { :conditions => ['start_date = :date AND end_date IS NULL OR (start_date <= :date AND end_date >= :date)', {:date => date}], | |
| 34 | + :order => 'start_date ASC' | |
| 35 | + } | |
| 36 | + } | |
| 37 | + | |
| 38 | + named_scope :next_events_from_month, lambda { |date| | |
| 39 | + date_temp = date.strftime("%Y-%m-%d") | |
| 40 | + { :conditions => ["start_date >= ?","#{date_temp}"], | |
| 41 | + :limit => 10, | |
| 42 | + :order => 'start_date ASC' | |
| 43 | + } | |
| 44 | + } | |
| 45 | + | |
| 46 | + named_scope :by_month, lambda { |date| | |
| 47 | + date_temp = date.strftime("%Y-%m") | |
| 48 | + { :conditions => ["EXTRACT(YEAR FROM start_date) = ? AND EXTRACT(MONTH FROM start_date) = ?",date.year,date.month], | |
| 49 | + :limit => 10, | |
| 50 | + :order => 'start_date ASC' | |
| 51 | + } | |
| 34 | 52 | } |
| 35 | 53 | |
| 36 | 54 | include WhiteListFilter |
| ... | ... | @@ -105,7 +123,7 @@ class Event < Article |
| 105 | 123 | |
| 106 | 124 | # TODO: some good soul, please clean this ugly hack: |
| 107 | 125 | if self.body |
| 108 | - html.div('_____XXXX_DESCRIPTION_GOES_HERE_XXXX_____', :class => 'event-description') | |
| 126 | + html.div('_____XXXX_DESCRIPTION_GOES_HERE_XXXX_____', :class => 'event-description') | |
| 109 | 127 | end |
| 110 | 128 | } |
| 111 | 129 | ... | ... |
app/models/image.rb
| ... | ... | @@ -17,7 +17,7 @@ class Image < ActiveRecord::Base |
| 17 | 17 | :icon => '20x20!' }, |
| 18 | 18 | :max_size => 5.megabytes # remember to update validate message below |
| 19 | 19 | |
| 20 | - validates_attachment :size => N_("%{fn} of uploaded file was larger than the maximum size of 5.0 MB").fix_i18n | |
| 20 | + validates_attachment :size => N_("{fn} of uploaded file was larger than the maximum size of 5.0 MB").fix_i18n | |
| 21 | 21 | |
| 22 | 22 | delay_attachment_fu_thumbnails |
| 23 | 23 | ... | ... |
app/models/link_list_block.rb
| ... | ... | @@ -33,6 +33,12 @@ class LinkListBlock < Block |
| 33 | 33 | ['chat', N_('Chat')] |
| 34 | 34 | ] |
| 35 | 35 | |
| 36 | + TARGET_OPTIONS = [ | |
| 37 | + [N_('Same page'), '_self'], | |
| 38 | + [N_('New tab'), '_blank'], | |
| 39 | + [N_('New window'), '_new'], | |
| 40 | + ] | |
| 41 | + | |
| 36 | 42 | settings_items :links, Array, :default => [] |
| 37 | 43 | |
| 38 | 44 | before_save do |block| |
| ... | ... | @@ -57,7 +63,7 @@ class LinkListBlock < Block |
| 57 | 63 | def link_html(link) |
| 58 | 64 | klass = 'icon-' + link[:icon] if link[:icon] |
| 59 | 65 | sanitize_link( |
| 60 | - link_to(link[:name], expand_address(link[:address]), :class => klass) | |
| 66 | + link_to(link[:name], expand_address(link[:address]), :target => link[:target], :class => klass) | |
| 61 | 67 | ) |
| 62 | 68 | end |
| 63 | 69 | ... | ... |
app/models/person.rb
| ... | ... | @@ -240,7 +240,7 @@ class Person < Profile |
| 240 | 240 | |
| 241 | 241 | validates_each :email, :on => :update do |record,attr,value| |
| 242 | 242 | if User.find(:first, :conditions => ['email = ? and id != ? and environment_id = ?', value, record.user.id, record.environment.id]) |
| 243 | - record.errors.add(attr, _('%{fn} is already used by other user').fix_i18n) | |
| 243 | + record.errors.add(attr, _('{fn} is already used by other user').fix_i18n) | |
| 244 | 244 | end |
| 245 | 245 | end |
| 246 | 246 | ... | ... |
app/models/profile.rb
| ... | ... | @@ -193,7 +193,7 @@ class Profile < ActiveRecord::Base |
| 193 | 193 | |
| 194 | 194 | has_many :tasks, :dependent => :destroy, :as => 'target' |
| 195 | 195 | |
| 196 | - has_many :events, :source => 'articles', :class_name => 'Event', :order => 'name' | |
| 196 | + has_many :events, :source => 'articles', :class_name => 'Event', :order => 'start_date' | |
| 197 | 197 | |
| 198 | 198 | def find_in_all_tasks(task_id) |
| 199 | 199 | begin | ... | ... |
app/models/recent_documents_block.rb
app/models/spammer_logger.rb
| ... | ... | @@ -6,6 +6,8 @@ class SpammerLogger < Logger |
| 6 | 6 | if object |
| 7 | 7 | if object.kind_of?(Comment) |
| 8 | 8 | @logger << "[#{Time.now.strftime('%F %T %z')}] Comment-id: #{object.id} IP: #{spammer_ip}\n" |
| 9 | + elsif object.kind_of?(SuggestArticle) | |
| 10 | + @logger << "[#{Time.now.strftime('%F %T %z')}] SuggestArticle-id: #{object.id} IP: #{spammer_ip}\n" | |
| 9 | 11 | end |
| 10 | 12 | else |
| 11 | 13 | @logger << "[#{Time.now.strftime('%F %T %z')}] IP: #{spammer_ip}\n" | ... | ... |
app/models/suggest_article.rb
| ... | ... | @@ -11,6 +11,17 @@ class SuggestArticle < Task |
| 11 | 11 | settings_items :source, :type => String |
| 12 | 12 | settings_items :source_name, :type => String |
| 13 | 13 | settings_items :highlighted, :type => :boolean, :default => false |
| 14 | + settings_items :ip_address, :type => String | |
| 15 | + settings_items :user_agent, :type => String | |
| 16 | + settings_items :referrer, :type => String | |
| 17 | + | |
| 18 | + after_create :schedule_spam_checking | |
| 19 | + | |
| 20 | + def schedule_spam_checking | |
| 21 | + self.delay.check_for_spam | |
| 22 | + end | |
| 23 | + | |
| 24 | + include Noosfero::Plugin::HotSpot | |
| 14 | 25 | |
| 15 | 26 | def sender |
| 16 | 27 | "#{name} (#{email})" |
| ... | ... | @@ -61,4 +72,12 @@ class SuggestArticle < Task |
| 61 | 72 | _('You need to login on %{system} in order to approve or reject this article.') % { :system => target.environment.name } |
| 62 | 73 | end |
| 63 | 74 | |
| 75 | + def after_spam! | |
| 76 | + SpammerLogger.log(ip_address, self) | |
| 77 | + self.delay.marked_as_spam | |
| 78 | + end | |
| 79 | + | |
| 80 | + def after_ham! | |
| 81 | + self.delay.marked_as_ham | |
| 82 | + end | |
| 64 | 83 | end | ... | ... |
app/models/tags_block.rb
app/models/task.rb
| ... | ... | @@ -235,6 +235,8 @@ class Task < ActiveRecord::Base |
| 235 | 235 | end |
| 236 | 236 | end |
| 237 | 237 | |
| 238 | + include Spammable | |
| 239 | + | |
| 238 | 240 | protected |
| 239 | 241 | |
| 240 | 242 | # This method must be overrided in subclasses, and its implementation must do |
| ... | ... | @@ -275,6 +277,7 @@ class Task < ActiveRecord::Base |
| 275 | 277 | named_scope :of, lambda { |type| conditions = type ? "type LIKE '#{type}'" : "1=1"; {:conditions => [conditions]} } |
| 276 | 278 | named_scope :order_by, lambda { |attribute, ord| {:order => "#{attribute} #{ord}"} } |
| 277 | 279 | |
| 280 | + | |
| 278 | 281 | named_scope :to, lambda { |profile| |
| 279 | 282 | environment_condition = nil |
| 280 | 283 | if profile.person? | ... | ... |
app/models/uploaded_file.rb
| ... | ... | @@ -41,7 +41,25 @@ class UploadedFile < Article |
| 41 | 41 | end |
| 42 | 42 | |
| 43 | 43 | def self.max_size |
| 44 | - UploadedFile.attachment_options[:max_size] | |
| 44 | + default = 5.megabytes | |
| 45 | + | |
| 46 | + multipliers = { | |
| 47 | + :KB => :kilobytes, | |
| 48 | + :MB => :megabytes, | |
| 49 | + :GB => :gigabytes, | |
| 50 | + :TB => :terabytes, | |
| 51 | + } | |
| 52 | + max_upload_size = NOOSFERO_CONF['max_upload_size'] | |
| 53 | + | |
| 54 | + if max_upload_size =~ /^(\d+(\.\d+)?)\s*(KB|MB|GB|TB)?$/ | |
| 55 | + number = $1.to_f | |
| 56 | + unit = $3 || :MB | |
| 57 | + multiplier = multipliers[unit.to_sym] | |
| 58 | + | |
| 59 | + number.send(multiplier).to_i | |
| 60 | + else | |
| 61 | + default | |
| 62 | + end | |
| 45 | 63 | end |
| 46 | 64 | |
| 47 | 65 | # FIXME need to define min/max file size |
| ... | ... | @@ -52,20 +70,28 @@ class UploadedFile < Article |
| 52 | 70 | has_attachment :storage => :file_system, |
| 53 | 71 | :thumbnails => { :icon => [24,24], :thumb => '130x130>', :slideshow => '320x240>', :display => '640X480>' }, |
| 54 | 72 | :thumbnail_class => Thumbnail, |
| 55 | - :max_size => 5.megabytes # remember to update validate message below | |
| 73 | + :max_size => self.max_size | |
| 56 | 74 | |
| 57 | - validates_attachment :size => N_("%{fn} of uploaded file was larger than the maximum size of 5.0 MB").fix_i18n | |
| 75 | + validates_attachment :size => N_("{fn} of uploaded file was larger than the maximum size of %{size}").sub('%{size}', self.max_size.to_humanreadable).fix_i18n | |
| 58 | 76 | |
| 59 | 77 | delay_attachment_fu_thumbnails |
| 60 | 78 | |
| 61 | 79 | postgresql_attachment_fu |
| 62 | 80 | |
| 81 | + # Use this method only to get the generic icon for this kind of content. | |
| 82 | + # If you want the specific icon for a file type or the iconified version | |
| 83 | + # of an image, use FilePresenter.for(uploaded_file).icon_name | |
| 63 | 84 | def self.icon_name(article = nil) |
| 64 | - if article | |
| 65 | - article.image? ? article.public_filename(:icon) : (article.mime_type ? article.mime_type.gsub(/[\/+.]/, '-') : 'upload-file') | |
| 66 | - else | |
| 67 | - 'upload-file' | |
| 85 | + unless article.nil? | |
| 86 | + warn = ('='*80) + "\n" + | |
| 87 | + 'The method `UploadedFile.icon_name(obj)` is deprecated. ' + | |
| 88 | + 'You must to encapsulate UploadedFile with `FilePresenter.for()`.' + | |
| 89 | + "\n" + ('='*80) | |
| 90 | + raise NoMethodError, warn if ENV['RAILS_ENV'] == 'test' | |
| 91 | + Rails.logger.warn warn if Rails.logger | |
| 92 | + puts warn if ENV['RAILS_ENV'] == 'development' | |
| 68 | 93 | end |
| 94 | + 'upload-file' | |
| 69 | 95 | end |
| 70 | 96 | |
| 71 | 97 | def mime_type |
| ... | ... | @@ -86,45 +112,38 @@ class UploadedFile < Article |
| 86 | 112 | self.name = self.filename |
| 87 | 113 | end |
| 88 | 114 | |
| 115 | + def download_headers | |
| 116 | + { | |
| 117 | + 'Content-Disposition' => "attachment; filename=\"#{self.filename}\"", | |
| 118 | + } | |
| 119 | + end | |
| 120 | + | |
| 89 | 121 | def data |
| 90 | 122 | File.read(self.full_filename) |
| 91 | 123 | end |
| 92 | 124 | |
| 93 | 125 | def to_html(options = {}) |
| 126 | + warn = ('='*80) + "\n" + | |
| 127 | + 'The method `UploadedFile#to_html()` is deprecated. ' + | |
| 128 | + 'You must to encapsulate UploadedFile with `FilePresenter.for()`.' + | |
| 129 | + "\n" + ('='*80) | |
| 130 | + raise NoMethodError, warn if ENV['RAILS_ENV'] == 'test' | |
| 131 | + Rails.logger.warn warn if Rails.logger | |
| 132 | + puts warn if ENV['RAILS_ENV'] == 'development' | |
| 94 | 133 | article = self |
| 95 | 134 | if image? |
| 96 | 135 | lambda do |
| 97 | - if article.gallery? && options[:gallery_view] | |
| 98 | - images = article.parent.images | |
| 99 | - current_index = images.index(article) | |
| 100 | - total_of_images = images.count | |
| 101 | - | |
| 102 | - link_to_previous = if current_index >= 1 | |
| 103 | - link_to(_('« Previous'), images[current_index - 1].view_url, :class => 'left') | |
| 104 | - else | |
| 105 | - content_tag('span', _('« Previous'), :class => 'left') | |
| 106 | - end | |
| 107 | - | |
| 108 | - link_to_next = if current_index < total_of_images - 1 | |
| 109 | - link_to(_('Next »'), images[current_index + 1].view_url, :class => 'right') | |
| 110 | - else | |
| 111 | - content_tag('span', _('Next »'), :class => 'right') | |
| 112 | - end | |
| 113 | - | |
| 114 | - content_tag( | |
| 115 | - 'div', | |
| 116 | - link_to_previous + (content_tag('span', _('image %d of %d'), :class => 'total-of-images') % [current_index + 1, total_of_images]).html_safe + link_to_next, | |
| 117 | - :class => 'gallery-navigation' | |
| 118 | - ) | |
| 119 | - end.to_s + | |
| 120 | - image_tag(article.public_filename(:display), :class => article.css_class_name, :style => 'max-width: 100%') + | |
| 121 | - content_tag('p', article.abstract, :class => 'uploaded-file-description') | |
| 122 | - | |
| 136 | + image_tag(article.public_filename(:display), | |
| 137 | + :class => article.css_class_name, | |
| 138 | + :style => 'max-width: 100%') + | |
| 139 | + content_tag('div', article.abstract, :class => 'uploaded-file-description') | |
| 123 | 140 | end |
| 124 | 141 | else |
| 125 | 142 | lambda do |
| 126 | - content_tag('ul', content_tag('li', link_to(article.name, article.url, :class => article.css_class_name))) + | |
| 127 | - content_tag('p', article.abstract, :class => 'uploaded-file-description') | |
| 143 | + content_tag('div', | |
| 144 | + link_to(article.name, article.url), | |
| 145 | + :class => article.css_class_name) + | |
| 146 | + content_tag('div', article.abstract, :class => 'uploaded-file-description') | |
| 128 | 147 | end |
| 129 | 148 | end |
| 130 | 149 | end | ... | ... |
app/models/user.rb
| ... | ... | @@ -114,7 +114,7 @@ class User < ActiveRecord::Base |
| 114 | 114 | before_save :encrypt_password |
| 115 | 115 | validates_format_of :email, :with => Noosfero::Constants::EMAIL_FORMAT, :if => (lambda {|user| !user.email.blank?}) |
| 116 | 116 | |
| 117 | - validates_inclusion_of :terms_accepted, :in => [ '1' ], :if => lambda { |u| ! u.terms_of_use.blank? }, :message => N_('%{fn} must be checked in order to signup.').fix_i18n | |
| 117 | + validates_inclusion_of :terms_accepted, :in => [ '1' ], :if => lambda { |u| ! u.terms_of_use.blank? }, :message => N_('{fn} must be checked in order to signup.').fix_i18n | |
| 118 | 118 | |
| 119 | 119 | # Authenticates a user by their login name or email and unencrypted password. Returns the user or nil. |
| 120 | 120 | def self.authenticate(login, password, environment = nil) | ... | ... |
| ... | ... | @@ -0,0 +1,14 @@ |
| 1 | +class FilePresenter::Image < FilePresenter | |
| 2 | + def self.accepts?(f) | |
| 3 | + return nil unless f.respond_to? :image? | |
| 4 | + f.image? ? 10 : nil | |
| 5 | + end | |
| 6 | + | |
| 7 | + def icon_name | |
| 8 | + public_filename :icon | |
| 9 | + end | |
| 10 | + | |
| 11 | + def short_description | |
| 12 | + _('Image (%s)') % content_type.split('/')[1].upcase | |
| 13 | + end | |
| 14 | +end | ... | ... |
app/sweepers/article_sweeper.rb
| ... | ... | @@ -16,15 +16,15 @@ class ArticleSweeper < ActiveRecord::Observer |
| 16 | 16 | end |
| 17 | 17 | end |
| 18 | 18 | |
| 19 | + | |
| 19 | 20 | protected |
| 20 | 21 | |
| 21 | 22 | def expire_caches(article) |
| 23 | + expire_blocks_cache(article.profile, [:article]) | |
| 24 | + | |
| 22 | 25 | return if !article.environment |
| 26 | + | |
| 23 | 27 | article.hierarchy(true).each { |a| a.touch if a != article } |
| 24 | - blocks = article.profile.blocks | |
| 25 | - blocks += article.profile.environment.blocks if article.profile.environment | |
| 26 | - blocks = blocks.select{|b|[RecentDocumentsBlock, BlogArchivesBlock].any?{|c| b.kind_of?(c)}} | |
| 27 | - BlockSweeper.expire_blocks(blocks) | |
| 28 | 28 | env = article.profile.environment |
| 29 | 29 | if env && (env.portal_community == article.profile) |
| 30 | 30 | article.environment.locales.keys.each do |locale| | ... | ... |
app/sweepers/category_sweeper.rb
| ... | ... | @@ -3,7 +3,13 @@ class CategorySweeper < ActiveRecord::Observer |
| 3 | 3 | include SweeperHelper |
| 4 | 4 | |
| 5 | 5 | def after_save(category) |
| 6 | + expire_blocks_cache(category.environment, [:category]) | |
| 7 | + | |
| 8 | + # Needed for environments with application layout | |
| 6 | 9 | expire_fragment(category.environment.id.to_s + "_categories_menu") |
| 7 | 10 | end |
| 8 | 11 | |
| 12 | + def after_destroy(category) | |
| 13 | + expire_blocks_cache(category.environment, [:category]) | |
| 14 | + end | |
| 9 | 15 | end | ... | ... |
app/views/box_organizer/_link_list_block.rhtml
| 1 | 1 | <strong><%= _('Links') %></strong> |
| 2 | 2 | <div id='edit-link-list-block' style='width:450px'> |
| 3 | 3 | <table id='links' class='noborder'> |
| 4 | - <tr><th><%= _('Icon') %></th><th><%= _('Name') %></th><th><%= _('Address') %></th></tr> | |
| 4 | + <tr><th><%= _('Icon') %></th><th><%= _('Name') %></th><th><%= _('Address') %></th><th><%= _('Target') %></th></tr> | |
| 5 | 5 | <% for link in @block.links do %> |
| 6 | 6 | <tr> |
| 7 | 7 | <td> |
| ... | ... | @@ -9,6 +9,9 @@ |
| 9 | 9 | </td> |
| 10 | 10 | <td><%= text_field_tag 'block[links][][name]', link[:name], :class => 'link-name', :maxlength => 20 %></td> |
| 11 | 11 | <td class='cel-address'><%= text_field_tag 'block[links][][address]', link[:address], :class => 'link-address' %></td> |
| 12 | + <td> | |
| 13 | + <%= select_tag('block[links][][target]', options_for_select(LinkListBlock::TARGET_OPTIONS, link[:target])) %> | |
| 14 | + </td> | |
| 12 | 15 | </tr> |
| 13 | 16 | <% end %> |
| 14 | 17 | </table> |
| ... | ... | @@ -18,7 +21,9 @@ |
| 18 | 21 | page.insert_html :bottom, 'links', content_tag('tr', |
| 19 | 22 | content_tag('td', icon_selector('ok')) + |
| 20 | 23 | content_tag('td', text_field_tag('block[links][][name]', '', :maxlength => 20)) + |
| 21 | - content_tag('td', text_field_tag('block[links][][address]', nil, :class => 'cel-address')) | |
| 24 | + content_tag('td', text_field_tag('block[links][][address]', nil, :class => 'link-address'), :class => 'cel-address') + | |
| 25 | + content_tag('td', select_tag('block[links][][target]', | |
| 26 | +options_for_select(LinkListBlock::TARGET_OPTIONS, link[:target]))) | |
| 22 | 27 | ) + |
| 23 | 28 | javascript_tag("$('edit-link-list-block').scrollTop = $('edit-link-list-block').scrollHeight") |
| 24 | 29 | end %> | ... | ... |
app/views/catalog/index.rhtml
| ... | ... | @@ -92,7 +92,7 @@ |
| 92 | 92 | <% end %> |
| 93 | 93 | <% product.price_details.each do |i| %> |
| 94 | 94 | <div class="search-product-input-dots-to-price"> |
| 95 | - <div class="search-product-input-name"><%= i.production_cost.name %></div> | |
| 95 | + <div class="search-product-input-name"><%= i.name %></div> | |
| 96 | 96 | <%= price_span i.price, :class => 'search-product-input-price' %> |
| 97 | 97 | </div> |
| 98 | 98 | <% end %> | ... | ... |
app/views/cms/_blog.rhtml
| ... | ... | @@ -54,6 +54,15 @@ |
| 54 | 54 | |
| 55 | 55 | <%= labelled_form_field(_('Description:'), text_area(:article, :body, :rows => 10)) %> |
| 56 | 56 | |
| 57 | +<% f.fields_for :image_builder, @article.image do |i| %> | |
| 58 | + <%= file_field_or_thumbnail(_('Cover image:'), @article.image, i)%> | |
| 59 | + <%= _("Max size: %s (.jpg, .gif, .png)")% Image.max_size.to_humanreadable %> | |
| 60 | +<% end %> | |
| 61 | + | |
| 62 | +<% unless @article.image.nil? %> | |
| 63 | + <%= labelled_check_box(_('Remove cover image'),'remove_image',true,false)%> | |
| 64 | +<% end %> | |
| 65 | + | |
| 57 | 66 | <%= labelled_form_field(_('How to display posts:'), f.select(:visualization_format, [ [ _('Full post'), 'full'], [ _('First paragraph'), 'short'] ])) %> |
| 58 | 67 | |
| 59 | 68 | <%= labelled_form_field(_('Posts per page:'), f.select(:posts_per_page, Blog.posts_per_page_options)) %> | ... | ... |
app/views/cms/view.rhtml
| ... | ... | @@ -2,6 +2,18 @@ |
| 2 | 2 | <%= _('Content management') %> |
| 3 | 3 | </h1> |
| 4 | 4 | |
| 5 | +<% if !environment.enabled?('cant_change_homepage') && !remove_content_button(:home) %> | |
| 6 | + <div class="cms-homepage"> | |
| 7 | + <%= _('Profile homepage:') %> | |
| 8 | + <% if profile.home_page %> | |
| 9 | + <%= link_to_article(profile.home_page) %> | |
| 10 | + <%= button_without_text(:'home-not', _('Reset homepage'), { :action => 'set_home_page', :id => nil }, :method => :post) %> | |
| 11 | + <% else %> | |
| 12 | + <span class="cms-homepage-default"><%= _('Profile Information') %></span> | |
| 13 | + <% end %> | |
| 14 | + </div> | |
| 15 | +<% end %> | |
| 16 | + | |
| 5 | 17 | <% button_bar(:style => 'margin-bottom: 1em;') do %> |
| 6 | 18 | <% parent_id = ((@article && @article.allow_children?) ? @article : nil) %> |
| 7 | 19 | |
| ... | ... | @@ -40,20 +52,27 @@ |
| 40 | 52 | </tr> |
| 41 | 53 | <% end %> |
| 42 | 54 | |
| 43 | - <% @articles.each do |article| %> | |
| 55 | + <% @articles.each do |article| article = FilePresenter.for article %> | |
| 44 | 56 | <tr title="<%= article.title%>" > |
| 45 | - <td> | |
| 57 | + <td class="article-name"> | |
| 46 | 58 | <%= link_to_article(article) %> |
| 47 | 59 | </td> |
| 48 | - <td> | |
| 49 | - <%= article.class.short_description %> | |
| 60 | + <% short_description = article.respond_to?(:short_description) ? | |
| 61 | + article.short_description : | |
| 62 | + article.class.short_description %> | |
| 63 | + <td class="article-mime" title=<%= short_description.to_json %>> | |
| 64 | + <%= short_description %> | |
| 50 | 65 | </td> |
| 51 | 66 | <td class="article-controls"> |
| 52 | 67 | <%= expirable_button article, :edit, _('Edit'), {:action => 'edit', :id => article.id} if !remove_content_button(:edit) %> |
| 53 | 68 | <%= button_without_text :eyes, _('Public view'), article.view_url %> |
| 54 | 69 | <%= display_spread_button(profile, article) unless article.folder? || remove_content_button(:spread)%> |
| 55 | 70 | <% if !environment.enabled?('cant_change_homepage') && !remove_content_button(:home) %> |
| 56 | - <%= expirable_button article, :home, _('Use as homepage'), { :action => 'set_home_page', :id => article.id }, :method => :post %> | |
| 71 | + <% if profile.home_page != article %> | |
| 72 | + <%= expirable_button article, :home, _('Use as homepage'), { :action => 'set_home_page', :id => article.id }, :method => :post %> | |
| 73 | + <% else %> | |
| 74 | + <%= button_without_text(:'home-not', _('Reset homepage'), { :action => 'set_home_page', :id => nil }, :method => :post) %> | |
| 75 | + <% end %> | |
| 57 | 76 | <% end %> |
| 58 | 77 | <%= display_delete_button(article) if !remove_content_button(:delete) %> |
| 59 | 78 | </td> | ... | ... |
app/views/content_viewer/_article_toolbar.rhtml
| ... | ... | @@ -52,6 +52,9 @@ |
| 52 | 52 | |
| 53 | 53 | </div> |
| 54 | 54 | <div id="article-header"> |
| 55 | + <% if @page.blog? and !@page.image.nil? %> | |
| 56 | + <div class="blog-cover"><%= image_tag(@page.image.public_filename())%></div> | |
| 57 | + <% end %> | |
| 55 | 58 | <%= link_to(image_tag('icons-mime/rss-feed.png'), @page.feed.url, :class => 'blog-feed-link') if @page.has_posts? && @page.feed %> |
| 56 | 59 | <%= article_title(@page, :no_link => true) %> |
| 57 | 60 | <%= article_translations(@page) %> | ... | ... |
app/views/events/_agenda.rhtml
| ... | ... | @@ -3,22 +3,14 @@ |
| 3 | 3 | <table class='noborder current-month'> |
| 4 | 4 | <caption> |
| 5 | 5 | <h2><%= show_month(params[:year], params[:month]) %></h2> |
| 6 | - <%= link_to_previous_month(params[:year], params[:month], '« %s' % _('previous')) %> | |
| 7 | - <%= link_to_next_month(params[:year], params[:month], '%s »' % _('next')) %> | |
| 6 | + <%= link_to_previous_month(params[:year], params[:month], show_month(params[:year], params[:month], :previous => true, :only_month => true)) %> | |
| 7 | + <%= link_to_next_month(params[:year], params[:month], show_month(params[:year], params[:month], :next => true, :only_month => true)) %> | |
| 8 | 8 | </caption> |
| 9 | 9 | <%= render :partial => 'events/month', :locals => {:calendar => @calendar, :abbreviated => true} %> |
| 10 | 10 | </table> |
| 11 | - <table class='noborder previous-month'> | |
| 12 | - <caption><h3><%= link_to_previous_month(params[:year], params[:month], show_month(params[:year], params[:month], :previous => true)) %></h3></caption> | |
| 13 | - <%= render :partial => 'events/month', :locals => {:calendar => @previous_calendar, :abbreviated => true} %> | |
| 14 | - </table> | |
| 15 | - <table class='noborder next-month'> | |
| 16 | - <caption><h3><%= link_to_next_month(params[:year], params[:month], show_month(params[:year], params[:month], :next => true)) %></h3></caption> | |
| 17 | - <%= render :partial => 'events/month', :locals => {:calendar => @next_calendar, :abbreviated => true} %> | |
| 18 | - </table> | |
| 19 | 11 | <br clear='both'/> |
| 20 | 12 | </div> |
| 21 | 13 | <div id='events-of-the-day'> |
| 22 | - <%= render :partial => 'events/events_by_day' %> | |
| 14 | + <%= render :partial => 'events/events' %> | |
| 23 | 15 | </div> |
| 24 | 16 | </div> | ... | ... |
app/views/events/_events_by_day.rhtml
| ... | ... | @@ -1 +0,0 @@ |
| 1 | -<%= list_events(@selected_day, @events_of_the_day) %> |
| ... | ... | @@ -0,0 +1,9 @@ |
| 1 | +<span class="download-link"> | |
| 2 | + <span>Download</span> | |
| 3 | + <strong><%= link_to generic.filename, generic.public_filename %></strong> | |
| 4 | +</span> | |
| 5 | + | |
| 6 | +<div class="uploaded-file-description <%= 'empty' if generic.abstract.blank? %>"> | |
| 7 | + <%= generic.abstract %> | |
| 8 | +</div> | |
| 9 | + | ... | ... |
| ... | ... | @@ -0,0 +1,36 @@ |
| 1 | +<% if image.gallery? && options[:gallery_view] %> | |
| 2 | +<% | |
| 3 | + images = image.parent.images | |
| 4 | + current_index = images.index(image.encapsulated_file) | |
| 5 | + total_of_images = images.count | |
| 6 | + link_to_previous = if current_index >= 1 | |
| 7 | + link_to(_('« Previous'), images[current_index - 1].view_url, :class => 'previous') | |
| 8 | + else | |
| 9 | + content_tag('span', _('« Previous'), :class => 'previous') | |
| 10 | + end | |
| 11 | + | |
| 12 | + link_to_next = if current_index < total_of_images - 1 | |
| 13 | + link_to(_('Next »'), images[current_index + 1].view_url, :class => 'next') | |
| 14 | + else | |
| 15 | + content_tag('span', _('Next »'), :class => 'next') | |
| 16 | + end | |
| 17 | +%> | |
| 18 | + | |
| 19 | +<div class="gallery-navigation"> | |
| 20 | + <%= link_to_previous %> | |
| 21 | + <span class="total-of-images"> | |
| 22 | + <%= _('image %d of %d') % [current_index + 1, total_of_images] %> | |
| 23 | + </span> | |
| 24 | + <%= link_to_next %> | |
| 25 | +</div> | |
| 26 | + | |
| 27 | +<% end %> | |
| 28 | + | |
| 29 | +<%# image_tag(article.public_filename(:display), :class => article.css_class_name, :style => 'max-width: 100%') %> | |
| 30 | + | |
| 31 | +<img src="<%=image.public_filename(:display)%>" class="<%=image.css_class_name%>"> | |
| 32 | + | |
| 33 | +<div class="uploaded-file-description <%= 'empty' if image.abstract.blank? %>"> | |
| 34 | + <%= image.abstract %> | |
| 35 | +</div> | |
| 36 | + | ... | ... |
app/views/memberships/new_community.rhtml
| ... | ... | @@ -46,9 +46,11 @@ |
| 46 | 46 | |
| 47 | 47 | <%= template_options(Community, 'community')%> |
| 48 | 48 | |
| 49 | + <%= hidden_field_tag('back_to', @back_to) %> | |
| 50 | + | |
| 49 | 51 | <% button_bar do %> |
| 50 | 52 | <%= submit_button(:save, _('Create')) %> |
| 51 | - <%= button(:cancel, _('Cancel'), :action => 'index') %> | |
| 53 | + <%= button(:cancel, _('Cancel'), @back_to ) %> | |
| 52 | 54 | <% end %> |
| 53 | 55 | |
| 54 | 56 | <% end %> | ... | ... |
app/views/profile/_person_profile.rhtml
| ... | ... | @@ -4,7 +4,7 @@ |
| 4 | 4 | </tr> |
| 5 | 5 | <%= display_field(_('Sex:'), profile, :sex) { |gender| { 'male' => _('Male'), 'female' => _('Female') }[gender] } %> |
| 6 | 6 | <%= display_field(_('Date of birth:'), profile, :birth_date) { |date| show_date(date) }%> |
| 7 | - <%= display_field(_('Location:'), profile, :location, true) %> | |
| 7 | + <%= display_field _('Location:'), profile, :location %> | |
| 8 | 8 | |
| 9 | 9 | <%= display_field(_('Type:'), profile, :privacy_setting, true) %> |
| 10 | 10 | ... | ... |
app/views/profile/_profile_activities_list.rhtml
| ... | ... | @@ -4,7 +4,7 @@ |
| 4 | 4 | <% if activity.kind_of?(ActionTracker::Record) %> |
| 5 | 5 | <%= render :partial => 'profile_activity', :locals => { :activity => activity, :tab_action => 'wall' } if activity.visible? %> |
| 6 | 6 | <% else %> |
| 7 | - <%= render :partial => 'profile_scrap', :locals => {:scrap => activity } %> | |
| 7 | + <%= render :partial => 'profile_scraps', :locals => { :activity => activity, :scrap => activity } %> | |
| 8 | 8 | <% end %> |
| 9 | 9 | <% end %> |
| 10 | 10 | <% end %> | ... | ... |
app/views/profile/_profile_comments.rhtml
| 1 | 1 | <hr /> |
| 2 | 2 | |
| 3 | -<% if activity.comments_count > 2 %> | |
| 3 | +<ul id="profile-wall-activities-comments-<%= activity.id %>" class="profile-wall-activities-comments" > | |
| 4 | +</ul> | |
| 5 | +<% if activity.comments_count > 0 %> | |
| 6 | +<div id="profile-wall-activities-comments-more-<%= activity.id %>" class="profile-wall-activities-comments" > | |
| 4 | 7 | <div class='view-all-comments icon-chat'> |
| 5 | - <%= link_to(_("View all %s comments") % activity.comments_count, '#') %> | |
| 8 | + <%= link_to(n_('View comment', "View all %s comments", activity.comments_count) % activity.comments_count, :profile => profile.identifier, :controller => 'profile', :action => 'more_comments', :activity => activity, :comment_page => (1)) %> | |
| 6 | 9 | </div> |
| 10 | +</div> | |
| 7 | 11 | <% end %> |
| 8 | - | |
| 9 | -<ul class="profile-wall-activities-comments" style="<%= 'display:none;' if (activity.comments_count > 2) %>" > | |
| 10 | - <%= render :partial => 'comment', :collection => activity.comments_as_thread %> | |
| 11 | -</ul> | |
| 12 | - | |
| 13 | 12 | <%= render :partial => 'profile_comment_form', :locals => { :activity => activity, :tab_action => tab_action } %> | ... | ... |
app/views/profile/_profile_scrap.rhtml
| ... | ... | @@ -16,13 +16,7 @@ |
| 16 | 16 | </div> |
| 17 | 17 | </div> |
| 18 | 18 | |
| 19 | - <% if scrap.replies.count > 2 %> | |
| 20 | - <div class='view-all-comments icon-chat'> | |
| 21 | - <%= link_to(_("View all %s comments") % scrap.replies.count, '#') %> | |
| 22 | - </div> | |
| 23 | - <% end %> | |
| 24 | - | |
| 25 | - <ul class="profile-wall-activities-comments scrap-replies" style="width: auto; <%= 'display:none;' if (scrap.replies.count > 2) %>" > | |
| 19 | + <ul class="profile-wall-activities-comments scrap-replies" style="width: auto;" > | |
| 26 | 20 | <% scrap.replies.map do |reply| %> |
| 27 | 21 | <%= render :partial => 'profile_scrap', :locals => {:scrap => reply} %> |
| 28 | 22 | <% end %> | ... | ... |
app/views/profile/_profile_scraps.rhtml
| 1 | -NÃO DEVE APARECER | |
| 1 | +<li class='profile-activity-item' id='profile-activity-item-<%= scrap.id %>'> | |
| 2 | + <div class='profile-activity-image'> | |
| 3 | + <%= link_to(profile_image(scrap.sender, :minor), scrap.sender.url) %> | |
| 4 | + </div> | |
| 5 | + <div class='profile-activity-description'> | |
| 6 | + <p class='profile-activity-sender'><%= link_to scrap.sender.name, scrap.sender.url %></p> | |
| 7 | + <p class='profile-activity-text'><%= txt2html scrap.content %></p> | |
| 8 | + <p class='profile-activity-time'><%= time_ago_as_sentence(scrap.created_at) %></p> | |
| 9 | + <div class='profile-wall-actions'> | |
| 10 | + <% if logged_in? && current_person.follows?(scrap.sender) %> | |
| 11 | + <span class='profile-activity-send-reply'> | |
| 12 | + <%= link_to_function s_('profile|Comment'), "hide_and_show(['#profile-wall-message-response-#{scrap.id}'],['#profile-wall-reply-#{scrap.id}', '#profile-wall-reply-form-#{scrap.id}']);$('reply_content_#{scrap.id}').value='';$('reply_content_#{scrap.id}').focus();return false", :class => "profile-send-reply" %> | |
| 13 | + </span> | |
| 14 | + <% end %> | |
| 15 | + <%= link_to_function(_('Remove'), 'remove_item_wall(this, %s, %s, %s); return false ;' % ["'.profile-activity-item'", url_for(:profile => params[:profile], :action => :remove_scrap, :scrap_id => scrap.id, :view => params[:view]).to_json, _('Are you sure you want to remove this scrap and all its replies?').to_json]) if logged_in? && user.can_control_scrap?(scrap) %> | |
| 16 | + </div> | |
| 17 | + </div> | |
| 18 | + | |
| 19 | + | |
| 20 | + <ul id="profile-wall-activities-comments-<%= activity.id %>" class="profile-wall-activities-comments scrap-replies" style="width: auto;" > | |
| 21 | + </ul> | |
| 22 | + | |
| 23 | + <% if scrap.replies.count > 0 %> | |
| 24 | + <div id="profile-wall-activities-comments-more-<%= activity.id %>" class="profile-wall-activities-comments"> | |
| 25 | + <div class='view-all-comments icon-chat'> | |
| 26 | + <%= link_to(n_('View comment', "View all %s comments", scrap.replies.count) % scrap.replies.count, :profile => profile.identifier, :controller => 'profile', :action => 'more_replies', :activity => activity, :comment_page => (1)) %> | |
| 27 | + </div> | |
| 28 | + </div> | |
| 29 | + <% end %> | |
| 30 | + <%= render :partial => 'profile_scrap_reply_form', :locals => { :scrap => scrap } %> | |
| 31 | + <hr /> | |
| 32 | +</li> | ... | ... |
app/views/shared/_list_groups.html.erb
| ... | ... | @@ -12,7 +12,9 @@ |
| 12 | 12 | <%= _('Members: %s') % group.members_count.to_s %> <br/> |
| 13 | 13 | <%= _('Created at: %s') % show_date(group.created_at) unless group.enterprise? %> <br/> |
| 14 | 14 | <% button_bar do %> |
| 15 | - <%= button 'menu-ctrl-panel', _('Control panel of this group'), group.admin_url %> | |
| 15 | + <% if user.has_permission?(:edit_profile, group) %> | |
| 16 | + <%= button 'menu-ctrl-panel', _('Control panel of this group'), group.admin_url %> | |
| 17 | + <% end %> | |
| 16 | 18 | <%= button 'menu-logout', _('Leave community'), group.leave_url(true), :class => 'leave-community' %> |
| 17 | 19 | <% if (group.community? && user.has_permission?(:destroy_profile, group)) %> |
| 18 | 20 | <%= button 'delete', _('Remove'), { :controller => 'profile_editor', :action => 'destroy_profile', :profile => group.identifier } %> | ... | ... |
app/views/shared/_manage_enterprises.rhtml
| ... | ... | @@ -1,8 +0,0 @@ |
| 1 | -<div id='manage-enterprises'> | |
| 2 | - <a href="#" id='manage-enterprises-link' class='simplemenu-trigger' title='<%= _('Manage enterprises') %>'><i class="icon-menu-enterprise"></i><strong><%= ui_icon('ui-icon-triangle-1-s') + _('My enterprises') %></strong></a> | |
| 3 | - <ul class='simplemenu-submenu'> | |
| 4 | - <% enterprises_link.each do |link| %> | |
| 5 | - <li class='simplemenu-item'><%= link %></li> | |
| 6 | - <% end %> | |
| 7 | - </ul> | |
| 8 | -</div> |
| ... | ... | @@ -0,0 +1,8 @@ |
| 1 | +<div id=<%= "manage-#{kind}" %> class="manage-groups"> | |
| 2 | + <a href="#" id=<%= "manage-#{kind}-link" %> class="simplemenu-trigger" title="<%= _('Manage %s') % kind %>"><i class=<%= "icon-menu-#{kind.singularize}" %>></i><strong><%= ui_icon('ui-icon-triangle-1-s') + _('My %s') % kind %></strong></a> | |
| 3 | + <ul class="simplemenu-submenu"> | |
| 4 | + <% link.each do |link| %> | |
| 5 | + <li class="simplemenu-item"><%= link %></li> | |
| 6 | + <% end %> | |
| 7 | + </ul> | |
| 8 | +</div> | ... | ... |
| ... | ... | @@ -0,0 +1,11 @@ |
| 1 | +<%# FIXME should not need to replicate the article structure like this to be able to use the same formatting as the comments listing %> | |
| 2 | +<div id='article'> | |
| 3 | + <div class="comments" id="comments_list"> | |
| 4 | + <ul class="article-comments-list"> | |
| 5 | + <%= render :partial => 'comment/comment', :collection => @comment_spam %> | |
| 6 | + </ul> | |
| 7 | + </div> | |
| 8 | +</div> | |
| 9 | + | |
| 10 | +<%= pagination_links @comment_spam, :param_name => :comments_page %> | |
| 11 | + | ... | ... |
| ... | ... | @@ -0,0 +1,21 @@ |
| 1 | +<% render :layout => 'task', :locals => { :task => task } do %> | |
| 2 | + <% content_for :extra_buttons do %> | |
| 3 | + <%= button_to_function('down', _('Show details'), "toggleDetails(this, '#{_('Hide details')}', '#{_('Show details')}')" ) %> | |
| 4 | + <% end %> | |
| 5 | + | |
| 6 | + <% content_for :extra_content do %> | |
| 7 | + <ul class="suggest-article-details" style="display: none"> | |
| 8 | + <li><strong><%=_('Sent by')%></strong>: <%=task.name%> </li> | |
| 9 | + <li><strong><%=_('Email')%></strong>: <%=task.email%> </li> | |
| 10 | + <li><strong><%=_('Source')%></strong>: <%=task.source_name%> </li> | |
| 11 | + <li><strong><%=_('Source URL')%></strong>: <%=task.source%> </li> | |
| 12 | + <li><strong><%=_('Folder')%></strong>: <%=(a = Article.find_by_id(task.article_parent_id))?a.name : '<em>' + s_('Folder|none') + '</em>'%> </li> | |
| 13 | + <li><strong><%=_('Lead')%></strong>: <%=task.article_abstract.blank? ? '<em>' + s_('Abstract|empty') + '</em>' : task.article_abstract%> </li> | |
| 14 | + <li><strong><%=_('Body')%></strong>: | |
| 15 | + <div class='suggest-article-body'> | |
| 16 | + <%= task.article_body %> | |
| 17 | + </div> | |
| 18 | + </li> | |
| 19 | + </ul> | |
| 20 | + <% end %> | |
| 21 | +<% end %> | ... | ... |
| ... | ... | @@ -0,0 +1,18 @@ |
| 1 | +<div class="task_box" id="task-<%= task.id %>"> | |
| 2 | + <%= render :partial => 'tasks/task_icon', :locals => {:task => task} %> | |
| 3 | + <%= render :partial => 'tasks/task_title', :locals => {:task => task} %> | |
| 4 | + <div class="task-information"> | |
| 5 | + <%= task_information(task) %> | |
| 6 | + </div> | |
| 7 | + | |
| 8 | + <%= yield %> <% # ??? %> | |
| 9 | + | |
| 10 | + <% button_bar do %> | |
| 11 | + <%= button_to_function('new', _('Mark as NOT SPAM'), 'removeTaskBox(this, %s, "%s", "")' % [url_for(:mark_task_as_ham => task.id).to_json, "task-#{task.id}"]) %> | |
| 12 | + <%= yield :extra_buttons %> | |
| 13 | + <%= button_to_function('delete', _('Remove'), 'removeTaskBox(this, %s, "%s", %s)' % [url_for(:profile => params[:profile], :remove_task => task.id).to_json, "task-#{task.id}", _('Are you sure you want to remove this article suggestion?').to_json]) %> | |
| 14 | + | |
| 15 | + <% end %> | |
| 16 | + | |
| 17 | + <%= yield :extra_content %> | |
| 18 | +</div> | ... | ... |
app/views/spam/index.rhtml
| 1 | +<%= stylesheet('tasks') %> | |
| 2 | + | |
| 1 | 3 | <h1><%= _('Manage SPAM') %></h1> |
| 2 | 4 | |
| 5 | +<% no_tabs = @comment_spam.blank? && @task_spam.blank? %> | |
| 6 | + | |
| 7 | +<%= _('There are no spams to review.') if no_tabs %> | |
| 8 | + | |
| 3 | 9 | <% button_bar do %> |
| 4 | 10 | <%= button :back, _('Back to control panel'), :controller => :profile_editor %> |
| 5 | 11 | <% end %> |
| 6 | 12 | |
| 7 | 13 | <%# FIXME should not need to replicate the article structure like this to be able to use the same formatting as the comments listing %> |
| 8 | -<div id='article'> | |
| 9 | - <div class="comments" id="comments_list"> | |
| 10 | - <ul class="article-comments-list"> | |
| 11 | - <%= render :partial => 'comment/comment', :collection => @spam %> | |
| 12 | - </ul> | |
| 13 | - </div> | |
| 14 | -</div> | |
| 15 | 14 | |
| 16 | -<%= pagination_links @spam %> | |
| 15 | +<% tabs = [] %> | |
| 16 | +<% tabs << {:title => _('Comment Spam'), :id => 'comment-spam', | |
| 17 | + :content => (render :partial => 'comment_spam')} if @comment_spam.present? %> | |
| 18 | +<% tabs << {:title => _('Task Spam'), :id => 'task-spam', | |
| 19 | + :content => (render :partial => 'task_spam') } if @task_spam.present? %> | |
| 20 | +<%= render_tabs(tabs) %> | |
| 17 | 21 | |
| 18 | -<% button_bar do %> | |
| 19 | - <%= button :back, _('Back to control panel'), :controller => :profile_editor %> | |
| 22 | +<% unless no_tabs %> | |
| 23 | + <% button_bar do %> | |
| 24 | + <%= button :back, _('Back to control panel'), :controller => :profile_editor %> | |
| 25 | + <% end %> | |
| 20 | 26 | <% end %> |
| 27 | + | |
| 28 | +<%= javascript_include_tag 'spam' %> | ... | ... |
app/views/tasks/_task.rhtml
| 1 | 1 | <div class="task_box" id="task-<%= task.id %>"> |
| 2 | 2 | |
| 3 | - <div class="task_icon"> | |
| 4 | - <% | |
| 5 | - icon_info = task.icon | |
| 6 | - if icon_info[:type] == :profile_image | |
| 7 | - icon = profile_image(icon_info[:profile], :minor) | |
| 8 | - elsif icon_info[:type] == :defined_image | |
| 9 | - icon = "<img src='#{icon_info[:src]}' alt='#{icon_info[:name]}' />" | |
| 10 | - end | |
| 11 | - %> | |
| 12 | - <%= | |
| 13 | - if icon_info[:url] | |
| 14 | - link_to(icon, icon_info[:url]) | |
| 15 | - else | |
| 16 | - icon | |
| 17 | - end | |
| 18 | - %> | |
| 19 | - | |
| 20 | - </div> | |
| 3 | + <%= render :partial => 'task_icon', :locals => {:task => task} %> | |
| 21 | 4 | |
| 22 | 5 | <div class="task_decisions"> |
| 23 | 6 | <%= |
| ... | ... | @@ -39,9 +22,7 @@ |
| 39 | 22 | %> |
| 40 | 23 | </div><!-- class="task_decisions" --> |
| 41 | 24 | |
| 42 | - <strong class="task_title"> | |
| 43 | - <%= task.title %> | |
| 44 | - </strong> | |
| 25 | + <%= render :partial => 'task_title', :locals => {:task => task} %> | |
| 45 | 26 | |
| 46 | 27 | <div class="task_information"> |
| 47 | 28 | <%= task_information(task) %> | ... | ... |
| ... | ... | @@ -0,0 +1,16 @@ |
| 1 | +<% | |
| 2 | + icon_info = task.icon | |
| 3 | + if icon_info[:type] == :profile_image | |
| 4 | + icon = profile_image(icon_info[:profile], :minor) | |
| 5 | + elsif icon_info[:type] == :defined_image | |
| 6 | + icon = "<img src='#{icon_info[:src]}' alt='#{icon_info[:name]}' />" | |
| 7 | + end | |
| 8 | + | |
| 9 | + if icon_info[:url] | |
| 10 | + icon = link_to(icon, icon_info[:url]) | |
| 11 | + end | |
| 12 | +%> | |
| 13 | + | |
| 14 | +<div class="task_icon"> | |
| 15 | + <%= icon %> | |
| 16 | +</div> | ... | ... |
config/database.yml.pgsql
| ... | ... | @@ -12,6 +12,7 @@ development: |
| 12 | 12 | adapter: postgresql |
| 13 | 13 | encoding: unicode |
| 14 | 14 | database: noosfero_development |
| 15 | + template: template0 | |
| 15 | 16 | username: noosfero |
| 16 | 17 | password: |
| 17 | 18 | |
| ... | ... | @@ -37,6 +38,7 @@ test: &TEST |
| 37 | 38 | adapter: postgresql |
| 38 | 39 | encoding: unicode |
| 39 | 40 | database: noosfero_test |
| 41 | + template: template0 | |
| 40 | 42 | username: noosfero |
| 41 | 43 | password: |
| 42 | 44 | |
| ... | ... | @@ -44,6 +46,7 @@ production: |
| 44 | 46 | adapter: postgresql |
| 45 | 47 | encoding: unicode |
| 46 | 48 | database: noosfero_production |
| 49 | + template: template0 | |
| 47 | 50 | username: noosfero |
| 48 | 51 | password: |
| 49 | 52 | ... | ... |
config/initializers/plugins.rb
config/noosfero.yml.dist
config/routes.rb
| ... | ... | @@ -55,6 +55,7 @@ ActionController::Routing::Routes.draw do |map| |
| 55 | 55 | |
| 56 | 56 | # events |
| 57 | 57 | map.events 'profile/:profile/events_by_day', :controller => 'events', :action => 'events_by_day', :profile => /#{Noosfero.identifier_format}/ |
| 58 | + map.events 'profile/:profile/events_by_month', :controller => 'events', :action => 'events_by_month', :profile => /#{Noosfero.identifier_format}/ | |
| 58 | 59 | map.events 'profile/:profile/events/:year/:month/:day', :controller => 'events', :action => 'events', :year => /\d*/, :month => /\d*/, :day => /\d*/, :profile => /#{Noosfero.identifier_format}/ |
| 59 | 60 | map.events 'profile/:profile/events/:year/:month', :controller => 'events', :action => 'events', :year => /\d*/, :month => /\d*/, :profile => /#{Noosfero.identifier_format}/ |
| 60 | 61 | map.events 'profile/:profile/events', :controller => 'events', :action => 'events', :profile => /#{Noosfero.identifier_format}/ | ... | ... |
| ... | ... | @@ -0,0 +1,13 @@ |
| 1 | +class AddSpamToTask < ActiveRecord::Migration | |
| 2 | + def self.up | |
| 3 | + change_table :tasks do |t| | |
| 4 | + t.boolean :spam, :default => false | |
| 5 | + end | |
| 6 | + Task.update_all ["spam = ?", false] | |
| 7 | + add_index :tasks, [:spam] | |
| 8 | + end | |
| 9 | + | |
| 10 | + def self.down | |
| 11 | + remove_column :tasks, :spam | |
| 12 | + end | |
| 13 | +end | ... | ... |
| ... | ... | @@ -0,0 +1,13 @@ |
| 1 | +class AddImageToArticle < ActiveRecord::Migration | |
| 2 | + | |
| 3 | + def self.up | |
| 4 | + add_column :articles, :image_id, :integer | |
| 5 | + add_column :article_versions, :image_id, :integer | |
| 6 | + end | |
| 7 | + | |
| 8 | + def self.down | |
| 9 | + remove_column :articles, :image_id | |
| 10 | + remove_column :article_versions, :image_id | |
| 11 | + end | |
| 12 | + | |
| 13 | +end | ... | ... |
| ... | ... | @@ -0,0 +1,13 @@ |
| 1 | +class AddPositionToArticle < ActiveRecord::Migration | |
| 2 | + | |
| 3 | + def self.up | |
| 4 | + add_column :articles, :position, :integer | |
| 5 | + add_column :article_versions, :position, :integer | |
| 6 | + end | |
| 7 | + | |
| 8 | + def self.down | |
| 9 | + remove_column :articles, :position | |
| 10 | + remove_column :article_versions, :position | |
| 11 | + end | |
| 12 | + | |
| 13 | +end | ... | ... |
db/migrate/20131116165327_enable_enterprises_list_on_user_menu.rb
0 → 100644
| ... | ... | @@ -0,0 +1,14 @@ |
| 1 | +class EnableEnterprisesListOnUserMenu < ActiveRecord::Migration | |
| 2 | + def self.up | |
| 3 | + # The enterprises were always listed on user menu. | |
| 4 | + # As now it is configured by admin, the running environments should not need to enable it | |
| 5 | + select_all("select id from environments").each do |environment| | |
| 6 | + env = Environment.find(environment['id']) | |
| 7 | + env.enable(:display_my_enterprises_on_user_menu) | |
| 8 | + end | |
| 9 | + end | |
| 10 | + | |
| 11 | + def self.down | |
| 12 | + #nothing to be done | |
| 13 | + end | |
| 14 | +end | ... | ... |
| ... | ... | @@ -0,0 +1,10 @@ |
| 1 | +class RemoveOrphanProfiles < ActiveRecord::Migration | |
| 2 | + def self.up | |
| 3 | + profiles = Profile.joins('LEFT JOIN environments ON profiles.environment_id=environments.id').where('environments.id IS NULL') | |
| 4 | + profiles.map(&:destroy) | |
| 5 | + end | |
| 6 | + | |
| 7 | + def self.down | |
| 8 | + say 'This migration can not be reverted.' | |
| 9 | + end | |
| 10 | +end | ... | ... |
db/schema.rb
| ... | ... | @@ -9,7 +9,7 @@ |
| 9 | 9 | # |
| 10 | 10 | # It's strongly recommended to check this file into your version control system. |
| 11 | 11 | |
| 12 | -ActiveRecord::Schema.define(:version => 20130711213046) do | |
| 12 | +ActiveRecord::Schema.define(:version => 20131116165327) do | |
| 13 | 13 | |
| 14 | 14 | create_table "abuse_reports", :force => true do |t| |
| 15 | 15 | t.integer "reporter_id" |
| ... | ... | @@ -86,6 +86,8 @@ ActiveRecord::Schema.define(:version => 20130711213046) do |
| 86 | 86 | t.string "language" |
| 87 | 87 | t.string "source_name" |
| 88 | 88 | t.integer "license_id" |
| 89 | + t.integer "image_id" | |
| 90 | + t.integer "position" | |
| 89 | 91 | end |
| 90 | 92 | |
| 91 | 93 | add_index "article_versions", ["article_id"], :name => "index_article_versions_on_article_id" |
| ... | ... | @@ -129,6 +131,8 @@ ActiveRecord::Schema.define(:version => 20130711213046) do |
| 129 | 131 | t.string "language" |
| 130 | 132 | t.string "source_name" |
| 131 | 133 | t.integer "license_id" |
| 134 | + t.integer "image_id" | |
| 135 | + t.integer "position" | |
| 132 | 136 | end |
| 133 | 137 | |
| 134 | 138 | add_index "articles", ["name"], :name => "index_articles_on_name" |
| ... | ... | @@ -547,8 +551,11 @@ ActiveRecord::Schema.define(:version => 20130711213046) do |
| 547 | 551 | t.datetime "created_at" |
| 548 | 552 | t.string "target_type" |
| 549 | 553 | t.integer "image_id" |
| 554 | + t.boolean "spam", :default => false | |
| 550 | 555 | end |
| 551 | 556 | |
| 557 | + add_index "tasks", ["spam"], :name => "index_tasks_on_spam" | |
| 558 | + | |
| 552 | 559 | create_table "thumbnails", :force => true do |t| |
| 553 | 560 | t.integer "size" |
| 554 | 561 | t.string "content_type" | ... | ... |
debian/changelog
| 1 | +noosfero (0.45.0) unstable; urgency=low | |
| 2 | + | |
| 3 | + * New features release | |
| 4 | + | |
| 5 | + -- Rodrigo Souto <rodrigo@colivre.coop.br> Tue, 10 Dec 2013 16:04:33 -0300 | |
| 6 | + | |
| 7 | +noosfero (0.45.0~rc20131202153818) squeeze-test; urgency=low | |
| 8 | + | |
| 9 | + * 0.45.0 RC2 | |
| 10 | + | |
| 11 | + -- Rodrigo Souto <rodrigo@colivre.coop.br> Mon, 02 Dec 2013 15:38:28 -0300 | |
| 12 | + | |
| 13 | +noosfero (0.44.6) unstable; urgency=low | |
| 14 | + | |
| 15 | + * 0.44.5 Addendum | |
| 16 | + | |
| 17 | + -- Rodrigo Souto <rodrigo@colivre.coop.br> Wed, 27 Nov 2013 16:45:02 -0300 | |
| 18 | + | |
| 19 | +noosfero (0.44.5) unstable; urgency=low | |
| 20 | + | |
| 21 | + * Bugfix release | |
| 22 | + | |
| 23 | + -- Rodrigo Souto <rodrigo@colivre.coop.br> Tue, 26 Nov 2013 17:39:39 -0300 | |
| 24 | + | |
| 1 | 25 | noosfero (0.44.4) unstable; urgency=low |
| 2 | 26 | |
| 3 | 27 | * Bugfix release | ... | ... |
debian/control
| ... | ... | @@ -31,13 +31,11 @@ Depends: |
| 31 | 31 | libgettext-rails-ruby1.8, |
| 32 | 32 | libsqlite3-ruby, |
| 33 | 33 | libpgsql-ruby, |
| 34 | - libmysql-ruby, | |
| 35 | 34 | librmagick-ruby, |
| 36 | 35 | libredcloth-ruby, |
| 37 | 36 | libwill-paginate-ruby (>= 2.3.12-1~), |
| 38 | 37 | iso-codes, |
| 39 | 38 | libfeedparser-ruby, |
| 40 | - openjdk-6-jre, | |
| 41 | 39 | libdaemons-ruby, |
| 42 | 40 | rcov, |
| 43 | 41 | thin, | ... | ... |
features/blog.feature
| ... | ... | @@ -15,6 +15,7 @@ Feature: blog |
| 15 | 15 | And I follow "Create blog" |
| 16 | 16 | Then I should see "My Blog" |
| 17 | 17 | When I fill in "Title" with "My Blog" |
| 18 | + And I fill in "Address" with "my-blog" | |
| 18 | 19 | And I press "Save" |
| 19 | 20 | And I go to joaosilva's control panel |
| 20 | 21 | Then I should see "Configure blog" |
| ... | ... | @@ -24,6 +25,7 @@ Feature: blog |
| 24 | 25 | And I follow "Create blog" |
| 25 | 26 | Then I should see "My Blog" |
| 26 | 27 | When I fill in "Title" with "My Blog" |
| 28 | + And I fill in "Address" with "my-blog" | |
| 27 | 29 | And I press "Save" |
| 28 | 30 | Then I should be on /joaosilva/my-blog |
| 29 | 31 | |
| ... | ... | @@ -33,6 +35,7 @@ Feature: blog |
| 33 | 35 | And I follow "New content" |
| 34 | 36 | When I follow "Blog" |
| 35 | 37 | And I fill in "Title" with "Blog from cms" |
| 38 | + And I fill in "Address" with "blog-from-cms" | |
| 36 | 39 | And I press "Save" |
| 37 | 40 | Then I should be on /joaosilva/blog-from-cms |
| 38 | 41 | |
| ... | ... | @@ -42,12 +45,14 @@ Feature: blog |
| 42 | 45 | And I follow "New content" |
| 43 | 46 | And I follow "Blog" |
| 44 | 47 | And I fill in "Title" with "Blog One" |
| 48 | + And I fill in "Address" with "blog-one" | |
| 45 | 49 | And I press "Save" |
| 46 | 50 | Then I go to joaosilva's control panel |
| 47 | 51 | And I follow "Manage Content" |
| 48 | 52 | And I follow "New content" |
| 49 | 53 | And I follow "Blog" |
| 50 | 54 | And I fill in "Title" with "Blog Two" |
| 55 | + And I fill in "Address" with "blog-two" | |
| 51 | 56 | And I press "Save" |
| 52 | 57 | Then I should not see "error" |
| 53 | 58 | And I should be on /joaosilva/blog-two |
| ... | ... | @@ -109,3 +114,24 @@ Feature: blog |
| 109 | 114 | And I follow "New content" |
| 110 | 115 | When I follow "Blog" |
| 111 | 116 | Then I should see "Tag list" |
| 117 | + | |
| 118 | + Scenario: do not display the "clear cover image" when there is no uploaded image | |
| 119 | + Given the following blogs | |
| 120 | + | owner | name | | |
| 121 | + | joaosilva | My Blog | | |
| 122 | + And I go to joaosilva's control panel | |
| 123 | + And I follow "Configure blog" | |
| 124 | + Then I should not see "Delete cover image" | |
| 125 | + | |
| 126 | + # the step for attaching a file on the input only works with capybara 1.1.2, but it requires rails 1.9.3 | |
| 127 | + @selenium-fixme | |
| 128 | + Scenario: display cover image after uploading an image as the blog cover | |
| 129 | + Given the following blogs | |
| 130 | + | owner | name | | |
| 131 | + | joaosilva | My Blog | | |
| 132 | + And I go to joaosilva's control panel | |
| 133 | + And I follow "Configure blog" | |
| 134 | + And I attach the file "public/images/rails.png" to "Uploaded data" | |
| 135 | + And I press "Save" | |
| 136 | + When I am on /joaosilva/my-blog | |
| 137 | + Then there should be a div with class "blog-cover" | ... | ... |
features/browse_catalogs.feature
| ... | ... | @@ -9,7 +9,7 @@ Feature: browse catalogs |
| 9 | 9 | And the following enterprises |
| 10 | 10 | | identifier | owner | name | enabled | |
| 11 | 11 | | artebonito | joaosilva | Associação de Artesanato de Bonito | true | |
| 12 | - And feature "disable_products_for_enterprises" is disabled on environment | |
| 12 | + And feature "products_for_enterprises" is enabled on environment | |
| 13 | 13 | And the following product_categories |
| 14 | 14 | | name | |
| 15 | 15 | | categ1 | | ... | ... |
features/browse_enterprises.feature
| ... | ... | @@ -6,7 +6,7 @@ Background: |
| 6 | 6 | Given the following enterprises |
| 7 | 7 | | identifier | name | |
| 8 | 8 | | shop1 | Shoes Shop | |
| 9 | - And feature "disable_products_for_enterprises" is disabled on environment | |
| 9 | + And feature "products_for_enterprises" is enabled on environment | |
| 10 | 10 | And feature "show_balloon_with_profile_links_when_clicked" is enabled on environment |
| 11 | 11 | |
| 12 | 12 | Scenario: show all enterprises | ... | ... |
features/enterprise_homepage.feature
features/events.feature
| ... | ... | @@ -12,43 +12,38 @@ Feature: events |
| 12 | 12 | |
| 13 | 13 | Scenario: go to next month |
| 14 | 14 | Given I am on /profile/josesilva/events/2009/10 |
| 15 | - When I follow "next »" | |
| 15 | + When I follow "November" | |
| 16 | 16 | Then I should see "November 2009" within ".current-month" |
| 17 | 17 | |
| 18 | 18 | Scenario: go to next month in global agenda |
| 19 | 19 | Given I am on /assets/events?year=2009&month=11 |
| 20 | - When I follow "next »" | |
| 20 | + When I follow "December" | |
| 21 | 21 | Then I should see "December 2009" within ".current-month" |
| 22 | 22 | |
| 23 | 23 | Scenario: go to previous month |
| 24 | 24 | Given I am on /profile/josesilva/events/2009/10 |
| 25 | - When I follow "« previous" | |
| 25 | + When I follow "September" | |
| 26 | 26 | Then I should see "September 2009" within ".current-month" |
| 27 | 27 | |
| 28 | 28 | Scenario: go to previous month in global agenda |
| 29 | 29 | Given I am on /assets/events?year=2009&month=11 |
| 30 | - When I follow "« previous" | |
| 30 | + When I follow "October" | |
| 31 | 31 | Then I should see "October 2009" within ".current-month" |
| 32 | 32 | |
| 33 | 33 | Scenario: go to next month by clicking in month name |
| 34 | 34 | Given I am on /profile/josesilva/events/2009/10 |
| 35 | - When I follow "November 2009" | |
| 35 | + When I follow "November" | |
| 36 | 36 | Then I should see "November 2009" within ".current-month" |
| 37 | 37 | |
| 38 | 38 | Scenario: go to previous month by clicking in month name |
| 39 | 39 | Given I am on /profile/josesilva/events/2009/10 |
| 40 | - When I follow "September 2009" | |
| 40 | + When I follow "September" | |
| 41 | 41 | Then I should see "September 2009" within ".current-month" |
| 42 | 42 | |
| 43 | - Scenario: go to specific day | |
| 44 | - Given I am on the homepage | |
| 45 | - When I am on /profile/josesilva/events/2009/01/20 | |
| 46 | - Then I should see "Events for January 20, 2009" | |
| 47 | - | |
| 48 | 43 | Scenario: go to specific day in global agenda |
| 49 | 44 | Given I am on the homepage |
| 50 | 45 | When I am on /assets/events?year=2009&month=11&day=12 |
| 51 | - Then I should see "Events for November 12, 2009" | |
| 46 | + Then I should see "Events for November, 2009" | |
| 52 | 47 | |
| 53 | 48 | Scenario: list events for specific day |
| 54 | 49 | Given I am on /profile/josesilva/events/2009/10 |
| ... | ... | @@ -64,7 +59,7 @@ Feature: events |
| 64 | 59 | | owner | name | start_date | |
| 65 | 60 | | josesilva | WikiSym 2009 | 2009-10-25 | |
| 66 | 61 | When I am on /profile/josesilva/events/2009/10/20 |
| 67 | - Then I should not see "WikiSym 2009" | |
| 62 | + Then I should see "WikiSym 2009" | |
| 68 | 63 | |
| 69 | 64 | Scenario: list event between a range |
| 70 | 65 | Given I am on /profile/josesilva/events/2009/10 |
| ... | ... | @@ -96,20 +91,11 @@ Feature: events |
| 96 | 91 | Then I should see "Another Conference" |
| 97 | 92 | And I should see "Manuel Birthday" |
| 98 | 93 | |
| 99 | - Scenario: ask for a day when no inform complete date | |
| 100 | - When I am on /profile/josesilva/events/2009/5 | |
| 101 | - Then I should see "Select a day on the left to display it's events here" | |
| 102 | - | |
| 103 | - Scenario: ask for a day when no inform complete date in global agenda | |
| 104 | - When I am on /assets/events?year=2009&month=5 | |
| 105 | - Then I should see "Select a day on the left to display it's events here" | |
| 106 | - | |
| 94 | + @selenium | |
| 107 | 95 | Scenario: provide links to days with events |
| 108 | 96 | Given I am on /profile/josesilva/events/2009/10 |
| 109 | 97 | Then I should see "24" link |
| 110 | - When I follow "next »" | |
| 111 | - Then I should see "24" link | |
| 112 | - When I follow "next »" | |
| 98 | + When I follow "November" | |
| 113 | 99 | Then I should not see "24" link |
| 114 | 100 | |
| 115 | 101 | Scenario: provide links to all days between start and end date |
| ... | ... | @@ -128,7 +114,7 @@ Feature: events |
| 128 | 114 | @selenium |
| 129 | 115 | Scenario: show events when i follow a specific day |
| 130 | 116 | Given I am on /profile/josesilva/events/2009/10 |
| 131 | - And I should not see "Another Conference" | |
| 117 | + And I should see "Another Conference" | |
| 132 | 118 | When I follow "24" |
| 133 | 119 | Then I should see "Another Conference" |
| 134 | 120 | |
| ... | ... | @@ -138,7 +124,7 @@ Feature: events |
| 138 | 124 | | owner | name | start_date | end_date | |
| 139 | 125 | | josesilva | YAPC::Brasil 2010 | 2010-10-30 | 2010-11-01 | |
| 140 | 126 | And I am on /profile/josesilva/events/2010/10 |
| 141 | - And I should not see "YAPC::Brasil 2010" | |
| 127 | + And I should see "YAPC::Brasil 2010" | |
| 142 | 128 | When I follow "31" |
| 143 | 129 | Then I should see "YAPC::Brasil 2010" |
| 144 | 130 | |
| ... | ... | @@ -150,10 +136,6 @@ Feature: events |
| 150 | 136 | When I follow "Back to josesilva" |
| 151 | 137 | Then I should be on josesilva's homepage |
| 152 | 138 | |
| 153 | - Scenario: warn when there is no events | |
| 154 | - When I am on /profile/josesilva/events/2020/12/1 | |
| 155 | - Then I should see "No events for this date" | |
| 156 | - | |
| 157 | 139 | Scenario: provide button to create new event |
| 158 | 140 | Given I am logged in as "josesilva" |
| 159 | 141 | When I am on /profile/josesilva/events/2020/12/1 |
| ... | ... | @@ -230,3 +212,35 @@ Feature: events |
| 230 | 212 | Then I should see "Leaded event" |
| 231 | 213 | And I should see "This is the abstract." |
| 232 | 214 | And I should not see "This is the real text." |
| 215 | + | |
| 216 | + Scenario: show range date of event | |
| 217 | + Given I am on /profile/josesilva/events/2009/10 | |
| 218 | + And the following events | |
| 219 | + | owner | name | start_date | end_date | | |
| 220 | + | josesilva | WikiSym 2009 | 2009-10-25 | 2009-10-27 | | |
| 221 | + When I am on /profile/josesilva/events/2009/10/26 | |
| 222 | + Then I should see "October 25, 2009 to October 27, 2009" | |
| 223 | + | |
| 224 | + Scenario: show place of the event | |
| 225 | + Given I am on /profile/josesilva/events/2009/10 | |
| 226 | + And the following events | |
| 227 | + | owner | name | start_date | end_date | address | | |
| 228 | + | josesilva | WikiSym 2009 | 2009-10-25 | 2009-10-27 | Earth Planet | | |
| 229 | + When I am on /profile/josesilva/events/2009/10/26 | |
| 230 | + Then I should see "Place: Earth Planet" | |
| 231 | + | |
| 232 | + Scenario: show event name as link | |
| 233 | + Given the following events | |
| 234 | + | owner | name | start_date | | |
| 235 | + | josesilva | Unpublished event | 2009-10-25 | | |
| 236 | + And I am logged in as "josesilva" | |
| 237 | + When I am on /profile/josesilva/events/2009/10/25 | |
| 238 | + Then I should see "Unpublished event" link | |
| 239 | + | |
| 240 | + Scenario: go to event page | |
| 241 | + Given the following events | |
| 242 | + | owner | name | start_date | | |
| 243 | + | josesilva | Oktoberfest | 2009-10-25 | | |
| 244 | + Given I am on /profile/josesilva/events/2009/10 | |
| 245 | + When I follow "Oktoberfest" | |
| 246 | + Then I should see "Oktoberfest" | ... | ... |
features/manage_inputs.feature
| ... | ... | @@ -19,7 +19,7 @@ Feature: manage inputs |
| 19 | 19 | And the following product |
| 20 | 20 | | owner | category | name | |
| 21 | 21 | | redemoinho | rock | Abbey Road | |
| 22 | - And feature "disable_products_for_enterprises" is disabled on environment | |
| 22 | + And feature "products_for_enterprises" is enabled on environment | |
| 23 | 23 | And the following units |
| 24 | 24 | | singular | plural | |
| 25 | 25 | | Meter | Meters | | ... | ... |
features/manage_product_price_details.feature
| ... | ... | @@ -19,7 +19,7 @@ Feature: manage product price details |
| 19 | 19 | And the following product |
| 20 | 20 | | owner | category | name | price | |
| 21 | 21 | | redemoinho | rock | Abbey Road | 80.0 | |
| 22 | - And feature "disable_products_for_enterprises" is disabled on environment | |
| 22 | + And feature "products_for_enterprises" is enabled on environment | |
| 23 | 23 | And the following inputs |
| 24 | 24 | | product | category | price_per_unit | amount_used | |
| 25 | 25 | | Abbey Road | Rock | 10.0 | 2 | | ... | ... |
features/manage_products.feature
| ... | ... | @@ -9,7 +9,7 @@ Feature: manage products |
| 9 | 9 | And the following enterprises |
| 10 | 10 | | identifier | owner | name | enabled | |
| 11 | 11 | | redemoinho | joaosilva | Rede Moinho | true | |
| 12 | - And feature "disable_products_for_enterprises" is disabled on environment | |
| 12 | + And feature "products_for_enterprises" is enabled on environment | |
| 13 | 13 | |
| 14 | 14 | Scenario: display "create new product" button |
| 15 | 15 | Given I am logged in as "joaosilva" | ... | ... |