@@ -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(' |
|
233 | @event_types.delete('wiki_pages') unless @project.wiki | |
233 |
@event_types.delete(' |
|
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. |
|
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 |
|
|
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? ? |
|
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 |
|
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) |
|
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'}, |
|
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: Voir |
|
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 |
|
|
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, |
|
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