Commit 45e5189b55d3effe6b73b68fee7a0f5400b02185

Authored by Rodrigo Souto
2 parents 56e1b119 7358e1d0

Merge branch 'work-assignment' into features

Conflicts:
	db/schema.rb
	test/functional/cms_controller_test.rb
	test/unit/article_test.rb
app/controllers/my_profile/cms_controller.rb
@@ -16,7 +16,12 @@ class CmsController < MyProfileController @@ -16,7 +16,12 @@ class CmsController < MyProfileController
16 16
17 before_filter :login_required, :except => [:suggest_an_article] 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 user && (user.has_permission?('post_content', profile) || user.has_permission?('publish_content', profile)) 25 user && (user.has_permission?('post_content', profile) || user.has_permission?('publish_content', profile))
21 end 26 end
22 27
@@ -92,7 +97,7 @@ class CmsController < MyProfileController @@ -92,7 +97,7 @@ class CmsController < MyProfileController
92 @article_types = [] 97 @article_types = []
93 available_article_types.each do |type| 98 available_article_types.each do |type|
94 @article_types.push({ 99 @article_types.push({
95 - :name => type.name, 100 + :class => type,
96 :short_description => type.short_description, 101 :short_description => type.short_description,
97 :description => type.description 102 :description => type.description
98 }) 103 })
@@ -117,6 +122,7 @@ class CmsController < MyProfileController @@ -117,6 +122,7 @@ class CmsController < MyProfileController
117 end 122 end
118 123
119 @article.profile = profile 124 @article.profile = profile
  125 + @article.author = user
120 @article.last_changed_by = user 126 @article.last_changed_by = user
121 127
122 translations if @article.translatable? 128 translations if @article.translatable?
@@ -154,7 +160,7 @@ class CmsController < MyProfileController @@ -154,7 +160,7 @@ class CmsController < MyProfileController
154 end 160 end
155 if request.post? && params[:uploaded_files] 161 if request.post? && params[:uploaded_files]
156 params[:uploaded_files].each do |file| 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 end 164 end
159 @errors = @uploaded_files.select { |f| f.errors.any? } 165 @errors = @uploaded_files.select { |f| f.errors.any? }
160 if @errors.any? 166 if @errors.any?
app/helpers/folder_helper.rb
@@ -52,8 +52,8 @@ module FolderHelper @@ -52,8 +52,8 @@ module FolderHelper
52 end 52 end
53 end 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 end 57 end
58 58
59 def custom_options_for_article(article) 59 def custom_options_for_article(article)
app/models/article.rb
@@ -13,6 +13,12 @@ class Article &lt; ActiveRecord::Base @@ -13,6 +13,12 @@ class Article &lt; ActiveRecord::Base
13 # xss_terminate plugin can't sanitize array fields 13 # xss_terminate plugin can't sanitize array fields
14 before_save :sanitize_tag_list 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 belongs_to :profile 22 belongs_to :profile
17 validates_presence_of :profile_id, :name 23 validates_presence_of :profile_id, :name
18 validates_presence_of :slug, :path, :if => lambda { |article| !article.name.blank? } 24 validates_presence_of :slug, :path, :if => lambda { |article| !article.name.blank? }
@@ -20,6 +26,7 @@ class Article &lt; ActiveRecord::Base @@ -20,6 +26,7 @@ class Article &lt; ActiveRecord::Base
20 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? } 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 belongs_to :last_changed_by, :class_name => 'Person', :foreign_key => 'last_changed_by_id' 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 has_many :comments, :class_name => 'Comment', :foreign_key => 'source_id', :dependent => :destroy, :order => 'created_at asc' 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 &lt; ActiveRecord::Base @@ -289,7 +296,7 @@ class Article &lt; ActiveRecord::Base
289 if last_comment 296 if last_comment
290 {:date => last_comment.created_at, :author_name => last_comment.author_name, :author_url => last_comment.author_url} 297 {:date => last_comment.created_at, :author_name => last_comment.author_name, :author_url => last_comment.author_url}
291 else 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 end 300 end
294 end 301 end
295 302
@@ -441,7 +448,7 @@ class Article &lt; ActiveRecord::Base @@ -441,7 +448,7 @@ class Article &lt; ActiveRecord::Base
441 end 448 end
442 449
443 def allow_post_content?(user = nil) 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 end 452 end
446 453
447 def allow_publish_content?(user = nil) 454 def allow_publish_content?(user = nil)
@@ -538,16 +545,8 @@ class Article &lt; ActiveRecord::Base @@ -538,16 +545,8 @@ class Article &lt; ActiveRecord::Base
538 false 545 false
539 end 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 def author_name 548 def author_name
550 - setting[:author_name].blank? ? author.name : setting[:author_name] 549 + author ? author.name : setting[:author_name]
551 end 550 end
552 551
553 alias :active_record_cache_key :cache_key 552 alias :active_record_cache_key :cache_key
@@ -572,11 +571,6 @@ class Article &lt; ActiveRecord::Base @@ -572,11 +571,6 @@ class Article &lt; ActiveRecord::Base
572 truncate sanitize_html(self.lead), :length => 170, :omission => '...' 571 truncate sanitize_html(self.lead), :length => 170, :omission => '...'
573 end 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 def notifiable? 574 def notifiable?
581 false 575 false
582 end 576 end
app/models/event.rb
@@ -38,7 +38,7 @@ class Event &lt; Article @@ -38,7 +38,7 @@ class Event &lt; Article
38 filter_iframes :body, :link, :address, :whitelist => lambda { profile && profile.environment && profile.environment.trusted_sites_for_iframe } 38 filter_iframes :body, :link, :address, :whitelist => lambda { profile && profile.environment && profile.environment.trusted_sites_for_iframe }
39 39
40 def self.description 40 def self.description
41 - _('A calendar event') 41 + _('A calendar event.')
42 end 42 end
43 43
44 def self.short_description 44 def self.short_description
app/models/person.rb
@@ -54,6 +54,8 @@ class Person &lt; Profile @@ -54,6 +54,8 @@ class Person &lt; Profile
54 54
55 has_many :scraps_sent, :class_name => 'Scrap', :foreign_key => :sender_id, :dependent => :destroy 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 named_scope :more_popular, 59 named_scope :more_popular,
58 :select => "#{Profile.qualified_column_names}, count(friend_id) as total", 60 :select => "#{Profile.qualified_column_names}, count(friend_id) as total",
59 :group => Profile.qualified_column_names, 61 :group => Profile.qualified_column_names,
app/models/raw_html_article.rb
@@ -5,11 +5,11 @@ class RawHTMLArticle &lt; TextArticle @@ -5,11 +5,11 @@ class RawHTMLArticle &lt; TextArticle
5 end 5 end
6 6
7 def self.short_description 7 def self.short_description
8 - _('Raw HTML text article.') 8 + _('Raw HTML text article')
9 end 9 end
10 10
11 def self.description 11 def self.description
12 - _('Allows HTML without filter (only for admins)') 12 + _('Allows HTML without filter (only for admins).')
13 end 13 end
14 14
15 xss_terminate :only => [ ] 15 xss_terminate :only => [ ]
app/models/tiny_mce_article.rb
1 class TinyMceArticle < TextArticle 1 class TinyMceArticle < TextArticle
2 2
3 def self.short_description 3 def self.short_description
4 - _('Text article with visual editor.') 4 + _('Text article with visual editor')
5 end 5 end
6 6
7 def self.description 7 def self.description
app/views/cms/select_article_type.rhtml
@@ -2,9 +2,9 @@ @@ -2,9 +2,9 @@
2 2
3 <ul id="article_types"> 3 <ul id="article_types">
4 <% for type in @article_types %> 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 <% content_tag('a', :href => url_for(action.merge(:parent_id => @parent_id, :back_to => @back_to))) do %> 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 <strong><%= type[:short_description] %></strong> 8 <strong><%= type[:short_description] %></strong>
9 <div class='description'><%= type[:description] %></div> 9 <div class='description'><%= type[:description] %></div>
10 </li> 10 </li>
app/views/content_viewer/_article_toolbar.rhtml
@@ -34,11 +34,11 @@ @@ -34,11 +34,11 @@
34 <%= expirable_button @page, :locale, content, url %> 34 <%= expirable_button @page, :locale, content, url %>
35 <% end %> 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 <% end %> 38 <% end %>
39 39
40 <% if @page.accept_uploads? && @page.allow_create?(user) %> 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 <% end %> 42 <% end %>
43 43
44 <% if !@page.allow_create?(user) && profile.community? && (@page.blog? || @page.parent && @page.parent.blog?) && !remove_content_button(:suggest) %> 44 <% if !@page.allow_create?(user) && profile.community? && (@page.blog? || @page.parent && @page.parent.blog?) && !remove_content_button(:suggest) %>
db/migrate/20121024220349_add_author_id_to_article.rb 0 → 100644
@@ -0,0 +1,11 @@ @@ -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 @@ @@ -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
@@ -9,7 +9,7 @@ @@ -9,7 +9,7 @@
9 # 9 #
10 # It's strongly recommended to check this file into your version control system. 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 create_table "abuse_reports", :force => true do |t| 14 create_table "abuse_reports", :force => true do |t|
15 t.integer "reporter_id" 15 t.integer "reporter_id"
@@ -86,6 +86,7 @@ ActiveRecord::Schema.define(:version =&gt; 20121008185303) do @@ -86,6 +86,7 @@ ActiveRecord::Schema.define(:version =&gt; 20121008185303) do
86 t.string "language" 86 t.string "language"
87 t.string "source_name" 87 t.string "source_name"
88 t.integer "license_id" 88 t.integer "license_id"
  89 + t.integer "author_id"
89 end 90 end
90 91
91 create_table "articles", :force => true do |t| 92 create_table "articles", :force => true do |t|
@@ -127,6 +128,7 @@ ActiveRecord::Schema.define(:version =&gt; 20121008185303) do @@ -127,6 +128,7 @@ ActiveRecord::Schema.define(:version =&gt; 20121008185303) do
127 t.string "language" 128 t.string "language"
128 t.string "source_name" 129 t.string "source_name"
129 t.integer "license_id" 130 t.integer "license_id"
  131 + t.integer "author_id"
130 end 132 end
131 133
132 add_index "articles", ["translation_of_id"], :name => "index_articles_on_translation_of_id" 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,7 +130,7 @@ class Noosfero::Plugin
130 end 130 end
131 131
132 # -> Adds plugin-specific content types to CMS 132 # -> Adds plugin-specific content types to CMS
133 - # returns = { content type class } 133 + # returns = [ContentClass1, ContentClass2, ...]
134 def content_types 134 def content_types
135 nil 135 nil
136 end 136 end
@@ -384,7 +384,9 @@ class Noosfero::Plugin @@ -384,7 +384,9 @@ class Noosfero::Plugin
384 private 384 private
385 385
386 def content_actions 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 end 390 end
389 391
390 end 392 end
plugins/work_assignment/lib/work_assignment_plugin.rb 0 → 100644
@@ -0,0 +1,52 @@ @@ -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 @@ @@ -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 @@ @@ -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
plugins/work_assignment/public/show_versions.js 0 → 100644
@@ -0,0 +1,16 @@ @@ -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/public/style.css 0 → 100644
@@ -0,0 +1,2 @@ @@ -0,0 +1,2 @@
  1 +.icon-newwork-assignment { background-image: url(../../designs/icons/tango/Tango/16x16/categories/applications-office.png) }
  2 +.icon-work-assignment { background-image: url(../../designs/icons/tango/Tango/16x16/categories/applications-office.png) }
plugins/work_assignment/test/functional/cms_controller_test.rb 0 → 100644
@@ -0,0 +1,34 @@ @@ -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 @@ @@ -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 @@ @@ -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 @@ @@ -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
@@ -0,0 +1,3 @@ @@ -0,0 +1,3 @@
  1 +<%= render :partial => 'folder', :locals => {:f => f} %>
  2 +
  3 +<%= f.check_box(:publish_submissions) %>
plugins/work_assignment/views/content_viewer/work_assignment.html.erb 0 → 100644
@@ -0,0 +1,10 @@ @@ -0,0 +1,10 @@
  1 +<% extend WorkAssignmentPlugin::Helper %>
  2 +
  3 +<% unless @page.body.blank? %>
  4 + <div><%= @page.body %></div>
  5 + <hr/>
  6 +<% end %>
  7 +
  8 +<%= display_submissions(@page, user) %>
  9 +
  10 +<%= javascript_include_tag '../plugins/work_assignment/show_versions' %>
test/functional/cms_controller_test.rb
@@ -1583,6 +1583,28 @@ class CmsControllerTest &lt; ActionController::TestCase @@ -1583,6 +1583,28 @@ class CmsControllerTest &lt; ActionController::TestCase
1583 assert_equal f2, article.parent 1583 assert_equal f2, article.parent
1584 end 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 protected 1608 protected
1587 1609
1588 # FIXME this is to avoid adding an extra dependency for a proper JSON parser. 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 &lt; ActiveSupport::TestCase @@ -708,14 +708,6 @@ class ArticleTest &lt; ActiveSupport::TestCase
708 assert_equal a.url, a.view_url 708 assert_equal a.url, a.view_url
709 end 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 should 'have published_at' do 711 should 'have published_at' do
720 assert_respond_to Article.new, :published_at 712 assert_respond_to Article.new, :published_at
721 end 713 end
@@ -1372,7 +1364,7 @@ class ArticleTest &lt; ActiveSupport::TestCase @@ -1372,7 +1364,7 @@ class ArticleTest &lt; ActiveSupport::TestCase
1372 assert Article.method_defined?('author_name') 1364 assert Article.method_defined?('author_name')
1373 end 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 author = mock() 1368 author = mock()
1377 author.expects(:name).returns('author name') 1369 author.expects(:name).returns('author name')
1378 a = Article.new 1370 a = Article.new
@@ -1818,4 +1810,25 @@ class ArticleTest &lt; ActiveSupport::TestCase @@ -1818,4 +1810,25 @@ class ArticleTest &lt; ActiveSupport::TestCase
1818 assert a1.errors.invalid?(:parent_id) 1810 assert a1.errors.invalid?(:parent_id)
1819 end 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 end 1834 end
test/unit/person_test.rb
@@ -1262,4 +1262,15 @@ class PersonTest &lt; ActiveSupport::TestCase @@ -1262,4 +1262,15 @@ class PersonTest &lt; ActiveSupport::TestCase
1262 1262
1263 assert person.has_permission?('bli', Profile.new) 1263 assert person.has_permission?('bli', Profile.new)
1264 end 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 end 1276 end