Commit 483f5d55ae046c308ea951ddb50d9c77715b759d
Exists in
master
and in
28 other branches
Merge remote branch 'diguliu/features' into work-assignment
Conflicts: test/functional/cms_controller_test.rb test/unit/article_test.rb
Showing
30 changed files
with
523 additions
and
64 deletions
Show diff stats
app/controllers/my_profile/cms_controller.rb
@@ -16,7 +16,13 @@ class CmsController < MyProfileController | @@ -16,7 +16,13 @@ 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 | + (article_id && profile.articles.find(article_id).allow_create?(user)) || | ||
22 | + (user && (user.has_permission?('post_content', profile) || user.has_permission?('publish_content', profile))) | ||
23 | + end | ||
24 | + | ||
25 | + 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)) | 26 | user && (user.has_permission?('post_content', profile) || user.has_permission?('publish_content', profile)) |
21 | end | 27 | end |
22 | 28 | ||
@@ -92,7 +98,7 @@ class CmsController < MyProfileController | @@ -92,7 +98,7 @@ class CmsController < MyProfileController | ||
92 | @article_types = [] | 98 | @article_types = [] |
93 | available_article_types.each do |type| | 99 | available_article_types.each do |type| |
94 | @article_types.push({ | 100 | @article_types.push({ |
95 | - :name => type.name, | 101 | + :class => type, |
96 | :short_description => type.short_description, | 102 | :short_description => type.short_description, |
97 | :description => type.description | 103 | :description => type.description |
98 | }) | 104 | }) |
@@ -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, :last_changed_by => 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/content_viewer_helper.rb
@@ -26,7 +26,7 @@ module ContentViewerHelper | @@ -26,7 +26,7 @@ module ContentViewerHelper | ||
26 | end | 26 | end |
27 | title << content_tag('span', | 27 | title << content_tag('span', |
28 | content_tag('span', show_date(article.published_at), :class => 'date') + | 28 | content_tag('span', show_date(article.published_at), :class => 'date') + |
29 | - content_tag('span', [_(", by %s") % link_to(article.author_name, article.author.url)], :class => 'author') + | 29 | + content_tag('span', [_(", by %s") % link_to(article.author_name, article.author_url)], :class => 'author') + |
30 | content_tag('span', comments, :class => 'comments'), | 30 | content_tag('span', comments, :class => 'comments'), |
31 | :class => 'created-at' | 31 | :class => 'created-at' |
32 | ) | 32 | ) |
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/helpers/forms_helper.rb
@@ -142,6 +142,38 @@ module FormsHelper | @@ -142,6 +142,38 @@ module FormsHelper | ||
142 | content_tag('table',rows.join("\n")) | 142 | content_tag('table',rows.join("\n")) |
143 | end | 143 | end |
144 | 144 | ||
145 | + def select_folder(label_text, field_id, collection, default_value=nil, html_options = {}, js_options = {}) | ||
146 | + root = profile ? profile.identifier : _("root") | ||
147 | + labelled_form_field( | ||
148 | + label_text, | ||
149 | + select_tag( | ||
150 | + field_id, | ||
151 | + options_for_select( | ||
152 | + [[root, '']] + | ||
153 | + collection.collect {|f| [ root + '/' + f.full_name, f.id ] }, | ||
154 | + default_value | ||
155 | + ), | ||
156 | + html_options.merge(js_options) | ||
157 | + ) | ||
158 | + ) | ||
159 | + end | ||
160 | + | ||
161 | + def select_profile_folder(label_text, field_id, profile, default_value='', html_options = {}, js_options = {}) | ||
162 | + result = labelled_form_field( | ||
163 | + label_text, | ||
164 | + select_tag( | ||
165 | + field_id, | ||
166 | + options_for_select( | ||
167 | + [[profile.identifier, '']] + | ||
168 | + profile.folders.collect {|f| [ profile.identifier + '/' + f.full_name, f.id ] }, | ||
169 | + default_value | ||
170 | + ), | ||
171 | + html_options.merge(js_options) | ||
172 | + ) | ||
173 | + ) | ||
174 | + return result | ||
175 | + end | ||
176 | + | ||
145 | def date_field(name, value, format = '%Y-%m-%d', datepicker_options = {}, html_options = {}) | 177 | def date_field(name, value, format = '%Y-%m-%d', datepicker_options = {}, html_options = {}) |
146 | datepicker_options[:disabled] ||= false | 178 | datepicker_options[:disabled] ||= false |
147 | datepicker_options[:alt_field] ||= '' | 179 | datepicker_options[:alt_field] ||= '' |
app/models/approve_article.rb
@@ -48,7 +48,7 @@ class ApproveArticle < Task | @@ -48,7 +48,7 @@ class ApproveArticle < Task | ||
48 | end | 48 | end |
49 | 49 | ||
50 | def perform | 50 | def perform |
51 | - article.copy!(:name => name, :abstract => abstract, :body => body, :profile => target, :reference_article => article, :parent => article_parent, :highlighted => highlighted, :source => article.source) | 51 | + article.copy!(:name => name, :abstract => abstract, :body => body, :profile => target, :reference_article => article, :parent => article_parent, :highlighted => highlighted, :source => article.source, :last_changed_by_id => article.author) |
52 | end | 52 | end |
53 | 53 | ||
54 | def title | 54 | def title |
app/models/article.rb
@@ -13,6 +13,12 @@ class Article < ActiveRecord::Base | @@ -13,6 +13,12 @@ class Article < 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_create do |article| | ||
17 | + if article.last_changed_by_id | ||
18 | + article.author_name = Person.find(article.last_changed_by_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? } |
@@ -289,7 +295,7 @@ class Article < ActiveRecord::Base | @@ -289,7 +295,7 @@ class Article < ActiveRecord::Base | ||
289 | if last_comment | 295 | if last_comment |
290 | {:date => last_comment.created_at, :author_name => last_comment.author_name, :author_url => last_comment.author_url} | 296 | {:date => last_comment.created_at, :author_name => last_comment.author_name, :author_url => last_comment.author_url} |
291 | else | 297 | else |
292 | - {:date => updated_at, :author_name => author.name, :author_url => author.url} | 298 | + {:date => updated_at, :author_name => author_name, :author_url => author_url} |
293 | end | 299 | end |
294 | end | 300 | end |
295 | 301 | ||
@@ -441,7 +447,7 @@ class Article < ActiveRecord::Base | @@ -441,7 +447,7 @@ class Article < ActiveRecord::Base | ||
441 | end | 447 | end |
442 | 448 | ||
443 | def allow_post_content?(user = nil) | 449 | def allow_post_content?(user = nil) |
444 | - user && (user.has_permission?('post_content', profile) || allow_publish_content?(user) && (user == self.creator)) | 450 | + user && (user.has_permission?('post_content', profile) || allow_publish_content?(user) && (user == author)) |
445 | end | 451 | end |
446 | 452 | ||
447 | def allow_publish_content?(user = nil) | 453 | def allow_publish_content?(user = nil) |
@@ -496,7 +502,6 @@ class Article < ActiveRecord::Base | @@ -496,7 +502,6 @@ class Article < ActiveRecord::Base | ||
496 | :slug, | 502 | :slug, |
497 | :updated_at, | 503 | :updated_at, |
498 | :created_at, | 504 | :created_at, |
499 | - :last_changed_by_id, | ||
500 | :version, | 505 | :version, |
501 | :lock_version, | 506 | :lock_version, |
502 | :type, | 507 | :type, |
@@ -539,15 +544,20 @@ class Article < ActiveRecord::Base | @@ -539,15 +544,20 @@ class Article < ActiveRecord::Base | ||
539 | end | 544 | end |
540 | 545 | ||
541 | def author | 546 | def author |
542 | - if reference_article | ||
543 | - reference_article.author | 547 | + if versions.empty? |
548 | + last_changed_by | ||
544 | else | 549 | else |
545 | - last_changed_by || profile | 550 | + author_id = versions.first.last_changed_by_id |
551 | + Person.exists?(author_id) ? Person.find(author_id) : nil | ||
546 | end | 552 | end |
547 | end | 553 | end |
548 | 554 | ||
549 | def author_name | 555 | def author_name |
550 | - setting[:author_name].blank? ? author.name : setting[:author_name] | 556 | + author ? author.name : (setting[:author_name] || _('Unknown')) |
557 | + end | ||
558 | + | ||
559 | + def author_url | ||
560 | + author ? author.url : nil | ||
551 | end | 561 | end |
552 | 562 | ||
553 | alias :active_record_cache_key :cache_key | 563 | alias :active_record_cache_key :cache_key |
@@ -572,11 +582,6 @@ class Article < ActiveRecord::Base | @@ -572,11 +582,6 @@ class Article < ActiveRecord::Base | ||
572 | truncate sanitize_html(self.lead), :length => 170, :omission => '...' | 582 | truncate sanitize_html(self.lead), :length => 170, :omission => '...' |
573 | end | 583 | end |
574 | 584 | ||
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? | 585 | def notifiable? |
581 | false | 586 | false |
582 | end | 587 | end |
app/models/event.rb
@@ -38,7 +38,7 @@ class Event < Article | @@ -38,7 +38,7 @@ class Event < 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/raw_html_article.rb
@@ -5,11 +5,11 @@ class RawHTMLArticle < TextArticle | @@ -5,11 +5,11 @@ class RawHTMLArticle < 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
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/schema.rb
@@ -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 => 20121022190819) 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" |
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 |
@@ -0,0 +1,14 @@ | @@ -0,0 +1,14 @@ | ||
1 | +require_dependency 'article' | ||
2 | +require_dependency 'uploaded_file' | ||
3 | + | ||
4 | +class UploadedFile < Article | ||
5 | + after_save do |uploaded_file| | ||
6 | + if uploaded_file.parent.kind_of?(WorkAssignmentPlugin::WorkAssignment) | ||
7 | + author_folder = uploaded_file.parent.find_or_create_author_folder(uploaded_file.author) | ||
8 | + uploaded_file.name = WorkAssignmentPlugin::WorkAssignment.versioned_name(uploaded_file, author_folder) | ||
9 | + uploaded_file.parent = author_folder | ||
10 | + logger.info("\n\n==> #{uploaded_file.name}\n\n") | ||
11 | + uploaded_file.save! | ||
12 | + end | ||
13 | + end | ||
14 | +end |
@@ -0,0 +1,54 @@ | @@ -0,0 +1,54 @@ | ||
1 | +require_dependency 'ext/uploaded_file' | ||
2 | + | ||
3 | +class WorkAssignmentPlugin < Noosfero::Plugin | ||
4 | + | ||
5 | + def self.plugin_name | ||
6 | + "Work Assignment" | ||
7 | + end | ||
8 | + | ||
9 | + def self.plugin_description | ||
10 | + _("New kind of content for organizations.") | ||
11 | + end | ||
12 | + | ||
13 | + def self.can_download_submission?(user, submission) | ||
14 | + work_assignment = submission.parent.parent | ||
15 | + work_assignment.publish_submissions || (user && (submission.author == user || user.has_permission?('view_private_content', work_assignment.profile))) | ||
16 | + end | ||
17 | + | ||
18 | + def self.is_submission?(content) | ||
19 | + content && content.parent && content.parent.parent && content.parent.parent.kind_of?(WorkAssignmentPlugin::WorkAssignment) | ||
20 | + end | ||
21 | + | ||
22 | + def content_types | ||
23 | + [WorkAssignmentPlugin::WorkAssignment] if context.profile.organization? | ||
24 | + end | ||
25 | + | ||
26 | + def stylesheet? | ||
27 | + true | ||
28 | + end | ||
29 | + | ||
30 | + def content_remove_new(content) | ||
31 | + content.kind_of?(WorkAssignmentPlugin::WorkAssignment) | ||
32 | + end | ||
33 | + | ||
34 | + def content_remove_upload(content) | ||
35 | + !content.profile.members.include?(context.send(:user)) | ||
36 | + end | ||
37 | + | ||
38 | + def content_viewer_controller_filters | ||
39 | + block = lambda do | ||
40 | + path = params[:page].join('/') | ||
41 | + content = profile.articles.find_by_path(path) | ||
42 | + | ||
43 | + if WorkAssignmentPlugin.is_submission?(content) && !WorkAssignmentPlugin.can_download_submission?(user, content) | ||
44 | + render_access_denied | ||
45 | + end | ||
46 | + end | ||
47 | + | ||
48 | + { :type => 'before_filter', | ||
49 | + :method_name => 'work_assingment_only_admin_or_owner_download', | ||
50 | + :options => {:only => 'view_page'}, | ||
51 | + :block => block } | ||
52 | + end | ||
53 | + | ||
54 | +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,48 @@ | @@ -0,0 +1,48 @@ | ||
1 | +class WorkAssignmentPlugin::WorkAssignment < Folder | ||
2 | + | ||
3 | + settings_items :publish_submissions, :type => :boolean, :default => false | ||
4 | + | ||
5 | + def self.icon_name(article = nil) | ||
6 | + 'work-assignment' | ||
7 | + end | ||
8 | + | ||
9 | + def self.short_description | ||
10 | + _('Work Assignment') | ||
11 | + end | ||
12 | + | ||
13 | + def self.description | ||
14 | + _('Defines a work to be done by the members and receives their submissions about this work.') | ||
15 | + end | ||
16 | + | ||
17 | + def self.versioned_name(submission, folder) | ||
18 | + "(V#{folder.children.count + 1}) #{submission.name}" | ||
19 | + end | ||
20 | + | ||
21 | + def accept_comments? | ||
22 | + true | ||
23 | + end | ||
24 | + | ||
25 | + def allow_create?(user) | ||
26 | + profile.members.include?(user) | ||
27 | + end | ||
28 | + | ||
29 | + def to_html(options = {}) | ||
30 | + lambda do | ||
31 | + render :file => 'content_viewer/work_assignment.html.erb' | ||
32 | + end | ||
33 | + end | ||
34 | + | ||
35 | + def find_or_create_author_folder(author) | ||
36 | + children.find_by_slug(author.identifier.to_slug) || Folder.create!(:name => author.name, :slug => author.identifier.to_slug, :parent => self, :profile => profile) | ||
37 | + end | ||
38 | + | ||
39 | + def submissions | ||
40 | + children.map(&:children).flatten.compact | ||
41 | + end | ||
42 | + | ||
43 | + def cache_key_with_person(params = {}, user = nil, language = 'en') | ||
44 | + cache_key_without_person + (user && profile.members.include?(user) ? "-#{user.identifier}" : '') | ||
45 | + end | ||
46 | + alias_method_chain :cache_key, :person | ||
47 | + | ||
48 | +end |
@@ -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/test/functional/cms_controller_test.rb
0 → 100644
@@ -0,0 +1,44 @@ | @@ -0,0 +1,44 @@ | ||
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 | + should 'upload submission and automatically move it to the author folder' do | ||
34 | + organization = fast_create(Organization) | ||
35 | + work_assignment = WorkAssignmentPlugin::WorkAssignment.create!(:name => 'Work Assignment', :profile => organization) | ||
36 | + organization.add_member(person) | ||
37 | + post :upload_files, :profile => organization.identifier, :parent_id => work_assignment.id, :uploaded_files => [fixture_file_upload('/files/test.txt', 'text/plain')] | ||
38 | + | ||
39 | + submission = UploadedFile.last | ||
40 | + assert_equal work_assignment.find_or_create_author_folder(person), submission.parent | ||
41 | + end | ||
42 | + | ||
43 | +end | ||
44 | + |
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,55 @@ | @@ -0,0 +1,55 @@ | ||
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 | + profile = fast_create(Profile) | ||
17 | + folder = fast_create(Folder, :profile_id => 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, :last_changed_by => author) | ||
39 | + | ||
40 | + author_folder = work_assignment.find_or_create_author_folder(author) | ||
41 | + assert author_folder, submission.parent | ||
42 | + end | ||
43 | + | ||
44 | + should 'add logged user on cache_key if is a member' do | ||
45 | + organization = fast_create(Organization) | ||
46 | + not_member = fast_create(Person) | ||
47 | + member = fast_create(Person) | ||
48 | + organization.add_member(member) | ||
49 | + work_assignment = WorkAssignmentPlugin::WorkAssignment.create!(:name => 'Sample Work Assignment', :profile => organization) | ||
50 | + | ||
51 | + assert_no_match(/-#{not_member.identifier}/, work_assignment.cache_key({}, not_member)) | ||
52 | + assert_match(/-#{member.identifier}/, work_assignment.cache_key({}, member)) | ||
53 | + end | ||
54 | + | ||
55 | +end |
plugins/work_assignment/test/unit/work_assingment_plugin_test.rb
0 → 100644
@@ -0,0 +1,54 @@ | @@ -0,0 +1,54 @@ | ||
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, :last_changed_by => fast_create(Person)) | ||
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(content.author) | ||
15 | + assert_equal author_folder, content.parent | ||
16 | + end | ||
17 | + | ||
18 | + should 'be able to download submission if work_assignment published submissions' do | ||
19 | + submission = create_submission | ||
20 | + assert !WorkAssignmentPlugin.can_download_submission?(nil, submission) | ||
21 | + | ||
22 | + work_assignment = submission.parent.parent | ||
23 | + work_assignment.publish_submissions = true | ||
24 | + work_assignment.save! | ||
25 | + assert WorkAssignmentPlugin.can_download_submission?(nil, submission) | ||
26 | + end | ||
27 | + | ||
28 | + should 'be able to download submission if the user is author of it' do | ||
29 | + person = fast_create(Person) | ||
30 | + submission = create_submission | ||
31 | + assert !WorkAssignmentPlugin.can_download_submission?(person, submission) | ||
32 | + | ||
33 | + submission = create_submission(person) | ||
34 | + assert WorkAssignmentPlugin.can_download_submission?(person, submission) | ||
35 | + end | ||
36 | + | ||
37 | + should 'be able to download submission if the user has the view_private_content permission on the profile' do | ||
38 | + person = fast_create(Person) | ||
39 | + submission = create_submission | ||
40 | + assert !WorkAssignmentPlugin.can_download_submission?(person, submission) | ||
41 | + | ||
42 | + moderator = create_user_with_permission('moderator', 'view_private_content', submission.profile) | ||
43 | + assert WorkAssignmentPlugin.can_download_submission?(moderator, submission) | ||
44 | + end | ||
45 | + | ||
46 | + private | ||
47 | + | ||
48 | + def create_submission(author=nil) | ||
49 | + organization = fast_create(Organization) | ||
50 | + work_assignment = WorkAssignmentPlugin::WorkAssignment.create!(:name => 'Work Assignment', :profile => organization) | ||
51 | + author_folder = work_assignment.find_or_create_author_folder(fast_create(Person)) | ||
52 | + UploadedFile.create!(:uploaded_data => fixture_file_upload('/files/rails.png', 'image/png'), :profile => organization, :parent => author_folder, :last_changed_by => author) | ||
53 | + end | ||
54 | +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
@@ -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 < ActionController::TestCase | @@ -1583,6 +1583,28 @@ class CmsControllerTest < 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/approve_article_test.rb
@@ -210,22 +210,21 @@ class ApproveArticleTest < ActiveSupport::TestCase | @@ -210,22 +210,21 @@ class ApproveArticleTest < ActiveSupport::TestCase | ||
210 | end | 210 | end |
211 | 211 | ||
212 | should 'use author from original article on published' do | 212 | should 'use author from original article on published' do |
213 | - article.stubs(:last_changed_by_id).returns(profile) | ||
214 | - | 213 | + article.class.any_instance.stubs(:author).returns(profile) |
215 | a = ApproveArticle.create!(:name => 'test name', :article => article, :target => community, :requestor => profile) | 214 | a = ApproveArticle.create!(:name => 'test name', :article => article, :target => community, :requestor => profile) |
216 | a.finish | 215 | a.finish |
217 | 216 | ||
218 | assert_equal profile, article.class.last.author | 217 | assert_equal profile, article.class.last.author |
219 | end | 218 | end |
220 | 219 | ||
221 | - | ||
222 | - should 'use owning profile as author when there is no referenced article' do | 220 | + should 'use original article author even if article is destroyed' do |
221 | + article.class.any_instance.stubs(:author).returns(profile) | ||
223 | a = ApproveArticle.create!(:article => article, :target => community, :requestor => profile) | 222 | a = ApproveArticle.create!(:article => article, :target => community, :requestor => profile) |
224 | a.finish | 223 | a.finish |
225 | 224 | ||
226 | article.destroy | 225 | article.destroy |
227 | 226 | ||
228 | - assert_equal community, article.class.last.author | 227 | + assert_equal profile, article.class.last.author |
229 | end | 228 | end |
230 | 229 | ||
231 | should 'the published article have parent if defined' do | 230 | should 'the published article have parent if defined' do |
test/unit/article_test.rb
@@ -708,14 +708,6 @@ class ArticleTest < ActiveSupport::TestCase | @@ -708,14 +708,6 @@ class ArticleTest < 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 |
@@ -791,15 +783,7 @@ class ArticleTest < ActiveSupport::TestCase | @@ -791,15 +783,7 @@ class ArticleTest < ActiveSupport::TestCase | ||
791 | assert_match(/-owner/, a.cache_key({}, c)) | 783 | assert_match(/-owner/, a.cache_key({}, c)) |
792 | end | 784 | end |
793 | 785 | ||
794 | - should 'have a creator method' do | ||
795 | - c = fast_create(Community) | ||
796 | - a = c.articles.create!(:name => 'a test article', :last_changed_by => profile) | ||
797 | - p = create_user('other_user').person | ||
798 | - a.update_attributes(:body => 'some content', :last_changed_by => p); a.save! | ||
799 | - assert_equal profile, a.creator | ||
800 | - end | ||
801 | - | ||
802 | - should 'allow creator to edit if is publisher' do | 786 | + should 'allow author to edit if is publisher' do |
803 | c = fast_create(Community) | 787 | c = fast_create(Community) |
804 | p = create_user_with_permission('test_user', 'publish_content', c) | 788 | p = create_user_with_permission('test_user', 'publish_content', c) |
805 | a = c.articles.create!(:name => 'a test article', :last_changed_by => p) | 789 | a = c.articles.create!(:name => 'a test article', :last_changed_by => p) |
@@ -1372,19 +1356,18 @@ class ArticleTest < ActiveSupport::TestCase | @@ -1372,19 +1356,18 @@ class ArticleTest < ActiveSupport::TestCase | ||
1372 | assert Article.method_defined?('author_name') | 1356 | assert Article.method_defined?('author_name') |
1373 | end | 1357 | end |
1374 | 1358 | ||
1375 | - should "the author_name returns the name od the article's author" do | ||
1376 | - author = mock() | ||
1377 | - author.expects(:name).returns('author name') | ||
1378 | - a = Article.new | ||
1379 | - a.expects(:author).returns(author) | ||
1380 | - assert_equal 'author name', a.author_name | 1359 | + should "the author_name returns the name of the article's author" do |
1360 | + author = fast_create(Person) | ||
1361 | + a = profile.articles.create!(:name => 'a test article', :last_changed_by => author) | ||
1362 | + assert_equal author.name, a.author_name | ||
1363 | + author.destroy | ||
1381 | a.author_name = 'some name' | 1364 | a.author_name = 'some name' |
1382 | assert_equal 'some name', a.author_name | 1365 | assert_equal 'some name', a.author_name |
1383 | end | 1366 | end |
1384 | 1367 | ||
1385 | should 'retrieve latest info from topic when has no comments' do | 1368 | should 'retrieve latest info from topic when has no comments' do |
1386 | forum = fast_create(Forum, :name => 'Forum test', :profile_id => profile.id) | 1369 | forum = fast_create(Forum, :name => 'Forum test', :profile_id => profile.id) |
1387 | - post = fast_create(TextileArticle, :name => 'First post', :profile_id => profile.id, :parent_id => forum.id, :updated_at => Time.now) | 1370 | + post = fast_create(TextileArticle, :name => 'First post', :profile_id => profile.id, :parent_id => forum.id, :updated_at => Time.now, :last_changed_by_id => profile.id) |
1388 | assert_equal post.updated_at, post.info_from_last_update[:date] | 1371 | assert_equal post.updated_at, post.info_from_last_update[:date] |
1389 | assert_equal profile.name, post.info_from_last_update[:author_name] | 1372 | assert_equal profile.name, post.info_from_last_update[:author_name] |
1390 | assert_equal profile.url, post.info_from_last_update[:author_url] | 1373 | assert_equal profile.url, post.info_from_last_update[:author_url] |
@@ -1818,4 +1801,15 @@ class ArticleTest < ActiveSupport::TestCase | @@ -1818,4 +1801,15 @@ class ArticleTest < ActiveSupport::TestCase | ||
1818 | assert a1.errors.invalid?(:parent_id) | 1801 | assert a1.errors.invalid?(:parent_id) |
1819 | end | 1802 | end |
1820 | 1803 | ||
1804 | + should 'set author_name before creating article if there is an author' do | ||
1805 | + author = fast_create(Person) | ||
1806 | + article = Article.create!(:name => 'Test', :profile => profile, :last_changed_by => author) | ||
1807 | + assert_equal author.name, article.author_name | ||
1808 | + | ||
1809 | + author_name = author.name | ||
1810 | + author.destroy | ||
1811 | + article.reload | ||
1812 | + assert_equal author_name, article.author_name | ||
1813 | + end | ||
1814 | + | ||
1821 | end | 1815 | end |
test/unit/folder_helper_test.rb
@@ -33,7 +33,7 @@ class FolderHelperTest < ActiveSupport::TestCase | @@ -33,7 +33,7 @@ class FolderHelperTest < ActiveSupport::TestCase | ||
33 | 33 | ||
34 | should 'display icon for type of article' do | 34 | should 'display icon for type of article' do |
35 | Article.expects(:icon_name).returns('article') | 35 | Article.expects(:icon_name).returns('article') |
36 | - assert_match /icon-newarticle/, icon_for_new_article('Article') | 36 | + assert_match /icon-newarticle/, icon_for_new_article(Article) |
37 | end | 37 | end |
38 | 38 | ||
39 | should 'list all the folder\'s children to the owner' do | 39 | should 'list all the folder\'s children to the owner' do |
test/unit/forum_helper_test.rb
@@ -29,17 +29,16 @@ class ForumHelperTest < ActiveSupport::TestCase | @@ -29,17 +29,16 @@ class ForumHelperTest < ActiveSupport::TestCase | ||
29 | end | 29 | end |
30 | 30 | ||
31 | should 'list posts with different classes' do | 31 | should 'list posts with different classes' do |
32 | - forum.children << older_post = TextileArticle.create!(:name => 'First post', :profile => profile, :parent => forum, :published => false) | 32 | + forum.children << older_post = TextileArticle.create!(:name => 'First post', :profile => profile, :parent => forum, :published => false, :last_changed_by => profile) |
33 | one_month_later = Time.now + 1.month | 33 | one_month_later = Time.now + 1.month |
34 | Time.stubs(:now).returns(one_month_later) | 34 | Time.stubs(:now).returns(one_month_later) |
35 | - forum.children << newer_post = TextileArticle.create!(:name => 'Second post', :profile => profile, :parent => forum, :published => true) | 35 | + forum.children << newer_post = TextileArticle.create!(:name => 'Second post', :profile => profile, :parent => forum, :published => true, :last_changed_by => profile) |
36 | assert_match /forum-post position-1 first odd-post.*forum-post position-2 last not-published even-post/, list_forum_posts(forum.posts) | 36 | assert_match /forum-post position-1 first odd-post.*forum-post position-2 last not-published even-post/, list_forum_posts(forum.posts) |
37 | end | 37 | end |
38 | 38 | ||
39 | should 'return post update if it has no comments' do | 39 | should 'return post update if it has no comments' do |
40 | author = create_user('forum test author').person | 40 | author = create_user('forum test author').person |
41 | - some_post = TextileArticle.create!(:name => 'First post', :profile => profile, :parent => forum, :published => true) | ||
42 | - some_post.expects(:author).returns(author).times(2) | 41 | + some_post = TextileArticle.create!(:name => 'First post', :profile => profile, :parent => forum, :published => true, :last_changed_by => author) |
43 | assert some_post.comments.empty? | 42 | assert some_post.comments.empty? |
44 | out = last_topic_update(some_post) | 43 | out = last_topic_update(some_post) |
45 | assert_match some_post.updated_at.to_s, out | 44 | assert_match some_post.updated_at.to_s, out |