annotate app/helpers/activities_helper.rb @ 1298:4f746d8966dd redmine_2.3_integration

Merge from redmine-2.3 branch to create new branch redmine-2.3-integration
author Chris Cannam
date Fri, 14 Jun 2013 09:28:30 +0100
parents eb168c1e9553 622f24f53b42
children
rev   line source
Chris@1295 1 # encoding: utf-8
Chris@1295 2 #
Chris@1295 3 # Redmine - project management software
Chris@1295 4 # Copyright (C) 2006-2013 Jean-Philippe Lang
Chris@1295 5 #
Chris@1295 6 # This program is free software; you can redistribute it and/or
Chris@1295 7 # modify it under the terms of the GNU General Public License
Chris@1295 8 # as published by the Free Software Foundation; either version 2
Chris@1295 9 # of the License, or (at your option) any later version.
Chris@1295 10 #
Chris@1295 11 # This program is distributed in the hope that it will be useful,
Chris@1295 12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
Chris@1295 13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
Chris@1295 14 # GNU General Public License for more details.
Chris@1295 15 #
Chris@1295 16 # You should have received a copy of the GNU General Public License
Chris@1295 17 # along with this program; if not, write to the Free Software
Chris@1295 18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
Chris@1295 19
Chris@1295 20 module ActivitiesHelper
chris@1011 21
chris@1205 22 def date_of_event(e)
chris@1205 23 if e.respond_to? :updated_at
chris@1205 24 e.updated_at
chris@1205 25 elsif e.respond_to? :updated_on
chris@1205 26 e.updated_on
chris@1205 27 elsif e.respond_to? :created_on
chris@1205 28 e.created_on
chris@1205 29 elsif e.respond_to? :committed_on
chris@1205 30 e.committed_on
chris@1205 31 else
chris@1205 32 nil
chris@1205 33 end
chris@1205 34 end
chris@1205 35
chris@1217 36 def project_activity_on_events(events)
chris@1186 37
chris@1186 38 # Score each project for which there are any events, by giving
chris@1186 39 # each event a score based on how long ago it was (the more recent
chris@1217 40 # the better). Return a hash mapping project id to score.
chris@1186 41
chris@1186 42 projhash = Hash.new
chris@1186 43
chris@1186 44 events.each do |e|
chris@1186 45 if e.respond_to?(:project)
chris@1186 46 p = e.project
chris@1205 47 d = date_of_event e
chris@1205 48 if !d.nil?
chris@1205 49 dd = Date.parse d.to_s
chris@1205 50 age = Date.today - dd
chris@1205 51 score = (age < 14 ? 15-age : 1)
chris@1205 52 if projhash.key? p
chris@1205 53 projhash[p] += score
chris@1205 54 else
chris@1205 55 projhash[p] = score
chris@1205 56 end
chris@1186 57 end
chris@1186 58 end
chris@1186 59 end
chris@1186 60
chris@1217 61 projhash
chris@1217 62 end
chris@1217 63
chris@1217 64 def projects_by_activity(user, count)
chris@1217 65
Chris@1227 66 # Return up to count of the user's project ids ordered by that user's
chris@1217 67 # recent activity, omitting any projects for which no activity
Chris@1219 68 # occurred in the recent past and any projects not visible to
Chris@1219 69 # the current user
chris@1217 70
Chris@1219 71 activity = Redmine::Activity::Fetcher.new(User.current, :author => user)
chris@1224 72
chris@1224 73 # Limit scope so as to exclude issues (which non-members can add)
chris@1224 74 activity.scope = [ "changesets", "files", "documents", "news", "wiki_edits", "messages", "time_entries", "publications" ]
chris@1224 75
chris@1217 76 days = Setting.activity_days_default.to_i
chris@1217 77 events = activity.events(Date.today - days, Date.today + 1)
chris@1217 78 projhash = project_activity_on_events(events)
chris@1217 79 projhash.keys.sort_by { |k| -projhash[k] }.first(count)
chris@1217 80 end
chris@1217 81
chris@1217 82 def render_active_colleagues(colleagues)
chris@1217 83
chris@1217 84 s = ""
chris@1217 85
chris@1222 86 start = Time.now
chris@1222 87
Chris@1226 88 my_inst = ""
Chris@1226 89 if ! User.current.ssamr_user_detail.nil?
Chris@1226 90 my_inst = User.current.ssamr_user_detail.institution_name
Chris@1226 91 end
Chris@1226 92
Chris@1227 93 actives = Hash.new
chris@1217 94 for c in colleagues
chris@1217 95 u = User.find_by_id(c)
chris@1217 96 active_projects = projects_by_activity(u, 3)
chris@1217 97 if !active_projects.empty?
Chris@1227 98 actives[c] = active_projects
Chris@1227 99 end
Chris@1227 100 end
Chris@1227 101
Chris@1227 102 if actives.empty?
Chris@1227 103 l(:label_no_active_colleagues)
Chris@1227 104 else
Chris@1227 105
Chris@1227 106 s << "<dl>"
Chris@1227 107 for c in actives.keys.sample(10)
Chris@1227 108 u = User.find_by_id(c)
chris@1224 109 s << "<dt>"
Chris@1219 110 s << avatar(u, :size => '24')
Chris@1219 111 s << "<span class='user'>"
Chris@1219 112 s << h(u.name)
chris@1217 113 s << "</span>"
Chris@1219 114 if !u.ssamr_user_detail.nil?
Chris@1226 115 inst = u.ssamr_user_detail.institution_name
Chris@1226 116 if inst != "" and inst != my_inst
Chris@1226 117 s << " - <span class='institution'>"
Chris@1226 118 s << h(u.ssamr_user_detail.institution_name)
Chris@1226 119 s << "</span>"
Chris@1226 120 end
Chris@1219 121 end
chris@1224 122 s << "</dt>"
chris@1224 123 s << "<dd>"
Chris@1219 124 s << "<span class='active'>"
Chris@1227 125 s << (actives[c].map { |p| link_to_project(p) }.join ", ")
Chris@1219 126 s << "</span>"
chris@1217 127 end
Chris@1227 128 s << "</dl>"
chris@1222 129
Chris@1227 130 finish = Time.now
Chris@1227 131 logger.info "render_active_colleagues: took #{finish-start}"
chris@1217 132
chris@1217 133 s
chris@1217 134 end
chris@1217 135 end
chris@1217 136
chris@1217 137 def busy_projects(events, count)
chris@1217 138
chris@1217 139 # Return a list of count projects randomly selected from amongst
chris@1217 140 # the busiest projects represented by the given activity events
chris@1217 141
chris@1217 142 projhash = project_activity_on_events(events)
chris@1217 143
chris@1186 144 # pick N highest values and use cutoff value as selection threshold
chris@1186 145 threshold = projhash.values.sort.last(count).first
chris@1186 146
chris@1186 147 # select projects above threshold and pick N from them randomly
chris@1186 148 busy = projhash.keys.select { |k| projhash[k] >= threshold }.sample(count)
chris@1186 149
chris@1186 150 # return projects rather than just ids
chris@1011 151 busy.map { |pid| Project.find(pid) }
chris@1011 152 end
chris@1011 153
chris@1011 154 def busy_institutions(events, count)
Chris@1013 155 authors = events.map do |e|
Chris@1013 156 e.event_author unless !e.respond_to?(:event_author)
Chris@1013 157 end.compact
Chris@1013 158 institutions = authors.map do |a|
Chris@1013 159 if a.respond_to?(:ssamr_user_detail) and !a.ssamr_user_detail.nil?
Chris@1013 160 a.ssamr_user_detail.institution_name
Chris@1013 161 end
Chris@1013 162 end
chris@1011 163 insthash = institutions.compact.sort.group_by { |i| i }
chris@1011 164 insthash = insthash.merge(insthash) { |k,v| v.length }
chris@1011 165 threshold = insthash.values.sort.last(count).first
chris@1011 166 insthash.keys.select { |k| insthash[k] >= threshold }.sample(count)
chris@1011 167 end
Chris@1298 168
Chris@1295 169 def sort_activity_events(events)
Chris@1295 170 events_by_group = events.group_by(&:event_group)
Chris@1295 171 sorted_events = []
Chris@1295 172 events.sort {|x, y| y.event_datetime <=> x.event_datetime}.each do |event|
Chris@1295 173 if group_events = events_by_group.delete(event.event_group)
Chris@1295 174 group_events.sort {|x, y| y.event_datetime <=> x.event_datetime}.each_with_index do |e, i|
Chris@1295 175 sorted_events << [e, i > 0]
Chris@1295 176 end
Chris@1295 177 end
Chris@1295 178 end
Chris@1295 179 sorted_events
Chris@1295 180 end
chris@1011 181
Chris@1295 182 end