You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

projects_helper.rb 7.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. # redMine - project management software
  2. # Copyright (C) 2006 Jean-Philippe Lang
  3. #
  4. # This program is free software; you can redistribute it and/or
  5. # modify it under the terms of the GNU General Public License
  6. # as published by the Free Software Foundation; either version 2
  7. # of the License, or (at your option) any later version.
  8. #
  9. # This program is distributed in the hope that it will be useful,
  10. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. # GNU General Public License for more details.
  13. #
  14. # You should have received a copy of the GNU General Public License
  15. # along with this program; if not, write to the Free Software
  16. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  17. module ProjectsHelper
  18. def link_to_version(version, options = {})
  19. return '' unless version && version.is_a?(Version)
  20. link_to h(version.name), { :controller => 'versions', :action => 'show', :id => version }, options
  21. end
  22. def format_activity_title(text)
  23. h(truncate_single_line(text, 100))
  24. end
  25. def format_activity_day(date)
  26. date == Date.today ? l(:label_today).titleize : format_date(date)
  27. end
  28. def format_activity_description(text)
  29. h(truncate(text, 250))
  30. end
  31. def project_settings_tabs
  32. tabs = [{:name => 'info', :action => :edit_project, :partial => 'projects/edit', :label => :label_information_plural},
  33. {:name => 'modules', :action => :select_project_modules, :partial => 'projects/settings/modules', :label => :label_module_plural},
  34. {:name => 'members', :action => :manage_members, :partial => 'projects/settings/members', :label => :label_member_plural},
  35. {:name => 'versions', :action => :manage_versions, :partial => 'projects/settings/versions', :label => :label_version_plural},
  36. {:name => 'categories', :action => :manage_categories, :partial => 'projects/settings/issue_categories', :label => :label_issue_category_plural},
  37. {:name => 'wiki', :action => :manage_wiki, :partial => 'projects/settings/wiki', :label => :label_wiki},
  38. {:name => 'repository', :action => :manage_repository, :partial => 'projects/settings/repository', :label => :label_repository},
  39. {:name => 'boards', :action => :manage_boards, :partial => 'projects/settings/boards', :label => :label_board_plural}
  40. ]
  41. tabs.select {|tab| User.current.allowed_to?(tab[:action], @project)}
  42. end
  43. # Generates a gantt image
  44. # Only defined if RMagick is avalaible
  45. def gantt_image(events, date_from, months, zoom)
  46. date_to = (date_from >> months)-1
  47. show_weeks = zoom > 1
  48. show_days = zoom > 2
  49. subject_width = 320
  50. header_heigth = 18
  51. # width of one day in pixels
  52. zoom = zoom*2
  53. g_width = (date_to - date_from + 1)*zoom
  54. g_height = 20 * events.length + 20
  55. headers_heigth = (show_weeks ? 2*header_heigth : header_heigth)
  56. height = g_height + headers_heigth
  57. imgl = Magick::ImageList.new
  58. imgl.new_image(subject_width+g_width+1, height)
  59. gc = Magick::Draw.new
  60. # Subjects
  61. top = headers_heigth + 20
  62. gc.fill('black')
  63. gc.stroke('transparent')
  64. gc.stroke_width(1)
  65. events.each do |i|
  66. gc.text(4, top + 2, (i.is_a?(Issue) ? i.subject : i.name))
  67. top = top + 20
  68. end
  69. # Months headers
  70. month_f = date_from
  71. left = subject_width
  72. months.times do
  73. width = ((month_f >> 1) - month_f) * zoom
  74. gc.fill('white')
  75. gc.stroke('grey')
  76. gc.stroke_width(1)
  77. gc.rectangle(left, 0, left + width, height)
  78. gc.fill('black')
  79. gc.stroke('transparent')
  80. gc.stroke_width(1)
  81. gc.text(left.round + 8, 14, "#{month_f.year}-#{month_f.month}")
  82. left = left + width
  83. month_f = month_f >> 1
  84. end
  85. # Weeks headers
  86. if show_weeks
  87. left = subject_width
  88. height = header_heigth
  89. if date_from.cwday == 1
  90. # date_from is monday
  91. week_f = date_from
  92. else
  93. # find next monday after date_from
  94. week_f = date_from + (7 - date_from.cwday + 1)
  95. width = (7 - date_from.cwday + 1) * zoom
  96. gc.fill('white')
  97. gc.stroke('grey')
  98. gc.stroke_width(1)
  99. gc.rectangle(left, header_heigth, left + width, 2*header_heigth + g_height-1)
  100. left = left + width
  101. end
  102. while week_f <= date_to
  103. width = (week_f + 6 <= date_to) ? 7 * zoom : (date_to - week_f + 1) * zoom
  104. gc.fill('white')
  105. gc.stroke('grey')
  106. gc.stroke_width(1)
  107. gc.rectangle(left.round, header_heigth, left.round + width, 2*header_heigth + g_height-1)
  108. gc.fill('black')
  109. gc.stroke('transparent')
  110. gc.stroke_width(1)
  111. gc.text(left.round + 2, header_heigth + 14, week_f.cweek.to_s)
  112. left = left + width
  113. week_f = week_f+7
  114. end
  115. end
  116. # Days details (week-end in grey)
  117. if show_days
  118. left = subject_width
  119. height = g_height + header_heigth - 1
  120. wday = date_from.cwday
  121. (date_to - date_from + 1).to_i.times do
  122. width = zoom
  123. gc.fill(wday == 6 || wday == 7 ? '#eee' : 'white')
  124. gc.stroke('grey')
  125. gc.stroke_width(1)
  126. gc.rectangle(left, 2*header_heigth, left + width, 2*header_heigth + g_height-1)
  127. left = left + width
  128. wday = wday + 1
  129. wday = 1 if wday > 7
  130. end
  131. end
  132. # border
  133. gc.fill('transparent')
  134. gc.stroke('grey')
  135. gc.stroke_width(1)
  136. gc.rectangle(0, 0, subject_width+g_width, headers_heigth)
  137. gc.stroke('black')
  138. gc.rectangle(0, 0, subject_width+g_width, g_height+ headers_heigth-1)
  139. # content
  140. top = headers_heigth + 20
  141. gc.stroke('transparent')
  142. events.each do |i|
  143. if i.is_a?(Issue)
  144. i_start_date = (i.start_date >= date_from ? i.start_date : date_from )
  145. i_end_date = (i.due_date <= date_to ? i.due_date : date_to )
  146. i_done_date = i.start_date + ((i.due_date - i.start_date+1)*i.done_ratio/100).floor
  147. i_done_date = (i_done_date <= date_from ? date_from : i_done_date )
  148. i_done_date = (i_done_date >= date_to ? date_to : i_done_date )
  149. i_late_date = [i_end_date, Date.today].min if i_start_date < Date.today
  150. i_left = subject_width + ((i_start_date - date_from)*zoom).floor
  151. i_width = ((i_end_date - i_start_date + 1)*zoom).floor # total width of the issue
  152. d_width = ((i_done_date - i_start_date)*zoom).floor # done width
  153. l_width = i_late_date ? ((i_late_date - i_start_date+1)*zoom).floor : 0 # delay width
  154. gc.fill('grey')
  155. gc.rectangle(i_left, top, i_left + i_width, top - 6)
  156. gc.fill('red')
  157. gc.rectangle(i_left, top, i_left + l_width, top - 6) if l_width > 0
  158. gc.fill('blue')
  159. gc.rectangle(i_left, top, i_left + d_width, top - 6) if d_width > 0
  160. gc.fill('black')
  161. gc.text(i_left + i_width + 5,top + 1, "#{i.status.name} #{i.done_ratio}%")
  162. else
  163. i_left = subject_width + ((i.start_date - date_from)*zoom).floor
  164. gc.fill('green')
  165. gc.rectangle(i_left, top, i_left + 6, top - 6)
  166. gc.fill('black')
  167. gc.text(i_left + 11, top + 1, i.name)
  168. end
  169. top = top + 20
  170. end
  171. # today red line
  172. if Date.today >= date_from and Date.today <= date_to
  173. gc.stroke('red')
  174. x = (Date.today-date_from+1)*zoom + subject_width
  175. gc.line(x, headers_heigth, x, headers_heigth + g_height-1)
  176. end
  177. gc.draw(imgl)
  178. imgl
  179. end if Object.const_defined?(:Magick)
  180. end