Commit f881e4367753075bbdbfaca1ea83a6ef80549b72
Exists in
spb-stable
and in
2 other branches
Merge pull request #7024 from skv-headless/linkto_issues_on_main_dashboard
links to issues on main dashboard
Showing
6 changed files
with
110 additions
and
78 deletions
Show diff stats
app/helpers/gitlab_markdown_helper.rb
@@ -19,7 +19,7 @@ module GitlabMarkdownHelper | @@ -19,7 +19,7 @@ module GitlabMarkdownHelper | ||
19 | escape_once(body) | 19 | escape_once(body) |
20 | end | 20 | end |
21 | 21 | ||
22 | - gfm_body = gfm(escaped_body, html_options) | 22 | + gfm_body = gfm(escaped_body, @project, html_options) |
23 | 23 | ||
24 | gfm_body.gsub!(%r{<a.*?>.*?</a>}m) do |match| | 24 | gfm_body.gsub!(%r{<a.*?>.*?</a>}m) do |match| |
25 | "</a>#{match}#{link_to("", url, html_options)[0..-5]}" # "</a>".length +1 | 25 | "</a>#{match}#{link_to("", url, html_options)[0..-5]}" # "</a>".length +1 |
app/helpers/issues_helper.rb
@@ -13,76 +13,80 @@ module IssuesHelper | @@ -13,76 +13,80 @@ module IssuesHelper | ||
13 | OpenStruct.new(id: 0, title: 'None (backlog)', name: 'Unassigned') | 13 | OpenStruct.new(id: 0, title: 'None (backlog)', name: 'Unassigned') |
14 | end | 14 | end |
15 | 15 | ||
16 | - def url_for_project_issues | ||
17 | - return "" if @project.nil? | 16 | + def url_for_project_issues(project = @project) |
17 | + return '' if project.nil? | ||
18 | 18 | ||
19 | - if @project.used_default_issues_tracker? || !external_issues_tracker_enabled? | ||
20 | - project_issues_path(@project) | 19 | + if project.used_default_issues_tracker? || !external_issues_tracker_enabled? |
20 | + project_issues_path(project) | ||
21 | else | 21 | else |
22 | - url = Gitlab.config.issues_tracker[@project.issues_tracker]["project_url"] | ||
23 | - url.gsub(':project_id', @project.id.to_s) | ||
24 | - .gsub(':issues_tracker_id', @project.issues_tracker_id.to_s) | 22 | + url = Gitlab.config.issues_tracker[project.issues_tracker]['project_url'] |
23 | + url.gsub(':project_id', project.id.to_s). | ||
24 | + gsub(':issues_tracker_id', project.issues_tracker_id.to_s) | ||
25 | end | 25 | end |
26 | end | 26 | end |
27 | 27 | ||
28 | - def url_for_new_issue | ||
29 | - return "" if @project.nil? | 28 | + def url_for_new_issue(project = @project) |
29 | + return '' if project.nil? | ||
30 | 30 | ||
31 | - if @project.used_default_issues_tracker? || !external_issues_tracker_enabled? | ||
32 | - url = new_project_issue_path project_id: @project | 31 | + if project.used_default_issues_tracker? || !external_issues_tracker_enabled? |
32 | + url = new_project_issue_path project_id: project | ||
33 | else | 33 | else |
34 | - url = Gitlab.config.issues_tracker[@project.issues_tracker]["new_issue_url"] | ||
35 | - url.gsub(':project_id', @project.id.to_s) | ||
36 | - .gsub(':issues_tracker_id', @project.issues_tracker_id.to_s) | 34 | + issues_tracker = Gitlab.config.issues_tracker[project.issues_tracker] |
35 | + url = issues_tracker['new_issue_url'] | ||
36 | + url.gsub(':project_id', project.id.to_s). | ||
37 | + gsub(':issues_tracker_id', project.issues_tracker_id.to_s) | ||
37 | end | 38 | end |
38 | end | 39 | end |
39 | 40 | ||
40 | - def url_for_issue(issue_iid) | ||
41 | - return "" if @project.nil? | 41 | + def url_for_issue(issue_iid, project = @project) |
42 | + return '' if project.nil? | ||
42 | 43 | ||
43 | - if @project.used_default_issues_tracker? || !external_issues_tracker_enabled? | ||
44 | - url = project_issue_url project_id: @project, id: issue_iid | 44 | + if project.used_default_issues_tracker? || !external_issues_tracker_enabled? |
45 | + url = project_issue_url project_id: project, id: issue_iid | ||
45 | else | 46 | else |
46 | - url = Gitlab.config.issues_tracker[@project.issues_tracker]["issues_url"] | ||
47 | - url.gsub(':id', issue_iid.to_s) | ||
48 | - .gsub(':project_id', @project.id.to_s) | ||
49 | - .gsub(':issues_tracker_id', @project.issues_tracker_id.to_s) | 47 | + url = Gitlab.config.issues_tracker[project.issues_tracker]['issues_url'] |
48 | + url.gsub(':id', issue_iid.to_s). | ||
49 | + gsub(':project_id', project.id.to_s). | ||
50 | + gsub(':issues_tracker_id', project.issues_tracker_id.to_s) | ||
50 | end | 51 | end |
51 | end | 52 | end |
52 | 53 | ||
53 | - def title_for_issue(issue_iid) | ||
54 | - return "" if @project.nil? | 54 | + def title_for_issue(issue_iid, project = @project) |
55 | + return '' if project.nil? | ||
55 | 56 | ||
56 | - if @project.used_default_issues_tracker? && issue = @project.issues.where(iid: issue_iid).first | ||
57 | - issue.title | ||
58 | - else | ||
59 | - "" | 57 | + if project.used_default_issues_tracker? |
58 | + issue = project.issues.where(iid: issue_iid).first | ||
59 | + return issue.title if issue | ||
60 | end | 60 | end |
61 | + | ||
62 | + '' | ||
61 | end | 63 | end |
62 | 64 | ||
63 | # Checks if issues_tracker setting exists in gitlab.yml | 65 | # Checks if issues_tracker setting exists in gitlab.yml |
64 | def external_issues_tracker_enabled? | 66 | def external_issues_tracker_enabled? |
65 | - if Gitlab.config.issues_tracker && Gitlab.config.issues_tracker.values.any? | ||
66 | - true | ||
67 | - else | ||
68 | - false | ||
69 | - end | 67 | + Gitlab.config.issues_tracker && Gitlab.config.issues_tracker.values.any? |
70 | end | 68 | end |
71 | 69 | ||
72 | def bulk_update_milestone_options | 70 | def bulk_update_milestone_options |
73 | - options_for_select(["None (backlog)"]) + options_from_collection_for_select(project_active_milestones, "id", "title", params[:milestone_id]) | 71 | + options_for_select(['None (backlog)']) + |
72 | + options_from_collection_for_select(project_active_milestones, 'id', | ||
73 | + 'title', params[:milestone_id]) | ||
74 | end | 74 | end |
75 | 75 | ||
76 | - def bulk_update_assignee_options | ||
77 | - options_for_select(["None (unassigned)"]) + options_from_collection_for_select(@project.team.members, "id", "name", params[:assignee_id]) | 76 | + def bulk_update_assignee_options(project = @project) |
77 | + options_for_select(['None (unassigned)']) + | ||
78 | + options_from_collection_for_select(project.team.members, 'id', | ||
79 | + 'name', params[:assignee_id]) | ||
78 | end | 80 | end |
79 | 81 | ||
80 | - def assignee_options object | ||
81 | - options_from_collection_for_select(@project.team.members.sort_by(&:name), 'id', 'name', object.assignee_id) | 82 | + def assignee_options(object, project = @project) |
83 | + options_from_collection_for_select(project.team.members.sort_by(&:name), | ||
84 | + 'id', 'name', object.assignee_id) | ||
82 | end | 85 | end |
83 | 86 | ||
84 | def milestone_options object | 87 | def milestone_options object |
85 | - options_from_collection_for_select(object.project.milestones.active, 'id', 'title', object.milestone_id) | 88 | + options_from_collection_for_select(object.project.milestones.active, |
89 | + 'id', 'title', object.milestone_id) | ||
86 | end | 90 | end |
87 | 91 | ||
88 | def issue_box_class(item) | 92 | def issue_box_class(item) |
app/views/events/_commit.html.haml
@@ -2,4 +2,4 @@ | @@ -2,4 +2,4 @@ | ||
2 | .commit-row-title | 2 | .commit-row-title |
3 | = link_to commit[:id][0..8], project_commit_path(project, commit[:id]), class: "commit_short_id", alt: '' | 3 | = link_to commit[:id][0..8], project_commit_path(project, commit[:id]), class: "commit_short_id", alt: '' |
4 | | 4 | |
5 | - = gfm event_commit_title(commit[:message]) | 5 | + = gfm event_commit_title(commit[:message]), project |
lib/gitlab/markdown.rb
@@ -33,10 +33,9 @@ module Gitlab | @@ -33,10 +33,9 @@ module Gitlab | ||
33 | # Public: Parse the provided text with GitLab-Flavored Markdown | 33 | # Public: Parse the provided text with GitLab-Flavored Markdown |
34 | # | 34 | # |
35 | # text - the source text | 35 | # text - the source text |
36 | + # project - extra options for the reference links as given to link_to | ||
36 | # html_options - extra options for the reference links as given to link_to | 37 | # html_options - extra options for the reference links as given to link_to |
37 | - # | ||
38 | - # Note: reference links will only be generated if @project is set | ||
39 | - def gfm(text, html_options = {}) | 38 | + def gfm(text, project = @project, html_options = {}) |
40 | return text if text.nil? | 39 | return text if text.nil? |
41 | 40 | ||
42 | # Duplicate the string so we don't alter the original, then call to_str | 41 | # Duplicate the string so we don't alter the original, then call to_str |
@@ -56,14 +55,19 @@ module Gitlab | @@ -56,14 +55,19 @@ module Gitlab | ||
56 | 55 | ||
57 | # TODO: add popups with additional information | 56 | # TODO: add popups with additional information |
58 | 57 | ||
59 | - text = parse(text) | 58 | + text = parse(text, project) |
60 | 59 | ||
61 | # Insert pre block extractions | 60 | # Insert pre block extractions |
62 | text.gsub!(/\{gfm-extraction-(\h{32})\}/) do | 61 | text.gsub!(/\{gfm-extraction-(\h{32})\}/) do |
63 | insert_piece($1) | 62 | insert_piece($1) |
64 | end | 63 | end |
65 | 64 | ||
66 | - sanitize text.html_safe, attributes: ActionView::Base.sanitized_allowed_attributes + %w(id class), tags: ActionView::Base.sanitized_allowed_tags + %w(table tr td th) | 65 | + allowed_attributes = ActionView::Base.sanitized_allowed_attributes |
66 | + allowed_tags = ActionView::Base.sanitized_allowed_tags | ||
67 | + | ||
68 | + sanitize text.html_safe, | ||
69 | + attributes: allowed_attributes + %w(id class), | ||
70 | + tags: allowed_tags + %w(table tr td th) | ||
67 | end | 71 | end |
68 | 72 | ||
69 | private | 73 | private |
@@ -84,11 +88,9 @@ module Gitlab | @@ -84,11 +88,9 @@ module Gitlab | ||
84 | # | 88 | # |
85 | # text - Text to parse | 89 | # text - Text to parse |
86 | # | 90 | # |
87 | - # Note: reference links will only be generated if @project is set | ||
88 | - # | ||
89 | # Returns parsed text | 91 | # Returns parsed text |
90 | - def parse(text) | ||
91 | - parse_references(text) if @project | 92 | + def parse(text, project = @project) |
93 | + parse_references(text, project) if project | ||
92 | parse_emoji(text) | 94 | parse_emoji(text) |
93 | 95 | ||
94 | text | 96 | text |
@@ -110,7 +112,7 @@ module Gitlab | @@ -110,7 +112,7 @@ module Gitlab | ||
110 | 112 | ||
111 | TYPES = [:user, :issue, :merge_request, :snippet, :commit].freeze | 113 | TYPES = [:user, :issue, :merge_request, :snippet, :commit].freeze |
112 | 114 | ||
113 | - def parse_references(text) | 115 | + def parse_references(text, project = @project) |
114 | # parse reference links | 116 | # parse reference links |
115 | text.gsub!(REFERENCE_PATTERN) do |match| | 117 | text.gsub!(REFERENCE_PATTERN) do |match| |
116 | prefix = $~[:prefix] | 118 | prefix = $~[:prefix] |
@@ -123,7 +125,7 @@ module Gitlab | @@ -123,7 +125,7 @@ module Gitlab | ||
123 | # Avoid HTML entities | 125 | # Avoid HTML entities |
124 | if prefix && suffix && prefix[0] == '&' && suffix[-1] == ';' | 126 | if prefix && suffix && prefix[0] == '&' && suffix[-1] == ';' |
125 | match | 127 | match |
126 | - elsif ref_link = reference_link(type, identifier) | 128 | + elsif ref_link = reference_link(type, identifier, project) |
127 | "#{prefix}#{ref_link}#{suffix}" | 129 | "#{prefix}#{ref_link}#{suffix}" |
128 | else | 130 | else |
129 | match | 131 | match |
@@ -153,7 +155,7 @@ module Gitlab | @@ -153,7 +155,7 @@ module Gitlab | ||
153 | # | 155 | # |
154 | # Returns boolean | 156 | # Returns boolean |
155 | def valid_emoji?(emoji) | 157 | def valid_emoji?(emoji) |
156 | - Emoji.find_by_name emoji | 158 | + Emoji.find_by_name(emoji) |
157 | end | 159 | end |
158 | 160 | ||
159 | # Private: Dispatches to a dedicated processing method based on reference | 161 | # Private: Dispatches to a dedicated processing method based on reference |
@@ -162,52 +164,77 @@ module Gitlab | @@ -162,52 +164,77 @@ module Gitlab | ||
162 | # identifier - Object identifier (Issue ID, SHA hash, etc.) | 164 | # identifier - Object identifier (Issue ID, SHA hash, etc.) |
163 | # | 165 | # |
164 | # Returns string rendered by the processing method | 166 | # Returns string rendered by the processing method |
165 | - def reference_link(type, identifier) | ||
166 | - send("reference_#{type}", identifier) | 167 | + def reference_link(type, identifier, project = @project) |
168 | + send("reference_#{type}", identifier, project) | ||
167 | end | 169 | end |
168 | 170 | ||
169 | - def reference_user(identifier) | ||
170 | - if user = User.find_by_username(identifier) | ||
171 | - link_to("@#{identifier}", user_url(identifier), html_options.merge(class: "gfm gfm-team_member #{html_options[:class]}")) | 171 | + def reference_user(identifier, project = @project) |
172 | + if user = User.find_by(username: identifier) | ||
173 | + options = html_options.merge( | ||
174 | + class: "gfm gfm-team_member #{html_options[:class]}" | ||
175 | + ) | ||
176 | + link_to("@#{identifier}", user_url(identifier), options) | ||
172 | end | 177 | end |
173 | end | 178 | end |
174 | 179 | ||
175 | - def reference_issue(identifier) | ||
176 | - if @project.used_default_issues_tracker? || !external_issues_tracker_enabled? | ||
177 | - if @project.issue_exists? identifier | ||
178 | - url = url_for_issue(identifier) | 180 | + def reference_issue(identifier, project = @project) |
181 | + if project.used_default_issues_tracker? || !external_issues_tracker_enabled? | ||
182 | + if project.issue_exists? identifier | ||
183 | + url = url_for_issue(identifier, project) | ||
179 | title = title_for_issue(identifier) | 184 | title = title_for_issue(identifier) |
185 | + options = html_options.merge( | ||
186 | + title: "Issue: #{title}", | ||
187 | + class: "gfm gfm-issue #{html_options[:class]}" | ||
188 | + ) | ||
180 | 189 | ||
181 | - link_to("##{identifier}", url, html_options.merge(title: "Issue: #{title}", class: "gfm gfm-issue #{html_options[:class]}")) | 190 | + link_to("##{identifier}", url, options) |
182 | end | 191 | end |
183 | - else | ||
184 | - reference_jira_issue(identifier) if @project.issues_tracker == "jira" | 192 | + elsif project.issues_tracker == 'jira' |
193 | + reference_jira_issue(identifier, project) | ||
185 | end | 194 | end |
186 | end | 195 | end |
187 | 196 | ||
188 | - def reference_merge_request(identifier) | ||
189 | - if merge_request = @project.merge_requests.where(iid: identifier).first | ||
190 | - link_to("!#{identifier}", project_merge_request_url(@project, merge_request), html_options.merge(title: "Merge Request: #{merge_request.title}", class: "gfm gfm-merge_request #{html_options[:class]}")) | 197 | + def reference_merge_request(identifier, project = @project) |
198 | + if merge_request = project.merge_requests.find_by(iid: identifier) | ||
199 | + options = html_options.merge( | ||
200 | + title: "Merge Request: #{merge_request.title}", | ||
201 | + class: "gfm gfm-merge_request #{html_options[:class]}" | ||
202 | + ) | ||
203 | + url = project_merge_request_url(project, merge_request) | ||
204 | + link_to("!#{identifier}", url, options) | ||
191 | end | 205 | end |
192 | end | 206 | end |
193 | 207 | ||
194 | - def reference_snippet(identifier) | ||
195 | - if snippet = @project.snippets.where(id: identifier).first | ||
196 | - link_to("$#{identifier}", project_snippet_url(@project, snippet), html_options.merge(title: "Snippet: #{snippet.title}", class: "gfm gfm-snippet #{html_options[:class]}")) | 208 | + def reference_snippet(identifier, project = @project) |
209 | + if snippet = project.snippets.find_by(id: identifier) | ||
210 | + options = html_options.merge( | ||
211 | + title: "Snippet: #{snippet.title}", | ||
212 | + class: "gfm gfm-snippet #{html_options[:class]}" | ||
213 | + ) | ||
214 | + link_to("$#{identifier}", project_snippet_url(project, snippet), | ||
215 | + options) | ||
197 | end | 216 | end |
198 | end | 217 | end |
199 | 218 | ||
200 | - def reference_commit(identifier) | ||
201 | - if @project.valid_repo? && commit = @project.repository.commit(identifier) | ||
202 | - link_to(identifier, project_commit_url(@project, commit), html_options.merge(title: commit.link_title, class: "gfm gfm-commit #{html_options[:class]}")) | 219 | + def reference_commit(identifier, project = @project) |
220 | + if project.valid_repo? && commit = project.repository.commit(identifier) | ||
221 | + options = html_options.merge( | ||
222 | + title: commit.link_title, | ||
223 | + class: "gfm gfm-commit #{html_options[:class]}" | ||
224 | + ) | ||
225 | + link_to(identifier, project_commit_url(project, commit), options) | ||
203 | end | 226 | end |
204 | end | 227 | end |
205 | 228 | ||
206 | - def reference_jira_issue(identifier) | 229 | + def reference_jira_issue(identifier, project = @project) |
207 | url = url_for_issue(identifier) | 230 | url = url_for_issue(identifier) |
208 | title = Gitlab.config.issues_tracker[@project.issues_tracker]["title"] | 231 | title = Gitlab.config.issues_tracker[@project.issues_tracker]["title"] |
209 | 232 | ||
210 | - link_to("#{identifier}", url, html_options.merge(title: "Issue in #{title}", class: "gfm gfm-issue #{html_options[:class]}")) | 233 | + options = html_options.merge( |
234 | + title: "Issue in #{title}", | ||
235 | + class: "gfm gfm-issue #{html_options[:class]}" | ||
236 | + ) | ||
237 | + link_to("#{identifier}", url, options) | ||
211 | end | 238 | end |
212 | end | 239 | end |
213 | end | 240 | end |
lib/gitlab/reference_extractor.rb
@@ -51,7 +51,7 @@ module Gitlab | @@ -51,7 +51,7 @@ module Gitlab | ||
51 | 51 | ||
52 | private | 52 | private |
53 | 53 | ||
54 | - def reference_link type, identifier | 54 | + def reference_link(type, identifier, project) |
55 | # Append identifier to the appropriate collection. | 55 | # Append identifier to the appropriate collection. |
56 | send("#{type}s") << identifier | 56 | send("#{type}s") << identifier |
57 | end | 57 | end |
spec/helpers/gitlab_markdown_helper_spec.rb
@@ -41,7 +41,8 @@ describe GitlabMarkdownHelper do | @@ -41,7 +41,8 @@ describe GitlabMarkdownHelper do | ||
41 | end | 41 | end |
42 | 42 | ||
43 | it "should forward HTML options to links" do | 43 | it "should forward HTML options to links" do |
44 | - gfm("Fixed in #{commit.id}", class: "foo").should have_selector("a.gfm.foo") | 44 | + gfm("Fixed in #{commit.id}", @project, class: 'foo'). |
45 | + should have_selector('a.gfm.foo') | ||
45 | end | 46 | end |
46 | 47 | ||
47 | describe "referencing a commit" do | 48 | describe "referencing a commit" do |