To check out this repository please hg clone the following URL, or open the URL using EasyMercurial or your preferred Mercurial client.
root / vendor / plugins / redmine_tags / lib / redmine_tags / patches / projects_helper_patch.rb @ 826:cb27dd527bd3
History | View | Annotate | Download (9.28 KB)
| 1 |
module RedmineTags |
|---|---|
| 2 |
module Patches |
| 3 |
module ProjectsHelperPatch |
| 4 |
|
| 5 |
def self.included(base) # :nodoc: |
| 6 |
base.send(:include, InstanceMethods) |
| 7 |
base.class_eval do
|
| 8 |
unloadable |
| 9 |
end
|
| 10 |
end
|
| 11 |
|
| 12 |
module InstanceMethods |
| 13 |
# Renders a tree of projects that the current user does not belong
|
| 14 |
# to, or of all projects if the current user is not logged in. The
|
| 15 |
# given collection may be a subset of the whole project tree
|
| 16 |
# (eg. some intermediate nodes are private and can not be seen). We
|
| 17 |
# are potentially interested in various things: the project name,
|
| 18 |
# description, manager(s), creation date, last activity date,
|
| 19 |
# general activity level, whether there is anything actually hosted
|
| 20 |
# here for the project, etc.
|
| 21 |
def render_project_table_with_filtering(projects, question) |
| 22 |
custom_fields = ""
|
| 23 |
s = ""
|
| 24 |
if projects.any?
|
| 25 |
tokens = RedmineProjectFiltering.calculate_tokens(question, custom_fields)
|
| 26 |
|
| 27 |
s << "<div class='autoscroll'>"
|
| 28 |
s << "<table class='list projects'>"
|
| 29 |
s << "<thead><tr>"
|
| 30 |
|
| 31 |
s << sort_header_tag('name', :caption => l("field_name")) |
| 32 |
s << "<th class='tags'>" << l("tags") << "</th>" |
| 33 |
s << "<th class='managers'>" << l("label_managers") << "</th>" |
| 34 |
s << sort_header_tag('created_on', :default_order => 'desc') |
| 35 |
s << sort_header_tag('updated_on', :default_order => 'desc') |
| 36 |
|
| 37 |
s << "</tr></thead><tbody>"
|
| 38 |
|
| 39 |
original_project = @project
|
| 40 |
|
| 41 |
projects.each do |project|
|
| 42 |
s << render_project_in_table_with_filtering(project, cycle('odd', 'even'), 0, tokens) |
| 43 |
end
|
| 44 |
|
| 45 |
s << "</table>"
|
| 46 |
else
|
| 47 |
s << "\n"
|
| 48 |
end
|
| 49 |
@project = original_project
|
| 50 |
|
| 51 |
s |
| 52 |
end
|
| 53 |
|
| 54 |
def render_project_in_table_with_filtering(project, oddeven, level, tokens) |
| 55 |
# set the project environment to please macros.
|
| 56 |
@project = project
|
| 57 |
|
| 58 |
classes = (level == 0 ? 'root' : 'child') |
| 59 |
|
| 60 |
s = ""
|
| 61 |
|
| 62 |
s << "<tr class='#{oddeven} #{classes} level#{level}'>"
|
| 63 |
s << "<td class='firstcol' align=top><div class='name hosted_here"
|
| 64 |
s << " no_description" if project.description.blank? |
| 65 |
s << "'>" << link_to( highlight_tokens(project.name, tokens), {:controller => 'projects', :action => 'show', :id => project}, :class => "project #{User.current.member_of?(project) ? 'my-project' : nil}") |
| 66 |
s << "</div>"
|
| 67 |
s << highlight_tokens(render_project_short_description(project), tokens) |
| 68 |
s << "</td>"
|
| 69 |
|
| 70 |
# taglist
|
| 71 |
s << "<td class='tags' align=top>" << project.tag_counts.collect{ |t| render_project_tag_link(t) }.join(', ') << "</td>" |
| 72 |
|
| 73 |
s << "<td class='managers' align=top>"
|
| 74 |
|
| 75 |
u = project.users_by_role |
| 76 |
if u
|
| 77 |
u.keys.each do |r|
|
| 78 |
if r.allowed_to?(:edit_project) |
| 79 |
mgrs = [] |
| 80 |
u[r].sort.each do |m|
|
| 81 |
mgrs << link_to_user(m) |
| 82 |
end
|
| 83 |
if mgrs.size < 3 |
| 84 |
s << '<nobr>' << mgrs.join(', ') << '</nobr>' |
| 85 |
else
|
| 86 |
s << mgrs.join(', ')
|
| 87 |
end
|
| 88 |
end
|
| 89 |
end
|
| 90 |
end
|
| 91 |
|
| 92 |
s << "</td>"
|
| 93 |
|
| 94 |
s << "<td class='created_on' align=top>" << format_date(project.created_on) << "</td>" |
| 95 |
s << "<td class='updated_on' align=top>" << format_date(project.updated_on) << "</td>" |
| 96 |
|
| 97 |
s << "</tr>"
|
| 98 |
|
| 99 |
project.children.each do |child|
|
| 100 |
if child.is_public? or User.current.member_of?(child) |
| 101 |
s << render_project_in_table_with_filtering(child, oddeven, level + 1, tokens)
|
| 102 |
end
|
| 103 |
end
|
| 104 |
|
| 105 |
s |
| 106 |
end
|
| 107 |
|
| 108 |
|
| 109 |
|
| 110 |
# Renders a tree of projects as a nested set of unordered lists
|
| 111 |
# The given collection may be a subset of the whole project tree
|
| 112 |
# (eg. some intermediate nodes are private and can not be seen)
|
| 113 |
def render_project_hierarchy_with_filtering(projects,custom_fields,question) |
| 114 |
s = [] |
| 115 |
if projects.any?
|
| 116 |
tokens = RedmineProjectFiltering.calculate_tokens(question, custom_fields)
|
| 117 |
debugger |
| 118 |
|
| 119 |
|
| 120 |
ancestors = [] |
| 121 |
original_project = @project
|
| 122 |
projects.each do |project|
|
| 123 |
# set the project environment to please macros.
|
| 124 |
@project = project
|
| 125 |
if (ancestors.empty? || project.is_descendant_of?(ancestors.last))
|
| 126 |
s << "<ul class='projects #{ ancestors.empty? ? 'root' : nil}'>"
|
| 127 |
else
|
| 128 |
ancestors.pop |
| 129 |
s << "</li>"
|
| 130 |
while (ancestors.any? && !project.is_descendant_of?(ancestors.last))
|
| 131 |
ancestors.pop |
| 132 |
s << "</ul></li>"
|
| 133 |
end
|
| 134 |
end
|
| 135 |
classes = (ancestors.empty? ? 'root' : 'child') |
| 136 |
s << "<li class='#{classes}'><div class='#{classes}'>" +
|
| 137 |
link_to( highlight_tokens(project.name, tokens), |
| 138 |
{:controller => 'projects', :action => 'show', :id => project},
|
| 139 |
:class => "project #{User.current.member_of?(project) ? 'my-project' : nil}" |
| 140 |
) |
| 141 |
s << "<ul class='filter_fields'>"
|
| 142 |
|
| 143 |
# CustomField.usable_for_project_filtering.each do |field|
|
| 144 |
# value_model = project.custom_value_for(field.id)
|
| 145 |
# value = value_model.present? ? value_model.value : nil
|
| 146 |
# s << "<li><b>#{field.name.humanize}:</b> #{highlight_tokens(value, tokens)}</li>" if value.present?
|
| 147 |
# end
|
| 148 |
|
| 149 |
s << "</ul>"
|
| 150 |
s << "<div class='clear'></div>"
|
| 151 |
unless project.description.blank?
|
| 152 |
s << "<div class='wiki description'>"
|
| 153 |
s << "<b>#{ t(:field_description) }:</b>"
|
| 154 |
s << highlight_tokens(textilizable(project.short_description, :project => project), tokens)
|
| 155 |
s << "\n</div>"
|
| 156 |
end
|
| 157 |
s << "</div>"
|
| 158 |
ancestors << project |
| 159 |
end
|
| 160 |
ancestors.size.times{ s << "</li></ul>" }
|
| 161 |
@project = original_project
|
| 162 |
end
|
| 163 |
s.join "\n"
|
| 164 |
end
|
| 165 |
|
| 166 |
# Renders a tree of projects where the current user belongs
|
| 167 |
# as a nested set of unordered lists
|
| 168 |
# The given collection may be a subset of the whole project tree
|
| 169 |
# (eg. some intermediate nodes are private and can not be seen)
|
| 170 |
def render_my_project_hierarchy_with_tags(projects) |
| 171 |
|
| 172 |
s = ''
|
| 173 |
|
| 174 |
original_project = @project
|
| 175 |
|
| 176 |
projects.each do |project|
|
| 177 |
if project.root? || !projects.include?(project.parent)
|
| 178 |
s << render_my_project_in_hierarchy_with_tags(project) |
| 179 |
end
|
| 180 |
end
|
| 181 |
|
| 182 |
@project = original_project
|
| 183 |
|
| 184 |
if s != '' |
| 185 |
a = ''
|
| 186 |
a << "<ul class='projects root'>\n"
|
| 187 |
a << s |
| 188 |
a << "</ul>\n"
|
| 189 |
s = a |
| 190 |
end
|
| 191 |
|
| 192 |
s |
| 193 |
|
| 194 |
end
|
| 195 |
|
| 196 |
|
| 197 |
|
| 198 |
|
| 199 |
def render_my_project_in_hierarchy_with_tags(project) |
| 200 |
|
| 201 |
s = ''
|
| 202 |
|
| 203 |
if User.current.member_of?(project) |
| 204 |
|
| 205 |
# set the project environment to please macros.
|
| 206 |
@project = project
|
| 207 |
|
| 208 |
classes = (project.root? ? 'root' : 'child') |
| 209 |
|
| 210 |
s << "<li class='#{classes}'><div class='#{classes}'>" +
|
| 211 |
link_to_project(project, {}, :class => "project my-project")
|
| 212 |
if project.is_public?
|
| 213 |
s << " <span class='public'>" << l(:field_is_public) << "</span>" |
| 214 |
else
|
| 215 |
s << " <span class='private'>" << l(:field_is_private) << "</span>" |
| 216 |
end
|
| 217 |
|
| 218 |
tc = project.tag_counts |
| 219 |
if tc.empty?
|
| 220 |
s << " <span class='no-tags'>" << l(:field_no_tags) << "</span>" |
| 221 |
else
|
| 222 |
s << " <span class='tags'>" << tc.collect{ |t| render_project_tag_link(t) }.join(', ') << "</span>" |
| 223 |
end
|
| 224 |
|
| 225 |
s << render_project_short_description(project) |
| 226 |
|
| 227 |
s << "</div>\n"
|
| 228 |
|
| 229 |
cs = ''
|
| 230 |
project.children.each do |child|
|
| 231 |
cs << render_my_project_in_hierarchy_with_tags(child) |
| 232 |
end
|
| 233 |
|
| 234 |
if cs != '' |
| 235 |
s << "<ul class='projects'>\n" << cs << "</ul>\n"; |
| 236 |
end
|
| 237 |
|
| 238 |
end
|
| 239 |
|
| 240 |
s |
| 241 |
|
| 242 |
end
|
| 243 |
|
| 244 |
|
| 245 |
|
| 246 |
private |
| 247 |
|
| 248 |
# copied from search_helper. This one doesn't escape html or limit the text length
|
| 249 |
def highlight_tokens(text, tokens) |
| 250 |
return text unless text && tokens && !tokens.empty? |
| 251 |
re_tokens = tokens.collect {|t| Regexp.escape(t)}
|
| 252 |
regexp = Regexp.new "(#{re_tokens.join('|')})", Regexp::IGNORECASE |
| 253 |
result = ''
|
| 254 |
text.split(regexp).each_with_index do |words, i|
|
| 255 |
words = words.mb_chars |
| 256 |
if i.even?
|
| 257 |
result << words |
| 258 |
else
|
| 259 |
t = (tokens.index(words.downcase) || 0) % 4 |
| 260 |
result << content_tag('span', words, :class => "highlight token-#{t}") |
| 261 |
end
|
| 262 |
end
|
| 263 |
result |
| 264 |
end
|
| 265 |
|
| 266 |
end
|
| 267 |
end
|
| 268 |
end
|
| 269 |
end
|
| 270 |
|