Feature #23954 » 0001-Adds-last-activity-column-to-projects-list.patch
app/controllers/projects_controller.rb | ||
---|---|---|
48 | 48 |
end |
49 | 49 | |
50 | 50 |
retrieve_project_query |
51 |
scope = project_scope |
|
52 | 51 | |
53 | 52 |
respond_to do |format| |
54 | 53 |
format.html { |
55 | 54 |
# TODO: see what to do with the board view and pagination |
56 | 55 |
if @query.display_type == 'board' |
57 |
@entries = scope.to_a |
|
56 |
@entries = project_scope.to_a
|
|
58 | 57 |
else |
59 |
@entry_count = scope.count
|
|
58 |
@entry_count = @query.result_count
|
|
60 | 59 |
@entry_pages = Paginator.new @entry_count, per_page_option, params['page'] |
61 |
@entries = scope.offset(@entry_pages.offset).limit(@entry_pages.per_page).to_a
|
|
60 |
@entries = project_scope(:offset => @entry_pages.offset, :limit => @entry_pages.per_page).to_a
|
|
62 | 61 |
end |
63 | 62 |
} |
64 | 63 |
format.api { |
65 | 64 |
@offset, @limit = api_offset_and_limit |
66 |
@project_count = scope.count
|
|
67 |
@projects = scope.offset(@offset).limit(@limit).to_a
|
|
65 |
@project_count = @query.result_count
|
|
66 |
@projects = project_scope(:offset => @offset, :limit => @limit)
|
|
68 | 67 |
} |
69 | 68 |
format.atom { |
70 |
projects = scope.reorder(:created_on => :desc).limit(Setting.feeds_limit.to_i).to_a
|
|
69 |
projects = project_scope(:order => {:created_on => :desc}, :limit => Setting.feeds_limit.to_i).to_a
|
|
71 | 70 |
render_feed(projects, :title => "#{Setting.app_title}: #{l(:label_project_latest)}") |
72 | 71 |
} |
73 | 72 |
format.csv { |
74 | 73 |
# Export all entries |
75 |
@entries = scope.to_a |
|
74 |
@entries = project_scope.to_a
|
|
76 | 75 |
send_data(query_to_csv(@entries, @query, params), :type => 'text/csv; header=present', :filename => 'projects.csv') |
77 | 76 |
} |
78 | 77 |
end |
app/models/project.rb | ||
---|---|---|
348 | 348 |
@due_date = nil |
349 | 349 |
@override_members = nil |
350 | 350 |
@assignable_users = nil |
351 |
@last_activity_date = nil |
|
351 | 352 |
base_reload(*args) |
352 | 353 |
end |
353 | 354 | |
... | ... | |
904 | 905 |
end |
905 | 906 |
end |
906 | 907 | |
908 |
def last_activity_date |
|
909 |
@last_activity_date || fetch_last_activity_date |
|
910 |
end |
|
911 | ||
912 |
# Preloads last activity date for a collection of projects |
|
913 |
def self.load_last_activity_date(projects, user=User.current) |
|
914 |
if projects.any? |
|
915 |
last_activities = Redmine::Activity::Fetcher.new(User.current).events(nil, nil, :last_by_project => true).to_h |
|
916 |
projects.each do |project| |
|
917 |
project.instance_variable_set("@last_activity_date", last_activities[project.id]) |
|
918 |
end |
|
919 |
end |
|
920 |
end |
|
921 | ||
907 | 922 |
private |
908 | 923 | |
909 | 924 |
def update_inherited_members |
... | ... | |
1179 | 1194 |
end |
1180 | 1195 |
update_attribute :status, STATUS_ARCHIVED |
1181 | 1196 |
end |
1197 | ||
1198 |
def fetch_last_activity_date |
|
1199 |
latest_activities = Redmine::Activity::Fetcher.new(User.current, :project => self).events(nil, nil, :last_by_project => true) |
|
1200 |
latest_activities.empty? ? nil : latest_activities.to_h[self.id] |
|
1201 |
end |
|
1182 | 1202 |
end |
app/models/project_query.rb | ||
---|---|---|
34 | 34 |
QueryColumn.new(:identifier, :sortable => "#{Project.table_name}.identifier"), |
35 | 35 |
QueryColumn.new(:parent_id, :sortable => "#{Project.table_name}.lft ASC", :default_order => 'desc', :caption => :field_parent), |
36 | 36 |
QueryColumn.new(:is_public, :sortable => "#{Project.table_name}.is_public", :groupable => true), |
37 |
QueryColumn.new(:created_on, :sortable => "#{Project.table_name}.created_on", :default_order => 'desc') |
|
37 |
QueryColumn.new(:created_on, :sortable => "#{Project.table_name}.created_on", :default_order => 'desc'), |
|
38 |
QueryColumn.new(:last_activity_date) |
|
38 | 39 |
] |
39 | 40 | |
40 | 41 |
def initialize(attributes=nil, *args) |
... | ... | |
94 | 95 |
Project.visible.where(statement) |
95 | 96 |
end |
96 | 97 | |
98 |
# Returns the project count |
|
99 |
def result_count |
|
100 |
base_scope.count |
|
101 |
rescue ::ActiveRecord::StatementInvalid => e |
|
102 |
raise StatementInvalid, e.message |
|
103 |
end |
|
104 | ||
97 | 105 |
def results_scope(options={}) |
98 | 106 |
order_option = [group_by_sort_order, (options[:order] || sort_clause)].flatten.reject(&:blank?) |
99 | 107 | |
... | ... | |
110 | 118 |
scope = scope.preload(:parent) |
111 | 119 |
end |
112 | 120 | |
113 |
scope |
|
121 |
projects = scope.to_a |
|
122 |
if has_column?(:last_activity_date) |
|
123 |
Project.load_last_activity_date(scope) |
|
124 |
end |
|
125 |
projects |
|
114 | 126 |
end |
115 | 127 |
end |
config/locales/en.yml | ||
---|---|---|
273 | 273 |
field_downloads: Downloads |
274 | 274 |
field_author: Author |
275 | 275 |
field_created_on: Created |
276 |
field_last_activity_date: Last activity |
|
276 | 277 |
field_updated_on: Updated |
277 | 278 |
field_closed_on: Closed |
278 | 279 |
field_field_format: Format |
config/locales/pt-BR.yml | ||
---|---|---|
228 | 228 |
field_downloads: Downloads |
229 | 229 |
field_author: Autor |
230 | 230 |
field_created_on: Criado em |
231 |
field_last_activity_date: Última atividade |
|
231 | 232 |
field_updated_on: Alterado em |
232 | 233 |
field_field_format: Formato |
233 | 234 |
field_is_for_all: Para todos os projetos |
lib/plugins/acts_as_activity_provider/lib/acts_as_activity_provider.rb | ||
---|---|---|
57 | 57 | |
58 | 58 |
scope = (provider_options[:scope] || self) |
59 | 59 | |
60 |
if from && to |
|
61 |
scope = scope.where("#{provider_options[:timestamp]} BETWEEN ? AND ?", from, to) |
|
62 |
end |
|
60 |
scope = scope.where("#{provider_options[:timestamp]} >= ?", from) if from |
|
61 |
scope = scope.where("#{provider_options[:timestamp]} <= ?", to) if to |
|
63 | 62 | |
64 | 63 |
if options[:author] |
65 | 64 |
return [] if provider_options[:author_key].nil? |
... | ... | |
80 | 79 |
scope = scope.where(Project.allowed_to_condition(user, "view_#{self.name.underscore.pluralize}".to_sym, options)) |
81 | 80 |
end |
82 | 81 | |
82 |
if options[:last_by_project] |
|
83 |
scope = scope.group("#{Project.table_name}.id").maximum(provider_options[:timestamp]) |
|
84 |
end |
|
85 | ||
83 | 86 |
scope.to_a |
84 | 87 |
end |
85 | 88 |
end |
lib/redmine/activity/fetcher.rb | ||
---|---|---|
87 | 87 |
def events(from = nil, to = nil, options={}) |
88 | 88 |
e = [] |
89 | 89 |
@options[:limit] = options[:limit] |
90 |
@options[:last_by_project] = options[:last_by_project] if options[:last_by_project] |
|
90 | 91 | |
91 | 92 |
@scope.each do |event_type| |
92 | 93 |
constantized_providers(event_type).each do |provider| |
... | ... | |
94 | 95 |
end |
95 | 96 |
end |
96 | 97 | |
97 |
e.sort! {|a,b| b.event_datetime <=> a.event_datetime} |
|
98 |
if options[:last_by_project] |
|
99 |
e.sort! |
|
100 |
else |
|
101 |
e.sort! {|a,b| b.event_datetime <=> a.event_datetime} |
|
98 | 102 | |
99 |
if options[:limit] |
|
100 |
e = e.slice(0, options[:limit]) |
|
103 |
if options[:limit] |
|
104 |
e = e.slice(0, options[:limit]) |
|
105 |
end |
|
101 | 106 |
end |
102 | 107 |
e |
103 | 108 |
end |
test/functional/projects_controller_test.rb | ||
---|---|---|
248 | 248 |
assert_select ".total-for-cf-#{field.id} span.value", :text => '9' |
249 | 249 |
end |
250 | 250 | |
251 |
def test_index_with_last_activity_date_column |
|
252 |
with_settings :project_list_defaults => {'column_names' => %w(name short_description last_activity_date)} do |
|
253 |
get :index, :params => { |
|
254 |
:display_type => 'list' |
|
255 |
} |
|
256 |
assert_response :success |
|
257 |
end |
|
258 | ||
259 |
assert_equal ['Name', 'Description', 'Last activity'], columns_in_list |
|
260 | ||
261 |
assert_select 'tr#project-1 td.last_activity_date', :text => format_time(Journal.find(3).created_on) |
|
262 |
assert_select 'tr#project-4 td.last_activity_date', :text => '' |
|
263 |
end |
|
264 | ||
251 | 265 |
def test_autocomplete_js |
252 | 266 |
get( |
253 | 267 |
:autocomplete, |
test/unit/project_test.rb | ||
---|---|---|
1081 | 1081 |
assert_equal 'valuea', project.custom_field_value(cf1) |
1082 | 1082 |
assert_nil project.custom_field_value(cf2) |
1083 | 1083 |
end |
1084 | ||
1085 |
def test_last_activity_date |
|
1086 |
# Note with id 3 is the last activity on Project 1 |
|
1087 |
assert_equal Journal.find(3).created_on, Project.find(1).last_activity_date |
|
1088 | ||
1089 |
# Project without activity should return nil |
|
1090 |
assert_equal nil, Project.find(4).last_activity_date |
|
1091 |
end |
|
1084 | 1092 |
end |
- « Previous
- 1
- …
- 7
- 8
- 9
- Next »