Commit eafa036da33d503072710eae3e214f05b1bdee33
Exists in
staging
and in
41 other branches
Merge branch 'master' into api
Conflicts: lib/noosfero/plugin.rb test/unit/article_test.rb test/unit/person_test.rb
Showing
120 changed files
with
1360 additions
and
799 deletions
Show diff stats
app/controllers/my_profile/cms_controller.rb
| ... | ... | @@ -105,6 +105,11 @@ class CmsController < MyProfileController |
| 105 | 105 | end |
| 106 | 106 | end |
| 107 | 107 | end |
| 108 | + | |
| 109 | + unless @article.kind_of?(RssFeed) | |
| 110 | + @escaped_body = CGI::escapeHTML(@article.body || '') | |
| 111 | + @escaped_abstract = CGI::escapeHTML(@article.abstract || '') | |
| 112 | + end | |
| 108 | 113 | end |
| 109 | 114 | |
| 110 | 115 | def new | ... | ... |
app/controllers/my_profile/friends_controller.rb
| 1 | 1 | class FriendsController < MyProfileController |
| 2 | - | |
| 2 | + | |
| 3 | 3 | protect 'manage_friends', :profile |
| 4 | - | |
| 4 | + | |
| 5 | 5 | def index |
| 6 | - @suggestions = profile.profile_suggestions.of_person.enabled.includes(:suggestion).limit(per_page) | |
| 6 | + @suggestions = profile.suggested_profiles.of_person.enabled.includes(:suggestion).limit(per_page) | |
| 7 | 7 | if is_cache_expired?(profile.manage_friends_cache_key(params)) |
| 8 | 8 | @friends = profile.friends.paginate(:per_page => per_page, :page => params[:npage]) |
| 9 | 9 | end |
| ... | ... | @@ -18,7 +18,7 @@ class FriendsController < MyProfileController |
| 18 | 18 | end |
| 19 | 19 | |
| 20 | 20 | def suggest |
| 21 | - @suggestions = profile.profile_suggestions.of_person.enabled.includes(:suggestion).limit(per_page) | |
| 21 | + @suggestions = profile.suggested_profiles.of_person.enabled.includes(:suggestion).limit(per_page) | |
| 22 | 22 | end |
| 23 | 23 | |
| 24 | 24 | def remove_suggestion |
| ... | ... | @@ -26,13 +26,13 @@ class FriendsController < MyProfileController |
| 26 | 26 | redirect_to :action => 'suggest' unless @person |
| 27 | 27 | if @person && request.post? |
| 28 | 28 | profile.remove_suggestion(@person) |
| 29 | - @suggestions = profile.profile_suggestions.of_person.enabled.includes(:suggestion).limit(per_page) | |
| 29 | + @suggestions = profile.suggested_profiles.of_person.enabled.includes(:suggestion).limit(per_page) | |
| 30 | 30 | render :partial => 'shared/profile_suggestions_list', :locals => { :suggestions => @suggestions, :collection => :friends_suggestions, :per_page => params[:per_page] || per_page } |
| 31 | 31 | end |
| 32 | 32 | end |
| 33 | 33 | |
| 34 | 34 | def connections |
| 35 | - @suggestion = profile.profile_suggestions.of_person.enabled.find_by_suggestion_id(params[:id]) | |
| 35 | + @suggestion = profile.suggested_profiles.of_person.enabled.find_by_suggestion_id(params[:id]) | |
| 36 | 36 | if @suggestion |
| 37 | 37 | @tags = @suggestion.tag_connections |
| 38 | 38 | @profiles = @suggestion.profile_connections | ... | ... |
app/controllers/my_profile/memberships_controller.rb
| ... | ... | @@ -40,7 +40,7 @@ class MembershipsController < MyProfileController |
| 40 | 40 | end |
| 41 | 41 | |
| 42 | 42 | def suggest |
| 43 | - @suggestions = profile.profile_suggestions.of_community.enabled.includes(:suggestion).limit(per_page) | |
| 43 | + @suggestions = profile.suggested_profiles.of_community.enabled.includes(:suggestion).limit(per_page) | |
| 44 | 44 | end |
| 45 | 45 | |
| 46 | 46 | def remove_suggestion |
| ... | ... | @@ -49,13 +49,13 @@ class MembershipsController < MyProfileController |
| 49 | 49 | redirect_to :action => 'suggest' unless @community |
| 50 | 50 | if @community && request.post? |
| 51 | 51 | profile.remove_suggestion(@community) |
| 52 | - @suggestions = profile.profile_suggestions.of_community.enabled.includes(:suggestion).limit(custom_per_page) | |
| 52 | + @suggestions = profile.suggested_profiles.of_community.enabled.includes(:suggestion).limit(custom_per_page) | |
| 53 | 53 | render :partial => 'shared/profile_suggestions_list', :locals => { :suggestions => @suggestions, :collection => :communities_suggestions, :per_page => custom_per_page} |
| 54 | 54 | end |
| 55 | 55 | end |
| 56 | 56 | |
| 57 | 57 | def connections |
| 58 | - @suggestion = profile.profile_suggestions.of_community.enabled.find_by_suggestion_id(params[:id]) | |
| 58 | + @suggestion = profile.suggested_profiles.of_community.enabled.find_by_suggestion_id(params[:id]) | |
| 59 | 59 | if @suggestion |
| 60 | 60 | @tags = @suggestion.tag_connections |
| 61 | 61 | @profiles = @suggestion.profile_connections | ... | ... |
app/controllers/my_profile/tasks_controller.rb
| 1 | 1 | class TasksController < MyProfileController |
| 2 | 2 | |
| 3 | - protect 'perform_task', :profile | |
| 3 | + protect [:perform_task, :view_tasks], :profile, :only => [:index] | |
| 4 | + protect :perform_task, :profile, :except => [:index] | |
| 4 | 5 | |
| 5 | 6 | def index |
| 6 | 7 | @filter_type = params[:filter_type].presence |
| ... | ... | @@ -15,6 +16,8 @@ class TasksController < MyProfileController |
| 15 | 16 | @failed = params ? params[:failed] : {} |
| 16 | 17 | |
| 17 | 18 | @responsible_candidates = profile.members.by_role(profile.roles.reject {|r| !r.has_permission?('perform_task')}) if profile.organization? |
| 19 | + | |
| 20 | + @view_only = !current_person.has_permission?(:perform_task, profile) | |
| 18 | 21 | end |
| 19 | 22 | |
| 20 | 23 | def processed |
| ... | ... | @@ -46,7 +49,7 @@ class TasksController < MyProfileController |
| 46 | 49 | task = profile.find_in_all_tasks(id) |
| 47 | 50 | begin |
| 48 | 51 | task.update_attributes(value[:task]) |
| 49 | - task.send(decision) | |
| 52 | + task.send(decision, current_person) | |
| 50 | 53 | rescue Exception => ex |
| 51 | 54 | message = "#{task.title} (#{task.requestor ? task.requestor.name : task.author_name})" |
| 52 | 55 | failed[ex.message] ? failed[ex.message] << message : failed[ex.message] = [message] | ... | ... |
app/controllers/public/content_viewer_controller.rb
| ... | ... | @@ -11,6 +11,7 @@ class ContentViewerController < ApplicationController |
| 11 | 11 | path = get_path(params[:page], params[:format]) |
| 12 | 12 | |
| 13 | 13 | @version = params[:version].to_i |
| 14 | + @npage = params[:npage] || '1' | |
| 14 | 15 | |
| 15 | 16 | if path.blank? |
| 16 | 17 | @page = profile.home_page |
| ... | ... | @@ -127,7 +128,7 @@ class ContentViewerController < ApplicationController |
| 127 | 128 | end |
| 128 | 129 | |
| 129 | 130 | unless @page.display_to?(user) |
| 130 | - if !profile.visible? || profile.secret? || (user && user.follows?(profile)) | |
| 131 | + if !profile.visible? || profile.secret? || (user && user.follows?(profile)) || user.blank? | |
| 131 | 132 | render_access_denied |
| 132 | 133 | else #!profile.public? |
| 133 | 134 | private_profile_partial_parameters | ... | ... |
app/helpers/application_helper.rb
| ... | ... | @@ -1215,35 +1215,6 @@ module ApplicationHelper |
| 1215 | 1215 | list.sort.inject(Hash.new(0)){|h,i| h[i] += 1; h }.collect{ |x, n| [n, connector, x].join(" ") }.sort |
| 1216 | 1216 | end |
| 1217 | 1217 | |
| 1218 | - #FIXME Use time_ago_in_words instead of this method if you're using Rails 2.2+ | |
| 1219 | - def time_ago_as_sentence(from_time, include_seconds = false) | |
| 1220 | - to_time = Time.now | |
| 1221 | - from_time = Time.parse(from_time.to_s) | |
| 1222 | - from_time = from_time.to_time if from_time.respond_to?(:to_time) | |
| 1223 | - to_time = to_time.to_time if to_time.respond_to?(:to_time) | |
| 1224 | - distance_in_minutes = (((to_time - from_time).abs)/60).round | |
| 1225 | - distance_in_seconds = ((to_time - from_time).abs).round | |
| 1226 | - case distance_in_minutes | |
| 1227 | - when 0..1 | |
| 1228 | - return (distance_in_minutes == 0) ? _('less than a minute') : _('1 minute') unless include_seconds | |
| 1229 | - case distance_in_seconds | |
| 1230 | - when 0..4 then _('less than 5 seconds') | |
| 1231 | - when 5..9 then _('less than 10 seconds') | |
| 1232 | - when 10..19 then _('less than 20 seconds') | |
| 1233 | - when 20..39 then _('half a minute') | |
| 1234 | - when 40..59 then _('less than a minute') | |
| 1235 | - else _('1 minute') | |
| 1236 | - end | |
| 1237 | - | |
| 1238 | - when 2..44 then _('%{distance} minutes ago') % { :distance => distance_in_minutes } | |
| 1239 | - when 45..89 then _('about 1 hour ago') | |
| 1240 | - when 90..1439 then _('about %{distance} hours ago') % { :distance => (distance_in_minutes.to_f / 60.0).round } | |
| 1241 | - when 1440..2879 then _('1 day ago') | |
| 1242 | - when 2880..10079 then _('%{distance} days ago') % { :distance => (distance_in_minutes / 1440).round } | |
| 1243 | - else show_time(from_time) | |
| 1244 | - end | |
| 1245 | - end | |
| 1246 | - | |
| 1247 | 1218 | def comment_balloon(options = {}, &block) |
| 1248 | 1219 | wrapper = content_tag(:div, capture(&block), :class => 'comment-balloon-content') |
| 1249 | 1220 | (1..8).to_a.reverse.each { |i| wrapper = content_tag(:div, wrapper, :class => "comment-wrapper-#{i}") } | ... | ... |
app/helpers/blog_helper.rb
| ... | ... | @@ -22,7 +22,9 @@ module BlogHelper |
| 22 | 22 | :param_name => 'npage', |
| 23 | 23 | :previous_label => _('« Newer posts'), |
| 24 | 24 | :next_label => _('Older posts »'), |
| 25 | - :params => {:action=>"view_page", :page=>articles.first.parent.path.split('/'), :controller=>"content_viewer"} | |
| 25 | + :params => {:action=>"view_page", | |
| 26 | + :page=>articles.first.parent.path.split('/'), | |
| 27 | + :controller=>"content_viewer"} | |
| 26 | 28 | }) if articles.present? && conf[:paginate] |
| 27 | 29 | content = [] |
| 28 | 30 | artic_len = articles.length |
| ... | ... | @@ -44,7 +46,7 @@ module BlogHelper |
| 44 | 46 | end |
| 45 | 47 | |
| 46 | 48 | def display_post(article, format = 'full') |
| 47 | - no_comments = (format == 'full') ? false : true | |
| 49 | + no_comments = (format == 'full' || format == 'compact' ) ? false : true | |
| 48 | 50 | title = article_title(article, :no_comments => no_comments) |
| 49 | 51 | method = "display_#{format.split('+')[0]}_format" |
| 50 | 52 | html = send(method, FilePresenter.for(article)).html_safe |
| ... | ... | @@ -55,8 +57,12 @@ module BlogHelper |
| 55 | 57 | else |
| 56 | 58 | '<div class="post-pic" style="background-image:url('+img+')"></div>' |
| 57 | 59 | end |
| 58 | - end.to_s + | |
| 59 | - title + html | |
| 60 | + end.to_s + title + html | |
| 61 | + end | |
| 62 | + | |
| 63 | + def display_compact_format(article) | |
| 64 | + render :file => 'content_viewer/_display_compact_format', | |
| 65 | + :locals => { :article => article, :format => "compact" } | |
| 60 | 66 | end |
| 61 | 67 | |
| 62 | 68 | def display_full_format(article) | ... | ... |
app/helpers/comment_helper.rb
app/helpers/content_viewer_helper.rb
| ... | ... | @@ -2,6 +2,7 @@ module ContentViewerHelper |
| 2 | 2 | |
| 3 | 3 | include BlogHelper |
| 4 | 4 | include ForumHelper |
| 5 | + include DatesHelper | |
| 5 | 6 | |
| 6 | 7 | def display_number_of_comments(n) |
| 7 | 8 | base_str = "<span class='comment-count hide'>#{n}</span>" |
| ... | ... | @@ -24,8 +25,9 @@ module ContentViewerHelper |
| 24 | 25 | unless args[:no_comments] || !article.accept_comments |
| 25 | 26 | comments = (" - %s") % link_to_comments(article) |
| 26 | 27 | end |
| 28 | + date_format = show_with_right_format_date article | |
| 27 | 29 | title << content_tag('span', |
| 28 | - content_tag('span', show_date(article.published_at), :class => 'date') + | |
| 30 | + date_format + | |
| 29 | 31 | content_tag('span', _(", by %s") % (article.author ? link_to(article.author_name, article.author_url) : article.author_name), :class => 'author') + |
| 30 | 32 | content_tag('span', comments, :class => 'comments'), |
| 31 | 33 | :class => 'created-at' |
| ... | ... | @@ -34,6 +36,24 @@ module ContentViewerHelper |
| 34 | 36 | title |
| 35 | 37 | end |
| 36 | 38 | |
| 39 | + def show_with_right_format_date article | |
| 40 | + date_format = article.environment.date_format | |
| 41 | + use_numbers = false | |
| 42 | + year = true | |
| 43 | + left_time = false | |
| 44 | + if date_format == 'numbers_with_year' | |
| 45 | + use_numbers = true | |
| 46 | + elsif date_format == 'numbers' | |
| 47 | + use_numbers = true | |
| 48 | + year = false | |
| 49 | + elsif date_format == 'month_name' | |
| 50 | + year = false | |
| 51 | + elsif date_format == 'past_time' | |
| 52 | + left_time = true | |
| 53 | + end | |
| 54 | + content_tag('span', show_date(article.published_at, use_numbers , year, left_time), :class => 'date') | |
| 55 | + end | |
| 56 | + | |
| 37 | 57 | def link_to_comments(article, args = {}) |
| 38 | 58 | return '' unless article.accept_comments? |
| 39 | 59 | reference_to_article number_of_comments(article), article, 'comments_list' | ... | ... |
app/helpers/dates_helper.rb
| ... | ... | @@ -2,6 +2,7 @@ require 'noosfero/i18n' |
| 2 | 2 | |
| 3 | 3 | module DatesHelper |
| 4 | 4 | |
| 5 | + include ActionView::Helpers::DateHelper | |
| 5 | 6 | def months |
| 6 | 7 | I18n.t('date.month_names') |
| 7 | 8 | end |
| ... | ... | @@ -15,10 +16,12 @@ module DatesHelper |
| 15 | 16 | end |
| 16 | 17 | |
| 17 | 18 | # formats a date for displaying. |
| 18 | - def show_date(date, use_numbers = false, year=true) | |
| 19 | + def show_date(date, use_numbers = false, year = true, left_time = false) | |
| 19 | 20 | if date && use_numbers |
| 20 | 21 | date_format = year ? _('%{month}/%{day}/%{year}') : _('%{month}/%{day}') |
| 21 | 22 | date_format % { :day => date.day, :month => date.month, :year => date.year } |
| 23 | + elsif date && left_time | |
| 24 | + date_format = time_ago_in_words(date) | |
| 22 | 25 | elsif date |
| 23 | 26 | date_format = year ? _('%{month_name} %{day}, %{year}') : _('%{month_name} %{day}') |
| 24 | 27 | date_format % { :day => date.day, :month_name => month_name(date.month), :year => date.year } | ... | ... |
app/helpers/events_helper.rb
app/helpers/folder_helper.rb
| ... | ... | @@ -25,49 +25,32 @@ module FolderHelper |
| 25 | 25 | articles.select {|article| article.display_to?(user)} |
| 26 | 26 | end |
| 27 | 27 | |
| 28 | - def display_content_in_listing(configure={}) | |
| 29 | - recursive = configure[:recursive] || false | |
| 30 | - list_type = configure[:list_type] || :folder | |
| 31 | - level = configure[:level] || 0 | |
| 32 | - content = FilePresenter.for configure[:content] | |
| 28 | + def display_content_icon(content_item) | |
| 29 | + content = FilePresenter.for content_item | |
| 33 | 30 | content_link = if content.image? |
| 34 | - link_to(' ' * (level * 4) + | |
| 35 | - image_tag(icon_for_article(content)) + short_filename(content.name), | |
| 31 | + link_to( | |
| 32 | + image_tag(icon_for_article(content, :bigicon)), | |
| 36 | 33 | content.url.merge(:view => true) |
| 37 | 34 | ) |
| 38 | 35 | else |
| 39 | - link_to(' ' * (level * 4) + | |
| 40 | - short_filename(content.name), | |
| 41 | - content.url.merge(:view => true), :class => icon_for_article(content) | |
| 36 | + link_to('', | |
| 37 | + content.url.merge(:view => true), | |
| 38 | + :class => icon_for_article(content, :bigicon) | |
| 42 | 39 | ) |
| 43 | 40 | end |
| 44 | - result = content_tag( | |
| 45 | - 'tr', | |
| 46 | - content_tag('td', content_link ) + | |
| 47 | - content_tag('td', show_date(content.updated_at), :class => 'last-update'), | |
| 48 | - :class => "#{list_type}-item" | |
| 49 | - ) | |
| 50 | - if recursive | |
| 51 | - result + content.children.map {|item| | |
| 52 | - display_content_in_listing :content=>item, :recursive=>recursive, | |
| 53 | - :list_type=>list_type, :level=>level+1 | |
| 54 | - }.join("\n") | |
| 55 | - else | |
| 56 | - result | |
| 57 | - end | |
| 58 | 41 | end |
| 59 | 42 | |
| 60 | - def icon_for_article(article) | |
| 43 | + def icon_for_article(article, size = 'icon') | |
| 61 | 44 | article = FilePresenter.for article |
| 62 | - icon = article.respond_to?(:icon_name) ? | |
| 63 | - article.icon_name : | |
| 64 | - article.class.icon_name(article) | |
| 65 | - if (icon =~ /\//) | |
| 66 | - icon | |
| 45 | + if article.respond_to?(:sized_icon) | |
| 46 | + article.sized_icon(size) | |
| 67 | 47 | else |
| 68 | - klasses = 'icon ' + [icon].flatten.map{|name| 'icon-'+name}.join(' ') | |
| 48 | + icon = article.respond_to?(:icon_name) ? | |
| 49 | + article.icon_name : | |
| 50 | + article.class.icon_name(article) | |
| 51 | + klasses = "#{size} " + [icon].flatten.map{|name| "#{size}-"+name}.join(' ') | |
| 69 | 52 | if article.kind_of?(UploadedFile) || article.kind_of?(FilePresenter) |
| 70 | - klasses += ' icon-upload-file' | |
| 53 | + klasses += " #{size}-upload-file" | |
| 71 | 54 | end |
| 72 | 55 | klasses |
| 73 | 56 | end | ... | ... |
app/helpers/forum_helper.rb
| 1 | 1 | module ForumHelper |
| 2 | + include ActionView::Helpers::DateHelper | |
| 2 | 3 | |
| 3 | 4 | def cms_label_for_new_children |
| 4 | 5 | _('New discussion topic') |
| ... | ... | @@ -42,9 +43,9 @@ module ForumHelper |
| 42 | 43 | def last_topic_update(article) |
| 43 | 44 | info = article.info_from_last_update |
| 44 | 45 | if info[:author_url] |
| 45 | - time_ago_as_sentence(info[:date]) + ' ' + _('by') + ' ' + link_to(info[:author_name], info[:author_url]) | |
| 46 | + time_ago_in_words(info[:date]) + ' ' + _('by') + ' ' + link_to(info[:author_name], info[:author_url]) | |
| 46 | 47 | else |
| 47 | - time_ago_as_sentence(info[:date]) + ' ' + _('by') + ' ' + info[:author_name] | |
| 48 | + time_ago_in_words(info[:date]) + ' ' + _('by') + ' ' + info[:author_name] | |
| 48 | 49 | end |
| 49 | 50 | end |
| 50 | 51 | ... | ... |
app/models/add_friend.rb
| ... | ... | @@ -54,7 +54,7 @@ class AddFriend < Task |
| 54 | 54 | end |
| 55 | 55 | |
| 56 | 56 | def remove_from_suggestion_list(task) |
| 57 | - suggestion = task.requestor.profile_suggestions.find_by_suggestion_id task.target.id | |
| 57 | + suggestion = task.requestor.suggested_profiles.find_by_suggestion_id task.target.id | |
| 58 | 58 | suggestion.disable if suggestion |
| 59 | 59 | end |
| 60 | 60 | end | ... | ... |
app/models/article.rb
| ... | ... | @@ -28,7 +28,7 @@ class Article < ActiveRecord::Base |
| 28 | 28 | def initialize(*params) |
| 29 | 29 | super |
| 30 | 30 | |
| 31 | - if !params.blank? && params.first.has_key?(:profile) | |
| 31 | + if !params.blank? && params.first.has_key?(:profile) && !params.first[:profile].blank? | |
| 32 | 32 | profile = params.first[:profile] |
| 33 | 33 | self.published = false unless profile.public? |
| 34 | 34 | end |
| ... | ... | @@ -96,6 +96,8 @@ class Article < ActiveRecord::Base |
| 96 | 96 | belongs_to :translation_of, :class_name => 'Article', :foreign_key => :translation_of_id |
| 97 | 97 | before_destroy :rotate_translations |
| 98 | 98 | |
| 99 | + acts_as_voteable | |
| 100 | + | |
| 99 | 101 | before_create do |article| |
| 100 | 102 | article.published_at ||= Time.now |
| 101 | 103 | if article.reference_article && !article.parent | ... | ... |
app/models/blog.rb
| ... | ... | @@ -76,9 +76,12 @@ class Blog < Folder |
| 76 | 76 | end |
| 77 | 77 | |
| 78 | 78 | settings_items :visualization_format, :type => :string, :default => 'full' |
| 79 | - validates_inclusion_of :visualization_format, :in => [ 'full', 'short', 'short+pic' ], :if => :visualization_format | |
| 79 | + validates_inclusion_of :visualization_format, | |
| 80 | + :in => [ 'full', 'short', 'short+pic', 'compact'], | |
| 81 | + :if => :visualization_format | |
| 80 | 82 | |
| 81 | - settings_items :display_posts_in_current_language, :type => :boolean, :default => false | |
| 83 | + settings_items :display_posts_in_current_language, | |
| 84 | + :type => :boolean, :default => false | |
| 82 | 85 | |
| 83 | 86 | alias :display_posts_in_current_language? :display_posts_in_current_language |
| 84 | 87 | ... | ... |
app/models/comment.rb
app/models/environment.rb
| ... | ... | @@ -3,7 +3,17 @@ |
| 3 | 3 | # domains. |
| 4 | 4 | class Environment < ActiveRecord::Base |
| 5 | 5 | |
| 6 | - attr_accessible :name, :is_default, :signup_welcome_text_subject, :signup_welcome_text_body, :terms_of_use, :message_for_disabled_enterprise, :news_amount_by_folder, :default_language, :languages, :description, :organization_approval_method, :enabled_plugins, :enabled_features, :redirection_after_login, :redirection_after_signup, :contact_email, :theme, :reports_lower_bound, :noreply_email, :signup_welcome_screen_body, :members_whitelist_enabled, :members_whitelist, :highlighted_news_amount, :portal_news_amount | |
| 6 | + attr_accessible :name, :is_default, :signup_welcome_text_subject, | |
| 7 | + :signup_welcome_text_body, :terms_of_use, | |
| 8 | + :message_for_disabled_enterprise, :news_amount_by_folder, | |
| 9 | + :default_language, :languages, :description, | |
| 10 | + :organization_approval_method, :enabled_plugins, | |
| 11 | + :enabled_features, :redirection_after_login, | |
| 12 | + :redirection_after_signup, :contact_email, :theme, | |
| 13 | + :reports_lower_bound, :noreply_email, | |
| 14 | + :signup_welcome_screen_body, :members_whitelist_enabled, | |
| 15 | + :members_whitelist, :highlighted_news_amount, | |
| 16 | + :portal_news_amount, :date_format | |
| 7 | 17 | |
| 8 | 18 | has_many :users |
| 9 | 19 | |
| ... | ... | @@ -14,6 +24,12 @@ class Environment < ActiveRecord::Base |
| 14 | 24 | |
| 15 | 25 | IDENTIFY_SCRIPTS = /(php[0-9s]?|[sp]htm[l]?|pl|py|cgi|rb)/ |
| 16 | 26 | |
| 27 | + validates_inclusion_of :date_format, | |
| 28 | + :in => [ 'numbers_with_year', 'numbers', | |
| 29 | + 'month_name_with_year', 'month_name', | |
| 30 | + 'past_time'], | |
| 31 | + :if => :date_format | |
| 32 | + | |
| 17 | 33 | def self.verify_filename(filename) |
| 18 | 34 | filename += '.txt' if File.extname(filename) =~ IDENTIFY_SCRIPTS |
| 19 | 35 | filename |
| ... | ... | @@ -75,7 +91,8 @@ class Environment < ActiveRecord::Base |
| 75 | 91 | 'edit_profile_design', |
| 76 | 92 | 'manage_products', |
| 77 | 93 | 'manage_friends', |
| 78 | - 'perform_task' | |
| 94 | + 'perform_task', | |
| 95 | + 'view_tasks' | |
| 79 | 96 | ] |
| 80 | 97 | ) |
| 81 | 98 | end | ... | ... |
app/models/person.rb
| ... | ... | @@ -92,9 +92,9 @@ roles] } |
| 92 | 92 | has_and_belongs_to_many :acepted_forums, :class_name => 'Forum', :join_table => 'terms_forum_people' |
| 93 | 93 | has_and_belongs_to_many :articles_with_access, :class_name => 'Article', :join_table => 'article_privacy_exceptions' |
| 94 | 94 | |
| 95 | - has_many :profile_suggestions, :foreign_key => :person_id, :order => 'score DESC', :dependent => :destroy | |
| 96 | - has_many :suggested_people, :through => :profile_suggestions, :source => :suggestion, :conditions => ['profile_suggestions.suggestion_type = ? AND profile_suggestions.enabled = ?', 'Person', true] | |
| 97 | - has_many :suggested_communities, :through => :profile_suggestions, :source => :suggestion, :conditions => ['profile_suggestions.suggestion_type = ? AND profile_suggestions.enabled = ?', 'Community', true] | |
| 95 | + has_many :suggested_profiles, :class_name => 'ProfileSuggestion', :foreign_key => :person_id, :order => 'score DESC', :dependent => :destroy | |
| 96 | + has_many :suggested_people, :through => :suggested_profiles, :source => :suggestion, :conditions => ['profile_suggestions.suggestion_type = ? AND profile_suggestions.enabled = ?', 'Person', true] | |
| 97 | + has_many :suggested_communities, :through => :suggested_profiles, :source => :suggestion, :conditions => ['profile_suggestions.suggestion_type = ? AND profile_suggestions.enabled = ?', 'Community', true] | |
| 98 | 98 | |
| 99 | 99 | scope :more_popular, :order => 'friends_count DESC' |
| 100 | 100 | |
| ... | ... | @@ -111,6 +111,8 @@ roles] } |
| 111 | 111 | |
| 112 | 112 | belongs_to :user, :dependent => :delete |
| 113 | 113 | |
| 114 | + acts_as_voter | |
| 115 | + | |
| 114 | 116 | def can_change_homepage? |
| 115 | 117 | !environment.enabled?('cant_change_homepage') || is_admin? |
| 116 | 118 | end |
| ... | ... | @@ -535,7 +537,7 @@ roles] } |
| 535 | 537 | end |
| 536 | 538 | |
| 537 | 539 | def remove_suggestion(profile) |
| 538 | - suggestion = profile_suggestions.find_by_suggestion_id profile.id | |
| 540 | + suggestion = suggested_profiles.find_by_suggestion_id profile.id | |
| 539 | 541 | suggestion.disable if suggestion |
| 540 | 542 | end |
| 541 | 543 | ... | ... |
app/models/profile.rb
| ... | ... | @@ -71,6 +71,7 @@ class Profile < ActiveRecord::Base |
| 71 | 71 | 'manage_friends' => N_('Manage friends'), |
| 72 | 72 | 'validate_enterprise' => N_('Validate enterprise'), |
| 73 | 73 | 'perform_task' => N_('Perform task'), |
| 74 | + 'view_tasks' => N_('View tasks'), | |
| 74 | 75 | 'moderate_comments' => N_('Moderate comments'), |
| 75 | 76 | 'edit_appearance' => N_('Edit appearance'), |
| 76 | 77 | 'view_private_content' => N_('View private content'), |
| ... | ... | @@ -969,19 +970,11 @@ private :generate_url, :url_options |
| 969 | 970 | self.save |
| 970 | 971 | end |
| 971 | 972 | |
| 972 | - def disabled? | |
| 973 | - !visible | |
| 974 | - end | |
| 975 | - | |
| 976 | 973 | def enable |
| 977 | 974 | self.visible = true |
| 978 | 975 | self.save |
| 979 | 976 | end |
| 980 | 977 | |
| 981 | - def enabled? | |
| 982 | - visible | |
| 983 | - end | |
| 984 | - | |
| 985 | 978 | def control_panel_settings_button |
| 986 | 979 | {:title => _('Edit Profile'), :icon => 'edit-profile'} |
| 987 | 980 | end |
| ... | ... | @@ -1041,7 +1034,7 @@ private :generate_url, :url_options |
| 1041 | 1034 | end |
| 1042 | 1035 | |
| 1043 | 1036 | def remove_from_suggestion_list(person) |
| 1044 | - suggestion = person.profile_suggestions.find_by_suggestion_id self.id | |
| 1037 | + suggestion = person.suggested_profiles.find_by_suggestion_id self.id | |
| 1045 | 1038 | suggestion.disable if suggestion |
| 1046 | 1039 | end |
| 1047 | 1040 | ... | ... |
app/models/profile_suggestion.rb
| ... | ... | @@ -113,14 +113,14 @@ class ProfileSuggestion < ActiveRecord::Base |
| 113 | 113 | suggested_profiles = all_suggestions(person) |
| 114 | 114 | return if suggested_profiles.nil? |
| 115 | 115 | |
| 116 | - already_suggested_profiles = person.profile_suggestions.map(&:suggestion_id).join(',') | |
| 116 | + already_suggested_profiles = person.suggested_profiles.map(&:suggestion_id).join(',') | |
| 117 | 117 | suggested_profiles = suggested_profiles.where("profiles.id NOT IN (#{already_suggested_profiles})") if already_suggested_profiles.present? |
| 118 | 118 | #TODO suggested_profiles = suggested_profiles.order('score DESC') |
| 119 | 119 | suggested_profiles = suggested_profiles.limit(N_SUGGESTIONS) |
| 120 | 120 | return if suggested_profiles.blank? |
| 121 | 121 | |
| 122 | 122 | suggested_profiles.each do |suggested_profile| |
| 123 | - suggestion = person.profile_suggestions.find_or_initialize_by_suggestion_id(suggested_profile.id) | |
| 123 | + suggestion = person.suggested_profiles.find_or_initialize_by_suggestion_id(suggested_profile.id) | |
| 124 | 124 | RULES.each do |rule, options| |
| 125 | 125 | begin |
| 126 | 126 | value = suggested_profile.send("#{rule}_count").to_i |
| ... | ... | @@ -273,7 +273,7 @@ class ProfileSuggestion < ActiveRecord::Base |
| 273 | 273 | end |
| 274 | 274 | |
| 275 | 275 | def self.generate_profile_suggestions(person, force = false) |
| 276 | - return if person.profile_suggestions.enabled.count >= MIN_LIMIT && !force | |
| 276 | + return if person.suggested_profiles.enabled.count >= MIN_LIMIT && !force | |
| 277 | 277 | Delayed::Job.enqueue ProfileSuggestionsJob.new(person.id) unless ProfileSuggestionsJob.exists?(person.id) |
| 278 | 278 | end |
| 279 | 279 | ... | ... |
app/models/task.rb
| ... | ... | @@ -34,6 +34,7 @@ class Task < ActiveRecord::Base |
| 34 | 34 | belongs_to :requestor, :class_name => 'Profile', :foreign_key => :requestor_id |
| 35 | 35 | belongs_to :target, :foreign_key => :target_id, :polymorphic => true |
| 36 | 36 | belongs_to :responsible, :class_name => 'Person', :foreign_key => :responsible_id |
| 37 | + belongs_to :closed_by, :class_name => 'Person', :foreign_key => :closed_by_id | |
| 37 | 38 | |
| 38 | 39 | validates_uniqueness_of :code, :on => :create |
| 39 | 40 | validates_presence_of :code |
| ... | ... | @@ -77,11 +78,9 @@ class Task < ActiveRecord::Base |
| 77 | 78 | # this method finished the task. It calls #perform, which must be overriden |
| 78 | 79 | # by subclasses. At the end a message (as returned by #finish_message) is |
| 79 | 80 | # sent to the requestor with #notify_requestor. |
| 80 | - def finish | |
| 81 | + def finish(closed_by=nil) | |
| 81 | 82 | transaction do |
| 82 | - self.status = Task::Status::FINISHED | |
| 83 | - self.end_date = Time.now | |
| 84 | - self.save! | |
| 83 | + close(Task::Status::FINISHED, closed_by) | |
| 85 | 84 | self.perform |
| 86 | 85 | begin |
| 87 | 86 | send_notification(:finished) |
| ... | ... | @@ -106,11 +105,9 @@ class Task < ActiveRecord::Base |
| 106 | 105 | |
| 107 | 106 | # this method cancels the task. At the end a message (as returned by |
| 108 | 107 | # #cancel_message) is sent to the requestor with #notify_requestor. |
| 109 | - def cancel | |
| 108 | + def cancel(closed_by=nil) | |
| 110 | 109 | transaction do |
| 111 | - self.status = Task::Status::CANCELLED | |
| 112 | - self.end_date = Time.now | |
| 113 | - self.save! | |
| 110 | + close(Task::Status::CANCELLED, closed_by) | |
| 114 | 111 | begin |
| 115 | 112 | send_notification(:cancelled) |
| 116 | 113 | rescue NotImplementedError => ex |
| ... | ... | @@ -119,6 +116,13 @@ class Task < ActiveRecord::Base |
| 119 | 116 | end |
| 120 | 117 | end |
| 121 | 118 | |
| 119 | + def close(status, closed_by) | |
| 120 | + self.status = status | |
| 121 | + self.end_date = Time.now | |
| 122 | + self.closed_by = closed_by | |
| 123 | + self.save! | |
| 124 | + end | |
| 125 | + | |
| 122 | 126 | # Here are the tasks customizable options. |
| 123 | 127 | |
| 124 | 128 | def title | ... | ... |
app/models/uploaded_file.rb
| ... | ... | @@ -65,7 +65,7 @@ class UploadedFile < Article |
| 65 | 65 | # :min_size => 2.megabytes |
| 66 | 66 | # :max_size => 5.megabytes |
| 67 | 67 | has_attachment :storage => :file_system, |
| 68 | - :thumbnails => { :icon => [24,24], :thumb => '130x130>', :slideshow => '320x240>', :display => '640X480>' }, | |
| 68 | + :thumbnails => { :icon => [24,24], :bigicon => [50,50], :thumb => '130x130>', :slideshow => '320x240>', :display => '640X480>' }, | |
| 69 | 69 | :thumbnail_class => Thumbnail, |
| 70 | 70 | :max_size => self.max_size |
| 71 | 71 | ... | ... |
app/presenters/image.rb
app/views/admin_panel/_site_info.html.erb
| ... | ... | @@ -3,6 +3,21 @@ |
| 3 | 3 | <%= labelled_form_field(_('No reply email'), text_field(:environment, :noreply_email)) %> |
| 4 | 4 | <% themes_options = Theme.system_themes.map {|theme| [theme.name, theme.id] }.sort %> |
| 5 | 5 | <%= labelled_form_field(_('Theme'), select(:environment, :theme, options_for_select(themes_options, environment.theme))) %> |
| 6 | + | |
| 7 | +<%= labelled_form_field( | |
| 8 | + _("Article's date format"), | |
| 9 | + select(:environment, :date_format, | |
| 10 | + options_for_select([ | |
| 11 | + [ _('mm/dd/yyyy'), 'numbers_with_year'], | |
| 12 | + [ _('mm/dd'), 'numbers'], | |
| 13 | + [ _('Month dd, yyyy'), 'month_name_with_year'], | |
| 14 | + [ _('Month dd'), 'month_name'], | |
| 15 | + [ _('X minutes/hours/days/months/years ago'), 'past_time'] | |
| 16 | + ], environment.date_format | |
| 17 | + ) | |
| 18 | + ) | |
| 19 | +) %> | |
| 20 | + | |
| 6 | 21 | <%= required f.text_field(:reports_lower_bound, :size => 3) %> |
| 7 | 22 | <%= labelled_form_field(_('Default language'), select(:environment, :default_language, environment.locales.invert, { :selected => environment.default_locale, :include_blank => true })) %> |
| 8 | 23 | <%= label_tag :languages, _('Available languages') %> | ... | ... |
app/views/blocks/profile_info_actions/_common.html.erb
app/views/box_organizer/edit.html.erb
| ... | ... | @@ -25,6 +25,7 @@ |
| 25 | 25 | </div> |
| 26 | 26 | <div class="move-modes"> |
| 27 | 27 | <%= labelled_form_field _('Move options:'), select_tag('block[move_modes]', options_from_collection_for_select(@block.move_block_options, :first, :last, @block.move_modes)) %> |
| 28 | + </div> | |
| 28 | 29 | <% end %> |
| 29 | 30 | |
| 30 | 31 | <% if @block.owner.kind_of?(Profile) && @block.owner.is_template? %> | ... | ... |
app/views/cms/_blog.html.erb
| ... | ... | @@ -67,7 +67,8 @@ |
| 67 | 67 | <%= labelled_form_field(_('How to display posts:'), f.select(:visualization_format, [ |
| 68 | 68 | [ _('Full post'), 'full'], |
| 69 | 69 | [ _('First paragraph'), 'short'], |
| 70 | - [ _('First paragraph, with post picture'), 'short+pic'] | |
| 70 | + [ _('First paragraph, with post picture'), 'short+pic'], | |
| 71 | + [ _("Title, Image, Lead"), 'compact'] | |
| 71 | 72 | ])) %> |
| 72 | 73 | |
| 73 | 74 | <%= labelled_form_field(_('Posts per page:'), f.select(:posts_per_page, Blog.posts_per_page_options)) %> | ... | ... |
app/views/content_viewer/_article_toolbar.html.erb
| ... | ... | @@ -62,7 +62,7 @@ |
| 62 | 62 | <% if @page.blog? and !@page.image.nil? %> |
| 63 | 63 | <div class="blog-cover"><%= image_tag(@page.image.public_filename())%></div> |
| 64 | 64 | <% end %> |
| 65 | - <%= link_to(image_tag('icons-mime/rss-feed.png'), @page.feed.url, :class => 'blog-feed-link') if @page.has_posts? && @page.feed %> | |
| 65 | + <%= link_to(image_tag('/images/icons-mime/rss-feed.png'), @page.feed.url, :class => 'blog-feed-link') if @page.has_posts? && @page.feed %> | |
| 66 | 66 | <%= @plugins.dispatch(:article_header_extra_contents, @page).collect { |content| instance_exec(&content) }.join("") %> |
| 67 | 67 | <%= article_title(@page, :no_link => true) %> |
| 68 | 68 | <%= article_translations(@page) %> | ... | ... |
app/views/content_viewer/_display_compact_format.html.erb
0 → 100644
| ... | ... | @@ -0,0 +1,21 @@ |
| 1 | +<% if article.image %> | |
| 2 | + <% className = "article-compact-abstract-with-image" %> | |
| 3 | + <% if article.image.thumbnails_processed? %> | |
| 4 | + <% image_file = article.image.public_filename(:big) %> | |
| 5 | + <% else %> | |
| 6 | + <% image_file = "/images/icons-app/image-loading-thumb.png" %> | |
| 7 | + <% end %> | |
| 8 | +<% else %> | |
| 9 | + <% className = "article-compact-abstract" %> | |
| 10 | +<% end %> | |
| 11 | + | |
| 12 | +<div> | |
| 13 | + <% if article.image %> | |
| 14 | + <div class = "article-compact-image"> | |
| 15 | + <%= image_tag(image_file) %> | |
| 16 | + </div> | |
| 17 | + <% end %> | |
| 18 | + <div class = <%= className %> > | |
| 19 | + <%= article.abstract.truncate(400) %> | |
| 20 | + </div> | |
| 21 | +</div> | ... | ... |
app/views/content_viewer/blog_page.html.erb
app/views/content_viewer/folder.html.erb
app/views/person_notifier/mailer/_comment.html.erb
| ... | ... | @@ -19,7 +19,7 @@ |
| 19 | 19 | <span style="font-size: 12px;"><%= comment.title %></span><br/> |
| 20 | 20 | <% end %> |
| 21 | 21 | <span style="font-size: 10px;"><%= txt2html comment.body %></span><br/> |
| 22 | - <span style="font-size: 8px; color: #929292"><%= time_ago_as_sentence(comment.created_at) %></span> | |
| 22 | + <span style="font-size: 8px; color: #929292"><%= time_ago_in_words(comment.created_at) %></span> | |
| 23 | 23 | <br style="clear: both;" /> |
| 24 | 24 | |
| 25 | 25 | <% unless comment.replies.blank? %> | ... | ... |
app/views/person_notifier/mailer/_create_article.html.erb
| ... | ... | @@ -6,7 +6,7 @@ |
| 6 | 6 | <p> |
| 7 | 7 | <span style="font-size: 14px;"><%= link_to activity.user.short_name(20), activity.user.url %></span> |
| 8 | 8 | <span style="font-size: 14px;"><%= _("has published on community %s") % link_to(activity.target.profile.short_name(20), activity.target.profile.url, :style => "color: #333; font-weight: bold; text-decoration: none;") if activity.target.profile.is_a?(Community) %></span> |
| 9 | - <span style="font-size: 10px; color: #929292; float:right;"><%= time_ago_as_sentence(activity.created_at) %></span> | |
| 9 | + <span style="font-size: 10px; color: #929292; float:right;"><%= time_ago_in_words(activity.created_at) %></span> | |
| 10 | 10 | </p> |
| 11 | 11 | <p> |
| 12 | 12 | <span style="font-size: 14px;"><%= link_to(activity.params['name'], activity.params['url'], :style => "color: #333; font-weight: bold; text-decoration: none;") %></span> | ... | ... |
app/views/person_notifier/mailer/_default_activity.html.erb
| ... | ... | @@ -5,7 +5,7 @@ |
| 5 | 5 | <td> |
| 6 | 6 | <p> |
| 7 | 7 | <span style="font-size: 14px;"><%= link_to activity.user.name, activity.user.url %> <%= describe activity %></span> |
| 8 | - <span style="font-size: 10px; color: #929292; float: right;"><%= time_ago_as_sentence(activity.created_at) %></span> | |
| 8 | + <span style="font-size: 10px; color: #929292; float: right;"><%= time_ago_in_words(activity.created_at) %></span> | |
| 9 | 9 | </p> |
| 10 | 10 | </td> |
| 11 | 11 | </tr> | ... | ... |
app/views/person_notifier/mailer/_task.html.erb
| ... | ... | @@ -12,7 +12,7 @@ |
| 12 | 12 | <span style="font-size: 14px"> |
| 13 | 13 | <%= task_information(task) %> |
| 14 | 14 | </span> |
| 15 | - <span style="font-size: 10px; color: #929292; float: right;"><%= time_ago_as_sentence(task.created_at) %></span> | |
| 15 | + <span style="font-size: 10px; color: #929292; float: right;"><%= time_ago_in_words(task.created_at) %></span> | |
| 16 | 16 | </div> |
| 17 | 17 | </td> |
| 18 | 18 | </tr> | ... | ... |
app/views/person_notifier/mailer/_upload_image.html.erb
| ... | ... | @@ -5,7 +5,7 @@ |
| 5 | 5 | <td> |
| 6 | 6 | <p> |
| 7 | 7 | <span style="font-size: 14px;"><%= link_to activity.user.name, activity.user.url %> <%= describe activity %></span> |
| 8 | - <span style="font-size: 10px; color: #929292; float:right;"><%= time_ago_as_sentence(activity.created_at) %></span> | |
| 8 | + <span style="font-size: 10px; color: #929292; float:right;"><%= time_ago_in_words(activity.created_at) %></span> | |
| 9 | 9 | </p> |
| 10 | 10 | </td> |
| 11 | 11 | </tr> | ... | ... |
app/views/profile/_comment.html.erb
app/views/profile/_create_article.html.erb
| ... | ... | @@ -12,7 +12,7 @@ |
| 12 | 12 | <%= image_tag(activity.params['first_image']) unless activity.params['first_image'].blank? %><%= strip_tags(truncate(activity.params['lead'], :length => 1000, :ommision => '...')).gsub(/(\xC2\xA0|\s)+/, ' ').gsub(/^\s+/, '') unless activity.params['lead'].blank? %> <small><%= link_to(_('See more'), activity.params['url']) unless activity.get_lead.blank? %></small> |
| 13 | 13 | </div> |
| 14 | 14 | <%= content_tag(:p, link_to(_('See complete forum'), activity.get_url), :class => 'see-forum') if activity.target.is_a?(Forum) %> |
| 15 | - <p class='profile-activity-time'><%= time_ago_as_sentence(activity.created_at) %></p> | |
| 15 | + <p class='profile-activity-time'><%= time_ago_in_words(activity.created_at) %></p> | |
| 16 | 16 | <div class='profile-wall-actions'> |
| 17 | 17 | <%= link_to s_('profile|Comment'), '#', { :class => 'focus-on-comment'} %> |
| 18 | 18 | <%= link_to_function(_('Remove'), 'remove_item_wall(this, \'%s\', \'%s\', \'%s\'); return false ;' % [".profile-activity-item", url_for(:profile => params[:profile], :action => :remove_activity, :activity_id => activity.id, :only_hide => true, :view => params[:view]), _('Are you sure you want to remove this activity and all its replies?')]) if logged_in? && current_person == @profile %> | ... | ... |
app/views/profile/_default_activity.html.erb
| ... | ... | @@ -3,7 +3,7 @@ |
| 3 | 3 | </div> |
| 4 | 4 | <div class='profile-activity-description'> |
| 5 | 5 | <p class='profile-activity-text'><%= link_to activity.user.name, activity.user.url %> <%= describe activity %></p> |
| 6 | - <p class='profile-activity-time'><%= time_ago_as_sentence(activity.created_at) %></p> | |
| 6 | + <p class='profile-activity-time'><%= time_ago_in_words(activity.created_at) %></p> | |
| 7 | 7 | <div class='profile-wall-actions'> |
| 8 | 8 | <%= link_to s_('profile|Comment'), '#', { :class => 'focus-on-comment'} %> |
| 9 | 9 | <%= link_to_function(_('Remove'), 'remove_item_wall(this, \'%s\', \'%s\', \'%s\'); return false ;' % [".profile-activity-item", url_for(:profile => params[:profile], :action => :remove_activity, :activity_id => activity.id, :view => params[:view]), _('Are you sure you want to remove this activity and all its replies?')]) if logged_in? && current_person == @profile %> | ... | ... |
app/views/profile/_leave_scrap.html.erb
| ... | ... | @@ -3,7 +3,7 @@ |
| 3 | 3 | </div> |
| 4 | 4 | <div class='profile-activity-description'> |
| 5 | 5 | <p class='profile-activity-text'><%= link_to activity.user.name, activity.user.url %> <%= describe activity %></p> |
| 6 | - <p class='profile-activity-time'><%= time_ago_as_sentence(activity.created_at) %></p> | |
| 6 | + <p class='profile-activity-time'><%= time_ago_in_words(activity.created_at) %></p> | |
| 7 | 7 | <div class='profile-wall-actions'> |
| 8 | 8 | <%= link_to_function(_('Remove'), 'remove_item_wall(this, \'%s\', \'%s\', \'%s\'); return false ;' % [".profile-activity-item", url_for(:profile => params[:profile], :action => :remove_activity, :activity_id => activity.id, :view => params[:view]), _('Are you sure you want to remove this activity and all its replies?')]) if logged_in? && current_person == @profile %> |
| 9 | 9 | </div> | ... | ... |
app/views/profile/_profile_scrap.html.erb
| ... | ... | @@ -5,7 +5,7 @@ |
| 5 | 5 | <div class='profile-activity-description'> |
| 6 | 6 | <p class='profile-activity-sender'><%= link_to scrap.sender.name, scrap.sender.url %></p> |
| 7 | 7 | <p class='profile-activity-text'><%= txt2html scrap.content %></p> |
| 8 | - <p class='profile-activity-time'><%= time_ago_as_sentence(scrap.created_at) %></p> | |
| 8 | + <p class='profile-activity-time'><%= time_ago_in_words(scrap.created_at) %></p> | |
| 9 | 9 | <div class='profile-wall-actions'> |
| 10 | 10 | <% if logged_in? && current_person.follows?(scrap.sender) %> |
| 11 | 11 | <span class='profile-activity-send-reply'> |
| ... | ... | @@ -22,5 +22,5 @@ |
| 22 | 22 | <% end %> |
| 23 | 23 | </ul> |
| 24 | 24 | <%= render :partial => 'profile_scrap_reply_form', :locals => { :scrap => scrap } %> |
| 25 | - <hr /> | |
| 25 | + <hr /> | |
| 26 | 26 | </li> | ... | ... |
app/views/profile/_profile_scraps.html.erb
| ... | ... | @@ -5,7 +5,7 @@ |
| 5 | 5 | <div class='profile-activity-description'> |
| 6 | 6 | <p class='profile-activity-sender'><%= link_to scrap.sender.name, scrap.sender.url %></p> |
| 7 | 7 | <p class='profile-activity-text'><%= txt2html scrap.content %></p> |
| 8 | - <p class='profile-activity-time'><%= time_ago_as_sentence(scrap.created_at) %></p> | |
| 8 | + <p class='profile-activity-time'><%= time_ago_in_words(scrap.created_at) %></p> | |
| 9 | 9 | <div class='profile-wall-actions'> |
| 10 | 10 | <% if logged_in? && current_person.follows?(scrap.sender) %> |
| 11 | 11 | <span class='profile-activity-send-reply'> | ... | ... |
app/views/profile/_upload_image.html.erb
| ... | ... | @@ -4,7 +4,7 @@ |
| 4 | 4 | </div> |
| 5 | 5 | <div class='profile-activity-description'> |
| 6 | 6 | <p class='profile-activity-text'><%= link_to activity.user.name, activity.user.url %> <%= describe activity %></p> |
| 7 | - <p class='profile-activity-time'><%= time_ago_as_sentence(activity.created_at) %></p> | |
| 7 | + <p class='profile-activity-time'><%= time_ago_in_words(activity.created_at) %></p> | |
| 8 | 8 | <div class='profile-wall-actions'> |
| 9 | 9 | <%= link_to_function(_('Remove'), 'remove_item_wall(this, \'%s\', \'%s\', \'%s\'); return false ;' % [".profile-activity-item", url_for(:profile => params[:profile], :action => :remove_activity, :activity_id => activity.id, :view => params[:view]), _('Are you sure you want to remove this activity and all its replies?')]) if logged_in? && current_person == @profile %> |
| 10 | 10 | </div> | ... | ... |
app/views/profile/content_tagged.html.erb
| ... | ... | @@ -5,7 +5,7 @@ |
| 5 | 5 | <h1><%= _('Content tagged with "%s"') % escaped_tag %></h1> |
| 6 | 6 | |
| 7 | 7 | <p> |
| 8 | -<%= link_to image_tag('icons-mime/rss-feed.png', :alt => _('Feed for this tag'), :title => _('Feed for this tag')), tag_feed_path, :class => 'blog-feed-link'%> | |
| 8 | +<%= link_to image_tag('/images/icons-mime/rss-feed.png', :alt => _('Feed for this tag'), :title => _('Feed for this tag')), tag_feed_path, :class => 'blog-feed-link'%> | |
| 9 | 9 | </p> |
| 10 | 10 | |
| 11 | 11 | <% cache_timeout(@tag_cache_key, 4.hour) do %> | ... | ... |
| ... | ... | @@ -0,0 +1,11 @@ |
| 1 | +<div id="list-item"> | |
| 2 | + <div class="item-info"> | |
| 3 | + <div class="item-icon" > | |
| 4 | + <%= display_content_icon(content) %> | |
| 5 | + </div> | |
| 6 | + <span class="item-description"> | |
| 7 | + <%= link_to(short_filename_upper_ext(content.name), content.url) %> | |
| 8 | + </span> | |
| 9 | + <span class="item-date"><%= _("Published at: #{show_date(content.updated_at)}") %></span> | |
| 10 | + </div> | |
| 11 | +</div> | |
| 0 | 12 | \ No newline at end of file | ... | ... |
app/views/shared/_lead_and_body.html.erb
| ... | ... | @@ -19,17 +19,27 @@ |
| 19 | 19 | |
| 20 | 20 | <div class='article-lead' id="article-lead-<%=lead_id.to_s%>"> |
| 21 | 21 | |
| 22 | + <% abstract_options = {:style => 'width: 100%; height: 200px;', :class => editor_type} %> | |
| 22 | 23 | <% if f %> |
| 23 | - <%= labelled_form_field(_(abstract_label), f.text_area(abstract_method, :style => 'width: 100%; height: 200px;', :class => editor_type)) %> | |
| 24 | + <%= labelled_form_field(_(abstract_label), f.text_area(abstract_method, abstract_options)) %> | |
| 24 | 25 | <% else %> |
| 25 | - <%= labelled_form_field(_(abstract_label), text_area(object, abstract_method, :style => 'width: 100%; height: 200px;', :class => editor_type)) %> | |
| 26 | + <% if @article.kind_of?(Article) %> | |
| 27 | + <%= labelled_form_field(_(abstract_label), text_area_tag("article[abstract]", @escaped_abstract, abstract_options)) %> | |
| 28 | + <% else %> | |
| 29 | + <%= labelled_form_field(_(abstract_label), text_area(object, abstract_method, abstract_options)) %> | |
| 30 | + <% end %> | |
| 26 | 31 | <% end %> |
| 27 | 32 | </div> |
| 28 | 33 | <div style="margin-top: 10px;"> |
| 34 | + <% body_options = {:style => 'width: 100%; height: 400px;', :class => editor_type} %> | |
| 29 | 35 | <% if f %> |
| 30 | - <%= labelled_form_field(_(body_label), f.text_area(body_method, :style => 'width: 100%; height: 400px;', :class => editor_type)) %> | |
| 36 | + <%= labelled_form_field(_(body_label), f.text_area(body_method, body_options)) %> | |
| 31 | 37 | <% else %> |
| 32 | - <%= labelled_form_field(_(body_label), text_area(object, body_method, :style => 'width: 100%; height: 400px;', :class => editor_type)) %> | |
| 38 | + <% if @article.kind_of?(Article) %> | |
| 39 | + <%= labelled_form_field(_(body_label), text_area_tag("article[body]", @escaped_body, body_options)) %> | |
| 40 | + <% else %> | |
| 41 | + <%= labelled_form_field(_(body_label), text_area(object, body_method, body_options)) %> | |
| 42 | + <% end %> | |
| 33 | 43 | <% end %> |
| 34 | 44 | </div> |
| 35 | 45 | ... | ... |
app/views/shared/content_list.html.erb
| 1 | -<table class="<%= list_type %>-content"> | |
| 2 | - <tr> | |
| 3 | - <th><%= _('Title') %></th> | |
| 4 | - <th><%= _('Last update') %></th> | |
| 5 | - </tr> | |
| 1 | +<ul class="<%= list_type %>-content"> | |
| 6 | 2 | <% contents.each do |content| %> |
| 7 | - <% if content.display_to?(user) %> | |
| 8 | - <%= display_content_in_listing :content=>content, :list_type=>list_type, :recursive=>recursive %> | |
| 9 | - <% end %> | |
| 3 | + <li class="<%= list_type %>-item"> | |
| 4 | + <% if content.display_to?(user) %> | |
| 5 | + <%= render :partial => 'shared/content_item', :locals => { :content => content } %> | |
| 6 | + <% end %> | |
| 7 | + </li> | |
| 10 | 8 | <% end %> |
| 11 | -</table> | |
| 9 | +</ul> | |
| 12 | 10 | |
| 13 | 11 | <p><%= pagination_links contents, :param_name => 'npage', :page_links => true %></p> | ... | ... |
app/views/tasks/_abuse_complaint_accept_details.html.erb
| ... | ... | @@ -2,7 +2,7 @@ |
| 2 | 2 | <% task.abuse_reports.each do |abuse_report| %> |
| 3 | 3 | <div> |
| 4 | 4 | <strong style="word-wrap: break-word; display: block; padding-right: 40px">"<%= abuse_report.reason %>"</strong> <br /> |
| 5 | - <i><%= _('Reported by %{reporter} %{time}.') % {:reporter => abuse_report.reporter.name, :time => time_ago_as_sentence(abuse_report.created_at) }%></i> <br /> | |
| 5 | + <i><%= _('Reported by %{reporter} %{time}.') % {:reporter => abuse_report.reporter.name, :time => time_ago_in_words(abuse_report.created_at) }%></i> <br /> | |
| 6 | 6 | <% if !abuse_report.content.blank? %> |
| 7 | 7 | <button class="display-abuse-report-details" data-report="<%=abuse_report.id%>"><%=_('View details')%></button> |
| 8 | 8 | <div style='display: none' id=<%= 'abuse-report-details-'+abuse_report.id.to_s %> class="abuse-report-details"> | ... | ... |
app/views/tasks/_task.html.erb
| ... | ... | @@ -2,7 +2,7 @@ |
| 2 | 2 | |
| 3 | 3 | <%= render :partial => 'task_icon', :locals => {:task => task} %> |
| 4 | 4 | |
| 5 | - <% if profile.organization? && @responsible_candidates.present? %> | |
| 5 | + <% if !@view_only && profile.organization? && @responsible_candidates.present? %> | |
| 6 | 6 | <div class="task_responsible"> |
| 7 | 7 | <span class="label"><%= _('Assign to:') %></span> |
| 8 | 8 | <span> |
| ... | ... | @@ -12,8 +12,16 @@ |
| 12 | 12 | </div> |
| 13 | 13 | <% end %> |
| 14 | 14 | |
| 15 | + <% if @view_only && task.responsible.present? %> | |
| 16 | + <div class="task_responsible"> | |
| 17 | + <span class="label"><%= _('Assigned to:') %></span> | |
| 18 | + <span class="value"><%= task.responsible.name %></span> | |
| 19 | + </div> | |
| 20 | + <% end %> | |
| 21 | + | |
| 15 | 22 | <div class="task_decisions"> |
| 16 | - <%= | |
| 23 | + <% unless @view_only %> | |
| 24 | + <%= | |
| 17 | 25 | labelled_radio_button(_("Accept"), "tasks[#{task.id}][decision]", 'finish', task.default_decision == 'accept', |
| 18 | 26 | :id => "decision-finish-#{task.id}", |
| 19 | 27 | :class => 'task_accept_radio', |
| ... | ... | @@ -29,7 +37,8 @@ |
| 29 | 37 | :class => 'task_skip_radio', |
| 30 | 38 | :disabled => task.skip_disabled?, |
| 31 | 39 | :task_id => "#{task.id}") |
| 32 | - %> | |
| 40 | + %> | |
| 41 | + <% end %> | |
| 33 | 42 | </div><!-- class="task_decisions" --> |
| 34 | 43 | |
| 35 | 44 | <div class="task_date"><%= show_time(task.created_at) %></div> | ... | ... |
app/views/tasks/index.html.erb
| ... | ... | @@ -46,36 +46,41 @@ |
| 46 | 46 | </p> |
| 47 | 47 | <% else %> |
| 48 | 48 | <%= form_tag :action => 'close' do%> |
| 49 | - <% button_bar do %> | |
| 49 | + <% button_bar(:class => 'task-actions') do %> | |
| 50 | 50 | <%# FiXME button(:edit, _('View my requests'), :action => 'list_requested') %> |
| 51 | 51 | <%# FIXME button('menu-mail', _('Send request'), :action => 'new') %> |
| 52 | 52 | <%= submit_button :save, _("Apply!") %> |
| 53 | 53 | <%= button(:edit, _('View processed tasks'), :action => 'processed') %> |
| 54 | 54 | <%= button(:back, _('Back to control panel'), :controller => 'profile_editor') %> |
| 55 | - <% end %> | |
| 55 | + <% end unless @view_only %> | |
| 56 | 56 | |
| 57 | 57 | <ul class='task-list'> |
| 58 | - <p> | |
| 59 | - <%= labelled_select(_("Set all to: "), 'set-decisions', 'first', 'last', nil, [['',""],['accept',_("Accept")],['reject',_("Reject")],['skip',_("Skip")]], :id => "up-set-all-tasks-to") %> | |
| 60 | - </p> | |
| 58 | + <% unless @view_only %> | |
| 59 | + <p> | |
| 60 | + <%= labelled_select(_("Set all to: "), 'set-decisions', 'first', 'last', nil, [['',""],['accept',_("Accept")],['reject',_("Reject")],['skip',_("Skip")]], :id => "up-set-all-tasks-to") %> | |
| 61 | + </p> | |
| 62 | + <% end %> | |
| 61 | 63 | |
| 62 | 64 | <div class="task_boxes"> |
| 63 | 65 | <%= render :partial => 'task', :collection => @tasks %> |
| 64 | 66 | </div> |
| 65 | - <p> | |
| 66 | - <%= labelled_select(_("Set all to: "), 'set-decisions', 'first', 'last', nil, [['',""],['accept',_("Accept")],['reject',_("Reject")],['skip',_("Skip")]], :id => "down-set-all-tasks-to") %> | |
| 67 | - </p> | |
| 67 | + | |
| 68 | + <% unless @view_only %> | |
| 69 | + <p> | |
| 70 | + <%= labelled_select(_("Set all to: "), 'set-decisions', 'first', 'last', nil, [['',""],['accept',_("Accept")],['reject',_("Reject")],['skip',_("Skip")]], :id => "down-set-all-tasks-to") %> | |
| 71 | + </p> | |
| 72 | + <% end %> | |
| 68 | 73 | </ul> |
| 69 | 74 | |
| 70 | 75 | <%= pagination_links(@tasks)%> |
| 71 | 76 | |
| 72 | - <% button_bar do %> | |
| 77 | + <% button_bar(:class => 'task-actions') do %> | |
| 73 | 78 | <%# FiXME button(:edit, _('View my requests'), :action => 'list_requested') %> |
| 74 | 79 | <%# FIXME button('menu-mail', _('Send request'), :action => 'new') %> |
| 75 | 80 | <%= submit_button :save, _("Apply!") %> |
| 76 | 81 | <%= button(:edit, _('View processed tasks'), :action => 'processed') %> |
| 77 | 82 | <%= button(:back, _('Back to control panel'), :controller => 'profile_editor') %> |
| 78 | - <% end %> | |
| 83 | + <% end unless @view_only %> | |
| 79 | 84 | <% end %> |
| 80 | 85 | <% end %> |
| 81 | 86 | </p> | ... | ... |
config/initializers/delayed_job_config.rb
| ... | ... | @@ -23,3 +23,13 @@ end |
| 23 | 23 | # end |
| 24 | 24 | # alias_method_chain :handle_failed_job, :loggin |
| 25 | 25 | #end |
| 26 | + | |
| 27 | +# Chain delayed job's handle_failed_job method to do exception notification | |
| 28 | +Delayed::Worker.class_eval do | |
| 29 | + def handle_failed_job_with_notification job, error | |
| 30 | + handle_failed_job_without_notification job, error | |
| 31 | + ExceptionNotifier.notify_exception error, exception_recipients: NOOSFERO_CONF['exception_recipients'], | |
| 32 | + data: {job: job, handler: job.handler} rescue nil | |
| 33 | + end | |
| 34 | + alias_method_chain :handle_failed_job, :notification | |
| 35 | +end | ... | ... |
config/initializers/noosfero_extensions.rb
| ... | ... | @@ -0,0 +1,19 @@ |
| 1 | +class FixTagsCaseDifferences < ActiveRecord::Migration | |
| 2 | + def up | |
| 3 | + tags = ActsAsTaggableOn::Tag.joins('LEFT JOIN tags as b on LOWER(tags.name) = b.name').where('b.id is null') | |
| 4 | + tags.find_each do |tag| | |
| 5 | + unless ActsAsTaggableOn::Tag.exists?(:name => tag.name.mb_chars.downcase) | |
| 6 | + ActsAsTaggableOn::Tag.create(:name => tag.name.mb_chars.downcase) | |
| 7 | + end | |
| 8 | + end | |
| 9 | + | |
| 10 | + execute("UPDATE taggings SET tag_id = new.id FROM taggings AS t INNER JOIN tags AS old ON t.tag_id = old.id INNER JOIN tags AS new ON LOWER(old.name) = new.name WHERE old.id != new.id AND taggings.id = t.id") | |
| 11 | + | |
| 12 | + execute("UPDATE tags SET taggings_count = (SELECT COUNT(*) FROM taggings WHERE taggings.tag_id = tags.id)") | |
| 13 | + execute("DELETE FROM tags WHERE taggings_count = 0") | |
| 14 | + end | |
| 15 | + | |
| 16 | + def down | |
| 17 | + say 'This migration is irreversible.' | |
| 18 | + end | |
| 19 | +end | ... | ... |
db/migrate/20150507204849_remove_broken_profile_suggestions.rb
0 → 100644
db/migrate/20150529180110_add_date_format_to_environment.rb
0 → 100644
db/schema.rb
| ... | ... | @@ -11,7 +11,7 @@ |
| 11 | 11 | # |
| 12 | 12 | # It's strongly recommended to check this file into your version control system. |
| 13 | 13 | |
| 14 | -ActiveRecord::Schema.define(:version => 20150525101430) do | |
| 14 | +ActiveRecord::Schema.define(:version => 20150602142030) do | |
| 15 | 15 | |
| 16 | 16 | create_table "abuse_reports", :force => true do |t| |
| 17 | 17 | t.integer "reporter_id" |
| ... | ... | @@ -320,17 +320,18 @@ ActiveRecord::Schema.define(:version => 20150525101430) do |
| 320 | 320 | t.text "design_data" |
| 321 | 321 | t.text "custom_header" |
| 322 | 322 | t.text "custom_footer" |
| 323 | - t.string "theme", :default => "default", :null => false | |
| 323 | + t.string "theme", :default => "default", :null => false | |
| 324 | 324 | t.text "terms_of_use_acceptance_text" |
| 325 | 325 | t.datetime "created_at" |
| 326 | 326 | t.datetime "updated_at" |
| 327 | - t.integer "reports_lower_bound", :default => 0, :null => false | |
| 327 | + t.integer "reports_lower_bound", :default => 0, :null => false | |
| 328 | 328 | t.string "redirection_after_login", :default => "keep_on_same_page" |
| 329 | 329 | t.text "signup_welcome_text" |
| 330 | 330 | t.string "languages" |
| 331 | 331 | t.string "default_language" |
| 332 | 332 | t.string "noreply_email" |
| 333 | 333 | t.string "redirection_after_signup", :default => "keep_on_same_page" |
| 334 | + t.string "date_format", :default => "month_name_with_year" | |
| 334 | 335 | end |
| 335 | 336 | |
| 336 | 337 | create_table "external_feeds", :force => true do |t| |
| ... | ... | @@ -691,6 +692,7 @@ ActiveRecord::Schema.define(:version => 20150525101430) do |
| 691 | 692 | t.integer "image_id" |
| 692 | 693 | t.boolean "spam", :default => false |
| 693 | 694 | t.integer "responsible_id" |
| 695 | + t.integer "closed_by_id" | |
| 694 | 696 | end |
| 695 | 697 | |
| 696 | 698 | add_index "tasks", ["requestor_id"], :name => "index_tasks_on_requestor_id" | ... | ... |
features/approve_article.feature
| ... | ... | @@ -62,7 +62,8 @@ Feature: approve article |
| 62 | 62 | And I press "Spread this" |
| 63 | 63 | And I follow "Delete" |
| 64 | 64 | And I confirm the browser dialog |
| 65 | - When I am logged in as "joaosilva" | |
| 65 | + And I follow "Logout" | |
| 66 | + And I am logged in as "joaosilva" | |
| 66 | 67 | And I go to sample-community's control panel |
| 67 | 68 | And I follow "Process requests" |
| 68 | 69 | And I choose "Reject" | ... | ... |
features/balloon.feature
| ... | ... | @@ -41,19 +41,19 @@ Feature: balloon |
| 41 | 41 | @selenium |
| 42 | 42 | Scenario: I should not see trigger if not enabled on page |
| 43 | 43 | Given feature "show_balloon_with_profile_links_when_clicked" is disabled on environment |
| 44 | - When I go to /assets/people | |
| 44 | + When I go to /search/people | |
| 45 | 45 | Then I should not see "Profile links" |
| 46 | 46 | |
| 47 | 47 | @selenium |
| 48 | 48 | Scenario: I should not see trigger by default on page |
| 49 | 49 | Given feature "show_balloon_with_profile_links_when_clicked" is enabled on environment |
| 50 | - When I go to /assets/communities | |
| 50 | + When I go to /search/communities | |
| 51 | 51 | Then I should not see "Members" |
| 52 | 52 | |
| 53 | 53 | @selenium |
| 54 | 54 | Scenario: I should see balloon when clicked on page trigger |
| 55 | 55 | Given feature "show_balloon_with_profile_links_when_clicked" is enabled on environment |
| 56 | - And I go to /assets/communities | |
| 56 | + And I go to /search/communities | |
| 57 | 57 | And display ".community-trigger" |
| 58 | 58 | When I follow "Profile links" |
| 59 | 59 | Then I should see "Members" | ... | ... |
features/browse_enterprises.feature
| ... | ... | @@ -13,20 +13,20 @@ Scenario: show all enterprises |
| 13 | 13 | Given the following enterprises |
| 14 | 14 | | identifier | name | |
| 15 | 15 | | shop2 | Fruits Shop | |
| 16 | - Given I am on /assets/enterprises | |
| 16 | + Given I am on /search/enterprises | |
| 17 | 17 | Then I should see "Enterprises" |
| 18 | 18 | And I should see "Shoes Shop" |
| 19 | 19 | And I should see "Fruits Shop" |
| 20 | 20 | |
| 21 | 21 | Scenario: show profile links button |
| 22 | - Given I am on /assets/enterprises | |
| 22 | + Given I am on /search/enterprises | |
| 23 | 23 | Then I should see "Profile links" within "a.enterprise-trigger" |
| 24 | 24 | And I should not see "Members" |
| 25 | 25 | And I should not see "Agenda" |
| 26 | 26 | |
| 27 | 27 | @selenium-fixme |
| 28 | 28 | Scenario: show profile links when clicked |
| 29 | - Given I am on /assets/enterprises | |
| 29 | + Given I am on /search/enterprises | |
| 30 | 30 | When I follow "Profile links" |
| 31 | 31 | Then I should see "Products" within "ul.menu-submenu-list" |
| 32 | 32 | And I should see "Members" within "ul.menu-submenu-list" |
| ... | ... | @@ -34,7 +34,7 @@ Scenario: show profile links when clicked |
| 34 | 34 | |
| 35 | 35 | @selenium-fixme |
| 36 | 36 | Scenario: go to catalog when click on products link |
| 37 | - Given I am on /assets/enterprises | |
| 37 | + Given I am on /search/enterprises | |
| 38 | 38 | When I follow "Profile links" |
| 39 | 39 | And I follow "Products" and wait |
| 40 | 40 | Then I should be exactly on /catalog/shop1 | ... | ... |
features/change_appearance.feature
| ... | ... | @@ -14,7 +14,7 @@ Feature: Change appearance |
| 14 | 14 | And I should not see an element ".box-4" |
| 15 | 15 | And I go to joaosilva's control panel |
| 16 | 16 | And I follow "Edit Appearance" |
| 17 | - And I follow "Left Top and Right" | |
| 17 | + And I follow "Top and Side Bars" | |
| 18 | 18 | And I go to joaosilva's control panel |
| 19 | 19 | And I follow "Edit sideboxes" |
| 20 | 20 | And I should see an element ".box-4" | ... | ... |
features/events.feature
| ... | ... | @@ -17,7 +17,7 @@ Feature: events |
| 17 | 17 | Then I should see "November 2009" within ".current-month" |
| 18 | 18 | |
| 19 | 19 | Scenario: go to next month in global agenda |
| 20 | - Given I am on /assets/events?year=2009&month=11 | |
| 20 | + Given I am on /search/events?year=2009&month=11 | |
| 21 | 21 | When I follow "December" |
| 22 | 22 | Then I should see "December 2009" within ".current-month" |
| 23 | 23 | |
| ... | ... | @@ -27,7 +27,7 @@ Feature: events |
| 27 | 27 | Then I should see "September 2009" within ".current-month" |
| 28 | 28 | |
| 29 | 29 | Scenario: go to previous month in global agenda |
| 30 | - Given I am on /assets/events?year=2009&month=11 | |
| 30 | + Given I am on /search/events?year=2009&month=11 | |
| 31 | 31 | When I follow "October" |
| 32 | 32 | Then I should see "October 2009" within ".current-month" |
| 33 | 33 | |
| ... | ... | @@ -43,7 +43,7 @@ Feature: events |
| 43 | 43 | |
| 44 | 44 | Scenario: go to specific day in global agenda |
| 45 | 45 | Given I am on the homepage |
| 46 | - When I am on /assets/events?year=2009&month=11&day=12 | |
| 46 | + When I am on /search/events?year=2009&month=11&day=12 | |
| 47 | 47 | Then I should see "Events for November, 2009" |
| 48 | 48 | |
| 49 | 49 | Scenario: list events for specific day |
| ... | ... | @@ -88,7 +88,7 @@ Feature: events |
| 88 | 88 | And the following events |
| 89 | 89 | | owner | name | start_date | |
| 90 | 90 | | josemanuel | Manuel Birthday | 2009-10-24 | |
| 91 | - When I am on /assets/events?year=2009&month=10&day=24 | |
| 91 | + When I am on /search/events?year=2009&month=10&day=24 | |
| 92 | 92 | Then I should see "Another Conference" |
| 93 | 93 | And I should see "Manuel Birthday" |
| 94 | 94 | |
| ... | ... | @@ -157,7 +157,7 @@ Feature: events |
| 157 | 157 | Then I should not see "New events" link |
| 158 | 158 | |
| 159 | 159 | Scenario: display environment name in global agenda |
| 160 | - When I am on /assets/events | |
| 160 | + When I am on /search/events | |
| 161 | 161 | Then I should see "Colivre.net's Events" |
| 162 | 162 | |
| 163 | 163 | @selenium | ... | ... |
features/profile_domain.feature
| ... | ... | @@ -21,9 +21,7 @@ Feature: domain for profile |
| 21 | 21 | Scenario: access profile control panel through profile blocks |
| 22 | 22 | Given I am logged in as "joaosilva" |
| 23 | 23 | When I go to joaosilva's homepage |
| 24 | - And I follow "Control panel" within ".profile-info-block" | |
| 25 | - Then I should see "Joao Silva" within "span.control-panel-title" | |
| 26 | - When I follow "Control panel" within ".profile-image-block" | |
| 24 | + And I follow "Control panel" within ".profile-image-block" | |
| 27 | 25 | Then I should see "Joao Silva" within "span.control-panel-title" |
| 28 | 26 | |
| 29 | 27 | @selenium | ... | ... |
features/profile_search.feature
| ... | ... | @@ -36,7 +36,7 @@ Feature: search inside a profile |
| 36 | 36 | | joaosilva | ProfileSearchBlock | |
| 37 | 37 | When I go to joaosilva's profile |
| 38 | 38 | And I fill in "q" with "bees" within ".profile-search-block" |
| 39 | - And I press "Search" | |
| 39 | + And I press "Search" within ".profile-search-block" | |
| 40 | 40 | Then I should see "bees and butterflies" within ".main-block" |
| 41 | 41 | |
| 42 | 42 | Scenario: not display unpublished articles | ... | ... |
features/register_enterprise.feature
| ... | ... | @@ -203,5 +203,5 @@ Feature: register enterprise |
| 203 | 203 | |
| 204 | 204 | Scenario: a user cant see button to register new enterprise if enterprise_registration disabled |
| 205 | 205 | Given feature "enterprise_registration" is disabled on environment |
| 206 | - When I am on /assets/enterprises | |
| 206 | + When I am on /search/enterprises | |
| 207 | 207 | Then I should not see "New enterprise" link | ... | ... |
features/search_enterprises.feature
| ... | ... | @@ -56,7 +56,7 @@ Feature: search enterprises |
| 56 | 56 | | owner | name | body | homepage | |
| 57 | 57 | | shop1 | Shoes home | This is the <i>homepage</i> of Shoes shop! It has a very long and pretty vague description, just so we can test wether the system will correctly create an excerpt of this text. We should probably talk about shoes. | true | |
| 58 | 58 | When I search enterprises for "shoes" |
| 59 | - And I choose the search filter "Full" | |
| 59 | + And I select "Full" from "display" | |
| 60 | 60 | Then I should see "This is the homepage of" within ".search-enterprise-description" |
| 61 | 61 | And I should see "about sho..." within ".search-enterprise-description" |
| 62 | 62 | |
| ... | ... | @@ -66,7 +66,7 @@ Feature: search enterprises |
| 66 | 66 | | identifier | name | description | |
| 67 | 67 | | shop4 | Clothes shop | This <b>clothes</b> shop also sells shoes! This too has a very long and pretty vague description, just so we can test wether the system will correctly create an excerpt of this text. Clothes are a really important part of our lives. | |
| 68 | 68 | When I search enterprises for "clothes" |
| 69 | - And I choose the search filter "Full" | |
| 69 | + And I select "Full" from "display" | |
| 70 | 70 | And I should see "This clothes shop" within ".search-enterprise-description" |
| 71 | 71 | And I should see "really import..." within ".search-enterprise-description" |
| 72 | 72 | ... | ... |
features/step_definitions/noosfero_steps.rb
| ... | ... | @@ -94,7 +94,7 @@ Given /^the following blocks$/ do |table| |
| 94 | 94 | owner.boxes<< Box.new |
| 95 | 95 | owner.boxes.first.blocks << MainBlock.new |
| 96 | 96 | end |
| 97 | - box = owner.boxes.where(:position => 3).first | |
| 97 | + box = owner.boxes.first | |
| 98 | 98 | klass.constantize.create!(item.merge(:box => box)) |
| 99 | 99 | end |
| 100 | 100 | end | ... | ... |
features/suggest_article.feature
| ... | ... | @@ -14,9 +14,12 @@ Feature: suggest article |
| 14 | 14 | |
| 15 | 15 | @selenium |
| 16 | 16 | Scenario: highlight an article before approval of a suggested article |
| 17 | - Given someone suggested the following article to be published | |
| 18 | - | target | article_name | article_body | name | email | | |
| 19 | - | sample-community | A suggested article | this is an article about whales | jose | jose@example.org | | |
| 17 | + Given I am on Sample Community's blog | |
| 18 | + And I follow "Suggest an article" | |
| 19 | + And I fill in "Title" with "Suggestion" | |
| 20 | + And I fill in "Your name" with "Some Guy" | |
| 21 | + And I fill in "Email" with "someguy@somewhere.com" | |
| 22 | + And I press "Save" | |
| 20 | 23 | When I am logged in as "joaosilva" |
| 21 | 24 | And I go to sample-community's control panel |
| 22 | 25 | And I follow "Process requests" | ... | ... |
lib/noosfero/plugin.rb
| 1 | 1 | require_dependency 'noosfero' |
| 2 | +require 'noosfero/plugin/parent_methods' | |
| 2 | 3 | |
| 3 | 4 | class Noosfero::Plugin |
| 4 | 5 | |
| ... | ... | @@ -14,13 +15,9 @@ class Noosfero::Plugin |
| 14 | 15 | |
| 15 | 16 | class << self |
| 16 | 17 | |
| 17 | - attr_writer :should_load | |
| 18 | + include Noosfero::Plugin::ParentMethods | |
| 18 | 19 | |
| 19 | - # Called for each ActiveRecord class with parents | |
| 20 | - # See http://apidock.com/rails/ActiveRecord/ModelSchema/ClassMethods/full_table_name_prefix | |
| 21 | - def table_name_prefix | |
| 22 | - @table_name_prefix ||= "#{name.to_s.underscore}_" | |
| 23 | - end | |
| 20 | + attr_writer :should_load | |
| 24 | 21 | |
| 25 | 22 | def should_load |
| 26 | 23 | @should_load.nil? && true || @boot |
| ... | ... | @@ -92,8 +89,14 @@ class Noosfero::Plugin |
| 92 | 89 | end |
| 93 | 90 | end |
| 94 | 91 | |
| 95 | - def load_plugin(plugin_name) | |
| 96 | - (plugin_name.to_s.camelize + 'Plugin').constantize | |
| 92 | + def load_plugin_identifier identifier | |
| 93 | + klass = identifier.to_s.camelize.constantize | |
| 94 | + klass = klass.const_get :Base if klass.class == Module | |
| 95 | + klass | |
| 96 | + end | |
| 97 | + | |
| 98 | + def load_plugin public_name | |
| 99 | + load_plugin_identifier "#{public_name.to_s.camelize}Plugin" | |
| 97 | 100 | end |
| 98 | 101 | |
| 99 | 102 | # This is a generic method that initialize any possible filter defined by a |
| ... | ... | @@ -135,7 +138,7 @@ class Noosfero::Plugin |
| 135 | 138 | filters = [filters] |
| 136 | 139 | end |
| 137 | 140 | filters.each do |plugin_filter| |
| 138 | - filter_method = (plugin.name.underscore.gsub('/','_') + '_' + plugin_filter[:method_name]).to_sym | |
| 141 | + filter_method = "#{plugin.identifier}_#{plugin_filter[:method_name]}".to_sym | |
| 139 | 142 | controller_class.send(plugin_filter[:type], filter_method, (plugin_filter[:options] || {})) |
| 140 | 143 | controller_class.send(:define_method, filter_method) do |
| 141 | 144 | instance_exec(&plugin_filter[:block]) if environment.plugin_enabled?(plugin) |
| ... | ... | @@ -167,44 +170,6 @@ class Noosfero::Plugin |
| 167 | 170 | def all |
| 168 | 171 | @all ||= available_plugins.map{ |dir| (File.basename(dir) + "_plugin").camelize } |
| 169 | 172 | end |
| 170 | - | |
| 171 | - def public_name | |
| 172 | - self.name.underscore.gsub('_plugin','') | |
| 173 | - end | |
| 174 | - | |
| 175 | - def public_path file = '', relative=false | |
| 176 | - File.join "#{if relative then '' else '/' end}plugins", public_name, file | |
| 177 | - end | |
| 178 | - | |
| 179 | - def root_path | |
| 180 | - Rails.root.join('plugins', public_name) | |
| 181 | - end | |
| 182 | - | |
| 183 | - def view_path | |
| 184 | - File.join(root_path,'views') | |
| 185 | - end | |
| 186 | - | |
| 187 | - # Here the developer should specify the meta-informations that the plugin can | |
| 188 | - # inform. | |
| 189 | - def plugin_name | |
| 190 | - self.name.underscore.humanize | |
| 191 | - end | |
| 192 | - def plugin_description | |
| 193 | - _("No description informed.") | |
| 194 | - end | |
| 195 | - | |
| 196 | - def admin_url | |
| 197 | - {:controller => "#{name.underscore}_admin", :action => 'index'} | |
| 198 | - end | |
| 199 | - | |
| 200 | - def has_admin_url? | |
| 201 | - File.exists?(File.join(root_path, 'controllers', "#{name.underscore}_admin_controller.rb")) | |
| 202 | - end | |
| 203 | - | |
| 204 | - # -> define grape class used to map resource api provided by the plugin | |
| 205 | - def api_mount_points | |
| 206 | - [] | |
| 207 | - end | |
| 208 | 173 | end |
| 209 | 174 | |
| 210 | 175 | def expanded_template(file_path, locals = {}) | ... | ... |
lib/noosfero/plugin/manager.rb
| ... | ... | @@ -76,7 +76,7 @@ class Noosfero::Plugin::Manager |
| 76 | 76 | |
| 77 | 77 | def enabled_plugins |
| 78 | 78 | @enabled_plugins ||= (Noosfero::Plugin.all & environment.enabled_plugins).map do |plugin| |
| 79 | - plugin.constantize.new(context) | |
| 79 | + Noosfero::Plugin.load_plugin_identifier(plugin).new context | |
| 80 | 80 | end |
| 81 | 81 | end |
| 82 | 82 | ... | ... |
| ... | ... | @@ -0,0 +1,67 @@ |
| 1 | +class Noosfero::Plugin | |
| 2 | + | |
| 3 | + # Plugins that are defined as modules should extend | |
| 4 | + # this module manually, for example: | |
| 5 | + # module MyPlugin | |
| 6 | + # extend Noosfero::Plugin::ParentMethods | |
| 7 | + # end | |
| 8 | + module ParentMethods | |
| 9 | + | |
| 10 | + def identifier | |
| 11 | + @identifier ||= (if self.parents.first.instance_of? Module then self.parents.first else self end).name.underscore | |
| 12 | + end | |
| 13 | + | |
| 14 | + def public_name | |
| 15 | + @public_name ||= self.identifier.gsub '_plugin', '' | |
| 16 | + end | |
| 17 | + | |
| 18 | + # Here the developer should specify the meta-informations that the plugin can | |
| 19 | + # inform. | |
| 20 | + def plugin_name | |
| 21 | + self.identifier.humanize | |
| 22 | + end | |
| 23 | + def plugin_description | |
| 24 | + _("No description informed.") | |
| 25 | + end | |
| 26 | + | |
| 27 | + # Called for each ActiveRecord model with parents | |
| 28 | + # See http://apidock.com/rails/ActiveRecord/ModelSchema/ClassMethods/full_table_name_prefix | |
| 29 | + def table_name_prefix | |
| 30 | + @table_name_prefix ||= "#{self.identifier}_" | |
| 31 | + end | |
| 32 | + | |
| 33 | + def public_path file = '', relative=false | |
| 34 | + File.join "#{if relative then '' else '/' end}plugins", public_name, file | |
| 35 | + end | |
| 36 | + | |
| 37 | + def root_path | |
| 38 | + Rails.root.join('plugins', public_name) | |
| 39 | + end | |
| 40 | + | |
| 41 | + def view_path | |
| 42 | + File.join(root_path,'views') | |
| 43 | + end | |
| 44 | + | |
| 45 | + def admin_url | |
| 46 | + {:controller => "#{self.identifier}_admin", :action => 'index'} | |
| 47 | + end | |
| 48 | + | |
| 49 | + def has_admin_url? | |
| 50 | + File.exists?(File.join(root_path, 'controllers', "#{self.identifier}_admin_controller.rb")) | |
| 51 | + end | |
| 52 | + | |
| 53 | + # -> define grape class used to map resource api provided by the plugin | |
| 54 | + def api_mount_points | |
| 55 | + [] | |
| 56 | + end | |
| 57 | + | |
| 58 | + def controllers | |
| 59 | + @controllers ||= Dir.glob("#{self.root_path}/controllers/*/*").map do |controller_file| | |
| 60 | + next unless controller_file =~ /_controller.rb$/ | |
| 61 | + controller = File.basename(controller_file).gsub(/.rb$/, '').camelize | |
| 62 | + end.compact | |
| 63 | + end | |
| 64 | + | |
| 65 | + end | |
| 66 | + | |
| 67 | +end | ... | ... |
lib/short_filename.rb
| 1 | 1 | module ShortFilename |
| 2 | 2 | |
| 3 | 3 | def short_filename(filename, limit_chars = 43) |
| 4 | - return filename if filename.size <= limit_chars | |
| 5 | 4 | extname = File.extname(filename) |
| 6 | 5 | basename = File.basename(filename,extname) |
| 6 | + return shrink(basename, extname, limit_chars) + extname | |
| 7 | + end | |
| 8 | + | |
| 9 | + def short_filename_upper_ext(filename, limit_chars = 43) | |
| 10 | + extname = File.extname(filename) | |
| 11 | + display_name = shrink(File.basename(filename, extname), extname, limit_chars) | |
| 12 | + return extname.present? ? (display_name + ' - ' + extname.upcase.delete(".")) : display_name | |
| 13 | + end | |
| 14 | + | |
| 15 | + def shrink(filename, extname, limit_chars) | |
| 16 | + return filename if filename.size <= limit_chars | |
| 7 | 17 | str_complement = '(...)' |
| 8 | - return basename[0..(limit_chars - extname.size - str_complement.size - 1)] + str_complement + extname | |
| 18 | + return filename[0..(limit_chars - extname.size - str_complement.size - 1)] + str_complement | |
| 9 | 19 | end |
| 10 | 20 | |
| 11 | 21 | end | ... | ... |
plugins/comment_classification/views/comment_classification_plugin_myprofile/add_status.html.erb
| ... | ... | @@ -13,7 +13,7 @@ |
| 13 | 13 | <ul> |
| 14 | 14 | <% @comment.comment_classification_plugin_comment_status_users.each do |relation| %> |
| 15 | 15 | <li> |
| 16 | - <%= _("<i>%{user}</i> added the status <i>%{status_name}</i> at <i>%{created_at}</i>.") % { :user => relation.profile.name, :status_name => relation.status.name, :created_at => time_ago_as_sentence(relation.created_at)} %> | |
| 16 | + <%= _("<i>%{user}</i> added the status <i>%{status_name}</i> at <i>%{created_at}</i>.") % { :user => relation.profile.name, :status_name => relation.status.name, :created_at => time_ago_in_words(relation.created_at)} %> | |
| 17 | 17 | <% unless relation.reason.blank? %> |
| 18 | 18 | <p><%= _("<i>Reason:</i> %s") % relation.reason %></p> |
| 19 | 19 | <% end %> | ... | ... |
plugins/custom_forms/views/custom_forms_plugin_profile/show.html.erb
| ... | ... | @@ -14,8 +14,8 @@ |
| 14 | 14 | |
| 15 | 15 | <%= form_for :submission do |f| %> |
| 16 | 16 | <% if !user %> |
| 17 | - <%= required labelled_form_field _('Author name'), text_field_tag(:author_name, @submission.author_name) %> | |
| 18 | - <%= required labelled_form_field _('Author email'), text_field_tag(:author_email, @submission.author_email) %> | |
| 17 | + <%= required labelled_form_field _('Name'), text_field_tag(:author_name, @submission.author_name) %> | |
| 18 | + <%= required labelled_form_field _('Email'), text_field_tag(:author_email, @submission.author_email) %> | |
| 19 | 19 | <% end %> |
| 20 | 20 | |
| 21 | 21 | <%= render :partial => 'shared/form_submission', :locals => {:f => f} %> | ... | ... |
plugins/metadata/lib/metadata_plugin.rb
| ... | ... | @@ -23,7 +23,7 @@ class MetadataPlugin < Noosfero::Plugin |
| 23 | 23 | }, |
| 24 | 24 | content_viewer: { |
| 25 | 25 | variable: proc do |
| 26 | - if profile and profile.home_page_id == @page.id | |
| 26 | + if profile and @page and profile.home_page_id == @page.id | |
| 27 | 27 | @profile |
| 28 | 28 | elsif @page.respond_to? :encapsulated_file |
| 29 | 29 | @page.encapsulated_file | ... | ... |
plugins/metadata/test/functional/content_viewer_controller_test.rb
| ... | ... | @@ -48,4 +48,13 @@ class ContentViewerControllerTest < ActionController::TestCase |
| 48 | 48 | assert_tag tag: 'meta', attributes: { property: 'og:image', content: /\/images\/x.png/ } |
| 49 | 49 | end |
| 50 | 50 | |
| 51 | + should 'render not_found page properly' do | |
| 52 | + assert_equal false, Article.exists?(:slug => 'non-existing-page') | |
| 53 | + assert_nothing_raised do | |
| 54 | + get :view_page, profile: profile.identifier, page: [ 'non-existing-page' ] | |
| 55 | + assert_response 404 # not found | |
| 56 | + assert_template 'not_found' | |
| 57 | + end | |
| 58 | + end | |
| 59 | + | |
| 51 | 60 | end | ... | ... |
plugins/vote/lib/ext/article.rb
plugins/vote/lib/ext/comment.rb
plugins/vote/lib/ext/person.rb
plugins/vote/lib/ext/vote.rb
plugins/vote/test/unit/article_test.rb
| ... | ... | @@ -1,24 +0,0 @@ |
| 1 | -require 'test_helper' | |
| 2 | - | |
| 3 | -class ArticleTest < ActiveSupport::TestCase | |
| 4 | - | |
| 5 | - def setup | |
| 6 | - @profile = create_user('testing').person | |
| 7 | - end | |
| 8 | - | |
| 9 | - attr_reader :profile | |
| 10 | - | |
| 11 | - should 'vote in a article' do | |
| 12 | - article = create(Article, :name => 'Test', :profile => profile, :last_changed_by => nil) | |
| 13 | - profile.vote(article, 5) | |
| 14 | - assert_equal 1, article.voters_who_voted.length | |
| 15 | - assert_equal 5, article.votes_total | |
| 16 | - end | |
| 17 | - | |
| 18 | - should 'be able to remove a voted article' do | |
| 19 | - article = create(Article, :name => 'Test', :profile => profile, :last_changed_by => nil) | |
| 20 | - profile.vote(article, 5) | |
| 21 | - article.destroy | |
| 22 | - end | |
| 23 | - | |
| 24 | -end |
plugins/vote/test/unit/comment_test.rb
| ... | ... | @@ -1,59 +0,0 @@ |
| 1 | -require 'test_helper' | |
| 2 | - | |
| 3 | -class CommentTest < ActiveSupport::TestCase | |
| 4 | - | |
| 5 | - should 'vote in a comment' do | |
| 6 | - comment = create_comment | |
| 7 | - person = create_user('voter').person | |
| 8 | - person.vote(comment, 5) | |
| 9 | - assert_equal 1, comment.voters_who_voted.length | |
| 10 | - assert_equal 5, comment.votes_total | |
| 11 | - end | |
| 12 | - | |
| 13 | - should 'like a comment' do | |
| 14 | - comment = create_comment | |
| 15 | - person = create_user('voter').person | |
| 16 | - assert !comment.voted_by?(person, true) | |
| 17 | - person.vote_for(comment) | |
| 18 | - assert comment.voted_by?(person, true) | |
| 19 | - assert !comment.voted_by?(person, false) | |
| 20 | - end | |
| 21 | - | |
| 22 | - should 'count voters for' do | |
| 23 | - comment = create_comment | |
| 24 | - person = create_user('voter').person | |
| 25 | - person2 = create_user('voter2').person | |
| 26 | - person3 = create_user('voter3').person | |
| 27 | - person.vote_for(comment) | |
| 28 | - person2.vote_for(comment) | |
| 29 | - person3.vote_against(comment) | |
| 30 | - assert_equal 2, comment.votes_for | |
| 31 | - end | |
| 32 | - | |
| 33 | - should 'count votes againts' do | |
| 34 | - comment = create_comment | |
| 35 | - person = create_user('voter').person | |
| 36 | - person2 = create_user('voter2').person | |
| 37 | - person3 = create_user('voter3').person | |
| 38 | - person.vote_against(comment) | |
| 39 | - person2.vote_against(comment) | |
| 40 | - person3.vote_for(comment) | |
| 41 | - assert_equal 2, comment.votes_against | |
| 42 | - end | |
| 43 | - | |
| 44 | - should 'be able to remove a voted comment' do | |
| 45 | - comment = create_comment | |
| 46 | - person = create_user('voter').person | |
| 47 | - person.vote(comment, 5) | |
| 48 | - comment.destroy | |
| 49 | - end | |
| 50 | - | |
| 51 | - private | |
| 52 | - | |
| 53 | - def create_comment(args = {}) | |
| 54 | - owner = create_user('testuser').person | |
| 55 | - article = create(TextileArticle, :profile_id => owner.id) | |
| 56 | - create(Comment, { :name => 'foo', :email => 'foo@example.com', :source => article }.merge(args)) | |
| 57 | - end | |
| 58 | - | |
| 59 | -end |
plugins/vote/test/unit/person_test.rb
| ... | ... | @@ -1,134 +0,0 @@ |
| 1 | -require 'test_helper' | |
| 2 | - | |
| 3 | -class PersonTest < ActiveSupport::TestCase | |
| 4 | - | |
| 5 | - should 'vote in a comment with value greater than 1' do | |
| 6 | - comment = fast_create(Comment) | |
| 7 | - person = fast_create(Person) | |
| 8 | - | |
| 9 | - person.vote(comment, 5) | |
| 10 | - assert_equal 1, person.vote_count | |
| 11 | - assert_equal 5, person.votes.first.vote | |
| 12 | - assert person.voted_on?(comment) | |
| 13 | - end | |
| 14 | - | |
| 15 | - should 'vote in a comment with value lesser than -1' do | |
| 16 | - comment = fast_create(Comment) | |
| 17 | - person = fast_create(Person) | |
| 18 | - | |
| 19 | - person.vote(comment, -5) | |
| 20 | - assert_equal 1, person.vote_count | |
| 21 | - assert_equal -5, person.votes.first.vote | |
| 22 | - end | |
| 23 | - | |
| 24 | - should 'vote for a comment' do | |
| 25 | - comment = fast_create(Comment) | |
| 26 | - person = fast_create(Person) | |
| 27 | - | |
| 28 | - assert !person.voted_for?(comment) | |
| 29 | - person.vote_for(comment) | |
| 30 | - assert person.voted_for?(comment) | |
| 31 | - assert !person.voted_against?(comment) | |
| 32 | - end | |
| 33 | - | |
| 34 | - should 'vote against a comment' do | |
| 35 | - comment = fast_create(Comment) | |
| 36 | - person = fast_create(Person) | |
| 37 | - | |
| 38 | - assert !person.voted_against?(comment) | |
| 39 | - person.vote_against(comment) | |
| 40 | - assert !person.voted_for?(comment) | |
| 41 | - assert person.voted_against?(comment) | |
| 42 | - end | |
| 43 | - | |
| 44 | - should 'do not vote against a comment twice' do | |
| 45 | - comment = fast_create(Comment) | |
| 46 | - person = fast_create(Person) | |
| 47 | - | |
| 48 | - assert person.vote_against(comment) | |
| 49 | - assert !person.vote_against(comment) | |
| 50 | - end | |
| 51 | - | |
| 52 | - should 'do not vote for a comment twice' do | |
| 53 | - comment = fast_create(Comment) | |
| 54 | - person = fast_create(Person) | |
| 55 | - | |
| 56 | - assert person.vote_for(comment) | |
| 57 | - assert !person.vote_for(comment) | |
| 58 | - end | |
| 59 | - | |
| 60 | - should 'not vote against a voted for comment' do | |
| 61 | - comment = fast_create(Comment) | |
| 62 | - person = fast_create(Person) | |
| 63 | - | |
| 64 | - person.vote_for(comment) | |
| 65 | - person.vote_against(comment) | |
| 66 | - assert person.voted_for?(comment) | |
| 67 | - assert !person.voted_against?(comment) | |
| 68 | - end | |
| 69 | - | |
| 70 | - should 'not vote for a voted against comment' do | |
| 71 | - comment = fast_create(Comment) | |
| 72 | - person = fast_create(Person) | |
| 73 | - | |
| 74 | - person.vote_against(comment) | |
| 75 | - person.vote_for(comment) | |
| 76 | - assert !person.voted_for?(comment) | |
| 77 | - assert person.voted_against?(comment) | |
| 78 | - end | |
| 79 | - | |
| 80 | - should 'undo a vote for a comment' do | |
| 81 | - comment = fast_create(Comment) | |
| 82 | - person = fast_create(Person) | |
| 83 | - | |
| 84 | - person.vote_for(comment) | |
| 85 | - assert person.voted_for?(comment) | |
| 86 | - person.votes.for_voteable(comment).destroy_all | |
| 87 | - assert !person.voted_for?(comment) | |
| 88 | - end | |
| 89 | - | |
| 90 | - should 'count comments voted' do | |
| 91 | - comment = fast_create(Comment) | |
| 92 | - person = fast_create(Person) | |
| 93 | - | |
| 94 | - comment2 = fast_create(Comment) | |
| 95 | - comment3 = fast_create(Comment) | |
| 96 | - person.vote_for(comment) | |
| 97 | - person.vote_for(comment2) | |
| 98 | - person.vote_against(comment3) | |
| 99 | - assert_equal 3, person.vote_count | |
| 100 | - assert_equal 2, person.vote_count(true) | |
| 101 | - assert_equal 1, person.vote_count(false) | |
| 102 | - end | |
| 103 | - | |
| 104 | - should 'vote in a article with value greater than 1' do | |
| 105 | - article = fast_create(Article) | |
| 106 | - person = fast_create(Person) | |
| 107 | - | |
| 108 | - person.vote(article, 5) | |
| 109 | - assert_equal 1, person.vote_count | |
| 110 | - assert_equal 5, person.votes.first.vote | |
| 111 | - assert person.voted_on?(article) | |
| 112 | - end | |
| 113 | - | |
| 114 | - should 'vote for a article' do | |
| 115 | - article = fast_create(Article) | |
| 116 | - person = fast_create(Person) | |
| 117 | - | |
| 118 | - assert !person.voted_for?(article) | |
| 119 | - person.vote_for(article) | |
| 120 | - assert person.voted_for?(article) | |
| 121 | - assert !person.voted_against?(article) | |
| 122 | - end | |
| 123 | - | |
| 124 | - should 'vote against a article' do | |
| 125 | - article = fast_create(Article) | |
| 126 | - person = fast_create(Person) | |
| 127 | - | |
| 128 | - assert !person.voted_against?(article) | |
| 129 | - person.vote_against(article) | |
| 130 | - assert !person.voted_for?(article) | |
| 131 | - assert person.voted_against?(article) | |
| 132 | - end | |
| 133 | - | |
| 134 | -end |
po/pt/noosfero.po
| ... | ... | @@ -13,10 +13,10 @@ msgid "" |
| 13 | 13 | msgstr "" |
| 14 | 14 | "Project-Id-Version: 1.1-166-gaf47713\n" |
| 15 | 15 | "POT-Creation-Date: 2015-06-01 17:26-0300\n" |
| 16 | -"PO-Revision-Date: 2015-03-29 01:47+0200\n" | |
| 17 | -"Last-Translator: daniel <dtygel@eita.org.br>\n" | |
| 18 | -"Language-Team: Portuguese <https://hosted.weblate.org/projects/noosfero/" | |
| 19 | -"noosfero/pt/>\n" | |
| 16 | +"PO-Revision-Date: 2015-06-02 19:44+0200\n" | |
| 17 | +"Last-Translator: Arthur Del Esposte <arthurmde@gmail.com>\n" | |
| 18 | +"Language-Team: Portuguese " | |
| 19 | +"<https://hosted.weblate.org/projects/noosfero/noosfero/pt/>\n" | |
| 20 | 20 | "Language: pt\n" |
| 21 | 21 | "MIME-Version: 1.0\n" |
| 22 | 22 | "Content-Type: text/plain; charset=UTF-8\n" |
| ... | ... | @@ -378,9 +378,8 @@ msgid "Manage environment users" |
| 378 | 378 | msgstr "Gerenciar usuários do ambiente" |
| 379 | 379 | |
| 380 | 380 | #: app/models/environment.rb:32 |
| 381 | -#, fuzzy | |
| 382 | 381 | msgid "Manage environment organizations" |
| 383 | -msgstr "Gerenciar ambiente de validadores" | |
| 382 | +msgstr "Gerenciar organizações do ambiente" | |
| 384 | 383 | |
| 385 | 384 | #: app/models/environment.rb:33 |
| 386 | 385 | msgid "Manage environment templates" |
| ... | ... | @@ -697,14 +696,12 @@ msgstr "" |
| 697 | 696 | "podem ser feitas." |
| 698 | 697 | |
| 699 | 698 | #: app/models/forum.rb:38 |
| 700 | -#, fuzzy | |
| 701 | 699 | msgid "Logged users" |
| 702 | -msgstr "Identificado(a) como %s" | |
| 700 | +msgstr "Usuários logados" | |
| 703 | 701 | |
| 704 | 702 | #: app/models/forum.rb:41 |
| 705 | -#, fuzzy | |
| 706 | 703 | msgid "Me" |
| 707 | -msgstr "Masculino" | |
| 704 | +msgstr "Eu" | |
| 708 | 705 | |
| 709 | 706 | #: app/models/forum.rb:42 app/models/block.rb:250 |
| 710 | 707 | #: app/helpers/application_helper.rb:563 |
| ... | ... | @@ -712,9 +709,8 @@ msgid "Friends" |
| 712 | 709 | msgstr "Amigos" |
| 713 | 710 | |
| 714 | 711 | #: app/models/forum.rb:45 |
| 715 | -#, fuzzy | |
| 716 | 712 | msgid "Administrators" |
| 717 | -msgstr "Administração" | |
| 713 | +msgstr "Administradores" | |
| 718 | 714 | |
| 719 | 715 | #: app/models/forum.rb:46 app/models/block.rb:250 |
| 720 | 716 | #: app/helpers/profile_helper.rb:43 app/helpers/application_helper.rb:571 |
| ... | ... | @@ -1057,9 +1053,9 @@ msgid "" |
| 1057 | 1053 | "User \"%{user}\" just requested to register. You have to approve or reject " |
| 1058 | 1054 | "it through the \"Pending Validations\" section in your control panel.\n" |
| 1059 | 1055 | msgstr "" |
| 1060 | -"O usuário \"%{user}\" requisitou a criação da comunidade %{community}. Você " | |
| 1061 | -"tem que aprová-lo ou rejeitá-lo através da seção \"Validações Pendentes\" no " | |
| 1062 | -"seu painel de controle.\n" | |
| 1056 | +"O usuário \"%{user}\" pediu para cadastrar-se. Você tem que aprová-lo ou " | |
| 1057 | +"rejeitá-lo através da seção \"Validações Pendentes\" no seu painel de " | |
| 1058 | +"controle.\n" | |
| 1063 | 1059 | |
| 1064 | 1060 | #: app/models/user.rb:10 app/models/change_password.rb:8 |
| 1065 | 1061 | #: app/views/invite/_select_address_book.html.erb:34 |
| ... | ... | @@ -1831,14 +1827,12 @@ msgid "Article suggestion" |
| 1831 | 1827 | msgstr "Sugestão de artigo" |
| 1832 | 1828 | |
| 1833 | 1829 | #: app/models/suggest_article.rb:64 |
| 1834 | -#, fuzzy | |
| 1835 | 1830 | msgid "%{requestor} suggested the publication of the article: %{subject}." |
| 1836 | -msgstr "%{sender} sugeriu a publicação do artigo: %{subject}." | |
| 1831 | +msgstr "%{requestor} sugeriu a publicação do artigo: %{subject}." | |
| 1837 | 1832 | |
| 1838 | 1833 | #: app/models/suggest_article.rb:77 |
| 1839 | -#, fuzzy | |
| 1840 | 1834 | msgid "%{requestor} suggested the publication of the article: %{article}." |
| 1841 | -msgstr "%{sender} sugeriu a publicação do artigo %{article}." | |
| 1835 | +msgstr "%{requestor} sugeriu a publicação do artigo %{article}." | |
| 1842 | 1836 | |
| 1843 | 1837 | #: app/models/rss_feed.rb:6 |
| 1844 | 1838 | msgid "RssFeed" |
| ... | ... | @@ -2221,11 +2215,11 @@ msgstr "Não logado" |
| 2221 | 2215 | |
| 2222 | 2216 | #: app/models/block.rb:256 |
| 2223 | 2217 | msgid "Can be modified" |
| 2224 | -msgstr "" | |
| 2218 | +msgstr "Pode ser modificada" | |
| 2225 | 2219 | |
| 2226 | 2220 | #: app/models/block.rb:257 |
| 2227 | 2221 | msgid "Cannot be modified" |
| 2228 | -msgstr "" | |
| 2222 | +msgstr "Não pode ser modificada" | |
| 2229 | 2223 | |
| 2230 | 2224 | #: app/models/block.rb:263 |
| 2231 | 2225 | msgid "Can be moved" |
| ... | ... | @@ -2563,9 +2557,8 @@ msgid "Public" |
| 2563 | 2557 | msgstr "Público" |
| 2564 | 2558 | |
| 2565 | 2559 | #: app/helpers/application_helper.rb:944 |
| 2566 | -#, fuzzy | |
| 2567 | 2560 | msgid "Clone %s" |
| 2568 | -msgstr "Clonar" | |
| 2561 | +msgstr "Clonar %s" | |
| 2569 | 2562 | |
| 2570 | 2563 | #: app/helpers/application_helper.rb:958 |
| 2571 | 2564 | msgid "Online Manual" |
| ... | ... | @@ -2842,21 +2835,20 @@ msgid "See all connections" |
| 2842 | 2835 | msgstr "Ver todas as conexões" |
| 2843 | 2836 | |
| 2844 | 2837 | #: app/helpers/application_helper.rb:1518 |
| 2845 | -#, fuzzy | |
| 2846 | 2838 | msgid "Full screen" |
| 2847 | -msgstr "Post completo" | |
| 2839 | +msgstr "Tela cheia" | |
| 2848 | 2840 | |
| 2849 | 2841 | #: app/helpers/application_helper.rb:1523 |
| 2850 | 2842 | msgid "Go to full screen mode" |
| 2851 | -msgstr "" | |
| 2843 | +msgstr "Ir para o modo tela cheia" | |
| 2852 | 2844 | |
| 2853 | 2845 | #: app/helpers/application_helper.rb:1526 |
| 2854 | 2846 | msgid "Exit full screen" |
| 2855 | -msgstr "" | |
| 2847 | +msgstr "Sair da tela cheia" | |
| 2856 | 2848 | |
| 2857 | 2849 | #: app/helpers/application_helper.rb:1532 |
| 2858 | 2850 | msgid "Exit full screen mode" |
| 2859 | -msgstr "" | |
| 2851 | +msgstr "Sair do modo tela cheia" | |
| 2860 | 2852 | |
| 2861 | 2853 | #: app/helpers/manage_products_helper.rb:156 |
| 2862 | 2854 | #: app/views/manage_products/_display_category.html.erb:3 |
| ... | ... | @@ -2988,9 +2980,8 @@ msgid "search in all categories" |
| 2988 | 2980 | msgstr "procurar em todas as categorias" |
| 2989 | 2981 | |
| 2990 | 2982 | #: app/helpers/search_helper.rb:158 |
| 2991 | -#, fuzzy | |
| 2992 | 2983 | msgid "Choose a template" |
| 2993 | -msgstr "O modelo \"%s\"" | |
| 2984 | +msgstr "Escolha um template" | |
| 2994 | 2985 | |
| 2995 | 2986 | #: app/helpers/boxes_helper.rb:106 |
| 2996 | 2987 | msgid "This block is invisible. Your visitors will not see it." |
| ... | ... | @@ -4081,9 +4072,8 @@ msgid "Community fields not updated successfully." |
| 4081 | 4072 | msgstr "Campos de comunidade não atualizados com sucesso." |
| 4082 | 4073 | |
| 4083 | 4074 | #: app/controllers/admin/organizations_controller.rb:7 |
| 4084 | -#, fuzzy | |
| 4085 | 4075 | msgid "Organization profiles" |
| 4086 | -msgstr "Método de Aprovação de Organização" | |
| 4076 | +msgstr "Perfis de organizações" | |
| 4087 | 4077 | |
| 4088 | 4078 | #: app/controllers/admin/organizations_controller.rb:9 |
| 4089 | 4079 | #: app/views/tasks/index.html.erb:7 app/views/tasks/index.html.erb:34 |
| ... | ... | @@ -4093,9 +4083,8 @@ msgid "All" |
| 4093 | 4083 | msgstr "Todos" |
| 4094 | 4084 | |
| 4095 | 4085 | #: app/controllers/admin/organizations_controller.rb:33 |
| 4096 | -#, fuzzy | |
| 4097 | 4086 | msgid "%s enabled" |
| 4098 | -msgstr "%s não foi habilitado." | |
| 4087 | +msgstr "%s habilitado" | |
| 4099 | 4088 | |
| 4100 | 4089 | #: app/controllers/admin/organizations_controller.rb:35 |
| 4101 | 4090 | #, fuzzy |
| ... | ... | @@ -4103,9 +4092,8 @@ msgid "%s could not be enabled" |
| 4103 | 4092 | msgstr "%s não pode ser enviado" |
| 4104 | 4093 | |
| 4105 | 4094 | #: app/controllers/admin/organizations_controller.rb:42 |
| 4106 | -#, fuzzy | |
| 4107 | 4095 | msgid "%s disabled" |
| 4108 | -msgstr "Desabilitado" | |
| 4096 | +msgstr "%s desabilitado" | |
| 4109 | 4097 | |
| 4110 | 4098 | #: app/controllers/admin/organizations_controller.rb:44 |
| 4111 | 4099 | #, fuzzy |
| ... | ... | @@ -4568,9 +4556,8 @@ msgid "Files" |
| 4568 | 4556 | msgstr "Arquivos" |
| 4569 | 4557 | |
| 4570 | 4558 | #: app/controllers/my_profile/profile_roles_controller.rb:52 |
| 4571 | -#, fuzzy | |
| 4572 | 4559 | msgid "Role successfuly removed!" |
| 4573 | -msgstr "Produto removido com sucesso" | |
| 4560 | +msgstr "Papel removido com sucesso!" | |
| 4574 | 4561 | |
| 4575 | 4562 | #: app/controllers/my_profile/profile_roles_controller.rb:54 |
| 4576 | 4563 | #, fuzzy |
| ... | ... | @@ -4579,7 +4566,7 @@ msgstr "Falhou em criar papel" |
| 4579 | 4566 | |
| 4580 | 4567 | #: app/controllers/my_profile/profile_roles_controller.rb:85 |
| 4581 | 4568 | msgid "Error" |
| 4582 | -msgstr "" | |
| 4569 | +msgstr "Erro" | |
| 4583 | 4570 | |
| 4584 | 4571 | #: app/controllers/my_profile/tasks_controller.rb:28 |
| 4585 | 4572 | #, fuzzy | ... | ... |
public/designs/icons/tango/style.css
| ... | ... | @@ -116,6 +116,107 @@ |
| 116 | 116 | .icon-clock { background-image: url(Tango/16x16/actions/appointment.png) } |
| 117 | 117 | .icon-fullscreen { background-image: url(Tango/16x16/actions/view-fullscreen.png) } |
| 118 | 118 | |
| 119 | +/******************BIG ICONS************************/ | |
| 120 | +.bigicon-embed { background-image: url(Tango/scalable/apps/utilities-terminal.svg) } | |
| 121 | +.bigicon-edit { background-image: url(Tango/scalable/apps/text-editor.svg) } | |
| 122 | +.bigicon-undo { background-image: url(Tango/scalable/actions/edit-undo.svg) } | |
| 123 | +.bigicon-home { background-image: url(Tango/scalable/actions/go-home.svg) } | |
| 124 | +.bigicon-home-not { background-image: url(mod/scalable/actions/go-home-not.svg) } | |
| 125 | +.bigicon-new, | |
| 126 | +.bigicon-suggest { background-image: url(Tango/scalable/actions/filenew.svg) } | |
| 127 | +.bigicon-close { background-image: url(Tango/scalable/actions/gtk-cancel.svg) } | |
| 128 | +.bigicon-newfolder { background-image: url(Tango/scalable/actions/folder-new.svg) } | |
| 129 | +.bigicon-folder { background-image: url(Tango/scalable/places/folder.svg) } | |
| 130 | +.bigicon-parent-folder { background-image: url(Tango/scalable/places/folder_home.svg) } | |
| 131 | +.bigicon-newblog { background-image: url(mod/scalable/apps/text-editor.svg) } | |
| 132 | +.bigicon-blog { background-image: url(mod/scalable/apps/text-editor.svg) } | |
| 133 | +.bigicon-save { background-image: url(Tango/scalable/actions/filesave.svg) } | |
| 134 | +.bigicon-send { background-image: url(Tango/scalable/actions/stock_mail-forward.svg) } | |
| 135 | +.bigicon-cancel { background-image: url(Tango/scalable/actions/gtk-cancel.svg) } | |
| 136 | +.bigicon-person { background-image: url(Tango/scalable/apps/system-config-users.svg) } | |
| 137 | +.bigicon-product { background-image: url(Tango/scalable/mimetypes/package.svg) } | |
| 138 | +.bigicon-delete { background-image: url(Tango/scalable/places/user-trash.svg) } | |
| 139 | +.bigicon-back { background-image: url(Tango/scalable/actions/back.svg) } | |
| 140 | +.bigicon-next { background-image: url(Tango/scalable/actions/go-next.svg) } | |
| 141 | +.bigicon-add { background-image: url(Tango/scalable/actions/add.svg) } | |
| 142 | +.bigicon-remove { background-image: url(Tango/scalable/actions/gtk-remove.svg) } | |
| 143 | +.bigicon-more { background-image: url(Tango/scalable/actions/add.svg) } | |
| 144 | +.bigicon-up { background-image: url(Tango/scalable/actions/go-up.svg) } | |
| 145 | +.bigicon-down { background-image: url(Tango/scalable/actions/go-down.svg) } | |
| 146 | +.bigicon-left { background-image: url(Tango/scalable/actions/go-previous.svg) } | |
| 147 | +.bigicon-right { background-image: url(Tango/scalable/actions/go-next.svg) } | |
| 148 | +.bigicon-up-disabled { background-image: url(Tango/scalable/actions/go-up.svg); opacity: 0.25; filter:alpha(opacity=25); } | |
| 149 | +.bigicon-down-disabled { background-image: url(Tango/scalable/actions/go-down.svg); opacity: 0.25; filter:alpha(opacity=25); } | |
| 150 | +.bigicon-left-disabled { background-image: url(Tango/scalable/actions/go-previous.svg); opacity: 0.25; filter:alpha(opacity=25); } | |
| 151 | +.bigicon-right-disabled { background-image: url(Tango/scalable/actions/go-next.svg); opacity: 0.25; filter:alpha(opacity=25); } | |
| 152 | +.bigicon-up-red { background-image: url(mod/scalable/actions/go-up-red.svg) } | |
| 153 | +.bigicon-forward { background-image: url(Tango/scalable/actions/go-next.svg) } | |
| 154 | +.bigicon-search { background-image: url(Tango/scalable/actions/search.svg) } | |
| 155 | +.bigicon-ok { background-image: url(Tango/scalable/actions/media-playback-start.svg) } | |
| 156 | +.bigicon-login { background-image: url(mod/scalable/actions/log-in.svg) } | |
| 157 | +.bigicon-help { background-image: url(Tango/scalable/apps/gnome-help.svg) } | |
| 158 | +.bigicon-help32on { background-image: url(Tango/scalable/apps/gnome-help.svg) } | |
| 159 | +.bigicon-help32off { background-image: url(mod/scalable/apps/gnome-help-red.svg) } | |
| 160 | +.bigicon-spread { background-image: url(mod/scalable/actions/spread.svg) } | |
| 161 | +.bigicon-todo { background-image: url(Tango/scalable/actions/stock_paste.svg) } | |
| 162 | +.bigicon-eyes { background-image: url(Tango/scalable/actions/find.svg) } | |
| 163 | +.bigicon-menu-home { background-image: url(Tango/scalable/actions/go-home.svg) } | |
| 164 | +.bigicon-menu-product { background-image: url(Tango/scalable/mimetypes/package.svg) } | |
| 165 | +.bigicon-menu-enterprise { background-image: url(Tango/scalable/actions/go-home.svg) } | |
| 166 | +.bigicon-menu-community { background-image: url(Tango/scalable/apps/system-config-users.svg) } | |
| 167 | +.bigicon-menu-ctrl-panel { background-image: url(Tango/scalable/categories/preferences-desktop.svg) } | |
| 168 | +.bigicon-menu-admin { background-image: url(Tango/scalable/categories/preferences-system.svg) } | |
| 169 | +.bigicon-menu-my-groups { background-image: url(Tango/scalable/apps/system-config-users.svg) } | |
| 170 | +.bigicon-menu-login { background-image: url(mod/scalable/actions/log-in.svg) } | |
| 171 | +.bigicon-menu-logout { background-image: url(mod/scalable/actions/log-out.svg) } | |
| 172 | +.bigicon-menu-search { background-image: url(Tango/scalable/actions/search.svg) } | |
| 173 | +.bigicon-menu-events { background-image: url(Tango/scalable/mimetypes/stock_calendar.svg) } | |
| 174 | +.bigicon-event { background-image: url(Tango/scalable/mimetypes/stock_calendar.svg) } | |
| 175 | +.bigicon-newevent { background-image: url(Tango/scalable/mimetypes/stock_calendar.svg) } | |
| 176 | +.bigicon-menu-articles { background-image: url(Tango/scalable/apps/text-editor.svg) } | |
| 177 | +.bigicon-menu-people { background-image: url(mod/scalable/apps/user.svg) } | |
| 178 | +.bigicon-menu-mail { background-image: url(Tango/scalable/apps/email.svg) } | |
| 179 | +.bigicon-upload-file { background-image: url(Tango/scalable/actions/filesave.svg) } | |
| 180 | +.bigicon-newupload-file { background-image: url(Tango/scalable/actions/filesave.svg) } | |
| 181 | +.bigicon-slideshow { background-image: url(Tango/scalable/mimetypes/x-office-presentation.svg) } | |
| 182 | +.bigicon-photos { background-image: url(Tango/scalable/devices/camera-photo.svg) } | |
| 183 | +.bigicon-vertical-toggle { background-image: url(Tango/scalable/actions/mail-send-receive.svg) } | |
| 184 | +.bigicon-text-html { background-image: url(Tango/scalable/mimetypes/text-html.svg) } | |
| 185 | +.bigicon-text-plain { background-image: url(Tango/scalable/mimetypes/text-x-generic.svg) } | |
| 186 | +.bigicon-image-svg-xml { background-image: url(Tango/scalable/mimetypes/image-x-generic.svg) } | |
| 187 | +.bigicon-application-octet-stream { background-image: url(Tango/scalable/mimetypes/binary.svg) } | |
| 188 | +.bigicon-application-x-gzip { background-image: url(Tango/scalable/mimetypes/gnome-mime-application-x-gzip.svg) } | |
| 189 | +.bigicon-application-postscript { background-image: url(Tango/scalable/mimetypes/gnome-mime-application-postscript.svg) } | |
| 190 | +.bigicon-application-pdf { background-image: url(Tango/scalable/mimetypes/gnome-mime-application-pdf.svg) } | |
| 191 | +.bigicon-application-ogg { background-image: url(Tango/scalable/mimetypes/gnome-mime-application-ogg.svg) } | |
| 192 | +.bigicon-video, .icon-video-mpeg { background-image: url(Tango/scalable/mimetypes/video-x-generic.svg) } | |
| 193 | +.bigicon-application-vnd-oasis-opendocument-text { background-image: url(Tango/scalable/mimetypes/gnome-mime-application-vnd.oasis.opendocument.text.svg) } | |
| 194 | +.bigicon-application-vnd-oasis-opendocument-spreadsheet { background-image: url(Tango/scalable/mimetypes/gnome-mime-application-vnd.oasis.opendocument.spreadsheet.svg) } | |
| 195 | +.bigicon-application-vnd-oasis-opendocument-presentation { background-image: url(Tango/scalable/mimetypes/gnome-mime-application-vnd.oasis.opendocument.presentation.svg) } | |
| 196 | +.bigicon-welcome-page { background-image: url(mod/scalable/mimetypes/welcome-page.svg) } | |
| 197 | +.bigicon-blocks { background-image: url(mod/scalable/mimetypes/blocks.svg) } | |
| 198 | +.bigicon-header-footer { background-image: url(mod/scalable/mimetypes/header-footer.svg) } | |
| 199 | +.bigicon-appearance { background-image: url(Tango/scalable/apps/preferences-desktop-wallpaper.svg) } | |
| 200 | +.bigicon-media-pause { background-image: url(Tango/scalable/actions/media-playback-pause.svg) } | |
| 201 | +.bigicon-media-play { background-image: url(Tango/scalable/actions/media-playback-start.svg) } | |
| 202 | +.bigicon-media-prev { background-image: url(Tango/scalable/actions/media-skip-backward.svg) } | |
| 203 | +.bigicon-media-next { background-image: url(Tango/scalable/actions/media-skip-forward.svg) } | |
| 204 | +.bigicon-lock { background-image: url(Tango/scalable/actions/lock.svg) } | |
| 205 | +.bigicon-chat { background-image: url(Tango/scalable/apps/internet-group-chat.svg); background-repeat: no-repeat } | |
| 206 | +.bigicon-reply { background-image: url(Tango/scalable/actions/mail-reply-sender.svg) } | |
| 207 | +.bigicon-newforum { background-image: url(Tango/scalable/apps/internet-group-chat.svg) } | |
| 208 | +.bigicon-forum { background-image: url(Tango/scalable/apps/system-users.svg) } | |
| 209 | +.bigicon-gallery { background-image: url(Tango/scalable/mimetypes/image-x-generic.svg) } | |
| 210 | +.bigicon-newgallery { background-image: url(Tango/scalable/mimetypes/image-x-generic.svg) } | |
| 211 | +.bigicon-locale { background-image: url(Tango/scalable/apps/preferences-desktop-locale.svg) } | |
| 212 | +.bigicon-user-removed { background-image: url(Tango/scalable/actions/gtk-cancel.svg) } | |
| 213 | +.bigicon-user-unknown { background-image: url(Tango/scalable/status/dialog-error.svg) } | |
| 214 | +.bigicon-alert { background-image: url(Tango/scalable/status/dialog-warning.svg) } | |
| 215 | +.bigicon-clone { background-image: url(Tango/scalable/actions/edit-copy.svg) } | |
| 216 | +.bigicon-activate-user { background-image: url(Tango/scalable/emblems/emblem-system.svg) } | |
| 217 | +.bigicon-deactivate-user { background-image: url(Tango/scalable/emblems/emblem-unreadable.svg) } | |
| 218 | +.bigicon-clock { background-image: url(Tango/scalable/actions/appointment.svg) } | |
| 219 | + | |
| 119 | 220 | /******************LARGE ICONS********************/ |
| 120 | 221 | .image-gallery-item .folder { background-image: url(mod/96x96/places/folder.png) } |
| 121 | 222 | .image-gallery-item .gallery { background-image: url(mod/96x96/mimetypes/image-x-generic.png) } | ... | ... |
3.24 KB
public/javascripts/media-panel.js
| 1 | -var file_id = 1; | |
| 2 | - | |
| 3 | -jQuery('.view-all-media').on('click', '.pagination a', function(event) { | |
| 4 | - jQuery.ajax({ | |
| 5 | - url: this.href, | |
| 6 | - beforeSend: function(){jQuery('.view-all-media').addClass('fetching')}, | |
| 7 | - complete: function() {jQuery('.view-all-media').removeClass('fetching')}, | |
| 8 | - dataType: 'script' | |
| 1 | +(function($) { | |
| 2 | + "use strict"; | |
| 3 | + | |
| 4 | + var file_id = 1; | |
| 5 | + | |
| 6 | + $('.view-all-media').on('click', '.pagination a', function(event) { | |
| 7 | + $.ajax({ | |
| 8 | + url: this.href, | |
| 9 | + beforeSend: function(){$('.view-all-media').addClass('fetching')}, | |
| 10 | + complete: function() {$('.view-all-media').removeClass('fetching')}, | |
| 11 | + dataType: 'script' | |
| 12 | + }); | |
| 13 | + return false; | |
| 9 | 14 | }); |
| 10 | - return false; | |
| 11 | -}); | |
| 12 | - | |
| 13 | -jQuery('#file').fileupload({ | |
| 14 | - add: function(e, data){ | |
| 15 | - data.files[0].id = file_id; | |
| 16 | - file_id++; | |
| 17 | - data.context = jQuery(tmpl("template-upload", data.files[0])); | |
| 18 | - jQuery('#media-upload-form').append(data.context); | |
| 19 | - data.submit(); | |
| 20 | - }, | |
| 21 | - progress: function (e, data) { | |
| 22 | - if (jQuery('#hide-uploads').data('bootstraped') == false) { | |
| 23 | - jQuery('#hide-uploads').show(); | |
| 24 | - jQuery('#hide-uploads').data('bootstraped', true); | |
| 25 | - } | |
| 26 | - if (data.context) { | |
| 27 | - progress = parseInt(data.loaded / data.total * 100, 10); | |
| 28 | - data.context.find('.bar').css('width', progress + '%'); | |
| 29 | - data.context.find('.percentage').text(progress + '%'); | |
| 30 | - } | |
| 31 | - }, | |
| 32 | - fail: function(e, data){ | |
| 33 | - var file_id = '#file-'+data.files[0].id; | |
| 34 | - jQuery(file_id).find('.progress .bar').addClass('error'); | |
| 35 | - jQuery(file_id).append("<div class='error-message'>" + data.jqXHR.responseText + "</div>") | |
| 36 | - } | |
| 37 | -}); | |
| 38 | - | |
| 39 | -jQuery('#hide-uploads').click(function(){ | |
| 40 | - jQuery('#hide-uploads').hide(); | |
| 41 | - jQuery('#show-uploads').show(); | |
| 42 | - jQuery('.upload').slideUp(); | |
| 43 | - return false; | |
| 44 | -}); | |
| 45 | - | |
| 46 | -jQuery('#show-uploads').click(function(){ | |
| 47 | - jQuery('#hide-uploads').show(); | |
| 48 | - jQuery('#show-uploads').hide(); | |
| 49 | - jQuery('.upload').slideDown(); | |
| 50 | - return false; | |
| 51 | -}); | |
| 52 | - | |
| 53 | -function loadPublishedMedia() { | |
| 54 | - var parent_id = jQuery('#published-media #parent_id').val(); | |
| 55 | - var q = jQuery('#published-media #q').val(); | |
| 56 | - var url = jQuery('#published-media').data('url'); | |
| 57 | - | |
| 58 | - jQuery('#published-media .items').addClass('fetching'); | |
| 59 | - jQuery.ajax({ | |
| 60 | - url: url, | |
| 61 | - data: {'parent_id': parent_id, 'q': q}, | |
| 62 | - dataType: 'html', | |
| 63 | - success: function(response) { | |
| 64 | - jQuery("#published-media .items").html(response); | |
| 65 | - jQuery('#published-media .items').removeClass('fetching'); | |
| 66 | - updateViewAllLinks(); | |
| 15 | + | |
| 16 | + | |
| 17 | + $('#file').fileupload({ | |
| 18 | + add: function(e, data){ | |
| 19 | + data.files[0].id = file_id; | |
| 20 | + file_id++; | |
| 21 | + data.context = $(tmpl("template-upload", data.files[0])); | |
| 22 | + $('#media-upload-form').append(data.context); | |
| 23 | + data.submit(); | |
| 24 | + }, | |
| 25 | + progress: function (e, data) { | |
| 26 | + if ($('#hide-uploads').data('bootstraped') == false) { | |
| 27 | + $('#hide-uploads').show(); | |
| 28 | + $('#hide-uploads').data('bootstraped', true); | |
| 29 | + } | |
| 30 | + if (data.context) { | |
| 31 | + var progress = parseInt(data.loaded / data.total * 100, 10); | |
| 32 | + data.context.find('.bar').css('width', progress + '%'); | |
| 33 | + data.context.find('.percentage').text(progress + '%'); | |
| 34 | + } | |
| 67 | 35 | }, |
| 68 | - error: function(response, textStatus, xhr) { | |
| 69 | - console.log(response); | |
| 70 | - console.log(textStatus); | |
| 36 | + fail: function(e, data){ | |
| 37 | + var file_id = '#file-'+data.files[0].id; | |
| 38 | + $(file_id).find('.progress .bar').addClass('error'); | |
| 39 | + $(file_id).append("<div class='error-message'>" + data.jqXHR.responseText + "</div>") | |
| 71 | 40 | } |
| 72 | 41 | }); |
| 73 | -} | |
| 74 | - | |
| 75 | -function updateViewAllLinks() { | |
| 76 | - var parent_id = jQuery('#published-media #parent_id').val(); | |
| 77 | - var q = jQuery('#published-media #q').val(); | |
| 78 | - jQuery('#published-media .view-all').each(function(){ | |
| 79 | - var key = jQuery(this).data('key'); | |
| 80 | - var params = {parent_id: parent_id, q: q, key: key} | |
| 81 | - var href = jQuery(this).attr('href'); | |
| 82 | - href = href.replace(/\?.*/, '?'+jQuery.param(params)); | |
| 83 | - jQuery(this).attr('href', href); | |
| 42 | + | |
| 43 | + | |
| 44 | + $('#hide-uploads').click(function(){ | |
| 45 | + $('#hide-uploads').hide(); | |
| 46 | + $('#show-uploads').show(); | |
| 47 | + $('.upload').slideUp(); | |
| 48 | + return false; | |
| 49 | + }); | |
| 50 | + | |
| 51 | + | |
| 52 | + $('#show-uploads').click(function(){ | |
| 53 | + $('#hide-uploads').show(); | |
| 54 | + $('#show-uploads').hide(); | |
| 55 | + $('.upload').slideDown(); | |
| 56 | + return false; | |
| 84 | 57 | }); |
| 85 | -} | |
| 86 | - | |
| 87 | -jQuery('#published-media #parent_id').change(function(){ loadPublishedMedia() }); | |
| 88 | - | |
| 89 | -jQuery("#published-media #q").typeWatch({ | |
| 90 | - callback: function (value) { loadPublishedMedia() }, | |
| 91 | - wait: 750, | |
| 92 | - highlight: true, | |
| 93 | - captureLength: 2 | |
| 94 | -}); | |
| 95 | - | |
| 96 | -jQuery("#published-media #q").bind('notext', function(){ loadPublishedMedia() }); | |
| 97 | - | |
| 98 | -jQuery("#new-folder-dialog").submit(function( event ) { | |
| 99 | - var name = jQuery('#new_folder').val(); | |
| 100 | - var parent_id = jQuery("#new-folder-dialog #parent_id").val(); | |
| 101 | - jQuery.ajax({ | |
| 102 | - url: this.action, | |
| 103 | - type: 'POST', | |
| 104 | - data: { | |
| 105 | - 'parent_id': parent_id, | |
| 106 | - 'article': {'name': name, 'published': true}, | |
| 107 | - 'type': jQuery('input[name=folder_type]:checked').val() }, | |
| 108 | - dataType: 'json', | |
| 109 | - beforeSend: function(){jQuery("#new-folder-dialog").addClass('fetching')}, | |
| 110 | - success: function(response) { | |
| 111 | - var option_selected = "<option value='"+ response.id +"' selected='selected'>"+ response.full_name +"</options>" | |
| 112 | - var option = "<option value='"+ response.id +"'>"+ response.full_name +"</options>" | |
| 113 | - jQuery('#media-upload-form #parent_id').append(option_selected); | |
| 114 | - jQuery('#published-media #parent_id').append(option); | |
| 115 | - jQuery('#new_folder').val(''); | |
| 116 | - }, | |
| 117 | - error: function(response, textStatus, xhr) { | |
| 118 | - console.log(response); | |
| 119 | - console.log(textStatus); | |
| 120 | - }, | |
| 121 | - complete: function(response){ | |
| 122 | - jQuery("#new-folder-dialog").removeClass('fetching'); | |
| 123 | - jQuery("#new-folder-dialog").dialog('close'); | |
| 124 | - } | |
| 58 | + | |
| 59 | + | |
| 60 | + function loadPublishedMedia() { | |
| 61 | + var parent_id = $('#published-media #parent_id').val(); | |
| 62 | + var q = $('#published-media #q').val(); | |
| 63 | + var url = $('#published-media').data('url'); | |
| 64 | + | |
| 65 | + $('#published-media .items').addClass('fetching'); | |
| 66 | + $.ajax({ | |
| 67 | + url: url, | |
| 68 | + data: {'parent_id': parent_id, 'q': q}, | |
| 69 | + dataType: 'html', | |
| 70 | + success: function(response) { | |
| 71 | + $("#published-media .items").html(response); | |
| 72 | + $('#published-media .items').removeClass('fetching'); | |
| 73 | + updateViewAllLinks(); | |
| 74 | + }, | |
| 75 | + error: function(response, textStatus, xhr) { | |
| 76 | + console.log(response); | |
| 77 | + console.log(textStatus); | |
| 78 | + } | |
| 79 | + }); | |
| 80 | + } | |
| 81 | + // make it global for usage in media_upload.js.erb | |
| 82 | + window.loadPublishedMedia = loadPublishedMedia; | |
| 83 | + | |
| 84 | + | |
| 85 | + function updateViewAllLinks() { | |
| 86 | + var parent_id = $('#published-media #parent_id').val(); | |
| 87 | + var q = $('#published-media #q').val(); | |
| 88 | + $('#published-media .view-all').each(function(){ | |
| 89 | + var key = $(this).data('key'); | |
| 90 | + var params = {parent_id: parent_id, q: q, key: key} | |
| 91 | + var href = $(this).attr('href'); | |
| 92 | + href = href.replace(/\?.*/, '?'+$.param(params)); | |
| 93 | + $(this).attr('href', href); | |
| 94 | + }); | |
| 95 | + } | |
| 96 | + | |
| 97 | + | |
| 98 | + $('#published-media #parent_id').change(function(){ | |
| 99 | + loadPublishedMedia() | |
| 100 | + }); | |
| 101 | + | |
| 102 | + | |
| 103 | + // Using a immediate function to make timer variable only visible for the keyup event | |
| 104 | + (function() { | |
| 105 | + var timer = null; | |
| 106 | + | |
| 107 | + $("#published-media #q").keyup(function() { | |
| 108 | + if(this.value.length > 2) { | |
| 109 | + timer = setTimeout(loadPublishedMedia, 750); | |
| 110 | + } | |
| 111 | + }).keydown(function() { | |
| 112 | + clearTimeout(timer); | |
| 113 | + }); | |
| 114 | + }) (); | |
| 115 | + | |
| 116 | + | |
| 117 | + $("#published-media #q").bind('notext', function(){ | |
| 118 | + loadPublishedMedia() | |
| 119 | + }); | |
| 120 | + | |
| 121 | + | |
| 122 | + $("#new-folder-dialog").submit(function( event ) { | |
| 123 | + var name = $('#new_folder').val(); | |
| 124 | + var parent_id = $("#new-folder-dialog #parent_id").val(); | |
| 125 | + $.ajax({ | |
| 126 | + url: this.action, | |
| 127 | + type: 'POST', | |
| 128 | + data: { | |
| 129 | + 'parent_id': parent_id, | |
| 130 | + 'article': {'name': name, 'published': true}, | |
| 131 | + 'type': $('input[name=folder_type]:checked').val() }, | |
| 132 | + dataType: 'json', | |
| 133 | + beforeSend: function(){$("#new-folder-dialog").addClass('fetching')}, | |
| 134 | + success: function(response) { | |
| 135 | + var option_selected = "<option value='"+ response.id +"' selected='selected'>"+ response.full_name +"</options>" | |
| 136 | + var option = "<option value='"+ response.id +"'>"+ response.full_name +"</options>" | |
| 137 | + $('#media-upload-form #parent_id').append(option_selected); | |
| 138 | + $('#published-media #parent_id').append(option); | |
| 139 | + $('#new_folder').val(''); | |
| 140 | + }, | |
| 141 | + error: function(response, textStatus, xhr) { | |
| 142 | + console.log(response); | |
| 143 | + console.log(textStatus); | |
| 144 | + }, | |
| 145 | + complete: function(response){ | |
| 146 | + $("#new-folder-dialog").removeClass('fetching'); | |
| 147 | + $("#new-folder-dialog").dialog('close'); | |
| 148 | + } | |
| 149 | + }); | |
| 150 | + return false; | |
| 151 | + }); | |
| 152 | + | |
| 153 | + $('.icon-vertical-toggle').click(function(){ | |
| 154 | + $('#content').toggleClass('show-media-panel'); | |
| 155 | + return false; | |
| 125 | 156 | }); |
| 126 | - return false; | |
| 127 | -}); | |
| 128 | - | |
| 129 | -jQuery('.text-editor-sidebar .header .icon-vertical-toggle').click(function(){ | |
| 130 | - jQuery('#content').toggleClass('show-media-panel'); | |
| 131 | - return false; | |
| 132 | -}); | |
| 133 | - | |
| 134 | -jQuery('#new-folder-button').click(function(){ | |
| 135 | - jQuery('#new-folder-dialog').dialog({modal: true}); | |
| 136 | - return false; | |
| 137 | -}); | |
| 157 | + | |
| 158 | + | |
| 159 | + $('#new-folder-button').click(function(){ | |
| 160 | + $('#new-folder-dialog').dialog({modal: true}); | |
| 161 | + return false; | |
| 162 | + }); | |
| 163 | + | |
| 164 | +}) (jQuery); | ... | ... |
public/stylesheets/application.scss
| ... | ... | @@ -1561,6 +1561,32 @@ div.article-body p img { |
| 1561 | 1561 | #content .blog-post .read-more a { |
| 1562 | 1562 | margin: 0 10px; |
| 1563 | 1563 | } |
| 1564 | + | |
| 1565 | +#content #article .blog-posts .blog-post .article-compact-abstract{ | |
| 1566 | + position: relative; | |
| 1567 | + float:left; | |
| 1568 | + margin-left: 10px; | |
| 1569 | + width: 100%; | |
| 1570 | + word-wrap: break-word; | |
| 1571 | +} | |
| 1572 | + | |
| 1573 | +#content #article .blog-posts .blog-post .article-compact-image{ | |
| 1574 | + position:relative; | |
| 1575 | + float:left; | |
| 1576 | + width: 27%; | |
| 1577 | + display: table-cell; | |
| 1578 | + vertical-align: middle; | |
| 1579 | + text-align: center; | |
| 1580 | + margin-top: 15px; | |
| 1581 | +} | |
| 1582 | + | |
| 1583 | +#content #article .blog-posts .blog-post .article-compact-abstract-with-image{ | |
| 1584 | + position: relative; | |
| 1585 | + float:left; | |
| 1586 | + margin-left: 10px; | |
| 1587 | + width: 70%; | |
| 1588 | + word-wrap: break-word; | |
| 1589 | +} | |
| 1564 | 1590 | /* NOT PUBLISHED BLOG POSTS */ |
| 1565 | 1591 | |
| 1566 | 1592 | .blog-post.not-published { |
| ... | ... | @@ -3832,6 +3858,11 @@ table.cms-articles .icon:hover { |
| 3832 | 3858 | |
| 3833 | 3859 | /* Folders */ |
| 3834 | 3860 | |
| 3861 | +.article-body ul.folder-content { | |
| 3862 | + list-style-type: none; | |
| 3863 | + padding: 0; | |
| 3864 | +} | |
| 3865 | + | |
| 3835 | 3866 | .folder-content .folder-item img { |
| 3836 | 3867 | vertical-align: middle; |
| 3837 | 3868 | position: relative; |
| ... | ... | @@ -3897,6 +3928,62 @@ table.cms-articles .icon:hover { |
| 3897 | 3928 | right: auto; |
| 3898 | 3929 | left: auto; |
| 3899 | 3930 | } |
| 3931 | + | |
| 3932 | +/**************Folder Style**********************/ | |
| 3933 | + | |
| 3934 | +.list-item{ | |
| 3935 | + font-family: arial; | |
| 3936 | + color: #172738; | |
| 3937 | +} | |
| 3938 | + | |
| 3939 | +div.folder-description { | |
| 3940 | + padding-bottom: 15px; | |
| 3941 | +} | |
| 3942 | + | |
| 3943 | +.list-item h2{ | |
| 3944 | + border-bottom:1px solid #ccc; | |
| 3945 | + margin:0px; | |
| 3946 | +} | |
| 3947 | + | |
| 3948 | +.item-info{ | |
| 3949 | + border-top: 1px solid #ccc; | |
| 3950 | + line-height: 25px; | |
| 3951 | + padding:25px 20px; | |
| 3952 | +} | |
| 3953 | + | |
| 3954 | +.item-info a{ | |
| 3955 | + text-decoration: none !important; | |
| 3956 | + font-size: 16px; | |
| 3957 | + font-weight: bold; | |
| 3958 | +} | |
| 3959 | + | |
| 3960 | +.item-icon a { | |
| 3961 | + float: left; | |
| 3962 | + width: 50px; | |
| 3963 | + height: 50px; | |
| 3964 | + background-repeat: no-repeat; | |
| 3965 | + background-position: center center; | |
| 3966 | +} | |
| 3967 | + | |
| 3968 | +span.item-type { | |
| 3969 | + font-size: 12px; | |
| 3970 | +} | |
| 3971 | + | |
| 3972 | +.item-description{ | |
| 3973 | + display: block; | |
| 3974 | + position:relative; | |
| 3975 | + margin-left: 15%; | |
| 3976 | + padding-left: 10px; | |
| 3977 | +} | |
| 3978 | + | |
| 3979 | +.item-date{ | |
| 3980 | + display:block; | |
| 3981 | + position:relative; | |
| 3982 | + font-size: 12px; | |
| 3983 | + margin-left: 15%; | |
| 3984 | + padding-left: 10px; | |
| 3985 | +} | |
| 3986 | + | |
| 3900 | 3987 | /************* enterprise homepage style *****************/ |
| 3901 | 3988 | |
| 3902 | 3989 | div.event-info { | ... | ... |
test/functional/admin_panel_controller_test.rb
| ... | ... | @@ -130,6 +130,19 @@ class AdminPanelControllerTest < ActionController::TestCase |
| 130 | 130 | assert_equal "This <strong>is</strong> my new environment", Environment.default.message_for_disabled_enterprise |
| 131 | 131 | end |
| 132 | 132 | |
| 133 | + should 'save site article date format option' do | |
| 134 | + post :site_info, :environment => { :date_format => "numbers_with_year" } | |
| 135 | + assert_redirected_to :action => 'index' | |
| 136 | + | |
| 137 | + assert_equal "numbers_with_year", Environment.default.date_format | |
| 138 | + end | |
| 139 | + | |
| 140 | + should 'dont save site article date format option when a invalid option is passed' do | |
| 141 | + post :site_info, :environment => { :date_format => "invalid_format" } | |
| 142 | + | |
| 143 | + assert_not_equal "invalid_format", Environment.default.date_format | |
| 144 | + end | |
| 145 | + | |
| 133 | 146 | should 'set portal community' do |
| 134 | 147 | e = Environment.default |
| 135 | 148 | @controller.stubs(:environment).returns(e) | ... | ... |
test/functional/application_controller_test.rb
| ... | ... | @@ -484,7 +484,7 @@ class ApplicationControllerTest < ActionController::TestCase |
| 484 | 484 | should 'change postgresql schema' do |
| 485 | 485 | uses_host 'schema1.com' |
| 486 | 486 | Noosfero::MultiTenancy.expects(:on?).returns(true) |
| 487 | - Noosfero::MultiTenancy.expects(:mapping).returns({ 'schema1.com' => 'schema1' }) | |
| 487 | + Noosfero::MultiTenancy.expects(:mapping).returns({ 'schema1.com' => 'schema1' }).at_least_once | |
| 488 | 488 | exception = assert_raise(ActiveRecord::StatementInvalid) { get :index } |
| 489 | 489 | assert_match /SET search_path TO schema1/, exception.message |
| 490 | 490 | end | ... | ... |
test/functional/content_viewer_controller_test.rb
| ... | ... | @@ -262,7 +262,7 @@ class ContentViewerControllerTest < ActionController::TestCase |
| 262 | 262 | |
| 263 | 263 | get :view_page, :profile => 'test_profile', :page => [ 'my-intranet' ] |
| 264 | 264 | |
| 265 | - assert_template "profile/_private_profile" | |
| 265 | + assert_template "shared/access_denied" | |
| 266 | 266 | end |
| 267 | 267 | |
| 268 | 268 | should 'not give access to private articles if logged in but not member' do |
| ... | ... | @@ -1527,12 +1527,12 @@ class ContentViewerControllerTest < ActionController::TestCase |
| 1527 | 1527 | should 'use context method in extra toolbar actions on article from plugins' do |
| 1528 | 1528 | class Plugin1 < Noosfero::Plugin |
| 1529 | 1529 | def article_extra_toolbar_buttons(article) |
| 1530 | - if current_person.public? | |
| 1530 | + if profile.public? | |
| 1531 | 1531 | {:title => 'some_title', :icon => 'some_icon', :url => '/someurl'} |
| 1532 | 1532 | else |
| 1533 | 1533 | {:title => 'another_title', :icon => 'another_icon', :url => '/anotherurl'} |
| 1534 | 1534 | end |
| 1535 | - end | |
| 1535 | + end | |
| 1536 | 1536 | end |
| 1537 | 1537 | Noosfero::Plugin.stubs(:all).returns([Plugin1.name]) |
| 1538 | 1538 | |
| ... | ... | @@ -1547,4 +1547,31 @@ class ContentViewerControllerTest < ActionController::TestCase |
| 1547 | 1547 | assert_tag :tag => 'div', :attributes => { :id => 'article-actions' }, :descendant => { :tag => 'a', :attributes => { :href => "/anotherurl" }} |
| 1548 | 1548 | end |
| 1549 | 1549 | |
| 1550 | + should 'show lead,image and title in compact blog visualization' do | |
| 1551 | + community = Community.create(:name => 'test-community') | |
| 1552 | + community.add_member(@profile) | |
| 1553 | + community.save! | |
| 1554 | + | |
| 1555 | + blog = community.articles.find_by_name("Blog") | |
| 1556 | + blog.visualization_format = 'compact' | |
| 1557 | + blog.save! | |
| 1558 | + | |
| 1559 | + article = TinyMceArticle.create(:name => 'Article to be shared with images', | |
| 1560 | + :body => 'This article should be shared with all social networks', | |
| 1561 | + :profile => @profile, | |
| 1562 | + :published => false, | |
| 1563 | + :abstract => "teste teste teste", | |
| 1564 | + :show_to_followers => true, | |
| 1565 | + :image_builder => { :uploaded_data => fixture_file_upload('/files/rails.png', 'image/png')} ) | |
| 1566 | + article.parent = blog | |
| 1567 | + article.save! | |
| 1568 | + | |
| 1569 | + login_as(@profile.identifier) | |
| 1570 | + | |
| 1571 | + | |
| 1572 | + get :view_page, :profile => community.identifier, "page" => 'blog' | |
| 1573 | + | |
| 1574 | + assert_tag :tag => 'div', :attributes => { :class => 'article-compact-image' } | |
| 1575 | + assert_tag :tag => 'div', :attributes => { :class => 'article-compact-abstract-with-image' } | |
| 1576 | + end | |
| 1550 | 1577 | end | ... | ... |
test/functional/friends_controller_test.rb
| ... | ... | @@ -46,7 +46,7 @@ class FriendsControllerTest < ActionController::TestCase |
| 46 | 46 | |
| 47 | 47 | should 'display find people button' do |
| 48 | 48 | get :index, :profile => 'testuser' |
| 49 | - assert_tag :tag => 'a', :content => 'Find people', :attributes => { :href => '/assets/people' } | |
| 49 | + assert_tag :tag => 'a', :content => 'Find people', :attributes => { :href => '/search/assets?asset=people' } | |
| 50 | 50 | end |
| 51 | 51 | |
| 52 | 52 | should 'not display invite friends button if any plugin tells not to' do |
| ... | ... | @@ -76,25 +76,25 @@ class FriendsControllerTest < ActionController::TestCase |
| 76 | 76 | end |
| 77 | 77 | |
| 78 | 78 | should 'display people suggestions' do |
| 79 | - profile.profile_suggestions.create(:suggestion => friend) | |
| 79 | + profile.suggested_profiles.create(:suggestion => friend) | |
| 80 | 80 | get :suggest, :profile => 'testuser' |
| 81 | 81 | assert_tag :tag => 'a', :content => "+ #{friend.name}", :attributes => { :href => "/profile/#{friend.identifier}/add" } |
| 82 | 82 | end |
| 83 | 83 | |
| 84 | 84 | should 'display button to add friend suggestion' do |
| 85 | - profile.profile_suggestions.create(:suggestion => friend) | |
| 85 | + profile.suggested_profiles.create(:suggestion => friend) | |
| 86 | 86 | get :suggest, :profile => 'testuser' |
| 87 | 87 | assert_tag :tag => 'a', :attributes => { :href => "/profile/#{friend.identifier}/add" } |
| 88 | 88 | end |
| 89 | 89 | |
| 90 | 90 | should 'display button to remove people suggestion' do |
| 91 | - profile.profile_suggestions.create(:suggestion => friend) | |
| 91 | + profile.suggested_profiles.create(:suggestion => friend) | |
| 92 | 92 | get :suggest, :profile => 'testuser' |
| 93 | 93 | assert_tag :tag => 'a', :attributes => { :href => /\/myprofile\/testuser\/friends\/remove_suggestion\/#{friend.identifier}/ } |
| 94 | 94 | end |
| 95 | 95 | |
| 96 | 96 | should 'remove suggestion of friend' do |
| 97 | - suggestion = profile.profile_suggestions.create(:suggestion => friend) | |
| 97 | + suggestion = profile.suggested_profiles.create(:suggestion => friend) | |
| 98 | 98 | post :remove_suggestion, :profile => 'testuser', :id => friend.identifier |
| 99 | 99 | |
| 100 | 100 | assert_response :success | ... | ... |
test/functional/memberships_controller_test.rb
| ... | ... | @@ -331,35 +331,35 @@ class MembershipsControllerTest < ActionController::TestCase |
| 331 | 331 | |
| 332 | 332 | should 'display list suggestions button' do |
| 333 | 333 | community = fast_create(Community) |
| 334 | - profile.profile_suggestions.create(:suggestion => community) | |
| 334 | + profile.suggested_profiles.create(:suggestion => community) | |
| 335 | 335 | get :index, :profile => 'testuser' |
| 336 | 336 | assert_tag :tag => 'a', :content => 'See some suggestions of communities...', :attributes => { :href => "/myprofile/testuser/memberships/suggest" } |
| 337 | 337 | end |
| 338 | 338 | |
| 339 | 339 | should 'display communities suggestions' do |
| 340 | 340 | community = fast_create(Community) |
| 341 | - profile.profile_suggestions.create(:suggestion => community) | |
| 341 | + profile.suggested_profiles.create(:suggestion => community) | |
| 342 | 342 | get :suggest, :profile => 'testuser' |
| 343 | 343 | assert_tag :tag => 'a', :content => "+ #{community.name}", :attributes => { :href => "/profile/#{community.identifier}/join" } |
| 344 | 344 | end |
| 345 | 345 | |
| 346 | 346 | should 'display button to join on community suggestion' do |
| 347 | 347 | community = fast_create(Community) |
| 348 | - profile.profile_suggestions.create(:suggestion => community) | |
| 348 | + profile.suggested_profiles.create(:suggestion => community) | |
| 349 | 349 | get :suggest, :profile => 'testuser' |
| 350 | 350 | assert_tag :tag => 'a', :attributes => { :href => "/profile/#{community.identifier}/join" } |
| 351 | 351 | end |
| 352 | 352 | |
| 353 | 353 | should 'display button to remove community suggestion' do |
| 354 | 354 | community = fast_create(Community) |
| 355 | - profile.profile_suggestions.create(:suggestion => community) | |
| 355 | + profile.suggested_profiles.create(:suggestion => community) | |
| 356 | 356 | get :suggest, :profile => 'testuser' |
| 357 | 357 | assert_tag :tag => 'a', :attributes => { :href => /\/myprofile\/testuser\/memberships\/remove_suggestion\/#{community.identifier}/ } |
| 358 | 358 | end |
| 359 | 359 | |
| 360 | 360 | should 'remove suggestion of community' do |
| 361 | 361 | community = fast_create(Community) |
| 362 | - suggestion = profile.profile_suggestions.create(:suggestion => community) | |
| 362 | + suggestion = profile.suggested_profiles.create(:suggestion => community) | |
| 363 | 363 | post :remove_suggestion, :profile => 'testuser', :id => community.identifier |
| 364 | 364 | |
| 365 | 365 | assert_response :success | ... | ... |
test/functional/organizations_controller_test.rb
| ... | ... | @@ -86,22 +86,22 @@ class OrganizationsControllerTest < ActionController::TestCase |
| 86 | 86 | |
| 87 | 87 | should 'activate organization profile' do |
| 88 | 88 | organization = fast_create(Organization, :visible => false, :environment_id => environment.id) |
| 89 | - assert organization.disabled? | |
| 89 | + assert !organization.visible? | |
| 90 | 90 | |
| 91 | 91 | get :activate, {:id => organization.id} |
| 92 | 92 | organization.reload |
| 93 | 93 | |
| 94 | - assert organization.enabled? | |
| 94 | + assert organization.visible | |
| 95 | 95 | end |
| 96 | 96 | |
| 97 | 97 | should 'deactivate organization profile' do |
| 98 | 98 | organization = fast_create(Organization, :visible => true, :environment_id => environment.id) |
| 99 | - assert organization.enabled? | |
| 99 | + assert organization.visible | |
| 100 | 100 | |
| 101 | 101 | get :deactivate, {:id => organization.id} |
| 102 | 102 | organization.reload |
| 103 | 103 | |
| 104 | - assert organization.disabled? | |
| 104 | + assert !organization.visible | |
| 105 | 105 | end |
| 106 | 106 | |
| 107 | 107 | should 'destroy organization profile' do | ... | ... |
test/functional/profile_controller_test.rb
| ... | ... | @@ -508,11 +508,15 @@ class ProfileControllerTest < ActionController::TestCase |
| 508 | 508 | end |
| 509 | 509 | |
| 510 | 510 | should 'show description of person' do |
| 511 | + environment = Environment.default | |
| 512 | + environment.custom_person_fields = {:description => { :active => true, :required => false, :signup => false }} | |
| 513 | + environment.save! | |
| 514 | + environment.reload | |
| 511 | 515 | login_as(@profile.identifier) |
| 512 | - @profile.description = 'Person\'s description' | |
| 513 | - @profile.save | |
| 516 | + @profile.description = 'Person description' | |
| 517 | + @profile.save! | |
| 514 | 518 | get :index, :profile => @profile.identifier |
| 515 | - assert_tag :tag => 'div', :attributes => { :class => 'public-profile-description' }, :content => /Person\'s description/ | |
| 519 | + assert_tag :tag => 'div', :attributes => { :class => 'public-profile-description' }, :content => /Person description/ | |
| 516 | 520 | end |
| 517 | 521 | |
| 518 | 522 | should 'not show description of orgarnization if not filled' do | ... | ... |
test/functional/tasks_controller_test.rb
| ... | ... | @@ -520,4 +520,120 @@ class TasksControllerTest < ActionController::TestCase |
| 520 | 520 | assert !json_response['success'] |
| 521 | 521 | end |
| 522 | 522 | |
| 523 | + should 'list tasks for user with only view_tasks permission' do | |
| 524 | + community = fast_create(Community) | |
| 525 | + @controller.stubs(:profile).returns(community) | |
| 526 | + person = create_user_with_permission('taskviewer', 'view_tasks', community) | |
| 527 | + login_as person.user.login | |
| 528 | + get :index | |
| 529 | + assert_response :success | |
| 530 | + assert assigns(:view_only) | |
| 531 | + end | |
| 532 | + | |
| 533 | + should 'forbid user with only view_tasks permission to close a task' do | |
| 534 | + community = fast_create(Community) | |
| 535 | + @controller.stubs(:profile).returns(community) | |
| 536 | + person = create_user_with_permission('taskviewer', 'view_tasks', community) | |
| 537 | + login_as person.user.login | |
| 538 | + post :close | |
| 539 | + assert_response 403 | |
| 540 | + end | |
| 541 | + | |
| 542 | + should 'hide tasks actions when user has only view_tasks permission' do | |
| 543 | + community = fast_create(Community) | |
| 544 | + @controller.stubs(:profile).returns(community) | |
| 545 | + person = create_user_with_permission('taskviewer', 'view_tasks', community) | |
| 546 | + login_as person.user.login | |
| 547 | + | |
| 548 | + Task.create!(:requestor => person, :target => community) | |
| 549 | + get :index | |
| 550 | + | |
| 551 | + assert_select '.task-actions', 0 | |
| 552 | + end | |
| 553 | + | |
| 554 | + should 'display tasks actions when user has perform_task permission' do | |
| 555 | + community = fast_create(Community) | |
| 556 | + @controller.stubs(:profile).returns(community) | |
| 557 | + person = create_user_with_permission('taskperformer', 'perform_task', community) | |
| 558 | + login_as person.user.login | |
| 559 | + | |
| 560 | + Task.create!(:requestor => person, :target => community) | |
| 561 | + get :index | |
| 562 | + | |
| 563 | + assert_select '.task-actions', 2 | |
| 564 | + end | |
| 565 | + | |
| 566 | + should 'hide decision selector when user has only view_tasks permission' do | |
| 567 | + community = fast_create(Community) | |
| 568 | + @controller.stubs(:profile).returns(community) | |
| 569 | + person = create_user_with_permission('taskviewer', 'view_tasks', community) | |
| 570 | + login_as person.user.login | |
| 571 | + | |
| 572 | + Task.create!(:requestor => person, :target => community) | |
| 573 | + get :index | |
| 574 | + | |
| 575 | + assert_select '#up-set-all-tasks-to', 0 | |
| 576 | + assert_select '#down-set-all-tasks-to', 0 | |
| 577 | + end | |
| 578 | + | |
| 579 | + should 'display decision selector when user has perform_task permission' do | |
| 580 | + community = fast_create(Community) | |
| 581 | + @controller.stubs(:profile).returns(community) | |
| 582 | + person = create_user_with_permission('taskperformer', 'perform_task', community) | |
| 583 | + login_as person.user.login | |
| 584 | + | |
| 585 | + Task.create!(:requestor => person, :target => community) | |
| 586 | + get :index | |
| 587 | + | |
| 588 | + assert_select '#up-set-all-tasks-to' | |
| 589 | + assert_select '#down-set-all-tasks-to' | |
| 590 | + end | |
| 591 | + | |
| 592 | + should 'hide decision buttons when user has only view_tasks permission' do | |
| 593 | + community = fast_create(Community) | |
| 594 | + @controller.stubs(:profile).returns(community) | |
| 595 | + person = create_user_with_permission('taskviewer', 'view_tasks', community) | |
| 596 | + login_as person.user.login | |
| 597 | + | |
| 598 | + task = Task.create!(:requestor => person, :target => community) | |
| 599 | + get :index | |
| 600 | + | |
| 601 | + assert_select "#decision-finish-#{task.id}", 0 | |
| 602 | + assert_select "#decision-cancel-#{task.id}", 0 | |
| 603 | + assert_select "#decision-skip-#{task.id}", 0 | |
| 604 | + end | |
| 605 | + | |
| 606 | + should 'display decision buttons when user has perform_task permission' do | |
| 607 | + community = fast_create(Community) | |
| 608 | + @controller.stubs(:profile).returns(community) | |
| 609 | + person = create_user_with_permission('taskperformer', 'perform_task', community) | |
| 610 | + login_as person.user.login | |
| 611 | + | |
| 612 | + task = Task.create!(:requestor => person, :target => community) | |
| 613 | + get :index | |
| 614 | + | |
| 615 | + assert_select "#decision-finish-#{task.id}" | |
| 616 | + assert_select "#decision-cancel-#{task.id}" | |
| 617 | + assert_select "#decision-skip-#{task.id}" | |
| 618 | + end | |
| 619 | + | |
| 620 | + should 'hide responsive selection when user has only view_tasks permission' do | |
| 621 | + community = fast_create(Community) | |
| 622 | + @controller.stubs(:profile).returns(community) | |
| 623 | + person = create_user_with_permission('taskviewer', 'view_tasks', community) | |
| 624 | + login_as person.user.login | |
| 625 | + | |
| 626 | + task = Task.create!(:requestor => person, :target => community, :responsible => person) | |
| 627 | + get :index | |
| 628 | + | |
| 629 | + assert_select ".task_responsible select", 0 | |
| 630 | + assert_select ".task_responsible .value" | |
| 631 | + end | |
| 632 | + | |
| 633 | + should 'store the person who closes a task' do | |
| 634 | + t = profile.tasks.build; t.save! | |
| 635 | + post :close, :tasks => {t.id => {:decision => 'finish', :task => {}}} | |
| 636 | + assert_equal profile, t.reload.closed_by | |
| 637 | + end | |
| 638 | + | |
| 523 | 639 | end | ... | ... |
test/integration/routing_test.rb
| ... | ... | @@ -135,7 +135,7 @@ class RoutingTest < ActionController::IntegrationTest |
| 135 | 135 | end |
| 136 | 136 | |
| 137 | 137 | def test_assets_routing |
| 138 | - assert_routing('/assets/my-asset/a/b/c', :controller => 'search', :action => 'assets', :asset => 'my-asset', :category_path => 'a/b/c') | |
| 138 | + assert_routing('/search/assets/a/b/c', :controller => 'search', :action => 'assets', :category_path => 'a/b/c') | |
| 139 | 139 | end |
| 140 | 140 | |
| 141 | 141 | def test_content_view_with_dot | ... | ... |
test/test_helper.rb
test/unit/article_test.rb
| ... | ... | @@ -2164,4 +2164,17 @@ class ArticleTest < ActiveSupport::TestCase |
| 2164 | 2164 | assert_equal [1, 2, 2], [a1.reload.hits, a2.reload.hits, a3.reload.hits] |
| 2165 | 2165 | end |
| 2166 | 2166 | |
| 2167 | + should 'vote in a article' do | |
| 2168 | + article = create(Article, :name => 'Test', :profile => profile, :last_changed_by => nil) | |
| 2169 | + profile.vote(article, 5) | |
| 2170 | + assert_equal 1, article.voters_who_voted.length | |
| 2171 | + assert_equal 5, article.votes_total | |
| 2172 | + end | |
| 2173 | + | |
| 2174 | + should 'be able to remove a voted article' do | |
| 2175 | + article = create(Article, :name => 'Test', :profile => profile, :last_changed_by => nil) | |
| 2176 | + profile.vote(article, 5) | |
| 2177 | + article.destroy | |
| 2178 | + end | |
| 2179 | + | |
| 2167 | 2180 | end | ... | ... |
test/unit/blog_test.rb
| ... | ... | @@ -161,7 +161,16 @@ class BlogTest < ActiveSupport::TestCase |
| 161 | 161 | assert_equal 'short', p.blog.visualization_format |
| 162 | 162 | end |
| 163 | 163 | |
| 164 | - should 'allow only full and short as visualization_format' do | |
| 164 | + should 'update visualization_format setting to compact' do | |
| 165 | + p = create_user('testuser').person | |
| 166 | + p.articles << build(Blog, :profile => p, :name => 'Blog test') | |
| 167 | + blog = p.blog | |
| 168 | + blog.visualization_format = 'compact' | |
| 169 | + assert blog.save! | |
| 170 | + assert_equal 'compact', p.blog.visualization_format | |
| 171 | + end | |
| 172 | + | |
| 173 | + should 'allow only full, short or compact as visualization_format' do | |
| 165 | 174 | blog = build(Blog, :name => 'blog') |
| 166 | 175 | blog.visualization_format = 'wrong_format' |
| 167 | 176 | blog.valid? |
| ... | ... | @@ -174,6 +183,10 @@ class BlogTest < ActiveSupport::TestCase |
| 174 | 183 | blog.visualization_format = 'full' |
| 175 | 184 | blog.valid? |
| 176 | 185 | assert !blog.errors[:visualization_format.to_s].present? |
| 186 | + | |
| 187 | + blog.visualization_format = 'compact' | |
| 188 | + blog.valid? | |
| 189 | + assert !blog.errors[:visualization_format.to_s].present? | |
| 177 | 190 | end |
| 178 | 191 | |
| 179 | 192 | should 'have posts' do | ... | ... |
test/unit/comment_test.rb
| ... | ... | @@ -703,6 +703,52 @@ class CommentTest < ActiveSupport::TestCase |
| 703 | 703 | assert_equivalent [c1,c4], Comment.without_reply |
| 704 | 704 | end |
| 705 | 705 | |
| 706 | + should 'vote in a comment' do | |
| 707 | + comment = create_comment | |
| 708 | + person = create_user('voter').person | |
| 709 | + person.vote(comment, 5) | |
| 710 | + assert_equal 1, comment.voters_who_voted.length | |
| 711 | + assert_equal 5, comment.votes_total | |
| 712 | + end | |
| 713 | + | |
| 714 | + should 'like a comment' do | |
| 715 | + comment = create_comment | |
| 716 | + person = create_user('voter').person | |
| 717 | + assert !comment.voted_by?(person, true) | |
| 718 | + person.vote_for(comment) | |
| 719 | + assert comment.voted_by?(person, true) | |
| 720 | + assert !comment.voted_by?(person, false) | |
| 721 | + end | |
| 722 | + | |
| 723 | + should 'count voters for' do | |
| 724 | + comment = create_comment | |
| 725 | + person = create_user('voter').person | |
| 726 | + person2 = create_user('voter2').person | |
| 727 | + person3 = create_user('voter3').person | |
| 728 | + person.vote_for(comment) | |
| 729 | + person2.vote_for(comment) | |
| 730 | + person3.vote_against(comment) | |
| 731 | + assert_equal 2, comment.votes_for | |
| 732 | + end | |
| 733 | + | |
| 734 | + should 'count votes againts' do | |
| 735 | + comment = create_comment | |
| 736 | + person = create_user('voter').person | |
| 737 | + person2 = create_user('voter2').person | |
| 738 | + person3 = create_user('voter3').person | |
| 739 | + person.vote_against(comment) | |
| 740 | + person2.vote_against(comment) | |
| 741 | + person3.vote_for(comment) | |
| 742 | + assert_equal 2, comment.votes_against | |
| 743 | + end | |
| 744 | + | |
| 745 | + should 'be able to remove a voted comment' do | |
| 746 | + comment = create_comment | |
| 747 | + person = create_user('voter').person | |
| 748 | + person.vote(comment, 5) | |
| 749 | + comment.destroy | |
| 750 | + end | |
| 751 | + | |
| 706 | 752 | private |
| 707 | 753 | |
| 708 | 754 | def create_comment(args = {}) | ... | ... |
test/unit/content_viewer_helper_test.rb
| ... | ... | @@ -18,7 +18,7 @@ class ContentViewerHelperTest < ActionView::TestCase |
| 18 | 18 | result = article_title(post) |
| 19 | 19 | assert_tag_in_string result, :tag => 'span', :content => show_date(post.published_at) |
| 20 | 20 | end |
| 21 | - | |
| 21 | + | |
| 22 | 22 | should 'display published-at for forum posts' do |
| 23 | 23 | forum = fast_create(Forum, :name => 'Forum test', :profile_id => profile.id) |
| 24 | 24 | post = TextileArticle.create!(:name => 'post test', :profile => profile, :parent => forum) |
| ... | ... | @@ -112,6 +112,42 @@ class ContentViewerHelperTest < ActionView::TestCase |
| 112 | 112 | assert_match 'bt-bookmark.gif', addthis_image_tag |
| 113 | 113 | end |
| 114 | 114 | |
| 115 | + should 'show date with mm/dd/yyyy' do | |
| 116 | + Environment.any_instance.stubs(:date_format).returns('numbers_with_year') | |
| 117 | + article = TextileArticle.new(:name => 'post for test', :body => 'post for test', :profile => profile) | |
| 118 | + article.published_at = Time.zone.local(2007, 2, 1, 15, 30, 45) | |
| 119 | + article.save! | |
| 120 | + result = show_with_right_format_date article | |
| 121 | + assert_match /2\/1\/2007/, result | |
| 122 | + end | |
| 123 | + | |
| 124 | + should 'show date with mm/dd' do | |
| 125 | + Environment.any_instance.stubs(:date_format).returns('numbers') | |
| 126 | + article = TextileArticle.new(:name => 'post for test', :body => 'post for test', :profile => profile) | |
| 127 | + article.published_at = Time.zone.local(2007, 2, 1, 15, 30, 45) | |
| 128 | + article.save! | |
| 129 | + result = show_with_right_format_date article | |
| 130 | + assert_match /2\/1/, result | |
| 131 | + end | |
| 132 | + | |
| 133 | + should 'show date with month name' do | |
| 134 | + Environment.any_instance.stubs(:date_format).returns('month_name') | |
| 135 | + article = TextileArticle.new(:name => 'post for test', :body => 'post for test', :profile => profile) | |
| 136 | + article.published_at = Time.zone.local(2007, 2, 1, 15, 30, 45) | |
| 137 | + article.save! | |
| 138 | + result = show_with_right_format_date article | |
| 139 | + assert_match /February 1/, result | |
| 140 | + end | |
| 141 | + | |
| 142 | + should 'show date with month name and year' do | |
| 143 | + Environment.any_instance.stubs(:date_format).returns('month_name_with_year') | |
| 144 | + article = TextileArticle.new(:name => 'post for test', :body => 'post for test', :profile => profile) | |
| 145 | + article.published_at = Time.zone.local(2007, 2, 1, 15, 30, 45) | |
| 146 | + article.save! | |
| 147 | + result = show_with_right_format_date article | |
| 148 | + assert_match /February 1, 2007/, result | |
| 149 | + end | |
| 150 | + | |
| 115 | 151 | protected |
| 116 | 152 | include NoosferoTestHelper |
| 117 | 153 | include ActionView::Helpers::TextHelper | ... | ... |
test/unit/dates_helper_test.rb
| ... | ... | @@ -146,4 +146,9 @@ class DatesHelperTest < ActiveSupport::TestCase |
| 146 | 146 | assert_equal Date.new(Date.today.year, Date.today.month, 1), build_date('', '') |
| 147 | 147 | end |
| 148 | 148 | |
| 149 | + should 'show how long it has passed since a specific date' do | |
| 150 | + date = Time.zone.now | |
| 151 | + assert_equal show_date(date, false, false, true), time_ago_in_words(date) | |
| 152 | + end | |
| 153 | + | |
| 149 | 154 | end | ... | ... |
test/unit/environment_test.rb
| ... | ... | @@ -1703,4 +1703,32 @@ class EnvironmentTest < ActiveSupport::TestCase |
| 1703 | 1703 | assert !e.has_license? |
| 1704 | 1704 | end |
| 1705 | 1705 | |
| 1706 | + should 'validates_inclusion_of date format' do | |
| 1707 | + environment = fast_create(Environment) | |
| 1708 | + | |
| 1709 | + environment.date_format = "invalid_format" | |
| 1710 | + environment.valid? | |
| 1711 | + assert environment.errors[:date_format.to_s].present? | |
| 1712 | + | |
| 1713 | + environment.date_format = "numbers_with_year" | |
| 1714 | + environment.valid? | |
| 1715 | + assert !environment.errors[:date_format.to_s].present? | |
| 1716 | + | |
| 1717 | + environment.date_format = "numbers" | |
| 1718 | + environment.valid? | |
| 1719 | + assert !environment.errors[:date_format.to_s].present? | |
| 1720 | + | |
| 1721 | + environment.date_format = "month_name_with_year" | |
| 1722 | + environment.valid? | |
| 1723 | + assert !environment.errors[:date_format.to_s].present? | |
| 1724 | + | |
| 1725 | + environment.date_format = "month_name" | |
| 1726 | + environment.valid? | |
| 1727 | + assert !environment.errors[:date_format.to_s].present? | |
| 1728 | + | |
| 1729 | + environment.date_format = "past_time" | |
| 1730 | + environment.valid? | |
| 1731 | + assert !environment.errors[:date_format.to_s].present? | |
| 1732 | + end | |
| 1733 | + | |
| 1706 | 1734 | end | ... | ... |
test/unit/events_helper_test.rb
| ... | ... | @@ -8,27 +8,13 @@ class EventsHelperTest < ActiveSupport::TestCase |
| 8 | 8 | user = create_user('userwithevents').person |
| 9 | 9 | stubs(:user).returns(user) |
| 10 | 10 | |
| 11 | - expects(:show_date_month).returns('') | |
| 12 | - expects(:_).with('Events for %s').returns('').once | |
| 13 | - expects(:_).with(' to ').returns('').twice | |
| 14 | - expects(:_).with('Place: ').returns('').twice | |
| 15 | - expects(:_).with('No events for this month').returns('').never | |
| 16 | - | |
| 17 | - event1 = mock; | |
| 18 | - event1.expects(:display_to?).with(anything).returns(true).once; | |
| 19 | - event1.expects(:start_date).returns(Date.today).once | |
| 20 | - event1.expects(:end_date).returns(Date.today + 1.day).twice | |
| 21 | - event1.expects(:name).returns('Event 1').once | |
| 22 | - event1.expects(:url).returns({}).once | |
| 23 | - event1.expects(:address).returns('The Shire').times(3) | |
| 24 | - | |
| 25 | - event2 = mock; | |
| 26 | - event2.expects(:display_to?).with(anything).returns(true).once | |
| 27 | - event2.expects(:start_date).returns(Date.today).once | |
| 28 | - event2.expects(:end_date).returns(Date.today + 1.day).twice | |
| 29 | - event2.expects(:name).returns('Event 2').once | |
| 30 | - event2.expects(:url).returns({}).once | |
| 31 | - event2.expects(:address).returns('Valfenda').times(3) | |
| 11 | + event1 = Event.new(name: "Event 1", start_date: Date.today, end_date: (Date.today + 1.day), address: 'The Shire') | |
| 12 | + event1.profile = user | |
| 13 | + event1.save | |
| 14 | + | |
| 15 | + event2 = Event.new(name: 'Event 2', start_date: Date.today, end_date: (Date.today + 1.day), address: 'Valfenda') | |
| 16 | + event2.profile = user | |
| 17 | + event2.save | |
| 32 | 18 | |
| 33 | 19 | result = list_events(Date.today, [event1, event2]) |
| 34 | 20 | ... | ... |
test/unit/folder_helper_test.rb
| ... | ... | @@ -89,27 +89,14 @@ class FolderHelperTest < ActionView::TestCase |
| 89 | 89 | assert_not_includes result, article |
| 90 | 90 | end |
| 91 | 91 | |
| 92 | - should 'list subitems as HTML content' do | |
| 92 | + should 'display the proper content icon' do | |
| 93 | 93 | profile = create_user('folder-owner').person |
| 94 | 94 | folder = fast_create(Folder, {:name => 'Parent Folder', :profile_id => profile.id}) |
| 95 | 95 | article1 = fast_create(Article, {:name => 'Article1', :parent_id => folder.id, :profile_id => profile.id, :updated_at => DateTime.now }) |
| 96 | 96 | article2 = fast_create(Article, {:name => 'Article2', :parent_id => folder.id, :profile_id => profile.id, :updated_at => DateTime.now }) |
| 97 | - self.stubs(:params).returns({:npage => nil}) | |
| 98 | - | |
| 99 | - contents = folder.children.order('updated_at DESC').paginate(:per_page => 10, :page => params[:npage]) | |
| 100 | - expects(:user).returns(profile).at_least_once | |
| 101 | - expects(:list_type).returns(:folder).at_least_once | |
| 102 | - expects(:recursive).returns(false).at_least_once | |
| 103 | - expects(:pagination_links).with(anything, anything).returns('') | |
| 104 | - list = render 'shared/content_list', binding | |
| 105 | - expects(:render).with(:file => 'shared/content_list', | |
| 106 | - :locals => { :contents => contents, :recursive => false, :list_type => :folder } | |
| 107 | - ).returns(list) | |
| 108 | - | |
| 109 | - result = list_contents(:contents=>contents) | |
| 110 | - | |
| 111 | - assert_tag_in_string result, :tag => 'td', :descendant => { :tag => 'a', :attributes => { :href => /.*\/folder-owner\/my-article-[0-9]*(\?|$)/ } }, :content => /Article1/ | |
| 112 | - assert_tag_in_string result, :tag => 'td', :descendant => { :tag => 'a', :attributes => { :href => /.*\/folder-owner\/my-article-[0-9]*(\?|$)/ } }, :content => /Article2/ | |
| 97 | + | |
| 98 | + assert_tag_in_string display_content_icon(article1), :tag => 'a', :attributes => { :href => /.*\/folder-owner\/my-article-[0-9]*(\?|$)/ } | |
| 99 | + assert_tag_in_string display_content_icon(article2), :tag => 'a', :attributes => { :href => /.*\/folder-owner\/my-article-[0-9]*(\?|$)/ } | |
| 113 | 100 | end |
| 114 | 101 | |
| 115 | 102 | should 'explictly advise if empty' do | ... | ... |
test/unit/forum_helper_test.rb
| ... | ... | @@ -7,6 +7,7 @@ class ForumHelperTest < ActiveSupport::TestCase |
| 7 | 7 | include ContentViewerHelper |
| 8 | 8 | include ActionView::Helpers::AssetTagHelper |
| 9 | 9 | include ApplicationHelper |
| 10 | + include ActionView::Helpers::DateHelper | |
| 10 | 11 | |
| 11 | 12 | def setup |
| 12 | 13 | @environment = Environment.default |
| ... | ... | @@ -41,7 +42,7 @@ class ForumHelperTest < ActiveSupport::TestCase |
| 41 | 42 | some_post = create(TextileArticle, :name => 'First post', :profile => profile, :parent => forum, :published => true, :author => author) |
| 42 | 43 | assert some_post.comments.empty? |
| 43 | 44 | out = last_topic_update(some_post) |
| 44 | - assert_match some_post.updated_at.to_s, out | |
| 45 | + assert_match time_ago_in_words(some_post.updated_at), out | |
| 45 | 46 | assert_match /forum test author/, out |
| 46 | 47 | end |
| 47 | 48 | |
| ... | ... | @@ -53,10 +54,11 @@ class ForumHelperTest < ActiveSupport::TestCase |
| 53 | 54 | c = Comment.last |
| 54 | 55 | assert_equal 2, some_post.comments.count |
| 55 | 56 | out = last_topic_update(some_post) |
| 56 | - assert_match c.created_at.to_s, out | |
| 57 | + result = time_ago_in_words(c.created_at) | |
| 58 | + assert_match result, out | |
| 57 | 59 | assert_match 'a2', out |
| 58 | 60 | |
| 59 | - assert_match(/#{Regexp.escape(c.created_at.to_s)} by <a href='[^']+'>a2<\/a>/, last_topic_update(some_post)) | |
| 61 | + assert_match(/#{result} by <a href='[^']+'>a2<\/a>/, last_topic_update(some_post)) | |
| 60 | 62 | end |
| 61 | 63 | |
| 62 | 64 | should "return last comment author's name from unauthenticated user" do |
| ... | ... | @@ -64,18 +66,15 @@ class ForumHelperTest < ActiveSupport::TestCase |
| 64 | 66 | some_post.comments << build(Comment, :name => 'John', :email => 'lenon@example.com', :title => 'test', :body => 'test') |
| 65 | 67 | c = Comment.last |
| 66 | 68 | out = last_topic_update(some_post) |
| 67 | - assert_match "#{c.created_at.to_s} by John", out | |
| 69 | + result = time_ago_in_words(c.created_at) | |
| 70 | + assert_match "#{result} by John", out | |
| 68 | 71 | assert_match 'John', out |
| 69 | 72 | |
| 70 | - assert_match(/#{Regexp.escape(c.created_at.to_s)} by John/m, last_topic_update(some_post)) | |
| 73 | + assert_match(/#{result} by John/m, last_topic_update(some_post)) | |
| 71 | 74 | end |
| 72 | 75 | |
| 73 | 76 | protected |
| 74 | 77 | |
| 75 | 78 | include NoosferoTestHelper |
| 76 | 79 | |
| 77 | - def time_ago_as_sentence(t = Time.now) | |
| 78 | - t.to_s | |
| 79 | - end | |
| 80 | - | |
| 81 | 80 | end | ... | ... |
test/unit/person_test.rb
| ... | ... | @@ -1683,4 +1683,133 @@ class PersonTest < ActiveSupport::TestCase |
| 1683 | 1683 | assert_not_includes people, p6 |
| 1684 | 1684 | end |
| 1685 | 1685 | |
| 1686 | + should 'vote in a comment with value greater than 1' do | |
| 1687 | + comment = fast_create(Comment) | |
| 1688 | + person = fast_create(Person) | |
| 1689 | + | |
| 1690 | + person.vote(comment, 5) | |
| 1691 | + assert_equal 1, person.vote_count | |
| 1692 | + assert_equal 5, person.votes.first.vote | |
| 1693 | + assert person.voted_on?(comment) | |
| 1694 | + end | |
| 1695 | + | |
| 1696 | + should 'vote in a comment with value lesser than -1' do | |
| 1697 | + comment = fast_create(Comment) | |
| 1698 | + person = fast_create(Person) | |
| 1699 | + | |
| 1700 | + person.vote(comment, -5) | |
| 1701 | + assert_equal 1, person.vote_count | |
| 1702 | + assert_equal -5, person.votes.first.vote | |
| 1703 | + end | |
| 1704 | + | |
| 1705 | + should 'vote for a comment' do | |
| 1706 | + comment = fast_create(Comment) | |
| 1707 | + person = fast_create(Person) | |
| 1708 | + | |
| 1709 | + assert !person.voted_for?(comment) | |
| 1710 | + person.vote_for(comment) | |
| 1711 | + assert person.voted_for?(comment) | |
| 1712 | + assert !person.voted_against?(comment) | |
| 1713 | + end | |
| 1714 | + | |
| 1715 | + should 'vote against a comment' do | |
| 1716 | + comment = fast_create(Comment) | |
| 1717 | + person = fast_create(Person) | |
| 1718 | + | |
| 1719 | + assert !person.voted_against?(comment) | |
| 1720 | + person.vote_against(comment) | |
| 1721 | + assert !person.voted_for?(comment) | |
| 1722 | + assert person.voted_against?(comment) | |
| 1723 | + end | |
| 1724 | + | |
| 1725 | + should 'do not vote against a comment twice' do | |
| 1726 | + comment = fast_create(Comment) | |
| 1727 | + person = fast_create(Person) | |
| 1728 | + | |
| 1729 | + assert person.vote_against(comment) | |
| 1730 | + assert !person.vote_against(comment) | |
| 1731 | + end | |
| 1732 | + | |
| 1733 | + should 'do not vote for a comment twice' do | |
| 1734 | + comment = fast_create(Comment) | |
| 1735 | + person = fast_create(Person) | |
| 1736 | + | |
| 1737 | + assert person.vote_for(comment) | |
| 1738 | + assert !person.vote_for(comment) | |
| 1739 | + end | |
| 1740 | + | |
| 1741 | + should 'not vote against a voted for comment' do | |
| 1742 | + comment = fast_create(Comment) | |
| 1743 | + person = fast_create(Person) | |
| 1744 | + | |
| 1745 | + person.vote_for(comment) | |
| 1746 | + person.vote_against(comment) | |
| 1747 | + assert person.voted_for?(comment) | |
| 1748 | + assert !person.voted_against?(comment) | |
| 1749 | + end | |
| 1750 | + | |
| 1751 | + should 'not vote for a voted against comment' do | |
| 1752 | + comment = fast_create(Comment) | |
| 1753 | + person = fast_create(Person) | |
| 1754 | + | |
| 1755 | + person.vote_against(comment) | |
| 1756 | + person.vote_for(comment) | |
| 1757 | + assert !person.voted_for?(comment) | |
| 1758 | + assert person.voted_against?(comment) | |
| 1759 | + end | |
| 1760 | + | |
| 1761 | + should 'undo a vote for a comment' do | |
| 1762 | + comment = fast_create(Comment) | |
| 1763 | + person = fast_create(Person) | |
| 1764 | + | |
| 1765 | + person.vote_for(comment) | |
| 1766 | + assert person.voted_for?(comment) | |
| 1767 | + person.votes.for_voteable(comment).destroy_all | |
| 1768 | + assert !person.voted_for?(comment) | |
| 1769 | + end | |
| 1770 | + | |
| 1771 | + should 'count comments voted' do | |
| 1772 | + comment = fast_create(Comment) | |
| 1773 | + person = fast_create(Person) | |
| 1774 | + | |
| 1775 | + comment2 = fast_create(Comment) | |
| 1776 | + comment3 = fast_create(Comment) | |
| 1777 | + person.vote_for(comment) | |
| 1778 | + person.vote_for(comment2) | |
| 1779 | + person.vote_against(comment3) | |
| 1780 | + assert_equal 3, person.vote_count | |
| 1781 | + assert_equal 2, person.vote_count(true) | |
| 1782 | + assert_equal 1, person.vote_count(false) | |
| 1783 | + end | |
| 1784 | + | |
| 1785 | + should 'vote in a article with value greater than 1' do | |
| 1786 | + article = fast_create(Article) | |
| 1787 | + person = fast_create(Person) | |
| 1788 | + | |
| 1789 | + person.vote(article, 5) | |
| 1790 | + assert_equal 1, person.vote_count | |
| 1791 | + assert_equal 5, person.votes.first.vote | |
| 1792 | + assert person.voted_on?(article) | |
| 1793 | + end | |
| 1794 | + | |
| 1795 | + should 'vote for a article' do | |
| 1796 | + article = fast_create(Article) | |
| 1797 | + person = fast_create(Person) | |
| 1798 | + | |
| 1799 | + assert !person.voted_for?(article) | |
| 1800 | + person.vote_for(article) | |
| 1801 | + assert person.voted_for?(article) | |
| 1802 | + assert !person.voted_against?(article) | |
| 1803 | + end | |
| 1804 | + | |
| 1805 | + should 'vote against a article' do | |
| 1806 | + article = fast_create(Article) | |
| 1807 | + person = fast_create(Person) | |
| 1808 | + | |
| 1809 | + assert !person.voted_against?(article) | |
| 1810 | + person.vote_against(article) | |
| 1811 | + assert !person.voted_for?(article) | |
| 1812 | + assert person.voted_against?(article) | |
| 1813 | + end | |
| 1814 | + | |
| 1686 | 1815 | end | ... | ... |
test/unit/plugin_test.rb
test/unit/profile_suggestion_test.rb
| ... | ... | @@ -142,7 +142,7 @@ class ProfileSuggestionTest < ActiveSupport::TestCase |
| 142 | 142 | p2 = create_user('testuser2').person |
| 143 | 143 | p3 = create_user('testuser3').person |
| 144 | 144 | p4 = create_user('testuser4').person |
| 145 | - p5 = create_user('testuser4').person | |
| 145 | + p5 = create_user('testuser5').person | |
| 146 | 146 | |
| 147 | 147 | p1.add_friend(p2) |
| 148 | 148 | p1.add_friend(p3) |
| ... | ... | @@ -212,8 +212,8 @@ class ProfileSuggestionTest < ActiveSupport::TestCase |
| 212 | 212 | |
| 213 | 213 | ProfileSuggestion.expects(:calculate_suggestions) |
| 214 | 214 | |
| 215 | - person.profile_suggestions.enabled.last.disable | |
| 216 | - person.profile_suggestions.enabled.last.destroy | |
| 215 | + person.suggested_profiles.enabled.last.disable | |
| 216 | + person.suggested_profiles.enabled.last.destroy | |
| 217 | 217 | process_delayed_job_queue |
| 218 | 218 | end |
| 219 | 219 | ... | ... |
test/unit/profile_test.rb
| ... | ... | @@ -2139,6 +2139,16 @@ class ProfileTest < ActiveSupport::TestCase |
| 2139 | 2139 | assert_equal false, ProfileSuggestion.find(suggestion.id).enabled |
| 2140 | 2140 | end |
| 2141 | 2141 | |
| 2142 | + should 'destroy related suggestion if profile is destroyed' do | |
| 2143 | + person = fast_create(Person) | |
| 2144 | + suggested_person = fast_create(Person) | |
| 2145 | + suggestion = ProfileSuggestion.create(:person => person, :suggestion => suggested_person, :enabled => true) | |
| 2146 | + | |
| 2147 | + assert_difference 'ProfileSuggestion.find_all_by_suggestion_id(suggested_person.id).count', -1 do | |
| 2148 | + suggested_person.destroy | |
| 2149 | + end | |
| 2150 | + end | |
| 2151 | + | |
| 2142 | 2152 | should 'enable profile visibility' do |
| 2143 | 2153 | profile = fast_create(Profile) |
| 2144 | 2154 | ... | ... |
test/unit/short_filename_test.rb
| ... | ... | @@ -16,5 +16,19 @@ class NoosferoFilenamesTest < ActiveSupport::TestCase |
| 16 | 16 | assert_equal 'filename.mp3', short_filename('filename.mp3') |
| 17 | 17 | end |
| 18 | 18 | |
| 19 | + should 'highlight the file extansion' do | |
| 20 | + assert_equal 'AGENDA(...) - MP3', short_filename_upper_ext('AGENDA_CULTURA_-_FESTA_DE_VAQUEIROS_PONTO_DE_SERRA_PRETA_BAIXA.mp3',15) | |
| 21 | + | |
| 22 | + assert_equal 'AGENDA - MP3', short_filename_upper_ext('AGENDA.mp3',15) | |
| 23 | + end | |
| 24 | + | |
| 25 | + should 'return the full filename if its size is smaller than the limit' do | |
| 26 | + assert_equal 'AGENDA', shrink('AGENDA', 'mp3', 15) | |
| 27 | + end | |
| 28 | + | |
| 29 | + should 'shrink the filename if its size is bigger than the limit' do | |
| 30 | + assert_equal 'AGENDA(...)', shrink('AGENDA_CULTURA_-_FESTA_DE_VAQUEIROS_PONTO_DE_SERRA_PRETA_BAIXA', 'mp3', 14) | |
| 31 | + end | |
| 32 | + | |
| 19 | 33 | end |
| 20 | 34 | ... | ... |
test/unit/task_test.rb
| ... | ... | @@ -440,6 +440,20 @@ class TaskTest < ActiveSupport::TestCase |
| 440 | 440 | assert_equal person, task.responsible |
| 441 | 441 | end |
| 442 | 442 | |
| 443 | + should 'store who finish the task' do | |
| 444 | + t = Task.create | |
| 445 | + person = fast_create(Person) | |
| 446 | + t.finish(person) | |
| 447 | + assert_equal person, t.reload.closed_by | |
| 448 | + end | |
| 449 | + | |
| 450 | + should 'store who cancel the task' do | |
| 451 | + t = Task.create | |
| 452 | + person = fast_create(Person) | |
| 453 | + t.cancel(person) | |
| 454 | + assert_equal person, t.reload.closed_by | |
| 455 | + end | |
| 456 | + | |
| 443 | 457 | protected |
| 444 | 458 | |
| 445 | 459 | def sample_user | ... | ... |
vendor/plugins/access_control/lib/permission_check.rb
| ... | ... | @@ -19,14 +19,14 @@ module PermissionCheck |
| 19 | 19 | before_filter actions do |c| |
| 20 | 20 | target = target_method.kind_of?(Symbol) ? c.send(target_method) : target_method |
| 21 | 21 | accessor = accessor_method.kind_of?(Symbol) ? c.send(accessor_method) : accessor_method |
| 22 | - unless accessor && accessor.has_permission?(permission.to_s, target) | |
| 22 | + unless Array.wrap(permission).map {|p| accessor && accessor.has_permission?(p.to_s, target)}.any? | |
| 23 | 23 | c.class.render_access_denied(c) && false |
| 24 | 24 | end |
| 25 | 25 | end |
| 26 | 26 | end |
| 27 | 27 | |
| 28 | 28 | def render_access_denied(c) |
| 29 | - if c.respond_to?(:render_access_denied) | |
| 29 | + if c.respond_to?(:render_access_denied, true) | |
| 30 | 30 | c.send(:render_access_denied) |
| 31 | 31 | else |
| 32 | 32 | c.send(:render, :template => access_denied_template_path, :status => 403) | ... | ... |
vendor/plugins/access_control/test/permission_check_test.rb
| ... | ... | @@ -28,9 +28,20 @@ class PermissionCheckTest < ActionController::TestCase |
| 28 | 28 | end |
| 29 | 29 | |
| 30 | 30 | def test_try_render_shared_access_denied_view |
| 31 | - File.expects(:exists?).with(File.join(Rails.root, 'app', 'views', 'access_control', 'access_denied.rhtml')) | |
| 32 | - File.expects(:exists?).with(File.join(Rails.root, 'app', 'views', 'shared', 'access_denied.rhtml')) | |
| 31 | + File.expects(:exists?).with(File.join(Rails.root, 'app', 'views', 'access_control', 'access_denied.html.erb')) | |
| 32 | + File.expects(:exists?).with(File.join(Rails.root, 'app', 'views', 'shared', 'access_denied.html.erb')) | |
| 33 | 33 | AccessControlTestController.access_denied_template_path |
| 34 | 34 | end |
| 35 | 35 | |
| 36 | + def test_allow_access_to_user_with_one_of_multiple_permissions | |
| 37 | + user = AccessControlTestAccessor.create!(:name => 'other_user') | |
| 38 | + role = Role.create!(:name => 'other_role', :permissions => ['permission1']) | |
| 39 | + resource = AccessControlTestResource.create!(:name => 'some_resource') | |
| 40 | + assert user.add_role(role, resource) | |
| 41 | + assert user.has_permission?('permission1', resource) | |
| 42 | + | |
| 43 | + get :stuff_with_multiple_permission, :user => user.id, :resource => resource.id | |
| 44 | + assert_response :success | |
| 45 | + end | |
| 46 | + | |
| 36 | 47 | end | ... | ... |
vendor/plugins/access_control/test/test_helper.rb
| ... | ... | @@ -41,6 +41,8 @@ class AccessControlTestController < ApplicationController |
| 41 | 41 | include PermissionCheck |
| 42 | 42 | protect 'see_index', 'global', :user, :only => :index |
| 43 | 43 | protect 'do_some_stuff', :resource, :user, :only => :other_stuff |
| 44 | + protect ['permission1', 'permission2'], :resource, :user, :only => :stuff_with_multiple_permission | |
| 45 | + | |
| 44 | 46 | def index |
| 45 | 47 | render :text => 'test controller' |
| 46 | 48 | end |
| ... | ... | @@ -49,6 +51,10 @@ class AccessControlTestController < ApplicationController |
| 49 | 51 | render :text => 'test stuff' |
| 50 | 52 | end |
| 51 | 53 | |
| 54 | + def stuff_with_multiple_permission | |
| 55 | + render :text => 'multiple permission' | |
| 56 | + end | |
| 57 | + | |
| 52 | 58 | protected |
| 53 | 59 | def user |
| 54 | 60 | AccessControlTestAccessor.find(params[:user]) if params[:user] | ... | ... |
vendor/plugins/delayed_job/lib/delayed/backend/base.rb
| ... | ... | @@ -73,9 +73,8 @@ module Delayed |
| 73 | 73 | ParseObjectFromYaml = /\!ruby\/\w+\:([^\s]+)/ |
| 74 | 74 | |
| 75 | 75 | def name |
| 76 | - @name ||= payload_object.respond_to?(:display_name) ? | |
| 77 | - payload_object.display_name : | |
| 78 | - payload_object.class.name | |
| 76 | + obj = payload_object | |
| 77 | + @name ||= obj.respond_to?(:display_name) ? obj.display_name : obj.class.name | |
| 79 | 78 | rescue DeserializationError |
| 80 | 79 | ParseObjectFromYaml.match(handler)[1] |
| 81 | 80 | end | ... | ... |
vendor/plugins/monkey_patches/rescue_delayed_job_crashes/init.rb
| ... | ... | @@ -1,57 +0,0 @@ |
| 1 | -Delayed::Worker.module_eval do | |
| 2 | - # based on https://groups.google.com/forum/#!topic/delayed_job/ZGMUFFppNgs | |
| 3 | - class Delayed::Worker::ExceptionNotification < ActionMailer::Base | |
| 4 | - def mail job, error | |
| 5 | - environment = Environment.default | |
| 6 | - | |
| 7 | - recipients NOOSFERO_CONF['exception_recipients'] | |
| 8 | - from environment.noreply_email | |
| 9 | - reply_to environment.noreply_email | |
| 10 | - subject "[#{environment.name}] DelayedJob ##{job.id}: #{error.message}" | |
| 11 | - body render(:text => " | |
| 12 | -Job: | |
| 13 | -#{job.inspect} | |
| 14 | - | |
| 15 | -Handler: | |
| 16 | -#{job.handler} | |
| 17 | - | |
| 18 | -Backtrace: | |
| 19 | -#{error.backtrace.join("\n")} | |
| 20 | - ") | |
| 21 | - end | |
| 22 | - end | |
| 23 | - | |
| 24 | - def handle_failed_job_with_notification(job, error) | |
| 25 | - Delayed::Worker::ExceptionNotification.deliver_mail job, error if NOOSFERO_CONF['exception_recipients'].present? | |
| 26 | - handle_failed_job_without_notification job, error | |
| 27 | - end | |
| 28 | - alias_method_chain :handle_failed_job, :notification | |
| 29 | - | |
| 30 | - def handle_failed_job_with_rescue(job, error) | |
| 31 | - handle_failed_job_without_rescue(job, error) | |
| 32 | - rescue => e # don't crash here | |
| 33 | - end | |
| 34 | - alias_method_chain :handle_failed_job, :rescue | |
| 35 | - | |
| 36 | - protected | |
| 37 | - | |
| 38 | - # This code must be replicated because there is no other way to pass the job | |
| 39 | - # through and use alias_method_chain as we used on the previous method | |
| 40 | - def reserve_and_run_one_job | |
| 41 | - # We get up to 5 jobs from the db. In case we cannot get exclusive access to a job we try the next. | |
| 42 | - # this leads to a more even distribution of jobs across the worker processes | |
| 43 | - job = Delayed::Job.find_available(name, 5, self.class.max_run_time).detect do |job| | |
| 44 | - if job.lock_exclusively!(self.class.max_run_time, name) | |
| 45 | - say "acquired lock on #{job.name}" | |
| 46 | - true | |
| 47 | - else | |
| 48 | - say "failed to acquire exclusive lock for #{job.name}", Logger::WARN | |
| 49 | - false | |
| 50 | - end | |
| 51 | - end | |
| 52 | - | |
| 53 | - run(job) if job | |
| 54 | - rescue => e | |
| 55 | - handle_failed_job(job, e) | |
| 56 | - end | |
| 57 | -end |