issuables_helper.rb 7.7 KB
Newer Older
1
module IssuablesHelper
2 3
  include GitlabRoutingHelper

4
  def sidebar_gutter_toggle_icon
F
Filipa Lacerda 已提交
5
    sidebar_gutter_collapsed? ? icon('angle-double-left', { 'aria-hidden': 'true' }) : icon('angle-double-right', { 'aria-hidden': 'true' })
6 7 8 9 10 11
  end

  def sidebar_gutter_collapsed_class
    "right-sidebar-#{sidebar_gutter_collapsed? ? 'collapsed' : 'expanded'}"
  end

12
  def multi_label_name(current_labels, default_label)
13
    if current_labels && current_labels.any?
14
      title = current_labels.first.try(:title)
15 16
      if current_labels.size > 1
        "#{title} +#{current_labels.size - 1} more"
J
Jacob Schatz 已提交
17
      else
18
        title
J
Jacob Schatz 已提交
19
      end
A
Arinde Eniola 已提交
20
    else
21
      default_label
J
Jacob Schatz 已提交
22 23 24
    end
  end

J
Jacob Schatz 已提交
25 26 27
  def issuable_json_path(issuable)
    project = issuable.project

D
Douwe Maan 已提交
28
    if issuable.is_a?(MergeRequest)
J
Jacob Schatz 已提交
29 30 31 32 33 34
      namespace_project_merge_request_path(project.namespace, project, issuable.iid, :json)
    else
      namespace_project_issue_path(project.namespace, project, issuable.iid, :json)
    end
  end

35 36 37 38 39
  def serialize_issuable(issuable)
    case issuable
    when Issue
      IssueSerializer.new.represent(issuable).to_json
    when MergeRequest
F
Fatih Acet 已提交
40 41 42 43
      MergeRequestSerializer
        .new(current_user: current_user, project: issuable.project)
        .represent(issuable)
        .to_json
44 45 46
    end
  end

47 48 49 50 51 52 53 54 55 56 57 58 59
  def template_dropdown_tag(issuable, &block)
    title = selected_template(issuable) || "Choose a template"
    options = {
      toggle_class: 'js-issuable-selector',
      title: title,
      filter: true,
      placeholder: 'Filter',
      footer_content: true,
      data: {
        data: issuable_templates(issuable),
        field_name: 'issuable_template',
        selected: selected_template(issuable),
        project_path: ref_project.path,
60
        namespace_path: ref_project.namespace.full_path
61 62 63 64 65 66 67 68
      }
    }

    dropdown_tag(title, options: options) do
      capture(&block)
    end
  end

69 70 71 72 73 74 75 76 77 78
  def users_dropdown_label(selected_users)
    if selected_users.length == 0
      "Unassigned"
    elsif selected_users.length == 1
      selected_users[0].name
    else
      "#{selected_users[0].name} + #{selected_users.length - 1} more"
    end
  end

79
  def user_dropdown_label(user_id, default_label)
P
Phil Hughes 已提交
80
    return default_label if user_id.nil?
81 82
    return "Unassigned" if user_id == "0"

P
Phil Hughes 已提交
83
    user = User.find_by(id: user_id)
84 85 86 87 88 89 90 91

    if user
      user.name
    else
      default_label
    end
  end

92 93 94 95 96 97 98
  def project_dropdown_label(project_id, default_label)
    return default_label if project_id.nil?
    return "Any project" if project_id == "0"

    project = Project.find_by(id: project_id)

    if project
99
      project.name_with_namespace
100 101 102 103 104
    else
      default_label
    end
  end

P
Phil Hughes 已提交
105
  def milestone_dropdown_label(milestone_title, default_label = "Milestone")
106 107 108 109 110 111
    title =
      case milestone_title
      when Milestone::Upcoming.name then Milestone::Upcoming.title
      when Milestone::Started.name then Milestone::Started.title
      else milestone_title.presence
      end
P
Phil Hughes 已提交
112

113
    h(title || default_label)
114 115
  end

116 117 118 119 120 121 122 123 124 125 126
  def to_url_reference(issuable)
    case issuable
    when Issue
      link_to issuable.to_reference, issue_url(issuable)
    when MergeRequest
      link_to issuable.to_reference, merge_request_url(issuable)
    else
      issuable.to_reference
    end
  end

127
  def issuable_meta(issuable, project, text)
128 129 130 131 132
    output = content_tag(:strong, class: "identifier") do
      concat("#{text} ")
      concat(to_url_reference(issuable))
    end

133
    output << " opened #{time_ago_with_tooltip(issuable.created_at)} by ".html_safe
134
    output << content_tag(:strong) do
135
      author_output = link_to_member(project, issuable.author, size: 24, mobile_classes: "hidden-xs", tooltip: true)
136 137
      author_output << link_to_member(project, issuable.author, size: 24, by_username: true, avatar: false, mobile_classes: "hidden-sm hidden-md hidden-lg")
    end
138 139 140

    if issuable.tasks?
      output << "&ensp;".html_safe
141 142
      output << content_tag(:span, issuable.task_status, id: "task_status", class: "hidden-xs hidden-sm")
      output << content_tag(:span, issuable.task_status_short, id: "task_status_short", class: "hidden-md hidden-lg")
143 144 145
    end

    output
146 147
  end

P
Phil Hughes 已提交
148
  def issuable_todo(issuable)
149
    if current_user
P
Phil Hughes 已提交
150
      current_user.todos.find_by(target: issuable, state: :pending)
151
    end
P
Phil Hughes 已提交
152 153
  end

P
Phil Hughes 已提交
154
  def issuable_labels_tooltip(labels, limit: 5)
P
Phil Hughes 已提交
155
    first, last = labels.partition.with_index{ |_, i| i < limit  }
156

P
Phil Hughes 已提交
157 158
    label_names = first.collect(&:name)
    label_names << "and #{last.size} more" unless last.empty?
159

P
Phil Hughes 已提交
160
    label_names.join(', ')
161 162
  end

163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180
  def issuables_state_counter_text(issuable_type, state)
    titles = {
      opened: "Open"
    }

    state_title = titles[state] || state.to_s.humanize

    count =
      Rails.cache.fetch(issuables_state_counter_cache_key(issuable_type, state), expires_in: 2.minutes) do
        issuables_count_for_state(issuable_type, state)
      end

    html = content_tag(:span, state_title)
    html << " " << content_tag(:span, number_with_delimiter(count), class: 'badge')

    html.html_safe
  end

181 182
  def assigned_issuables_count(issuable_type)
    current_user.public_send("assigned_open_#{issuable_type}_count")
183 184
  end

185 186 187 188 189 190 191 192 193 194
  def issuable_filter_params
    [
      :search,
      :author_id,
      :assignee_id,
      :milestone_title,
      :label_name
    ]
  end

195 196 197 198
  def issuable_reference(issuable)
    @show_full_reference ? issuable.to_reference(full: true) : issuable.to_reference(@group || @project)
  end

199 200 201 202
  def issuable_filter_present?
    issuable_filter_params.any? { |k| params.key?(k) }
  end

203 204 205 206 207 208 209
  private

  def sidebar_gutter_collapsed?
    cookies[:collapsed_gutter] == 'true'
  end

  def base_issuable_scope(issuable)
210
    issuable.project.send(issuable.class.table_name).send(issuable_state_scope(issuable))
211 212 213
  end

  def issuable_state_scope(issuable)
214 215 216 217 218
    if issuable.respond_to?(:merged?) && issuable.merged?
      :merged
    else
      issuable.open? ? :opened : :closed
    end
219
  end
220 221

  def issuables_count_for_state(issuable_type, state)
S
Sean McGivern 已提交
222 223 224
    @counts ||= {}
    @counts[issuable_type] ||= public_send("#{issuable_type}_finder").count_by_state
    @counts[issuable_type][state]
225 226
  end

D
Douwe Maan 已提交
227
  IRRELEVANT_PARAMS_FOR_CACHE_KEY = %i[utf8 sort page].freeze
228 229 230
  private_constant :IRRELEVANT_PARAMS_FOR_CACHE_KEY

  def issuables_state_counter_cache_key(issuable_type, state)
231 232 233
    opts = params.with_indifferent_access
    opts[:state] = state
    opts.except!(*IRRELEVANT_PARAMS_FOR_CACHE_KEY)
234
    opts.delete_if { |_, value| value.blank? }
235 236 237

    hexdigest(['issuables_count', issuable_type, opts.sort].flatten.join('-'))
  end
238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259

  def issuable_templates(issuable)
    @issuable_templates ||=
      case issuable
      when Issue
        issue_template_names
      when MergeRequest
        merge_request_template_names
      else
        raise 'Unknown issuable type!'
      end
  end

  def merge_request_template_names
    @merge_request_templates ||= Gitlab::Template::MergeRequestTemplate.dropdown_names(ref_project)
  end

  def issue_template_names
    @issue_templates ||= Gitlab::Template::IssueTemplate.dropdown_names(ref_project)
  end

  def selected_template(issuable)
260
    params[:issuable_template] if issuable_templates(issuable).any?{ |template| template[:name] == params[:issuable_template] }
261
  end
P
Phil Hughes 已提交
262 263 264 265 266 267 268 269 270 271 272 273 274 275 276

  def issuable_todo_button_data(issuable, todo, is_collapsed)
    {
      todo_text: "Add todo",
      mark_text: "Mark done",
      todo_icon: (is_collapsed ? icon('plus-square') : nil),
      mark_icon: (is_collapsed ? icon('check-square', class: 'todo-undone') : nil),
      issuable_id: issuable.id,
      issuable_type: issuable.class.name.underscore,
      url: namespace_project_todos_path(@project.namespace, @project),
      delete_path: (dashboard_todo_path(todo) if todo),
      placement: (is_collapsed ? 'left' : nil),
      container: (is_collapsed ? 'body' : nil)
    }
  end
277
end