Project

General

Profile

« Previous | Next » 

Revision 1227

Activity enhancements:
  • overall activity view and feed added, link is available on the project list (#423, #494)
  • switch added on the project activity view to include subprojects (closes #530)

View differences:

trunk/app/controllers/projects_controller.rb
24 24
  menu_item :settings, :only => :settings
25 25
  menu_item :issues, :only => [:changelog]
26 26
  
27
  before_filter :find_project, :except => [ :index, :list, :add ]
28
  before_filter :authorize, :except => [ :index, :list, :add, :archive, :unarchive, :destroy ]
27
  before_filter :find_project, :except => [ :index, :list, :add, :activity ]
28
  before_filter :find_optional_project, :only => :activity
29
  before_filter :authorize, :except => [ :index, :list, :add, :archive, :unarchive, :destroy, :activity ]
29 30
  before_filter :require_admin, :only => [ :add, :archive, :unarchive, :destroy ]
30 31
  accept_key_auth :activity, :calendar
31 32
  
......
228 229
    @date_from = @date_to - @days
229 230
    
230 231
    @event_types = %w(issues news files documents changesets wiki_pages messages)
231
    @event_types.delete('wiki_pages') unless @project.wiki
232
    @event_types.delete('changesets') unless @project.repository
233
    @event_types.delete('messages') unless @project.boards.any?
234
    # only show what the user is allowed to view
235
    @event_types = @event_types.select {|o| User.current.allowed_to?("view_#{o}".to_sym, @project)}
236
    
232
    if @project
233
      @event_types.delete('wiki_pages') unless @project.wiki
234
      @event_types.delete('changesets') unless @project.repository
235
      @event_types.delete('messages') unless @project.boards.any?
236
      # only show what the user is allowed to view
237
      @event_types = @event_types.select {|o| User.current.allowed_to?("view_#{o}".to_sym, @project)}
238
      @with_subprojects = params[:with_subprojects].nil? ? Setting.display_subprojects_issues? : (params[:with_subprojects] == '1')
239
    end
237 240
    @scope = @event_types.select {|t| params["show_#{t}"]}
238 241
    # default events if none is specified in parameters
239 242
    @scope = (@event_types - %w(wiki_pages messages))if @scope.empty?
......
241 244
    @events = []    
242 245
    
243 246
    if @scope.include?('issues')
244
      @events += @project.issues.find(:all, :include => [:author, :tracker], :conditions => ["#{Issue.table_name}.created_on>=? and #{Issue.table_name}.created_on<=?", @date_from, @date_to] )
245
      @events += @project.issues_status_changes(@date_from, @date_to)
247
      cond = ARCondition.new(Project.allowed_to_condition(User.current, :view_issues, :project => @project, :with_subprojects => @with_subprojects))
248
      cond.add(["#{Issue.table_name}.created_on BETWEEN ? AND ?", @date_from, @date_to])
249
      @events += Issue.find(:all, :include => [:project, :author, :tracker], :conditions => cond.conditions)
250
      
251
      cond = ARCondition.new(Project.allowed_to_condition(User.current, :view_issues, :project => @project, :with_subprojects => @with_subprojects))
252
      cond.add(["#{Journal.table_name}.journalized_type = 'Issue' AND #{JournalDetail.table_name}.prop_key = 'status_id' AND #{Journal.table_name}.created_on BETWEEN ? AND ?", @date_from, @date_to])
253
      @events += Journal.find(:all, :include => [{:issue => :project}, :details, :user], :conditions => cond.conditions)
246 254
    end
247 255
    
248 256
    if @scope.include?('news')
249
      @events += @project.news.find(:all, :conditions => ["#{News.table_name}.created_on>=? and #{News.table_name}.created_on<=?", @date_from, @date_to], :include => :author )
257
      cond = ARCondition.new(Project.allowed_to_condition(User.current, :view_news, :project => @project, :with_subprojects => @with_subprojects))
258
      cond.add(["#{News.table_name}.created_on BETWEEN ? AND ?", @date_from, @date_to])
259
      @events += News.find(:all, :include => [:project, :author], :conditions => cond.conditions)
250 260
    end
251 261
    
252 262
    if @scope.include?('files')
253
      @events += Attachment.find(:all, :select => "#{Attachment.table_name}.*", :joins => "LEFT JOIN #{Version.table_name} ON #{Version.table_name}.id = #{Attachment.table_name}.container_id", :conditions => ["#{Attachment.table_name}.container_type='Version' and #{Version.table_name}.project_id=? and #{Attachment.table_name}.created_on>=? and #{Attachment.table_name}.created_on<=?", @project.id, @date_from, @date_to], :include => :author )
263
      cond = ARCondition.new(Project.allowed_to_condition(User.current, :view_files, :project => @project, :with_subprojects => @with_subprojects))
264
      cond.add(["#{Attachment.table_name}.created_on BETWEEN ? AND ?", @date_from, @date_to])
265
      @events += Attachment.find(:all, :select => "#{Attachment.table_name}.*", 
266
                                       :joins => "LEFT JOIN #{Version.table_name} ON #{Attachment.table_name}.container_type='Version' AND #{Version.table_name}.id = #{Attachment.table_name}.container_id " +
267
                                                 "LEFT JOIN #{Project.table_name} ON #{Version.table_name}.project_id = #{Project.table_name}.id",
268
                                       :conditions => cond.conditions)
254 269
    end
255 270
    
256 271
    if @scope.include?('documents')
257
      @events += @project.documents.find(:all, :conditions => ["#{Document.table_name}.created_on>=? and #{Document.table_name}.created_on<=?", @date_from, @date_to] )
258
      @events += Attachment.find(:all, :select => "attachments.*", :joins => "LEFT JOIN #{Document.table_name} ON #{Document.table_name}.id = #{Attachment.table_name}.container_id", :conditions => ["#{Attachment.table_name}.container_type='Document' and #{Document.table_name}.project_id=? and #{Attachment.table_name}.created_on>=? and #{Attachment.table_name}.created_on<=?", @project.id, @date_from, @date_to], :include => :author )
272
      cond = ARCondition.new(Project.allowed_to_condition(User.current, :view_documents, :project => @project, :with_subprojects => @with_subprojects))
273
      cond.add(["#{Document.table_name}.created_on BETWEEN ? AND ?", @date_from, @date_to])
274
      @events += Document.find(:all, :include => :project, :conditions => cond.conditions)
275
      
276
      cond = ARCondition.new(Project.allowed_to_condition(User.current, :view_documents, :project => @project, :with_subprojects => @with_subprojects))
277
      cond.add(["#{Attachment.table_name}.created_on BETWEEN ? AND ?", @date_from, @date_to])
278
      @events += Attachment.find(:all, :select => "#{Attachment.table_name}.*", 
279
                                       :joins => "LEFT JOIN #{Document.table_name} ON #{Attachment.table_name}.container_type='Document' AND #{Document.table_name}.id = #{Attachment.table_name}.container_id " +
280
                                                 "LEFT JOIN #{Project.table_name} ON #{Document.table_name}.project_id = #{Project.table_name}.id",
281
                                       :conditions => cond.conditions)
259 282
    end
260 283
    
261 284
    if @scope.include?('wiki_pages')
......
264 287
               "#{WikiContent.versioned_table_name}.page_id, #{WikiContent.versioned_table_name}.author_id, " +
265 288
               "#{WikiContent.versioned_table_name}.id"
266 289
      joins = "LEFT JOIN #{WikiPage.table_name} ON #{WikiPage.table_name}.id = #{WikiContent.versioned_table_name}.page_id " +
267
              "LEFT JOIN #{Wiki.table_name} ON #{Wiki.table_name}.id = #{WikiPage.table_name}.wiki_id "
268
      conditions = ["#{Wiki.table_name}.project_id = ? AND #{WikiContent.versioned_table_name}.updated_on BETWEEN ? AND ?",
269
                    @project.id, @date_from, @date_to]
290
              "LEFT JOIN #{Wiki.table_name} ON #{Wiki.table_name}.id = #{WikiPage.table_name}.wiki_id " +
291
              "LEFT JOIN #{Project.table_name} ON #{Project.table_name}.id = #{Wiki.table_name}.project_id"
270 292

  
271
      @events += WikiContent.versioned_class.find(:all, :select => select, :joins => joins, :conditions => conditions)
293
      cond = ARCondition.new(Project.allowed_to_condition(User.current, :view_wiki_pages, :project => @project, :with_subprojects => @with_subprojects))
294
      cond.add(["#{WikiContent.versioned_table_name}.updated_on BETWEEN ? AND ?", @date_from, @date_to])
295
      @events += WikiContent.versioned_class.find(:all, :select => select, :joins => joins, :conditions => cond.conditions)
272 296
    end
273 297

  
274 298
    if @scope.include?('changesets')
275
      @events += Changeset.find(:all, :include => :repository, :conditions => ["#{Repository.table_name}.project_id = ? AND #{Changeset.table_name}.committed_on BETWEEN ? AND ?", @project.id, @date_from, @date_to])
299
      cond = ARCondition.new(Project.allowed_to_condition(User.current, :view_changesets, :project => @project, :with_subprojects => @with_subprojects))
300
      cond.add(["#{Changeset.table_name}.committed_on BETWEEN ? AND ?", @date_from, @date_to])
301
      @events += Changeset.find(:all, :include => {:repository => :project}, :conditions => cond.conditions)
276 302
    end
277 303
    
278 304
    if @scope.include?('messages')
279
      @events += Message.find(:all, 
280
                              :include => [:board, :author], 
281
                              :conditions => ["#{Board.table_name}.project_id=? AND #{Message.table_name}.created_on BETWEEN ? AND ?", @project.id, @date_from, @date_to])
305
      cond = ARCondition.new(Project.allowed_to_condition(User.current, :view_messages, :project => @project, :with_subprojects => @with_subprojects))
306
      cond.add(["#{Message.table_name}.created_on BETWEEN ? AND ?", @date_from, @date_to])
307
      @events += Message.find(:all, :include => [{:board => :project}, :author], :conditions => cond.conditions)
282 308
    end
283 309
    
284 310
    @events_by_day = @events.group_by(&:event_date)
285 311
    
286 312
    respond_to do |format|
287 313
      format.html { render :layout => false if request.xhr? }
288
      format.atom { render_feed(@events, :title => "#{@project.name}: #{l(:label_activity)}") }
314
      format.atom { render_feed(@events, :title => "#{@project || Setting.app_title}: #{l(:label_activity)}") }
289 315
    end
290 316
  end
291 317
  
......
381 407
    render_404
382 408
  end
383 409
  
410
  def find_optional_project
411
    return true unless params[:id]
412
    @project = Project.find(params[:id])
413
    authorize
414
  rescue ActiveRecord::RecordNotFound
415
    render_404
416
  end
417

  
384 418
  def retrieve_selected_tracker_ids(selectable_trackers)
385 419
    if ids = params[:tracker_ids]
386 420
      @selected_tracker_ids = (ids.is_a? Array) ? ids.collect { |id| id.to_i.to_s } : ids.split('/').collect { |id| id.to_i.to_s }
trunk/app/models/attachment.rb
26 26
  validates_length_of :disk_filename, :maximum => 255
27 27

  
28 28
  acts_as_event :title => :filename,
29
                :description => :filename,
30 29
                :url => Proc.new {|o| {:controller => 'attachments', :action => 'download', :id => o.id}}
31 30

  
32 31
  cattr_accessor :storage_path
trunk/app/models/changeset.rb
45 45
    super
46 46
  end
47 47
  
48
  def project
49
    repository.project
50
  end
51
  
48 52
  def after_create
49 53
    scan_comment_for_issue_ids
50 54
  end
trunk/app/models/project.rb
84 84
    end 
85 85
  end
86 86

  
87
  # Return all issues status changes for the project between the 2 given dates
88
  def issues_status_changes(from, to)
89
    Journal.find(:all, :include => [:issue, :details, :user],
90
                       :conditions => ["#{Journal.table_name}.journalized_type = 'Issue'" +
91
                                       " AND #{Issue.table_name}.project_id = ?" +
92
                                       " AND #{JournalDetail.table_name}.prop_key = 'status_id'" +
93
                                       " AND #{Journal.table_name}.created_on BETWEEN ? AND ?",
94
                                       id, from, to+1])
95
  end
96

  
97 87
  # returns latest created projects
98 88
  # non public projects will be returned only if user is a member of those
99 89
  def self.latest(user=nil, count=5)
......
110 100
    end
111 101
  end
112 102
  
113
  def self.allowed_to_condition(user, permission)
103
  def self.allowed_to_condition(user, permission, options={})
114 104
    statements = []
115
    active_statement = "#{Project.table_name}.status=#{Project::STATUS_ACTIVE}"
105
    base_statement = "#{Project.table_name}.status=#{Project::STATUS_ACTIVE}"
106
    if options[:project]
107
      project_statement = "#{Project.table_name}.id = #{options[:project].id}"
108
      project_statement << " OR #{Project.table_name}.parent_id = #{options[:project].id}" if options[:with_subprojects]
109
      base_statement = "(#{project_statement}) AND (#{base_statement})"
110
    end
116 111
    if user.admin?
117 112
      # no restriction
118 113
    elsif user.logged?
119 114
      statements << "#{Project.table_name}.is_public = #{connection.quoted_true}" if Role.non_member.allowed_to?(permission)
120 115
      allowed_project_ids = user.memberships.select {|m| m.role.allowed_to?(permission)}.collect {|m| m.project_id}
121 116
      statements << "#{Project.table_name}.id IN (#{allowed_project_ids.join(',')})" if allowed_project_ids.any?
117
    elsif Role.anonymous.allowed_to?(permission)
118
      # anonymous user allowed on public project
119
      statements << "#{Project.table_name}.is_public = #{connection.quoted_true}" 
122 120
    else
123
      statements << "#{Project.table_name}.is_public = #{connection.quoted_true}" if Role.anonymous.allowed_to?(permission)
121
      # anonymous user is not authorized
122
      statements << "1=0"
124 123
    end
125
    statements.empty? ? active_statement : "(#{active_statement} AND (#{statements.join(' OR ')}))"
124
    statements.empty? ? base_statement : "((#{base_statement}) AND (#{statements.join(' OR ')}))"
126 125
  end
127 126
  
128 127
  def self.find(*args)
trunk/app/models/wiki_content.rb
61 61
      end      
62 62
    end
63 63
    
64
    def project
65
      page.project
66
    end
67
    
64 68
    # Returns the previous version or nil
65 69
    def previous
66 70
      @previous ||= WikiContent::Version.find(:first, 
trunk/app/views/common/feed.atom.rxml
9 9
  xml.generator(:uri => Redmine::Info.url, :version => Redmine::VERSION) { xml.text! Redmine::Info.versioned_name; }
10 10
  @items.each do |item|
11 11
    xml.entry do
12
      url = url_for(item.event_url(:only_path => false))
12 13
      xml.title truncate(item.event_title, 100)
13
      xml.link "rel" => "alternate", "href" => url_for(item.event_url(:only_path => false))
14
      xml.id url_for(item.event_url(:only_path => false))
14
      xml.link "rel" => "alternate", "href" => url
15
      xml.id url
15 16
      xml.updated item.event_datetime.xmlschema
16 17
      author = item.event_author if item.respond_to?(:author)
17 18
      xml.author do
trunk/app/views/projects/activity.rhtml
6 6
<dl>
7 7
<% @events_by_day[day].sort {|x,y| y.event_datetime <=> x.event_datetime }.each do |e| -%>
8 8
  <dt class="<%= e.class.name.downcase %>"><span class="time"><%= format_time(e.event_datetime, false) %></span>
9
  <%= link_to h(truncate(e.event_title, 100)), e.event_url %></dt>
9
  <%= content_tag('span', h(e.project), :class => 'project') if @project.nil? || @project != e.project %> <%= link_to h(truncate(e.event_title, 100)), e.event_url %></dt>
10 10
  <dd><% unless e.event_description.blank? -%>
11 11
  <span class="description"><%= format_activity_description(e.event_description) %></span><br />
12 12
  <% end %>
......
35 35
</p>
36 36

  
37 37
<% content_for :header_tags do %>
38
<%= auto_discovery_link_tag(:atom, params.merge(:format => 'atom', :year => nil, :month => nil, :key => User.current.rss_key).delete_if{|k,v|k=="commit"}) %>
38
<%= auto_discovery_link_tag(:atom, params.merge(:format => 'atom', :year => nil, :month => nil, :key => User.current.rss_key)) %>
39 39
<% end %>
40 40

  
41 41
<% content_for :sidebar do %>
42
<% form_tag do %>
42
<% form_tag({}, :method => :get) do %>
43 43
<h3><%= l(:label_activity) %></h3>
44 44
<p><% @event_types.each do |t| %>
45 45
<label><%= check_box_tag "show_#{t}", 1, @scope.include?(t) %> <%= l("label_#{t.singularize}_plural")%></label><br />
46 46
<% end %></p>
47
<p><%= submit_tag l(:button_apply), :class => 'button-small' %></p>
47
<% if @project && @project.active_children.any? %>
48
    <p><label><%= check_box_tag 'with_subprojects', 1, @with_subprojects %> <%=l(:label_subproject_plural)%></label></p>
49
    <%= hidden_field_tag 'with_subprojects', 0 %>
48 50
<% end %>
51
<p><%= submit_tag l(:button_apply), :class => 'button-small', :name => nil %></p>
49 52
<% end %>
53
<% end %>
50 54

  
51 55
<% html_title(l(:label_activity)) -%>
trunk/app/views/projects/list.rhtml
1
<div class="contextual">
2
    <%= link_to l(:label_issue_view_all), { :controller => 'issues' } %> |
3
    <%= link_to l(:label_overall_activity), { :controller => 'projects', :action => 'activity' }%>
4
</div>
5

  
1 6
<h2><%=l(:label_project_plural)%></h2>
2 7

  
3 8
<% @project_tree.keys.sort.each do |project| %>
trunk/app/views/welcome/index.rhtml
26 26
</div>	
27 27

  
28 28
<% content_for :header_tags do %>
29
<%= auto_discovery_link_tag(:atom, {:controller => 'news', :action => 'index', :key => User.current.rss_key, :format => 'atom'}, {:title => l(:label_news_latest)}) %>
29
<%= auto_discovery_link_tag(:atom, {:controller => 'news', :action => 'index', :key => User.current.rss_key, :format => 'atom'},
30
                                   :title => "#{Setting.app_title}: #{l(:label_news_latest)}") %>
31
<%= auto_discovery_link_tag(:atom, {:controller => 'projects', :action => 'activity', :key => User.current.rss_key, :format => 'atom'},
32
                                   :title => "#{Setting.app_title}: #{l(:label_activity)}") %>
30 33
<% end %>
trunk/lang/bg.yml
613 613
label_reverse_chronological_order: In reverse chronological order
614 614
label_preferences: Preferences
615 615
setting_display_subprojects_issues: Display subprojects issues on main projects by default
616
label_overall_activity: Overall activity
trunk/lang/cs.yml
613 613
label_reverse_chronological_order: In reverse chronological order
614 614
label_preferences: Preferences
615 615
setting_display_subprojects_issues: Display subprojects issues on main projects by default
616
label_overall_activity: Overall activity
trunk/lang/da.yml
615 615
text_reassign_time_entries: 'Reassign reported hours to this issue:'
616 616
label_reverse_chronological_order: In reverse chronological order
617 617
label_preferences: Preferences
618
label_overall_activity: Overall activity
trunk/lang/de.yml
614 614
label_reverse_chronological_order: In reverse chronological order
615 615
label_preferences: Preferences
616 616
setting_display_subprojects_issues: Display subprojects issues on main projects by default
617
label_overall_activity: Overall activity
trunk/lang/en.yml
280 280
label_last_updates_plural: %d last updated
281 281
label_registered_on: Registered on
282 282
label_activity: Activity
283
label_overall_activity: Overall activity
283 284
label_new: New
284 285
label_logged_as: Logged as
285 286
label_environment: Environment
trunk/lang/es.yml
616 616
label_reverse_chronological_order: In reverse chronological order
617 617
label_preferences: Preferences
618 618
setting_display_subprojects_issues: Display subprojects issues on main projects by default
619
label_overall_activity: Overall activity
trunk/lang/fi.yml
620 620
field_comments_sorting: Display comments
621 621
label_reverse_chronological_order: In reverse chronological order
622 622
label_preferences: Preferences
623
label_overall_activity: Overall activity
trunk/lang/fr.yml
165 165
field_subproject: Sous-projet
166 166
field_hours: Heures
167 167
field_activity: Activité
168
label_overall_activity: Activité globale
168 169
field_spent_on: Date
169 170
field_identifier: Identifiant
170 171
field_is_filter: Utilisé comme filtre
......
452 453
label_start_to_end: début à fin
453 454
label_stay_logged_in: Rester connecté
454 455
label_disabled: désactivé
455
label_show_completed_versions: Voire les versions passées
456
label_show_completed_versions: Voir les versions passées
456 457
label_me: moi
457 458
label_board: Forum
458 459
label_board_new: Nouveau forum
trunk/lang/he.yml
613 613
label_reverse_chronological_order: In reverse chronological order
614 614
label_preferences: Preferences
615 615
setting_display_subprojects_issues: Display subprojects issues on main projects by default
616
label_overall_activity: Overall activity
trunk/lang/it.yml
613 613
label_reverse_chronological_order: In reverse chronological order
614 614
label_preferences: Preferences
615 615
setting_display_subprojects_issues: Display subprojects issues on main projects by default
616
label_overall_activity: Overall activity
trunk/lang/ja.yml
614 614
label_reverse_chronological_order: In reverse chronological order
615 615
label_preferences: Preferences
616 616
setting_display_subprojects_issues: Display subprojects issues on main projects by default
617
label_overall_activity: Overall activity
trunk/lang/ko.yml
613 613
label_reverse_chronological_order: In reverse chronological order
614 614
label_preferences: Preferences
615 615
setting_display_subprojects_issues: Display subprojects issues on main projects by default
616
label_overall_activity: Overall activity
trunk/lang/lt.yml
614 614
label_reverse_chronological_order: In reverse chronological order
615 615
label_preferences: Preferences
616 616
setting_display_subprojects_issues: Display subprojects issues on main projects by default
617
label_overall_activity: Overall activity
trunk/lang/nl.yml
614 614
label_reverse_chronological_order: In reverse chronological order
615 615
label_preferences: Preferences
616 616
setting_display_subprojects_issues: Display subprojects issues on main projects by default
617
label_overall_activity: Overall activity
trunk/lang/pl.yml
613 613
field_comments_sorting: Display comments
614 614
label_reverse_chronological_order: In reverse chronological order
615 615
label_preferences: Preferences
616
label_overall_activity: Overall activity
trunk/lang/pt-br.yml
613 613
label_reverse_chronological_order: In reverse chronological order
614 614
label_preferences: Preferences
615 615
setting_display_subprojects_issues: Display subprojects issues on main projects by default
616
label_overall_activity: Overall activity
trunk/lang/pt.yml
613 613
label_reverse_chronological_order: In reverse chronological order
614 614
label_preferences: Preferences
615 615
setting_display_subprojects_issues: Display subprojects issues on main projects by default
616
label_overall_activity: Overall activity
trunk/lang/ro.yml
613 613
label_reverse_chronological_order: In reverse chronological order
614 614
label_preferences: Preferences
615 615
setting_display_subprojects_issues: Display subprojects issues on main projects by default
616
label_overall_activity: Overall activity
trunk/lang/ru.yml
617 617
label_reverse_chronological_order: In reverse chronological order
618 618
label_preferences: Preferences
619 619
setting_display_subprojects_issues: Display subprojects issues on main projects by default
620
label_overall_activity: Overall activity
trunk/lang/sr.yml
614 614
label_reverse_chronological_order: In reverse chronological order
615 615
label_preferences: Preferences
616 616
setting_display_subprojects_issues: Display subprojects issues on main projects by default
617
label_overall_activity: Overall activity
trunk/lang/sv.yml
614 614
label_reverse_chronological_order: In reverse chronological order
615 615
label_preferences: Preferences
616 616
setting_display_subprojects_issues: Display subprojects issues on main projects by default
617
label_overall_activity: Overall activity
trunk/lang/uk.yml
615 615
label_reverse_chronological_order: In reverse chronological order
616 616
label_preferences: Preferences
617 617
setting_display_subprojects_issues: Display subprojects issues on main projects by default
618
label_overall_activity: Overall activity
trunk/lang/zh-tw.yml
614 614
enumeration_issue_priorities: 項目優先權
615 615
enumeration_doc_categories: 文件分類
616 616
enumeration_activities: 活動 (time tracking)
617
label_overall_activity: Overall activity
trunk/lang/zh.yml
614 614
enumeration_issue_priorities: 问题优先级
615 615
enumeration_doc_categories: 文档类别
616 616
enumeration_activities: 活动(时间跟踪)
617
label_overall_activity: Overall activity
trunk/lib/ar_condition.rb
20 20
  
21 21
  def initialize(condition=nil)
22 22
    @conditions = ['1=1']
23
    @conditions.add(condition) if condition
23
    add(condition) if condition
24 24
  end
25 25
  
26 26
  def add(condition)
trunk/public/stylesheets/application.css
169 169
div#activity dt { margin-bottom: 1px; }
170 170
div#activity dt .time { color: #777; font-size: 80%; }
171 171
div#activity dd .description { font-style: italic; }
172
div#activity span.project:after { content: " -"; }
172 173

  
173 174
div#roadmap fieldset.related-issues { margin-bottom: 1em; }
174 175
div#roadmap fieldset.related-issues ul { margin-top: 0.3em; margin-bottom: 0.3em; }
trunk/test/fixtures/issues.yml
44 44
  start_date: <%= 1.day.from_now.to_date.to_s(:db) %>
45 45
  due_date: <%= 40.day.ago.to_date.to_s(:db) %>
46 46
issues_004: 
47
  created_on: 2006-07-19 21:07:27 +02:00
47
  created_on: <%= 5.days.ago.to_date.to_s(:db) %>
48 48
  project_id: 2
49
  updated_on: 2006-07-19 21:07:27 +02:00
49
  updated_on: <%= 2.days.ago.to_date.to_s(:db) %>
50 50
  priority_id: 4
51 51
  subject: Issue on project 2
52 52
  id: 4
......
57 57
  assigned_to_id: 
58 58
  author_id: 2
59 59
  status_id: 1
60
issues_005: 
61
  created_on: <%= 5.days.ago.to_date.to_s(:db) %>
62
  project_id: 3
63
  updated_on: <%= 2.days.ago.to_date.to_s(:db) %>
64
  priority_id: 4
65
  subject: Subproject issue
66
  id: 5
67
  fixed_version_id: 
68
  category_id: 
69
  description: This is an issue on a cookbook subproject
70
  tracker_id: 1
71
  assigned_to_id: 
72
  author_id: 2
73
  status_id: 1
60 74
  
trunk/test/fixtures/messages.yml
45 45
  parent_id: 
46 46
  board_id: 1
47 47
messages_005: 
48
  created_on: 2007-09-12 17:18:00 +02:00
49
  updated_on: 2007-09-12 17:18:00 +02:00
48
  created_on: <%= 3.days.ago.to_date.to_s(:db) %>
49
  updated_on: <%= 3.days.ago.to_date.to_s(:db) %>
50 50
  subject: 'RE: post 2'
51 51
  id: 5
52 52
  replies_count: 0
trunk/test/functional/projects_controller_test.rb
22 22
class ProjectsController; def rescue_action(e) raise e end; end
23 23

  
24 24
class ProjectsControllerTest < Test::Unit::TestCase
25
  fixtures :projects, :versions, :users, :roles, :members, :issues, :journals, :journal_details, :trackers, :projects_trackers, :issue_statuses, :enabled_modules, :enumerations
25
  fixtures :projects, :versions, :users, :roles, :members, :issues, :journals, :journal_details,
26
           :trackers, :projects_trackers, :issue_statuses, :enabled_modules, :enumerations, :boards, :messages
26 27

  
27 28
  def setup
28 29
    @controller = ProjectsController.new
......
129 130
    assert assigns(:versions).include?(Version.find(1))
130 131
  end
131 132

  
132
  def test_activity
133
    get :activity, :id => 1
133
  def test_project_activity
134
    get :activity, :id => 1, :with_subprojects => 0
134 135
    assert_response :success
135 136
    assert_template 'activity'
136 137
    assert_not_nil assigns(:events_by_day)
138
    assert_not_nil assigns(:events)
139

  
140
    # subproject issue not included by default
141
    assert !assigns(:events).include?(Issue.find(5))
137 142
    
138 143
    assert_tag :tag => "h3", 
139 144
               :content => /#{2.days.ago.to_date.day}/,
......
163 168
               }
164 169
  end
165 170
  
171
  def test_activity_with_subprojects
172
    get :activity, :id => 1, :with_subprojects => 1
173
    assert_response :success
174
    assert_template 'activity'
175
    assert_not_nil assigns(:events)
176
    
177
    assert assigns(:events).include?(Issue.find(1))
178
    assert !assigns(:events).include?(Issue.find(4))
179
    # subproject issue
180
    assert assigns(:events).include?(Issue.find(5))
181
  end
182
  
183
  def test_global_activity_anonymous
184
    get :activity
185
    assert_response :success
186
    assert_template 'activity'
187
    assert_not_nil assigns(:events)
188
    
189
    assert assigns(:events).include?(Issue.find(1))
190
    # Issue of a private project
191
    assert !assigns(:events).include?(Issue.find(4))
192
  end
193
  
194
  def test_global_activity_logged_user
195
    @request.session[:user_id] = 2 # manager
196
    get :activity
197
    assert_response :success
198
    assert_template 'activity'
199
    assert_not_nil assigns(:events)
200
    
201
    assert assigns(:events).include?(Issue.find(1))
202
    # Issue of a private project the user belongs to
203
    assert assigns(:events).include?(Issue.find(4))
204
  end
205

  
206
  
207
  def test_global_activity_with_all_types
208
    get :activity, :show_issues => 1, :show_news => 1, :show_files => 1, :show_documents => 1, :show_changesets => 1, :show_wiki_pages => 1, :show_messages => 1
209
    assert_response :success
210
    assert_template 'activity'
211
    assert_not_nil assigns(:events)
212
    
213
    assert assigns(:events).include?(Issue.find(1))
214
    assert !assigns(:events).include?(Issue.find(4))
215
    assert assigns(:events).include?(Message.find(5))
216
  end
217

  
166 218
  def test_calendar
167 219
    get :calendar, :id => 1
168 220
    assert_response :success
trunk/test/unit/project_test.rb
126 126
    assert_equal [1, 2, 3], parent.rolled_up_trackers.collect(&:id)
127 127
    assert_equal [2, 3], child.rolled_up_trackers.collect(&:id)
128 128
  end
129

  
130
  def test_issues_status_changes
131
    journals = @ecookbook.issues_status_changes 3.days.ago.to_date, Date.today
132
    assert_equal 1, journals.size
133
    assert_kind_of Journal, journals.first
134
    
135
    journals = @ecookbook.issues_status_changes 30.days.ago.to_date, 10.days.ago.to_date
136
    assert_equal 0, journals.size
137
  end
138 129
end

Also available in: Unified diff