Commit 45e5189b55d3effe6b73b68fee7a0f5400b02185
Exists in
master
and in
22 other branches
Merge branch 'work-assignment' into features
Conflicts: db/schema.rb test/functional/cms_controller_test.rb test/unit/article_test.rb
Showing
27 changed files
with
482 additions
and
41 deletions
Show diff stats
app/controllers/my_profile/cms_controller.rb
| ... | ... | @@ -16,7 +16,12 @@ class CmsController < MyProfileController |
| 16 | 16 | |
| 17 | 17 | before_filter :login_required, :except => [:suggest_an_article] |
| 18 | 18 | |
| 19 | - protect_if :except => [:suggest_an_article, :set_home_page, :edit, :destroy, :publish] do |c, user, profile| | |
| 19 | + protect_if :only => :upload_files do |c, user, profile| | |
| 20 | + article_id = c.params[:parent_id] | |
| 21 | + profile.articles.find(article_id).allow_create?(user) | |
| 22 | + end | |
| 23 | + | |
| 24 | + protect_if :except => [:suggest_an_article, :set_home_page, :edit, :destroy, :publish, :upload_files] do |c, user, profile| | |
| 20 | 25 | user && (user.has_permission?('post_content', profile) || user.has_permission?('publish_content', profile)) |
| 21 | 26 | end |
| 22 | 27 | |
| ... | ... | @@ -92,7 +97,7 @@ class CmsController < MyProfileController |
| 92 | 97 | @article_types = [] |
| 93 | 98 | available_article_types.each do |type| |
| 94 | 99 | @article_types.push({ |
| 95 | - :name => type.name, | |
| 100 | + :class => type, | |
| 96 | 101 | :short_description => type.short_description, |
| 97 | 102 | :description => type.description |
| 98 | 103 | }) |
| ... | ... | @@ -117,6 +122,7 @@ class CmsController < MyProfileController |
| 117 | 122 | end |
| 118 | 123 | |
| 119 | 124 | @article.profile = profile |
| 125 | + @article.author = user | |
| 120 | 126 | @article.last_changed_by = user |
| 121 | 127 | |
| 122 | 128 | translations if @article.translatable? |
| ... | ... | @@ -154,7 +160,7 @@ class CmsController < MyProfileController |
| 154 | 160 | end |
| 155 | 161 | if request.post? && params[:uploaded_files] |
| 156 | 162 | params[:uploaded_files].each do |file| |
| 157 | - @uploaded_files << UploadedFile.create(:uploaded_data => file, :profile => profile, :parent => @parent) unless file == '' | |
| 163 | + @uploaded_files << UploadedFile.create(:uploaded_data => file, :profile => profile, :parent => @parent, :author => user) unless file == '' | |
| 158 | 164 | end |
| 159 | 165 | @errors = @uploaded_files.select { |f| f.errors.any? } |
| 160 | 166 | if @errors.any? | ... | ... |
app/helpers/folder_helper.rb
| ... | ... | @@ -52,8 +52,8 @@ module FolderHelper |
| 52 | 52 | end |
| 53 | 53 | end |
| 54 | 54 | |
| 55 | - def icon_for_new_article(type) | |
| 56 | - "icon-new icon-new%s" % type.constantize.icon_name | |
| 55 | + def icon_for_new_article(klass) | |
| 56 | + "icon-new icon-new%s" % klass.icon_name | |
| 57 | 57 | end |
| 58 | 58 | |
| 59 | 59 | def custom_options_for_article(article) | ... | ... |
app/models/article.rb
| ... | ... | @@ -13,6 +13,12 @@ class Article < ActiveRecord::Base |
| 13 | 13 | # xss_terminate plugin can't sanitize array fields |
| 14 | 14 | before_save :sanitize_tag_list |
| 15 | 15 | |
| 16 | + before_save do |article| | |
| 17 | + if article.author_id | |
| 18 | + article.author_name = Person.find(article.author_id).name | |
| 19 | + end | |
| 20 | + end | |
| 21 | + | |
| 16 | 22 | belongs_to :profile |
| 17 | 23 | validates_presence_of :profile_id, :name |
| 18 | 24 | validates_presence_of :slug, :path, :if => lambda { |article| !article.name.blank? } |
| ... | ... | @@ -20,6 +26,7 @@ class Article < ActiveRecord::Base |
| 20 | 26 | validates_uniqueness_of :slug, :scope => ['profile_id', 'parent_id'], :message => N_('The title (article name) is already being used by another article, please use another title.'), :if => lambda { |article| !article.slug.blank? } |
| 21 | 27 | |
| 22 | 28 | belongs_to :last_changed_by, :class_name => 'Person', :foreign_key => 'last_changed_by_id' |
| 29 | + belongs_to :author, :class_name => 'Person', :foreign_key => 'author_id' | |
| 23 | 30 | |
| 24 | 31 | has_many :comments, :class_name => 'Comment', :foreign_key => 'source_id', :dependent => :destroy, :order => 'created_at asc' |
| 25 | 32 | |
| ... | ... | @@ -289,7 +296,7 @@ class Article < ActiveRecord::Base |
| 289 | 296 | if last_comment |
| 290 | 297 | {:date => last_comment.created_at, :author_name => last_comment.author_name, :author_url => last_comment.author_url} |
| 291 | 298 | else |
| 292 | - {:date => updated_at, :author_name => author.name, :author_url => author.url} | |
| 299 | + {:date => updated_at, :author_name => author_name, :author_url => author ? author.url : nil} | |
| 293 | 300 | end |
| 294 | 301 | end |
| 295 | 302 | |
| ... | ... | @@ -441,7 +448,7 @@ class Article < ActiveRecord::Base |
| 441 | 448 | end |
| 442 | 449 | |
| 443 | 450 | def allow_post_content?(user = nil) |
| 444 | - user && (user.has_permission?('post_content', profile) || allow_publish_content?(user) && (user == self.creator)) | |
| 451 | + user && (user.has_permission?('post_content', profile) || allow_publish_content?(user) && (user == author)) | |
| 445 | 452 | end |
| 446 | 453 | |
| 447 | 454 | def allow_publish_content?(user = nil) |
| ... | ... | @@ -538,16 +545,8 @@ class Article < ActiveRecord::Base |
| 538 | 545 | false |
| 539 | 546 | end |
| 540 | 547 | |
| 541 | - def author | |
| 542 | - if reference_article | |
| 543 | - reference_article.author | |
| 544 | - else | |
| 545 | - last_changed_by || profile | |
| 546 | - end | |
| 547 | - end | |
| 548 | - | |
| 549 | 548 | def author_name |
| 550 | - setting[:author_name].blank? ? author.name : setting[:author_name] | |
| 549 | + author ? author.name : setting[:author_name] | |
| 551 | 550 | end |
| 552 | 551 | |
| 553 | 552 | alias :active_record_cache_key :cache_key |
| ... | ... | @@ -572,11 +571,6 @@ class Article < ActiveRecord::Base |
| 572 | 571 | truncate sanitize_html(self.lead), :length => 170, :omission => '...' |
| 573 | 572 | end |
| 574 | 573 | |
| 575 | - def creator | |
| 576 | - creator_id = versions[0][:last_changed_by_id] | |
| 577 | - creator_id && Profile.find(creator_id) | |
| 578 | - end | |
| 579 | - | |
| 580 | 574 | def notifiable? |
| 581 | 575 | false |
| 582 | 576 | end | ... | ... |
app/models/event.rb
| ... | ... | @@ -38,7 +38,7 @@ class Event < Article |
| 38 | 38 | filter_iframes :body, :link, :address, :whitelist => lambda { profile && profile.environment && profile.environment.trusted_sites_for_iframe } |
| 39 | 39 | |
| 40 | 40 | def self.description |
| 41 | - _('A calendar event') | |
| 41 | + _('A calendar event.') | |
| 42 | 42 | end |
| 43 | 43 | |
| 44 | 44 | def self.short_description | ... | ... |
app/models/person.rb
| ... | ... | @@ -54,6 +54,8 @@ class Person < Profile |
| 54 | 54 | |
| 55 | 55 | has_many :scraps_sent, :class_name => 'Scrap', :foreign_key => :sender_id, :dependent => :destroy |
| 56 | 56 | |
| 57 | + has_many :creations, :class_name => 'Article', :foreign_key => :author_id | |
| 58 | + | |
| 57 | 59 | named_scope :more_popular, |
| 58 | 60 | :select => "#{Profile.qualified_column_names}, count(friend_id) as total", |
| 59 | 61 | :group => Profile.qualified_column_names, | ... | ... |
app/models/raw_html_article.rb
| ... | ... | @@ -5,11 +5,11 @@ class RawHTMLArticle < TextArticle |
| 5 | 5 | end |
| 6 | 6 | |
| 7 | 7 | def self.short_description |
| 8 | - _('Raw HTML text article.') | |
| 8 | + _('Raw HTML text article') | |
| 9 | 9 | end |
| 10 | 10 | |
| 11 | 11 | def self.description |
| 12 | - _('Allows HTML without filter (only for admins)') | |
| 12 | + _('Allows HTML without filter (only for admins).') | |
| 13 | 13 | end |
| 14 | 14 | |
| 15 | 15 | xss_terminate :only => [ ] | ... | ... |
app/models/tiny_mce_article.rb
app/views/cms/select_article_type.rhtml
| ... | ... | @@ -2,9 +2,9 @@ |
| 2 | 2 | |
| 3 | 3 | <ul id="article_types"> |
| 4 | 4 | <% for type in @article_types %> |
| 5 | - <% action = type[:name] == 'UploadedFile' ? {:action => 'upload_files'} : {:action => 'new', :type => type[:name]} %> | |
| 5 | + <% action = type[:class].name == 'UploadedFile' ? {:action => 'upload_files'} : {:action => 'new', :type => type[:class].name} %> | |
| 6 | 6 | <% content_tag('a', :href => url_for(action.merge(:parent_id => @parent_id, :back_to => @back_to))) do %> |
| 7 | - <li class="<%= icon_for_new_article(type[:name]) %>" onmouseover="javascript: jQuery(this).addClass('mouseover')" onmouseout="jQuery(this).removeClass('mouseover')"> | |
| 7 | + <li class="<%= icon_for_new_article(type[:class]) %>" onmouseover="javascript: jQuery(this).addClass('mouseover')" onmouseout="jQuery(this).removeClass('mouseover')"> | |
| 8 | 8 | <strong><%= type[:short_description] %></strong> |
| 9 | 9 | <div class='description'><%= type[:description] %></div> |
| 10 | 10 | </li> | ... | ... |
app/views/content_viewer/_article_toolbar.rhtml
| ... | ... | @@ -34,11 +34,11 @@ |
| 34 | 34 | <%= expirable_button @page, :locale, content, url %> |
| 35 | 35 | <% end %> |
| 36 | 36 | |
| 37 | - <%= colorbox_button(:new, label_for_new_article(@page), profile.admin_url.merge(:controller => 'cms', :action => 'new', :parent_id => (@page.folder? ? @page : (@page.parent.nil? ? nil : @page.parent)))) %> | |
| 37 | + <%= colorbox_button(:new, label_for_new_article(@page), profile.admin_url.merge(:controller => 'cms', :action => 'new', :parent_id => (@page.folder? ? @page : (@page.parent.nil? ? nil : @page.parent)))) if !remove_content_button(:new) %> | |
| 38 | 38 | <% end %> |
| 39 | 39 | |
| 40 | 40 | <% if @page.accept_uploads? && @page.allow_create?(user) %> |
| 41 | - <%= button('upload-file', _('Upload files'), profile.admin_url.merge(:controller => 'cms', :action => 'upload_files', :parent_id => (@page.folder? ? @page : @page.parent))) %> | |
| 41 | + <%= button('upload-file', _('Upload files'), profile.admin_url.merge(:controller => 'cms', :action => 'upload_files', :parent_id => (@page.folder? ? @page : @page.parent))) if !remove_content_button(:upload)%> | |
| 42 | 42 | <% end %> |
| 43 | 43 | |
| 44 | 44 | <% if !@page.allow_create?(user) && profile.community? && (@page.blog? || @page.parent && @page.parent.blog?) && !remove_content_button(:suggest) %> | ... | ... |
| ... | ... | @@ -0,0 +1,11 @@ |
| 1 | +class AddAuthorIdToArticle < ActiveRecord::Migration | |
| 2 | + def self.up | |
| 3 | + add_column :articles, :author_id, :integer | |
| 4 | + add_column :article_versions, :author_id, :integer | |
| 5 | + end | |
| 6 | + | |
| 7 | + def self.down | |
| 8 | + remove_column :articles, :author_id | |
| 9 | + remove_column :article_versions, :author_id, :integer | |
| 10 | + end | |
| 11 | +end | ... | ... |
db/migrate/20121024222938_set_authors_based_on_article_versions.rb
0 → 100644
| ... | ... | @@ -0,0 +1,9 @@ |
| 1 | +class SetAuthorsBasedOnArticleVersions < ActiveRecord::Migration | |
| 2 | + def self.up | |
| 3 | + update('UPDATE articles SET author_id = (SELECT profiles.id FROM articles as a INNER JOIN article_versions ON a.id = article_versions.article_id INNER JOIN profiles ON profiles.id = article_versions.last_changed_by_id WHERE article_versions.version = 1 AND articles.id = a.id)') | |
| 4 | + end | |
| 5 | + | |
| 6 | + def self.down | |
| 7 | + say "Can not be revesed!" | |
| 8 | + end | |
| 9 | +end | ... | ... |
db/schema.rb
| ... | ... | @@ -9,7 +9,7 @@ |
| 9 | 9 | # |
| 10 | 10 | # It's strongly recommended to check this file into your version control system. |
| 11 | 11 | |
| 12 | -ActiveRecord::Schema.define(:version => 20121008185303) do | |
| 12 | +ActiveRecord::Schema.define(:version => 20121024222938) do | |
| 13 | 13 | |
| 14 | 14 | create_table "abuse_reports", :force => true do |t| |
| 15 | 15 | t.integer "reporter_id" |
| ... | ... | @@ -86,6 +86,7 @@ ActiveRecord::Schema.define(:version => 20121008185303) do |
| 86 | 86 | t.string "language" |
| 87 | 87 | t.string "source_name" |
| 88 | 88 | t.integer "license_id" |
| 89 | + t.integer "author_id" | |
| 89 | 90 | end |
| 90 | 91 | |
| 91 | 92 | create_table "articles", :force => true do |t| |
| ... | ... | @@ -127,6 +128,7 @@ ActiveRecord::Schema.define(:version => 20121008185303) do |
| 127 | 128 | t.string "language" |
| 128 | 129 | t.string "source_name" |
| 129 | 130 | t.integer "license_id" |
| 131 | + t.integer "author_id" | |
| 130 | 132 | end |
| 131 | 133 | |
| 132 | 134 | add_index "articles", ["translation_of_id"], :name => "index_articles_on_translation_of_id" | ... | ... |
lib/noosfero/plugin.rb
| ... | ... | @@ -130,7 +130,7 @@ class Noosfero::Plugin |
| 130 | 130 | end |
| 131 | 131 | |
| 132 | 132 | # -> Adds plugin-specific content types to CMS |
| 133 | - # returns = { content type class } | |
| 133 | + # returns = [ContentClass1, ContentClass2, ...] | |
| 134 | 134 | def content_types |
| 135 | 135 | nil |
| 136 | 136 | end |
| ... | ... | @@ -384,7 +384,9 @@ class Noosfero::Plugin |
| 384 | 384 | private |
| 385 | 385 | |
| 386 | 386 | def content_actions |
| 387 | - %w[edit delete spread locale suggest home] | |
| 387 | + #FIXME 'new' and 'upload' only works for content_remove. It should work for | |
| 388 | + #content_expire too. | |
| 389 | + %w[edit delete spread locale suggest home new upload] | |
| 388 | 390 | end |
| 389 | 391 | |
| 390 | 392 | end | ... | ... |
| ... | ... | @@ -0,0 +1,52 @@ |
| 1 | +class WorkAssignmentPlugin < Noosfero::Plugin | |
| 2 | + | |
| 3 | + def self.plugin_name | |
| 4 | + "Work Assignment" | |
| 5 | + end | |
| 6 | + | |
| 7 | + def self.plugin_description | |
| 8 | + _("New kind of content for organizations.") | |
| 9 | + end | |
| 10 | + | |
| 11 | + def self.can_download_submission?(user, submission) | |
| 12 | + work_assignment = submission.parent.parent | |
| 13 | + work_assignment.publish_submissions || (user && (submission.author == user || user.has_permission?('view_private_content', work_assignment.profile))) | |
| 14 | + end | |
| 15 | + | |
| 16 | + def self.is_submission?(content) | |
| 17 | + content && content.parent && content.parent.parent && content.parent.parent.kind_of?(WorkAssignmentPlugin::WorkAssignment) | |
| 18 | + end | |
| 19 | + | |
| 20 | + def content_types | |
| 21 | + [WorkAssignmentPlugin::WorkAssignment] if context.profile.organization? | |
| 22 | + end | |
| 23 | + | |
| 24 | + def stylesheet? | |
| 25 | + true | |
| 26 | + end | |
| 27 | + | |
| 28 | + def content_remove_new(content) | |
| 29 | + content.kind_of?(WorkAssignmentPlugin::WorkAssignment) | |
| 30 | + end | |
| 31 | + | |
| 32 | + def content_remove_upload(content) | |
| 33 | + !content.profile.members.include?(context.send(:user)) | |
| 34 | + end | |
| 35 | + | |
| 36 | + def content_viewer_controller_filters | |
| 37 | + block = lambda do | |
| 38 | + path = params[:page].join('/') | |
| 39 | + content = profile.articles.find_by_path(path) | |
| 40 | + | |
| 41 | + if WorkAssignmentPlugin.is_submission?(content) && !WorkAssignmentPlugin.can_download_submission?(user, content) | |
| 42 | + render_access_denied | |
| 43 | + end | |
| 44 | + end | |
| 45 | + | |
| 46 | + { :type => 'before_filter', | |
| 47 | + :method_name => 'work_assingment_only_admin_or_owner_download', | |
| 48 | + :options => {:only => 'view_page'}, | |
| 49 | + :block => block } | |
| 50 | + end | |
| 51 | + | |
| 52 | +end | ... | ... |
plugins/work_assignment/lib/work_assignment_plugin/helper.rb
0 → 100644
| ... | ... | @@ -0,0 +1,59 @@ |
| 1 | +module WorkAssignmentPlugin::Helper | |
| 2 | + def display_submissions(work_assignment, user) | |
| 3 | + return if work_assignment.submissions.empty? | |
| 4 | + content_tag('table', | |
| 5 | + content_tag('tr', | |
| 6 | + content_tag('th', _('Author'), :style => 'width: 50%') + | |
| 7 | + content_tag('th', _('Submission date')) + | |
| 8 | + content_tag('th', _('Versions'), :style => 'text-align: center') + | |
| 9 | + content_tag('th', '') | |
| 10 | + ) + | |
| 11 | + work_assignment.children.map {|author_folder| display_author_folder(author_folder, user)}.join("\n") | |
| 12 | + ) | |
| 13 | + end | |
| 14 | + | |
| 15 | + def display_author_folder(author_folder, user) | |
| 16 | + return if author_folder.children.empty? | |
| 17 | + content_tag('tr', | |
| 18 | + content_tag('td', link_to_last_submission(author_folder, user)) + | |
| 19 | + content_tag('td', time_format(author_folder.children.last.created_at)) + | |
| 20 | + content_tag('td', author_folder.children.count, :style => 'text-align: center') + | |
| 21 | + content_tag('td', content_tag('button', _('View all versions'), :class => 'view-author-versions', 'data-folder-id' => author_folder.id)) | |
| 22 | + ) + | |
| 23 | + author_folder.children.map {|submission| display_submission(submission, user)}.join("\n") | |
| 24 | + end | |
| 25 | + | |
| 26 | + def display_submission(submission, user) | |
| 27 | + content_tag('tr', | |
| 28 | + content_tag('td', link_to_submission(submission, user)) + | |
| 29 | + content_tag('td', time_format(submission.created_at), :colspan => 3), | |
| 30 | + :class => "submission-from-#{submission.parent.id}", | |
| 31 | + :style => 'display: none' | |
| 32 | + ) | |
| 33 | + end | |
| 34 | + | |
| 35 | + def link_to_submission(submission, user) | |
| 36 | + if WorkAssignmentPlugin.can_download_submission?(user, submission) | |
| 37 | + link_to(submission.name, submission.url) | |
| 38 | + else | |
| 39 | + submission.name | |
| 40 | + end | |
| 41 | + end | |
| 42 | + | |
| 43 | + | |
| 44 | + def link_to_last_submission(author_folder, user) | |
| 45 | + if WorkAssignmentPlugin.can_download_submission?(user, author_folder.children.last) | |
| 46 | + link_to(author_folder.name, author_folder.children.last.url) | |
| 47 | + else | |
| 48 | + author_folder.name | |
| 49 | + end | |
| 50 | + end | |
| 51 | + # FIXME Copied from custom-froms. Consider passing it to core... | |
| 52 | + def time_format(time) | |
| 53 | + minutes = (time.min == 0) ? '' : ':%M' | |
| 54 | + hour = (time.hour == 0 && minutes.blank?) ? '' : ' %H' | |
| 55 | + h = hour.blank? ? '' : 'h' | |
| 56 | + time.strftime("%Y-%m-%d#{hour+minutes+h}") | |
| 57 | + end | |
| 58 | + | |
| 59 | +end | ... | ... |
plugins/work_assignment/lib/work_assignment_plugin/work_assignment.rb
0 → 100644
| ... | ... | @@ -0,0 +1,52 @@ |
| 1 | +class WorkAssignmentPlugin::WorkAssignment < Folder | |
| 2 | + | |
| 3 | + after_save do |work_assignment| | |
| 4 | + work_assignment.children.select {|child| child.kind_of?(UploadedFile)}.each do |submission| | |
| 5 | + author_folder = work_assignment.find_or_create_author_folder(submission.author) | |
| 6 | + submission.name = versioned_name(submission, author_folder) if !(submission.name =~ /\(V[0-9]*\)/) | |
| 7 | + submission.parent = author_folder | |
| 8 | + submission.save! | |
| 9 | + end | |
| 10 | + end | |
| 11 | + | |
| 12 | + settings_items :publish_submissions, :type => :boolean, :default => false | |
| 13 | + | |
| 14 | + def self.icon_name(article = nil) | |
| 15 | + 'work-assignment' | |
| 16 | + end | |
| 17 | + | |
| 18 | + def self.short_description | |
| 19 | + _('Work Assignment') | |
| 20 | + end | |
| 21 | + | |
| 22 | + def self.description | |
| 23 | + _('Defines a work to be done by the members and receives their submissions about this work.') | |
| 24 | + end | |
| 25 | + | |
| 26 | + def self.versioned_name(submission, folder) | |
| 27 | + "(V#{folder.children.count + 1}) #{submission.name}" | |
| 28 | + end | |
| 29 | + | |
| 30 | + def accept_comments? | |
| 31 | + true | |
| 32 | + end | |
| 33 | + | |
| 34 | + def allow_create?(user) | |
| 35 | + profile.members.include?(user) | |
| 36 | + end | |
| 37 | + | |
| 38 | + def to_html(options = {}) | |
| 39 | + lambda do | |
| 40 | + render :file => 'content_viewer/work_assignment.html.erb' | |
| 41 | + end | |
| 42 | + end | |
| 43 | + | |
| 44 | + def find_or_create_author_folder(author) | |
| 45 | + children.find_by_slug(author.identifier) || Folder.create!(:name => author.name, :slug => author.identifier, :parent => self, :profile => profile) | |
| 46 | + end | |
| 47 | + | |
| 48 | + def submissions | |
| 49 | + children.map(&:children).flatten.compact | |
| 50 | + end | |
| 51 | + | |
| 52 | +end | ... | ... |
| ... | ... | @@ -0,0 +1,16 @@ |
| 1 | +jQuery(".view-author-versions").each(function(index, bt){ | |
| 2 | + jQuery(bt).button({ | |
| 3 | + icons: { | |
| 4 | + primary: "ui-icon-info" | |
| 5 | + }, | |
| 6 | + text: false | |
| 7 | + }); | |
| 8 | + bt.onclick = function(){ | |
| 9 | + var folderId = this.getAttribute("data-folder-id"); | |
| 10 | + var tr = jQuery(".submission-from-"+folderId); | |
| 11 | + if ( tr[0].style.display == "none" ) | |
| 12 | + tr.show(); | |
| 13 | + else | |
| 14 | + tr.hide(); | |
| 15 | + } | |
| 16 | +}); | ... | ... |
plugins/work_assignment/test/functional/cms_controller_test.rb
0 → 100644
| ... | ... | @@ -0,0 +1,34 @@ |
| 1 | +require 'test_helper' | |
| 2 | +require 'cms_controller' | |
| 3 | + | |
| 4 | +# Re-raise errors caught by the controller. | |
| 5 | +class CmsController; def rescue_action(e) raise e end; end | |
| 6 | + | |
| 7 | +class CmsControllerTest < ActionController::TestCase | |
| 8 | + | |
| 9 | + def setup | |
| 10 | + @controller = CmsController.new | |
| 11 | + @request = ActionController::TestRequest.new | |
| 12 | + @response = ActionController::TestResponse.new | |
| 13 | + @person = create_user('test_user').person | |
| 14 | + login_as :test_user | |
| 15 | + end | |
| 16 | + | |
| 17 | + attr_accessor :person | |
| 18 | + | |
| 19 | + should 'not allow non-members to upload submissions on work_assignment' do | |
| 20 | + organization = fast_create(Organization) | |
| 21 | + work_assignment = WorkAssignmentPlugin::WorkAssignment.create!(:name => 'Work Assignment', :profile => organization) | |
| 22 | + | |
| 23 | + get :upload_files, :profile => organization.identifier, :parent_id => work_assignment.id | |
| 24 | + assert_response :forbidden | |
| 25 | + assert_template 'access_denied.rhtml' | |
| 26 | + | |
| 27 | + organization.add_member(person) | |
| 28 | + | |
| 29 | + get :upload_files, :profile => organization.identifier, :parent_id => work_assignment.id | |
| 30 | + assert_response :success | |
| 31 | + end | |
| 32 | + | |
| 33 | +end | |
| 34 | + | ... | ... |
plugins/work_assignment/test/functional/content_viewer_controller_test.rb
0 → 100644
| ... | ... | @@ -0,0 +1,41 @@ |
| 1 | +require 'test_helper' | |
| 2 | +require 'content_viewer_controller' | |
| 3 | + | |
| 4 | +# Re-raise errors caught by the controller. | |
| 5 | +class ContentViewerController; def rescue_action(e) raise e end; end | |
| 6 | + | |
| 7 | +class ContentViewerControllerTest < ActionController::TestCase | |
| 8 | + | |
| 9 | + def setup | |
| 10 | + @controller = ContentViewerController.new | |
| 11 | + @request = ActionController::TestRequest.new | |
| 12 | + @response = ActionController::TestResponse.new | |
| 13 | + | |
| 14 | + @organization = fast_create(Organization) | |
| 15 | + @work_assignment = WorkAssignmentPlugin::WorkAssignment.create!(:name => 'Work Assignment', :profile => @organization) | |
| 16 | + @person = create_user('test_user').person | |
| 17 | + @environment = @organization.environment | |
| 18 | + @environment.enable_plugin(WorkAssignmentPlugin) | |
| 19 | + @environment.save! | |
| 20 | + login_as(:test_user) | |
| 21 | + end | |
| 22 | + attr_reader :organization, :person, :work_assignment | |
| 23 | + | |
| 24 | + should 'can download work_assignment' do | |
| 25 | + random_member = fast_create(Person) | |
| 26 | + organization.add_member(random_member) | |
| 27 | + folder = work_assignment.find_or_create_author_folder(random_member) | |
| 28 | + submission = UploadedFile.create!(:uploaded_data => fixture_file_upload('/files/rails.png', 'image/png'), :profile => organization, :parent => folder) | |
| 29 | + WorkAssignmentPlugin.stubs(:can_download_submission?).returns(false) | |
| 30 | + | |
| 31 | + get :view_page, :profile => organization.identifier, :page => submission.explode_path | |
| 32 | + assert_response :forbidden | |
| 33 | + assert_template 'access_denied.rhtml' | |
| 34 | + | |
| 35 | + WorkAssignmentPlugin.stubs(:can_download_submission?).returns(true) | |
| 36 | + | |
| 37 | + get :view_page, :profile => organization.identifier, :page => submission.explode_path | |
| 38 | + assert_response :success | |
| 39 | + end | |
| 40 | + | |
| 41 | +end | ... | ... |
plugins/work_assignment/test/unit/work_assingment_plugin/work_assignment_test.rb
0 → 100644
| ... | ... | @@ -0,0 +1,43 @@ |
| 1 | +require "test_helper" | |
| 2 | + | |
| 3 | +class WorkAssignmentTest < ActiveSupport::TestCase | |
| 4 | + should 'find or create sub-folder based on author identifier' do | |
| 5 | + profile = fast_create(Profile) | |
| 6 | + author = fast_create(Person) | |
| 7 | + work_assignment = WorkAssignmentPlugin::WorkAssignment.create!(:name => 'Sample Work Assignment', :profile => profile) | |
| 8 | + assert_nil work_assignment.children.find_by_slug(author.identifier) | |
| 9 | + | |
| 10 | + folder = work_assignment.find_or_create_author_folder(author) | |
| 11 | + assert_not_nil work_assignment.children.find_by_slug(author.identifier) | |
| 12 | + assert_equal folder, work_assignment.find_or_create_author_folder(author) | |
| 13 | + end | |
| 14 | + | |
| 15 | + should 'return versioned name' do | |
| 16 | + folder = fast_create(Folder) | |
| 17 | + profile = fast_create(Profile) | |
| 18 | + a1 = Article.create!(:name => "Article 1", :profile => profile) | |
| 19 | + a2 = Article.create!(:name => "Article 2", :profile => profile) | |
| 20 | + a3 = Article.create!(:name => "Article 3", :profile => profile) | |
| 21 | + klass = WorkAssignmentPlugin::WorkAssignment | |
| 22 | + | |
| 23 | + assert_equal "(V1) #{a1.name}", klass.versioned_name(a1, folder) | |
| 24 | + | |
| 25 | + a1.parent = folder | |
| 26 | + a1.save! | |
| 27 | + assert_equal "(V2) #{a2.name}", klass.versioned_name(a2, folder) | |
| 28 | + | |
| 29 | + a2.parent = folder | |
| 30 | + a2.save! | |
| 31 | + assert_equal "(V3) #{a3.name}", klass.versioned_name(a3, folder) | |
| 32 | + end | |
| 33 | + | |
| 34 | + should 'move submission to its correct author folder' do | |
| 35 | + organization = fast_create(Organization) | |
| 36 | + author = fast_create(Person) | |
| 37 | + work_assignment = WorkAssignmentPlugin::WorkAssignment.create!(:name => 'Sample Work Assignment', :profile => organization) | |
| 38 | + submission = UploadedFile.create!(:uploaded_data => fixture_file_upload('/files/rails.png', 'image/png'), :profile => organization, :parent => work_assignment, :author => author) | |
| 39 | + | |
| 40 | + author_folder = work_assignment.find_or_create_author_folder(author) | |
| 41 | + assert author_folder, submission.parent | |
| 42 | + end | |
| 43 | +end | ... | ... |
plugins/work_assignment/test/unit/work_assingment_plugin_test.rb
0 → 100644
| ... | ... | @@ -0,0 +1,57 @@ |
| 1 | +require 'test_helper' | |
| 2 | + | |
| 3 | +class WorkAssignmentPluginTest < ActiveSupport::TestCase | |
| 4 | + should 'verify if a content is a work_assignment submission' do | |
| 5 | + organization = fast_create(Organization) | |
| 6 | + content = UploadedFile.create!(:uploaded_data => fixture_file_upload('/files/rails.png', 'image/png'), :profile => organization) | |
| 7 | + assert !WorkAssignmentPlugin.is_submission?(content) | |
| 8 | + | |
| 9 | + work_assignment = WorkAssignmentPlugin::WorkAssignment.create!(:name => 'Work Assignment', :profile => organization) | |
| 10 | + content.parent = work_assignment | |
| 11 | + content.save! | |
| 12 | + assert !WorkAssignmentPlugin.is_submission?(content) | |
| 13 | + | |
| 14 | + author_folder = work_assignment.find_or_create_author_folder(fast_create(Person)) | |
| 15 | + content.parent = author_folder | |
| 16 | + content.save! | |
| 17 | + assert WorkAssignmentPlugin.is_submission?(content) | |
| 18 | + end | |
| 19 | + | |
| 20 | + should 'be able to download submission if work_assignment published submissions' do | |
| 21 | + submission = create_submission | |
| 22 | + assert !WorkAssignmentPlugin.can_download_submission?(nil, submission) | |
| 23 | + | |
| 24 | + work_assignment = submission.parent.parent | |
| 25 | + work_assignment.publish_submissions = true | |
| 26 | + work_assignment.save! | |
| 27 | + assert WorkAssignmentPlugin.can_download_submission?(nil, submission) | |
| 28 | + end | |
| 29 | + | |
| 30 | + should 'be able to download submission if the user is author of it' do | |
| 31 | + person = fast_create(Person) | |
| 32 | + submission = create_submission | |
| 33 | + assert !WorkAssignmentPlugin.can_download_submission?(person, submission) | |
| 34 | + | |
| 35 | + submission.author = person | |
| 36 | + submission.save! | |
| 37 | + assert WorkAssignmentPlugin.can_download_submission?(person, submission) | |
| 38 | + end | |
| 39 | + | |
| 40 | + should 'be able to download submission if the user has the view_private_content permission on the profile' do | |
| 41 | + person = fast_create(Person) | |
| 42 | + submission = create_submission | |
| 43 | + assert !WorkAssignmentPlugin.can_download_submission?(person, submission) | |
| 44 | + | |
| 45 | + moderator = create_user_with_permission('moderator', 'view_private_content', submission.profile) | |
| 46 | + assert WorkAssignmentPlugin.can_download_submission?(moderator, submission) | |
| 47 | + end | |
| 48 | + | |
| 49 | + private | |
| 50 | + | |
| 51 | + def create_submission | |
| 52 | + organization = fast_create(Organization) | |
| 53 | + work_assignment = WorkAssignmentPlugin::WorkAssignment.create!(:name => 'Work Assignment', :profile => organization) | |
| 54 | + author_folder = work_assignment.find_or_create_author_folder(fast_create(Person)) | |
| 55 | + UploadedFile.create!(:uploaded_data => fixture_file_upload('/files/rails.png', 'image/png'), :profile => organization, :parent => author_folder) | |
| 56 | + end | |
| 57 | +end | ... | ... |
plugins/work_assignment/views/cms/work_assignment_plugin/_work_assignment.html.erb
0 → 100644
plugins/work_assignment/views/content_viewer/work_assignment.html.erb
0 → 100644
test/functional/cms_controller_test.rb
| ... | ... | @@ -1583,6 +1583,28 @@ class CmsControllerTest < ActionController::TestCase |
| 1583 | 1583 | assert_equal f2, article.parent |
| 1584 | 1584 | end |
| 1585 | 1585 | |
| 1586 | + should 'set author when creating article' do | |
| 1587 | + login_as(profile.identifier) | |
| 1588 | + | |
| 1589 | + post :new, :type => 'TinyMceArticle', :profile => profile.identifier, :article => { :name => 'Sample Article', :body => 'content ...' } | |
| 1590 | + | |
| 1591 | + a = profile.articles.find_by_path('sample-article') | |
| 1592 | + assert_not_nil a | |
| 1593 | + assert_equal profile, a.author | |
| 1594 | + end | |
| 1595 | + | |
| 1596 | + should 'not allow user upload files if he can not create on the parent folder' do | |
| 1597 | + c = Community.create!(:name => 'test_comm', :identifier => 'test_comm') | |
| 1598 | + u = create_user('test_user') | |
| 1599 | + a = c.articles.create!(:name => 'test_article') | |
| 1600 | + a.stubs(:allow_create?).with(u).returns(true) | |
| 1601 | + login_as :test_user | |
| 1602 | + | |
| 1603 | + get :upload_files, :profile => c.identifier, :parent_id => a.id | |
| 1604 | + assert_response :forbidden | |
| 1605 | + assert_template 'access_denied.rhtml' | |
| 1606 | + end | |
| 1607 | + | |
| 1586 | 1608 | protected |
| 1587 | 1609 | |
| 1588 | 1610 | # FIXME this is to avoid adding an extra dependency for a proper JSON parser. | ... | ... |
test/unit/article_test.rb
| ... | ... | @@ -708,14 +708,6 @@ class ArticleTest < ActiveSupport::TestCase |
| 708 | 708 | assert_equal a.url, a.view_url |
| 709 | 709 | end |
| 710 | 710 | |
| 711 | - should 'know its author' do | |
| 712 | - assert_equal profile, Article.new(:last_changed_by => profile).author | |
| 713 | - end | |
| 714 | - | |
| 715 | - should 'use owning profile as author when we dont know who did the last change' do | |
| 716 | - assert_equal profile, Article.new(:last_changed_by => nil, :profile => profile).author | |
| 717 | - end | |
| 718 | - | |
| 719 | 711 | should 'have published_at' do |
| 720 | 712 | assert_respond_to Article.new, :published_at |
| 721 | 713 | end |
| ... | ... | @@ -1372,7 +1364,7 @@ class ArticleTest < ActiveSupport::TestCase |
| 1372 | 1364 | assert Article.method_defined?('author_name') |
| 1373 | 1365 | end |
| 1374 | 1366 | |
| 1375 | - should "the author_name returns the name od the article's author" do | |
| 1367 | + should "the author_name returns the name of the article's author" do | |
| 1376 | 1368 | author = mock() |
| 1377 | 1369 | author.expects(:name).returns('author name') |
| 1378 | 1370 | a = Article.new |
| ... | ... | @@ -1818,4 +1810,25 @@ class ArticleTest < ActiveSupport::TestCase |
| 1818 | 1810 | assert a1.errors.invalid?(:parent_id) |
| 1819 | 1811 | end |
| 1820 | 1812 | |
| 1813 | + should 'be able to have an author' do | |
| 1814 | + author = fast_create(Person) | |
| 1815 | + article = Article.new | |
| 1816 | + assert_nothing_raised do | |
| 1817 | + article.author = author | |
| 1818 | + end | |
| 1819 | + end | |
| 1820 | + | |
| 1821 | + should 'set author_name before saving article if there is an author' do | |
| 1822 | + author = fast_create(Person) | |
| 1823 | + article = fast_create(Article, :profile_id => fast_create(Profile).id) | |
| 1824 | + article.author = author | |
| 1825 | + article.save! | |
| 1826 | + assert_equal author.name, article.author_name | |
| 1827 | + | |
| 1828 | + author_name = author.name | |
| 1829 | + author.destroy | |
| 1830 | + article.reload | |
| 1831 | + assert_equal author_name, article.author_name | |
| 1832 | + end | |
| 1833 | + | |
| 1821 | 1834 | end | ... | ... |
test/unit/person_test.rb
| ... | ... | @@ -1262,4 +1262,15 @@ class PersonTest < ActiveSupport::TestCase |
| 1262 | 1262 | |
| 1263 | 1263 | assert person.has_permission?('bli', Profile.new) |
| 1264 | 1264 | end |
| 1265 | + | |
| 1266 | + should 'have creations' do | |
| 1267 | + person = create_user('some-user').person | |
| 1268 | + a1 = fast_create(Article, :author_id => person.id) | |
| 1269 | + a2 = fast_create(Article, :author_id => person.id) | |
| 1270 | + a3 = fast_create(Article) | |
| 1271 | + | |
| 1272 | + assert_includes person.creations, a1 | |
| 1273 | + assert_includes person.creations, a2 | |
| 1274 | + assert_not_includes person.creations, a3 | |
| 1275 | + end | |
| 1265 | 1276 | end | ... | ... |