##// END OF EJS Templates
Activity enhancements:...
Jean-Philippe Lang -
r1213:624723d0cef9
parent child
Show More
@@ -24,8 +24,9 class ProjectsController < ApplicationController
24 menu_item :settings, :only => :settings
24 menu_item :settings, :only => :settings
25 menu_item :issues, :only => [:changelog]
25 menu_item :issues, :only => [:changelog]
26
26
27 before_filter :find_project, :except => [ :index, :list, :add ]
27 before_filter :find_project, :except => [ :index, :list, :add, :activity ]
28 before_filter :authorize, :except => [ :index, :list, :add, :archive, :unarchive, :destroy ]
28 before_filter :find_optional_project, :only => :activity
29 before_filter :authorize, :except => [ :index, :list, :add, :archive, :unarchive, :destroy, :activity ]
29 before_filter :require_admin, :only => [ :add, :archive, :unarchive, :destroy ]
30 before_filter :require_admin, :only => [ :add, :archive, :unarchive, :destroy ]
30 accept_key_auth :activity, :calendar
31 accept_key_auth :activity, :calendar
31
32
@@ -228,12 +229,14 class ProjectsController < ApplicationController
228 @date_from = @date_to - @days
229 @date_from = @date_to - @days
229
230
230 @event_types = %w(issues news files documents changesets wiki_pages messages)
231 @event_types = %w(issues news files documents changesets wiki_pages messages)
231 @event_types.delete('wiki_pages') unless @project.wiki
232 if @project
232 @event_types.delete('changesets') unless @project.repository
233 @event_types.delete('wiki_pages') unless @project.wiki
233 @event_types.delete('messages') unless @project.boards.any?
234 @event_types.delete('changesets') unless @project.repository
234 # only show what the user is allowed to view
235 @event_types.delete('messages') unless @project.boards.any?
235 @event_types = @event_types.select {|o| User.current.allowed_to?("view_#{o}".to_sym, @project)}
236 # only show what the user is allowed to view
236
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 @scope = @event_types.select {|t| params["show_#{t}"]}
240 @scope = @event_types.select {|t| params["show_#{t}"]}
238 # default events if none is specified in parameters
241 # default events if none is specified in parameters
239 @scope = (@event_types - %w(wiki_pages messages))if @scope.empty?
242 @scope = (@event_types - %w(wiki_pages messages))if @scope.empty?
@@ -241,21 +244,41 class ProjectsController < ApplicationController
241 @events = []
244 @events = []
242
245
243 if @scope.include?('issues')
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] )
247 cond = ARCondition.new(Project.allowed_to_condition(User.current, :view_issues, :project => @project, :with_subprojects => @with_subprojects))
245 @events += @project.issues_status_changes(@date_from, @date_to)
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 end
254 end
247
255
248 if @scope.include?('news')
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 end
260 end
251
261
252 if @scope.include?('files')
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 end
269 end
255
270
256 if @scope.include?('documents')
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] )
272 cond = ARCondition.new(Project.allowed_to_condition(User.current, :view_documents, :project => @project, :with_subprojects => @with_subprojects))
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 )
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 end
282 end
260
283
261 if @scope.include?('wiki_pages')
284 if @scope.include?('wiki_pages')
@@ -264,28 +287,31 class ProjectsController < ApplicationController
264 "#{WikiContent.versioned_table_name}.page_id, #{WikiContent.versioned_table_name}.author_id, " +
287 "#{WikiContent.versioned_table_name}.page_id, #{WikiContent.versioned_table_name}.author_id, " +
265 "#{WikiContent.versioned_table_name}.id"
288 "#{WikiContent.versioned_table_name}.id"
266 joins = "LEFT JOIN #{WikiPage.table_name} ON #{WikiPage.table_name}.id = #{WikiContent.versioned_table_name}.page_id " +
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 "
290 "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 ?",
291 "LEFT JOIN #{Project.table_name} ON #{Project.table_name}.id = #{Wiki.table_name}.project_id"
269 @project.id, @date_from, @date_to]
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 end
296 end
273
297
274 if @scope.include?('changesets')
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 end
302 end
277
303
278 if @scope.include?('messages')
304 if @scope.include?('messages')
279 @events += Message.find(:all,
305 cond = ARCondition.new(Project.allowed_to_condition(User.current, :view_messages, :project => @project, :with_subprojects => @with_subprojects))
280 :include => [:board, :author],
306 cond.add(["#{Message.table_name}.created_on BETWEEN ? AND ?", @date_from, @date_to])
281 :conditions => ["#{Board.table_name}.project_id=? AND #{Message.table_name}.created_on BETWEEN ? AND ?", @project.id, @date_from, @date_to])
307 @events += Message.find(:all, :include => [{:board => :project}, :author], :conditions => cond.conditions)
282 end
308 end
283
309
284 @events_by_day = @events.group_by(&:event_date)
310 @events_by_day = @events.group_by(&:event_date)
285
311
286 respond_to do |format|
312 respond_to do |format|
287 format.html { render :layout => false if request.xhr? }
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 end
315 end
290 end
316 end
291
317
@@ -381,6 +407,14 private
381 render_404
407 render_404
382 end
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 def retrieve_selected_tracker_ids(selectable_trackers)
418 def retrieve_selected_tracker_ids(selectable_trackers)
385 if ids = params[:tracker_ids]
419 if ids = params[:tracker_ids]
386 @selected_tracker_ids = (ids.is_a? Array) ? ids.collect { |id| id.to_i.to_s } : ids.split('/').collect { |id| id.to_i.to_s }
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 }
@@ -26,7 +26,6 class Attachment < ActiveRecord::Base
26 validates_length_of :disk_filename, :maximum => 255
26 validates_length_of :disk_filename, :maximum => 255
27
27
28 acts_as_event :title => :filename,
28 acts_as_event :title => :filename,
29 :description => :filename,
30 :url => Proc.new {|o| {:controller => 'attachments', :action => 'download', :id => o.id}}
29 :url => Proc.new {|o| {:controller => 'attachments', :action => 'download', :id => o.id}}
31
30
32 cattr_accessor :storage_path
31 cattr_accessor :storage_path
@@ -45,6 +45,10 class Changeset < ActiveRecord::Base
45 super
45 super
46 end
46 end
47
47
48 def project
49 repository.project
50 end
51
48 def after_create
52 def after_create
49 scan_comment_for_issue_ids
53 scan_comment_for_issue_ids
50 end
54 end
@@ -84,16 +84,6 class Project < ActiveRecord::Base
84 end
84 end
85 end
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 # returns latest created projects
87 # returns latest created projects
98 # non public projects will be returned only if user is a member of those
88 # non public projects will be returned only if user is a member of those
99 def self.latest(user=nil, count=5)
89 def self.latest(user=nil, count=5)
@@ -110,19 +100,28 class Project < ActiveRecord::Base
110 end
100 end
111 end
101 end
112
102
113 def self.allowed_to_condition(user, permission)
103 def self.allowed_to_condition(user, permission, options={})
114 statements = []
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 if user.admin?
111 if user.admin?
117 # no restriction
112 # no restriction
118 elsif user.logged?
113 elsif user.logged?
119 statements << "#{Project.table_name}.is_public = #{connection.quoted_true}" if Role.non_member.allowed_to?(permission)
114 statements << "#{Project.table_name}.is_public = #{connection.quoted_true}" if Role.non_member.allowed_to?(permission)
120 allowed_project_ids = user.memberships.select {|m| m.role.allowed_to?(permission)}.collect {|m| m.project_id}
115 allowed_project_ids = user.memberships.select {|m| m.role.allowed_to?(permission)}.collect {|m| m.project_id}
121 statements << "#{Project.table_name}.id IN (#{allowed_project_ids.join(',')})" if allowed_project_ids.any?
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 else
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 end
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 end
125 end
127
126
128 def self.find(*args)
127 def self.find(*args)
@@ -61,6 +61,10 class WikiContent < ActiveRecord::Base
61 end
61 end
62 end
62 end
63
63
64 def project
65 page.project
66 end
67
64 # Returns the previous version or nil
68 # Returns the previous version or nil
65 def previous
69 def previous
66 @previous ||= WikiContent::Version.find(:first,
70 @previous ||= WikiContent::Version.find(:first,
@@ -9,9 +9,10 xml.feed "xmlns" => "http://www.w3.org/2005/Atom" do
9 xml.generator(:uri => Redmine::Info.url, :version => Redmine::VERSION) { xml.text! Redmine::Info.versioned_name; }
9 xml.generator(:uri => Redmine::Info.url, :version => Redmine::VERSION) { xml.text! Redmine::Info.versioned_name; }
10 @items.each do |item|
10 @items.each do |item|
11 xml.entry do
11 xml.entry do
12 url = url_for(item.event_url(:only_path => false))
12 xml.title truncate(item.event_title, 100)
13 xml.title truncate(item.event_title, 100)
13 xml.link "rel" => "alternate", "href" => url_for(item.event_url(:only_path => false))
14 xml.link "rel" => "alternate", "href" => url
14 xml.id url_for(item.event_url(:only_path => false))
15 xml.id url
15 xml.updated item.event_datetime.xmlschema
16 xml.updated item.event_datetime.xmlschema
16 author = item.event_author if item.respond_to?(:author)
17 author = item.event_author if item.respond_to?(:author)
17 xml.author do
18 xml.author do
@@ -6,7 +6,7
6 <dl>
6 <dl>
7 <% @events_by_day[day].sort {|x,y| y.event_datetime <=> x.event_datetime }.each do |e| -%>
7 <% @events_by_day[day].sort {|x,y| y.event_datetime <=> x.event_datetime }.each do |e| -%>
8 <dt class="<%= e.class.name.downcase %>"><span class="time"><%= format_time(e.event_datetime, false) %></span>
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 <dd><% unless e.event_description.blank? -%>
10 <dd><% unless e.event_description.blank? -%>
11 <span class="description"><%= format_activity_description(e.event_description) %></span><br />
11 <span class="description"><%= format_activity_description(e.event_description) %></span><br />
12 <% end %>
12 <% end %>
@@ -35,16 +35,20
35 </p>
35 </p>
36
36
37 <% content_for :header_tags do %>
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 <% end %>
39 <% end %>
40
40
41 <% content_for :sidebar do %>
41 <% content_for :sidebar do %>
42 <% form_tag do %>
42 <% form_tag({}, :method => :get) do %>
43 <h3><%= l(:label_activity) %></h3>
43 <h3><%= l(:label_activity) %></h3>
44 <p><% @event_types.each do |t| %>
44 <p><% @event_types.each do |t| %>
45 <label><%= check_box_tag "show_#{t}", 1, @scope.include?(t) %> <%= l("label_#{t.singularize}_plural")%></label><br />
45 <label><%= check_box_tag "show_#{t}", 1, @scope.include?(t) %> <%= l("label_#{t.singularize}_plural")%></label><br />
46 <% end %></p>
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 %>
50 <% end %>
51 <p><%= submit_tag l(:button_apply), :class => 'button-small', :name => nil %></p>
48 <% end %>
52 <% end %>
49 <% end %>
53 <% end %>
50
54
@@ -1,3 +1,8
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 <h2><%=l(:label_project_plural)%></h2>
6 <h2><%=l(:label_project_plural)%></h2>
2
7
3 <% @project_tree.keys.sort.each do |project| %>
8 <% @project_tree.keys.sort.each do |project| %>
@@ -26,5 +26,8
26 </div>
26 </div>
27
27
28 <% content_for :header_tags do %>
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 <% end %>
33 <% end %>
@@ -613,3 +613,4 field_comments_sorting: Display comments
613 label_reverse_chronological_order: In reverse chronological order
613 label_reverse_chronological_order: In reverse chronological order
614 label_preferences: Preferences
614 label_preferences: Preferences
615 setting_display_subprojects_issues: Display subprojects issues on main projects by default
615 setting_display_subprojects_issues: Display subprojects issues on main projects by default
616 label_overall_activity: Overall activity
@@ -613,3 +613,4 field_comments_sorting: Display comments
613 label_reverse_chronological_order: In reverse chronological order
613 label_reverse_chronological_order: In reverse chronological order
614 label_preferences: Preferences
614 label_preferences: Preferences
615 setting_display_subprojects_issues: Display subprojects issues on main projects by default
615 setting_display_subprojects_issues: Display subprojects issues on main projects by default
616 label_overall_activity: Overall activity
@@ -615,3 +615,4 field_comments_sorting: Display comments
615 text_reassign_time_entries: 'Reassign reported hours to this issue:'
615 text_reassign_time_entries: 'Reassign reported hours to this issue:'
616 label_reverse_chronological_order: In reverse chronological order
616 label_reverse_chronological_order: In reverse chronological order
617 label_preferences: Preferences
617 label_preferences: Preferences
618 label_overall_activity: Overall activity
@@ -614,3 +614,4 field_comments_sorting: Display comments
614 label_reverse_chronological_order: In reverse chronological order
614 label_reverse_chronological_order: In reverse chronological order
615 label_preferences: Preferences
615 label_preferences: Preferences
616 setting_display_subprojects_issues: Display subprojects issues on main projects by default
616 setting_display_subprojects_issues: Display subprojects issues on main projects by default
617 label_overall_activity: Overall activity
@@ -280,6 +280,7 label_last_updates: Last updated
280 label_last_updates_plural: %d last updated
280 label_last_updates_plural: %d last updated
281 label_registered_on: Registered on
281 label_registered_on: Registered on
282 label_activity: Activity
282 label_activity: Activity
283 label_overall_activity: Overall activity
283 label_new: New
284 label_new: New
284 label_logged_as: Logged as
285 label_logged_as: Logged as
285 label_environment: Environment
286 label_environment: Environment
@@ -616,3 +616,4 field_comments_sorting: Display comments
616 label_reverse_chronological_order: In reverse chronological order
616 label_reverse_chronological_order: In reverse chronological order
617 label_preferences: Preferences
617 label_preferences: Preferences
618 setting_display_subprojects_issues: Display subprojects issues on main projects by default
618 setting_display_subprojects_issues: Display subprojects issues on main projects by default
619 label_overall_activity: Overall activity
@@ -620,3 +620,4 setting_display_subprojects_issues: Display subprojects issues on main projects
620 field_comments_sorting: Display comments
620 field_comments_sorting: Display comments
621 label_reverse_chronological_order: In reverse chronological order
621 label_reverse_chronological_order: In reverse chronological order
622 label_preferences: Preferences
622 label_preferences: Preferences
623 label_overall_activity: Overall activity
@@ -165,6 +165,7 field_start_page: Page de démarrage
165 field_subproject: Sous-projet
165 field_subproject: Sous-projet
166 field_hours: Heures
166 field_hours: Heures
167 field_activity: Activité
167 field_activity: Activité
168 label_overall_activity: Activité globale
168 field_spent_on: Date
169 field_spent_on: Date
169 field_identifier: Identifiant
170 field_identifier: Identifiant
170 field_is_filter: Utilisé comme filtre
171 field_is_filter: Utilisé comme filtre
@@ -452,7 +453,7 label_start_to_start: début à début
452 label_start_to_end: début à fin
453 label_start_to_end: début à fin
453 label_stay_logged_in: Rester connecté
454 label_stay_logged_in: Rester connecté
454 label_disabled: désactivé
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 label_me: moi
457 label_me: moi
457 label_board: Forum
458 label_board: Forum
458 label_board_new: Nouveau forum
459 label_board_new: Nouveau forum
@@ -613,3 +613,4 field_comments_sorting: Display comments
613 label_reverse_chronological_order: In reverse chronological order
613 label_reverse_chronological_order: In reverse chronological order
614 label_preferences: Preferences
614 label_preferences: Preferences
615 setting_display_subprojects_issues: Display subprojects issues on main projects by default
615 setting_display_subprojects_issues: Display subprojects issues on main projects by default
616 label_overall_activity: Overall activity
@@ -613,3 +613,4 field_comments_sorting: Display comments
613 label_reverse_chronological_order: In reverse chronological order
613 label_reverse_chronological_order: In reverse chronological order
614 label_preferences: Preferences
614 label_preferences: Preferences
615 setting_display_subprojects_issues: Display subprojects issues on main projects by default
615 setting_display_subprojects_issues: Display subprojects issues on main projects by default
616 label_overall_activity: Overall activity
@@ -614,3 +614,4 field_comments_sorting: Display comments
614 label_reverse_chronological_order: In reverse chronological order
614 label_reverse_chronological_order: In reverse chronological order
615 label_preferences: Preferences
615 label_preferences: Preferences
616 setting_display_subprojects_issues: Display subprojects issues on main projects by default
616 setting_display_subprojects_issues: Display subprojects issues on main projects by default
617 label_overall_activity: Overall activity
@@ -613,3 +613,4 field_comments_sorting: Display comments
613 label_reverse_chronological_order: In reverse chronological order
613 label_reverse_chronological_order: In reverse chronological order
614 label_preferences: Preferences
614 label_preferences: Preferences
615 setting_display_subprojects_issues: Display subprojects issues on main projects by default
615 setting_display_subprojects_issues: Display subprojects issues on main projects by default
616 label_overall_activity: Overall activity
@@ -614,3 +614,4 field_comments_sorting: Display comments
614 label_reverse_chronological_order: In reverse chronological order
614 label_reverse_chronological_order: In reverse chronological order
615 label_preferences: Preferences
615 label_preferences: Preferences
616 setting_display_subprojects_issues: Display subprojects issues on main projects by default
616 setting_display_subprojects_issues: Display subprojects issues on main projects by default
617 label_overall_activity: Overall activity
@@ -614,3 +614,4 field_comments_sorting: Display comments
614 label_reverse_chronological_order: In reverse chronological order
614 label_reverse_chronological_order: In reverse chronological order
615 label_preferences: Preferences
615 label_preferences: Preferences
616 setting_display_subprojects_issues: Display subprojects issues on main projects by default
616 setting_display_subprojects_issues: Display subprojects issues on main projects by default
617 label_overall_activity: Overall activity
@@ -613,3 +613,4 setting_display_subprojects_issues: Display subprojects issues on main projects
613 field_comments_sorting: Display comments
613 field_comments_sorting: Display comments
614 label_reverse_chronological_order: In reverse chronological order
614 label_reverse_chronological_order: In reverse chronological order
615 label_preferences: Preferences
615 label_preferences: Preferences
616 label_overall_activity: Overall activity
@@ -613,3 +613,4 field_comments_sorting: Display comments
613 label_reverse_chronological_order: In reverse chronological order
613 label_reverse_chronological_order: In reverse chronological order
614 label_preferences: Preferences
614 label_preferences: Preferences
615 setting_display_subprojects_issues: Display subprojects issues on main projects by default
615 setting_display_subprojects_issues: Display subprojects issues on main projects by default
616 label_overall_activity: Overall activity
@@ -613,3 +613,4 field_comments_sorting: Display comments
613 label_reverse_chronological_order: In reverse chronological order
613 label_reverse_chronological_order: In reverse chronological order
614 label_preferences: Preferences
614 label_preferences: Preferences
615 setting_display_subprojects_issues: Display subprojects issues on main projects by default
615 setting_display_subprojects_issues: Display subprojects issues on main projects by default
616 label_overall_activity: Overall activity
@@ -613,3 +613,4 field_comments_sorting: Display comments
613 label_reverse_chronological_order: In reverse chronological order
613 label_reverse_chronological_order: In reverse chronological order
614 label_preferences: Preferences
614 label_preferences: Preferences
615 setting_display_subprojects_issues: Display subprojects issues on main projects by default
615 setting_display_subprojects_issues: Display subprojects issues on main projects by default
616 label_overall_activity: Overall activity
@@ -617,3 +617,4 field_comments_sorting: Display comments
617 label_reverse_chronological_order: In reverse chronological order
617 label_reverse_chronological_order: In reverse chronological order
618 label_preferences: Preferences
618 label_preferences: Preferences
619 setting_display_subprojects_issues: Display subprojects issues on main projects by default
619 setting_display_subprojects_issues: Display subprojects issues on main projects by default
620 label_overall_activity: Overall activity
@@ -614,3 +614,4 field_comments_sorting: Display comments
614 label_reverse_chronological_order: In reverse chronological order
614 label_reverse_chronological_order: In reverse chronological order
615 label_preferences: Preferences
615 label_preferences: Preferences
616 setting_display_subprojects_issues: Display subprojects issues on main projects by default
616 setting_display_subprojects_issues: Display subprojects issues on main projects by default
617 label_overall_activity: Overall activity
@@ -614,3 +614,4 field_comments_sorting: Display comments
614 label_reverse_chronological_order: In reverse chronological order
614 label_reverse_chronological_order: In reverse chronological order
615 label_preferences: Preferences
615 label_preferences: Preferences
616 setting_display_subprojects_issues: Display subprojects issues on main projects by default
616 setting_display_subprojects_issues: Display subprojects issues on main projects by default
617 label_overall_activity: Overall activity
@@ -615,3 +615,4 field_comments_sorting: Display comments
615 label_reverse_chronological_order: In reverse chronological order
615 label_reverse_chronological_order: In reverse chronological order
616 label_preferences: Preferences
616 label_preferences: Preferences
617 setting_display_subprojects_issues: Display subprojects issues on main projects by default
617 setting_display_subprojects_issues: Display subprojects issues on main projects by default
618 label_overall_activity: Overall activity
@@ -614,3 +614,4 default_activity_development: 開發
614 enumeration_issue_priorities: 項目優先權
614 enumeration_issue_priorities: 項目優先權
615 enumeration_doc_categories: 文件分類
615 enumeration_doc_categories: 文件分類
616 enumeration_activities: 活動 (time tracking)
616 enumeration_activities: 活動 (time tracking)
617 label_overall_activity: Overall activity
@@ -614,3 +614,4 default_activity_development: 开发
614 enumeration_issue_priorities: 问题优先级
614 enumeration_issue_priorities: 问题优先级
615 enumeration_doc_categories: 文档类别
615 enumeration_doc_categories: 文档类别
616 enumeration_activities: 活动(时间跟踪)
616 enumeration_activities: 活动(时间跟踪)
617 label_overall_activity: Overall activity
@@ -20,7 +20,7 class ARCondition
20
20
21 def initialize(condition=nil)
21 def initialize(condition=nil)
22 @conditions = ['1=1']
22 @conditions = ['1=1']
23 @conditions.add(condition) if condition
23 add(condition) if condition
24 end
24 end
25
25
26 def add(condition)
26 def add(condition)
@@ -169,6 +169,7 div#activity dd { margin-bottom: 1em; }
169 div#activity dt { margin-bottom: 1px; }
169 div#activity dt { margin-bottom: 1px; }
170 div#activity dt .time { color: #777; font-size: 80%; }
170 div#activity dt .time { color: #777; font-size: 80%; }
171 div#activity dd .description { font-style: italic; }
171 div#activity dd .description { font-style: italic; }
172 div#activity span.project:after { content: " -"; }
172
173
173 div#roadmap fieldset.related-issues { margin-bottom: 1em; }
174 div#roadmap fieldset.related-issues { margin-bottom: 1em; }
174 div#roadmap fieldset.related-issues ul { margin-top: 0.3em; margin-bottom: 0.3em; }
175 div#roadmap fieldset.related-issues ul { margin-top: 0.3em; margin-bottom: 0.3em; }
@@ -44,9 +44,9 issues_003:
44 start_date: <%= 1.day.from_now.to_date.to_s(:db) %>
44 start_date: <%= 1.day.from_now.to_date.to_s(:db) %>
45 due_date: <%= 40.day.ago.to_date.to_s(:db) %>
45 due_date: <%= 40.day.ago.to_date.to_s(:db) %>
46 issues_004:
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 project_id: 2
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 priority_id: 4
50 priority_id: 4
51 subject: Issue on project 2
51 subject: Issue on project 2
52 id: 4
52 id: 4
@@ -57,4 +57,18 issues_004:
57 assigned_to_id:
57 assigned_to_id:
58 author_id: 2
58 author_id: 2
59 status_id: 1
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
@@ -45,8 +45,8 messages_004:
45 parent_id:
45 parent_id:
46 board_id: 1
46 board_id: 1
47 messages_005:
47 messages_005:
48 created_on: 2007-09-12 17:18:00 +02:00
48 created_on: <%= 3.days.ago.to_date.to_s(:db) %>
49 updated_on: 2007-09-12 17:18:00 +02:00
49 updated_on: <%= 3.days.ago.to_date.to_s(:db) %>
50 subject: 'RE: post 2'
50 subject: 'RE: post 2'
51 id: 5
51 id: 5
52 replies_count: 0
52 replies_count: 0
@@ -22,7 +22,8 require 'projects_controller'
22 class ProjectsController; def rescue_action(e) raise e end; end
22 class ProjectsController; def rescue_action(e) raise e end; end
23
23
24 class ProjectsControllerTest < Test::Unit::TestCase
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 def setup
28 def setup
28 @controller = ProjectsController.new
29 @controller = ProjectsController.new
@@ -129,11 +130,15 class ProjectsControllerTest < Test::Unit::TestCase
129 assert assigns(:versions).include?(Version.find(1))
130 assert assigns(:versions).include?(Version.find(1))
130 end
131 end
131
132
132 def test_activity
133 def test_project_activity
133 get :activity, :id => 1
134 get :activity, :id => 1, :with_subprojects => 0
134 assert_response :success
135 assert_response :success
135 assert_template 'activity'
136 assert_template 'activity'
136 assert_not_nil assigns(:events_by_day)
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 assert_tag :tag => "h3",
143 assert_tag :tag => "h3",
139 :content => /#{2.days.ago.to_date.day}/,
144 :content => /#{2.days.ago.to_date.day}/,
@@ -163,6 +168,53 class ProjectsControllerTest < Test::Unit::TestCase
163 }
168 }
164 end
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 def test_calendar
218 def test_calendar
167 get :calendar, :id => 1
219 get :calendar, :id => 1
168 assert_response :success
220 assert_response :success
@@ -126,13 +126,4 class ProjectTest < Test::Unit::TestCase
126 assert_equal [1, 2, 3], parent.rolled_up_trackers.collect(&:id)
126 assert_equal [1, 2, 3], parent.rolled_up_trackers.collect(&:id)
127 assert_equal [2, 3], child.rolled_up_trackers.collect(&:id)
127 assert_equal [2, 3], child.rolled_up_trackers.collect(&:id)
128 end
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 end
129 end
General Comments 0
You need to be logged in to leave comments. Login now