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