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 8.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. # frozen_string_literal: true
  2. # Redmine - project management software
  3. # Copyright (C) 2006-2022 Jean-Philippe Lang
  4. #
  5. # This program is free software; you can redistribute it and/or
  6. # modify it under the terms of the GNU General Public License
  7. # as published by the Free Software Foundation; either version 2
  8. # of the License, or (at your option) any later version.
  9. #
  10. # This program is distributed in the hope that it will be useful,
  11. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. # GNU General Public License for more details.
  14. #
  15. # You should have received a copy of the GNU General Public License
  16. # along with this program; if not, write to the Free Software
  17. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  18. module ProjectsHelper
  19. def project_settings_tabs
  20. tabs =
  21. [
  22. {:name => 'info', :action => :edit_project,
  23. :partial => 'projects/edit', :label => :label_project},
  24. {:name => 'members', :action => :manage_members,
  25. :partial => 'projects/settings/members', :label => :label_member_plural},
  26. {:name => 'issues', :action => :edit_project, :module => :issue_tracking,
  27. :partial => 'projects/settings/issues', :label => :label_issue_tracking},
  28. {:name => 'versions', :action => :manage_versions,
  29. :partial => 'projects/settings/versions', :label => :label_version_plural,
  30. :url => {:tab => 'versions', :version_status => params[:version_status],
  31. :version_name => params[:version_name]}},
  32. {:name => 'categories', :action => :manage_categories,
  33. :partial => 'projects/settings/issue_categories',
  34. :label => :label_issue_category_plural},
  35. {:name => 'repositories', :action => :manage_repository,
  36. :partial => 'projects/settings/repositories', :label => :label_repository_plural},
  37. {:name => 'boards', :action => :manage_boards,
  38. :partial => 'projects/settings/boards', :label => :label_board_plural},
  39. {:name => 'activities', :action => :manage_project_activities,
  40. :partial => 'projects/settings/activities', :label => :label_time_tracking}
  41. ]
  42. tabs.
  43. select {|tab| User.current.allowed_to?(tab[:action], @project)}.
  44. select {|tab| tab[:module].nil? || @project.module_enabled?(tab[:module])}
  45. end
  46. def parent_project_select_tag(project)
  47. selected = project.parent
  48. # retrieve the requested parent project
  49. parent_id = (params[:project] && params[:project][:parent_id]) || params[:parent_id]
  50. if parent_id
  51. selected = (parent_id.blank? ? nil : Project.find(parent_id))
  52. end
  53. options = +''
  54. options << "<option value=''>&nbsp;</option>" if project.allowed_parents.include?(nil)
  55. options << project_tree_options_for_select(project.allowed_parents.compact, :selected => selected)
  56. content_tag('select', options.html_safe, :name => 'project[parent_id]', :id => 'project_parent_id')
  57. end
  58. def render_project_action_links
  59. links = (+"").html_safe
  60. if User.current.allowed_to?(:add_project, nil, :global => true)
  61. links << link_to(l(:label_project_new), new_project_path, :class => 'icon icon-add')
  62. end
  63. if User.current.admin?
  64. links << link_to(l(:label_administration), admin_projects_path, :class => 'icon icon-settings')
  65. end
  66. links
  67. end
  68. # Renders the projects index
  69. def render_project_hierarchy(projects)
  70. bookmarked_project_ids = User.current.bookmarked_project_ids
  71. render_project_nested_lists(projects) do |project|
  72. classes = project.css_classes.split
  73. classes += %w(icon icon-user my-project) if User.current.member_of?(project)
  74. classes += %w(icon icon-bookmarked-project) if bookmarked_project_ids.include?(project.id)
  75. s = link_to_project(project, {}, :class => classes.uniq.join(' '))
  76. if project.description.present?
  77. s << content_tag('div', textilizable(project.short_description, :project => project), :class => 'wiki description')
  78. end
  79. s
  80. end
  81. end
  82. # Returns a set of options for a select field, grouped by project.
  83. def version_options_for_select(versions, selected=nil)
  84. grouped = Hash.new {|h, k| h[k] = []}
  85. versions.each do |version|
  86. grouped[version.project.name] << [version.name, version.id]
  87. end
  88. selected = selected.is_a?(Version) ? selected.id : selected
  89. if grouped.keys.size > 1
  90. grouped_options_for_select(grouped, selected)
  91. else
  92. options_for_select((grouped.values.first || []), selected)
  93. end
  94. end
  95. def project_default_version_options(project)
  96. versions = project.shared_versions.open.to_a
  97. if project.default_version && !versions.include?(project.default_version)
  98. versions << project.default_version
  99. end
  100. version_options_for_select(versions, project.default_version)
  101. end
  102. def project_default_assigned_to_options(project)
  103. assignable_users = (project.assignable_users.to_a + [project.default_assigned_to]).uniq.compact
  104. principals_options_for_select(assignable_users, project.default_assigned_to)
  105. end
  106. def project_default_issue_query_options(project)
  107. public_queries = IssueQuery.only_public
  108. grouped = {
  109. l('label_default_queries.for_all_projects') => public_queries.where(project_id: nil).pluck(:name, :id),
  110. l('label_default_queries.for_current_project') => public_queries.where(project: project).pluck(:name, :id)
  111. }
  112. grouped_options_for_select(grouped, project.default_issue_query_id)
  113. end
  114. def format_version_sharing(sharing)
  115. sharing = 'none' unless Version::VERSION_SHARINGS.include?(sharing)
  116. l("label_version_sharing_#{sharing}")
  117. end
  118. def render_boards_tree(boards, parent=nil, level=0, &block)
  119. selection = boards.select {|b| b.parent == parent}
  120. return '' if selection.empty?
  121. s = ''.html_safe
  122. selection.each do |board|
  123. node = capture(board, level, &block)
  124. node << render_boards_tree(boards, board, level+1, &block)
  125. s << content_tag('div', node)
  126. end
  127. content_tag('div', s, :class => 'sort-level')
  128. end
  129. def render_api_includes(project, api)
  130. api.array :trackers do
  131. project.rolled_up_trackers(false).visible.each do |tracker|
  132. api.tracker(:id => tracker.id, :name => tracker.name)
  133. end
  134. end if include_in_api_response?('trackers')
  135. api.array :issue_categories do
  136. project.issue_categories.each do |category|
  137. api.issue_category(:id => category.id, :name => category.name)
  138. end
  139. end if include_in_api_response?('issue_categories')
  140. api.array :time_entry_activities do
  141. project.activities.each do |activity|
  142. api.time_entry_activity(:id => activity.id, :name => activity.name)
  143. end
  144. end if include_in_api_response?('time_entry_activities')
  145. api.array :enabled_modules do
  146. project.enabled_modules.each do |enabled_module|
  147. api.enabled_module(:id => enabled_module.id, :name => enabled_module.name)
  148. end
  149. end if include_in_api_response?('enabled_modules')
  150. api.array :issue_custom_fields do
  151. project.issue_custom_fields.each do |custom_field|
  152. api.custom_field(:id => custom_field.id, :name => custom_field.name)
  153. end
  154. end if include_in_api_response?('issue_custom_fields')
  155. end
  156. def bookmark_link(project, user = User.current)
  157. return '' unless user && user.logged?
  158. @jump_box ||= Redmine::ProjectJumpBox.new user
  159. bookmarked = @jump_box.bookmark?(project)
  160. css = +"icon bookmark "
  161. if bookmarked
  162. css << "icon-bookmark"
  163. method = "delete"
  164. text = l(:button_project_bookmark_delete)
  165. else
  166. css << "icon-bookmark-off"
  167. method = "post"
  168. text = l(:button_project_bookmark)
  169. end
  170. url = bookmark_project_path(project)
  171. link_to text, url, remote: true, method: method, class: css
  172. end
  173. def grouped_project_list(projects, query, &block)
  174. ancestors = []
  175. grouped_query_results(projects, query) do |project, group_name, group_count, group_totals|
  176. ancestors.pop while ancestors.any? && !project.is_descendant_of?(ancestors.last)
  177. yield project, ancestors.size, group_name, group_count, group_totals
  178. ancestors << project unless project.leaf?
  179. end
  180. end
  181. end