BigW Consortium Gitlab

search_helper.rb 6.12 KB
Newer Older
1
module SearchHelper
2
  def search_autocomplete_opts(term)
3
    return unless current_user
4 5 6

    resources_results = [
      groups_autocomplete(term),
7
      projects_autocomplete(term)
8 9
    ].flatten

10 11
    search_pattern = Regexp.new(Regexp.escape(term), "i")

12
    generic_results = project_autocomplete + default_autocomplete + help_autocomplete
13
    generic_results.select! { |result| result[:label] =~ search_pattern }
14

15
    [
16 17
      resources_results,
      generic_results
18 19
    ].flatten.uniq do |item|
      item[:label]
20
    end
21 22
  end

Phil Hughes committed
23
  def search_entries_info(collection, scope, term)
24
    return unless collection.count > 0
25

26 27 28 29 30
    from = collection.offset_value + 1
    to = collection.offset_value + collection.length
    count = collection.total_count

    "Showing #{from} - #{to} of #{count} #{scope.humanize(capitalize: false)} for \"#{term}\""
31 32
  end

33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
  def parse_search_result(result)
    ref = nil
    filename = nil
    basename = nil
    startline = 0

    result.each_line.each_with_index do |line, index|
      if line =~ /^.*:.*:\d+:/
        ref, filename, startline = line.split(':')
        startline = startline.to_i - index
        extname = Regexp.escape(File.extname(filename))
        basename = filename.sub(/#{extname}$/, '')
        break
      end
    end

    data = ""

    result.each_line do |line|
      data << line.sub(ref, '').sub(filename, '').sub(/^:-\d+-/, '').sub(/^::\d+:/, '')
    end

    OpenStruct.new(
      filename: filename,
      basename: basename,
      ref: ref,
      startline: startline,
      data: data
    )
  end

64 65 66 67 68
  private

  # Autocomplete results for various settings pages
  def default_autocomplete
    [
69 70 71 72
      { category: "Settings", label: "Profile settings", url: profile_path },
      { category: "Settings", label: "SSH Keys",         url: profile_keys_path },
      { category: "Settings", label: "Dashboard",        url: root_path },
      { category: "Settings", label: "Admin Section",    url: admin_root_path },
73 74 75 76 77 78
    ]
  end

  # Autocomplete results for internal help pages
  def help_autocomplete
    [
79
      { category: "Help", label: "API Help",           url: help_page_path("api/README") },
80
      { category: "Help", label: "Markdown Help",      url: help_page_path("user/markdown") },
81
      { category: "Help", label: "Permissions Help",   url: help_page_path("user/permissions") },
82 83 84 85 86 87
      { category: "Help", label: "Public Access Help", url: help_page_path("public_access/public_access") },
      { category: "Help", label: "Rake Tasks Help",    url: help_page_path("raketasks/README") },
      { category: "Help", label: "SSH Keys Help",      url: help_page_path("ssh/README") },
      { category: "Help", label: "System Hooks Help",  url: help_page_path("system_hooks/system_hooks") },
      { category: "Help", label: "Webhooks Help",      url: help_page_path("web_hooks/web_hooks") },
      { category: "Help", label: "Workflow Help",      url: help_page_path("workflow/README") },
88 89 90 91 92 93
    ]
  end

  # Autocomplete results for the current project, if it's defined
  def project_autocomplete
    if @project && @project.repository.exists? && @project.repository.root_ref
94
      ref = @ref || @project.repository.root_ref
95 96

      [
97 98 99 100 101 102 103 104 105 106
        { category: "Current Project", label: "Files",          url: namespace_project_tree_path(@project.namespace, @project, ref) },
        { category: "Current Project", label: "Commits",        url: namespace_project_commits_path(@project.namespace, @project, ref) },
        { category: "Current Project", label: "Network",        url: namespace_project_network_path(@project.namespace, @project, ref) },
        { category: "Current Project", label: "Graph",          url: namespace_project_graph_path(@project.namespace, @project, ref) },
        { category: "Current Project", label: "Issues",         url: namespace_project_issues_path(@project.namespace, @project) },
        { category: "Current Project", label: "Merge Requests", url: namespace_project_merge_requests_path(@project.namespace, @project) },
        { category: "Current Project", label: "Milestones",     url: namespace_project_milestones_path(@project.namespace, @project) },
        { category: "Current Project", label: "Snippets",       url: namespace_project_snippets_path(@project.namespace, @project) },
        { category: "Current Project", label: "Members",        url: namespace_project_project_members_path(@project.namespace, @project) },
        { category: "Current Project", label: "Wiki",           url: namespace_project_wikis_path(@project.namespace, @project) },
107 108 109 110 111 112 113
      ]
    else
      []
    end
  end

  # Autocomplete results for the current user's groups
114
  def groups_autocomplete(term, limit = 5)
115
    current_user.authorized_groups.search(term).limit(limit).map do |group|
116
      {
117
        category: "Groups",
118 119
        id: group.id,
        label: "#{search_result_sanitize(group.name)}",
120 121
        url: group_path(group)
      }
122 123 124 125
    end
  end

  # Autocomplete results for the current user's projects
126
  def projects_autocomplete(term, limit = 5)
127
    current_user.authorized_projects.search_by_title(term).
128
      sorted_by_stars.non_archived.limit(limit).map do |p|
129
      {
130
        category: "Projects",
131 132 133
        id: p.id,
        value: "#{search_result_sanitize(p.name)}",
        label: "#{search_result_sanitize(p.name_with_namespace)}",
Vinnie Okada committed
134
        url: namespace_project_path(p.namespace, p)
135
      }
136 137
    end
  end
138

139
  def search_result_sanitize(str)
140 141
    Sanitize.clean(str)
  end
142

143
  def search_filter_path(options = {})
144 145 146 147
    exist_opts = {
      search: params[:search],
      project_id: params[:project_id],
      group_id: params[:group_id],
barthc committed
148 149
      scope: params[:scope],
      repository_ref: params[:repository_ref]
150 151 152
    }

    options = exist_opts.merge(options)
153
    search_path(options)
154
  end
155

156 157 158 159 160 161 162 163 164 165 166 167
  # Sanitize a HTML field for search display. Most tags are stripped out and the
  # maximum length is set to 200 characters.
  def search_md_sanitize(object, field)
    html = markdown_field(object, field)
    html = Truncato.truncate(
      html,
      count_tags: false,
      count_tail: false,
      max_length: 200
    )

    # Truncato's filtered_tags and filtered_attributes are not quite the same
168
    sanitize(html, tags: %w(a p ol ul li pre code))
169
  end
170
end