Show More
@@ -38,44 +38,39 b' default one. See the instructions in :re' | |||||
38 |
|
38 | |||
39 | .. _issue-tr-eg-ref: |
|
39 | .. _issue-tr-eg-ref: | |
40 |
|
40 | |||
|
41 | ||||
41 | Jira Integration |
|
42 | Jira Integration | |
42 | ---------------- |
|
43 | ---------------- | |
43 |
|
44 | |||
44 | * Regex = ``(?:^#|\s#)(\w+-\d+)`` |
|
45 | Please check examples in the view for configuration the issue trackers. | |
45 | * URL = ``https://myissueserver.com/browse/${id}`` |
|
46 | ||
46 | * Issue Prefix = ``#`` |
|
|||
47 |
|
47 | |||
48 | Confluence (Wiki) |
|
48 | Confluence (Wiki) | |
49 | ----------------- |
|
49 | ----------------- | |
50 |
|
50 | |||
51 | * Regex = ``(?:conf-)([A-Z0-9]+)`` |
|
51 | Please check examples in the view for configuration the issue trackers. | |
52 | * URL = ``https://example.atlassian.net/display/wiki/${id}/${repo_name}`` |
|
52 | ||
53 | * issue prefix = ``CONF-`` |
|
|||
54 |
|
53 | |||
55 | Redmine Integration |
|
54 | Redmine Integration | |
56 | ------------------- |
|
55 | ------------------- | |
57 |
|
56 | |||
58 | * Regex = ``(issue-+\d+)`` |
|
57 | Please check examples in the view for configuration the issue trackers. | |
59 | * URL = ``https://myissueserver.com/redmine/issue/${id}`` |
|
58 | ||
60 | * Issue Prefix = ``issue-`` |
|
|||
61 |
|
59 | |||
62 |
Redmine |
|
60 | Redmine wiki Integration | |
63 | -------------- |
|
61 | ------------------------ | |
64 |
|
62 | |||
65 | * Regex = ``(?:wiki-)([a-zA-Z0-9]+)`` |
|
63 | Please check examples in the view for configuration the issue trackers. | |
66 | * URL = ``https://example.com/redmine/projects/wiki/${repo_name}`` |
|
64 | ||
67 | * Issue prefix = ``Issue-`` |
|
|||
68 |
|
65 | |||
69 | Pivotal Tracker |
|
66 | Pivotal Tracker | |
70 | --------------- |
|
67 | --------------- | |
71 |
|
68 | |||
72 | * Regex = ``(?:pivot-)(?<project_id>\d+)-(?<story>\d+)`` |
|
69 | Please check examples in the view for configuration the issue trackers. | |
73 | * URL = ``https://www.pivotaltracker.com/s/projects/${project_id}/stories/${story}`` |
|
70 | ||
74 | * Issue prefix = ``Piv-`` |
|
|||
75 |
|
71 | |||
76 | Trello |
|
72 | Trello | |
77 | ------ |
|
73 | ------ | |
78 |
|
74 | |||
79 | * Regex = ``(?:trello-)(?<card_id>[a-zA-Z0-9]+)`` |
|
75 | Please check examples in the view for configuration the issue trackers. | |
80 | * URL = ``https://trello.com/example.com/${card_id}`` |
|
76 | ||
81 | * Issue prefix = ``Trello-`` |
|
@@ -726,7 +726,7 b' class TestAdminSettingsIssueTracker(obje' | |||||
726 | IssueTrackerSettingsModel().delete_entries(self.uid) |
|
726 | IssueTrackerSettingsModel().delete_entries(self.uid) | |
727 |
|
727 | |||
728 | def test_delete_issuetracker_pattern( |
|
728 | def test_delete_issuetracker_pattern( | |
729 | self, autologin_user, backend, csrf_token, settings_util): |
|
729 | self, autologin_user, backend, csrf_token, settings_util, xhr_header): | |
730 | pattern = 'issuetracker_pat' |
|
730 | pattern = 'issuetracker_pat' | |
731 | uid = md5(pattern) |
|
731 | uid = md5(pattern) | |
732 | settings_util.create_rhodecode_setting( |
|
732 | settings_util.create_rhodecode_setting( | |
@@ -737,6 +737,6 b' class TestAdminSettingsIssueTracker(obje' | |||||
737 | 'uid': uid, |
|
737 | 'uid': uid, | |
738 | 'csrf_token': csrf_token |
|
738 | 'csrf_token': csrf_token | |
739 | } |
|
739 | } | |
740 |
self.app.post(post_url, post_data, status= |
|
740 | self.app.post(post_url, post_data, extra_environ=xhr_header, status=200) | |
741 | settings = SettingsModel().get_all_settings() |
|
741 | settings = SettingsModel().get_all_settings() | |
742 | assert 'rhodecode_%s%s' % (self.SHORT_PATTERN_KEY, uid) not in settings |
|
742 | assert 'rhodecode_%s%s' % (self.SHORT_PATTERN_KEY, uid) not in settings |
@@ -518,7 +518,7 b' class AdminSettingsView(BaseAppView):' | |||||
518 | @CSRFRequired() |
|
518 | @CSRFRequired() | |
519 | @view_config( |
|
519 | @view_config( | |
520 | route_name='admin_settings_issuetracker_delete', request_method='POST', |
|
520 | route_name='admin_settings_issuetracker_delete', request_method='POST', | |
521 | renderer='rhodecode:templates/admin/settings/settings.mako') |
|
521 | renderer='json_ext', xhr=True) | |
522 | def settings_issuetracker_delete(self): |
|
522 | def settings_issuetracker_delete(self): | |
523 | _ = self.request.translate |
|
523 | _ = self.request.translate | |
524 | self.load_default_context() |
|
524 | self.load_default_context() | |
@@ -528,8 +528,11 b' class AdminSettingsView(BaseAppView):' | |||||
528 | except Exception: |
|
528 | except Exception: | |
529 | log.exception('Failed to delete issue tracker setting %s', uid) |
|
529 | log.exception('Failed to delete issue tracker setting %s', uid) | |
530 | raise HTTPNotFound() |
|
530 | raise HTTPNotFound() | |
531 | h.flash(_('Removed issue tracker entry'), category='success') |
|
531 | ||
532 | raise HTTPFound(h.route_path('admin_settings_issuetracker')) |
|
532 | SettingsModel().invalidate_settings_cache() | |
|
533 | h.flash(_('Removed issue tracker entry.'), category='success') | |||
|
534 | ||||
|
535 | return {'deleted': uid} | |||
533 |
|
536 | |||
534 | @LoginRequired() |
|
537 | @LoginRequired() | |
535 | @HasPermissionAllDecorator('hg.admin') |
|
538 | @HasPermissionAllDecorator('hg.admin') |
@@ -125,7 +125,7 b' class TestRepoIssueTracker(object):' | |||||
125 | self.settings_model.delete_entries(self.uid) |
|
125 | self.settings_model.delete_entries(self.uid) | |
126 |
|
126 | |||
127 | def test_delete_issuetracker_pattern( |
|
127 | def test_delete_issuetracker_pattern( | |
128 | self, autologin_user, backend, csrf_token, settings_util): |
|
128 | self, autologin_user, backend, csrf_token, settings_util, xhr_header): | |
129 | repo = backend.create_repo() |
|
129 | repo = backend.create_repo() | |
130 | repo_name = repo.repo_name |
|
130 | repo_name = repo.repo_name | |
131 | entry_key = 'issuetracker_pat_' |
|
131 | entry_key = 'issuetracker_pat_' | |
@@ -141,8 +141,9 b' class TestRepoIssueTracker(object):' | |||||
141 | repo_name=backend.repo.repo_name), |
|
141 | repo_name=backend.repo.repo_name), | |
142 | { |
|
142 | { | |
143 | 'uid': uid, |
|
143 | 'uid': uid, | |
144 | 'csrf_token': csrf_token |
|
144 | 'csrf_token': csrf_token, | |
145 | }, status=302) |
|
145 | '': '' | |
|
146 | }, extra_environ=xhr_header, status=200) | |||
146 | settings = IssueTrackerSettingsModel( |
|
147 | settings = IssueTrackerSettingsModel( | |
147 | repo=Repository.get_by_repo_name(repo_name)).get_repo_settings() |
|
148 | repo=Repository.get_by_repo_name(repo_name)).get_repo_settings() | |
148 | assert 'rhodecode_%s%s' % (entry_key, uid) not in settings |
|
149 | assert 'rhodecode_%s%s' % (entry_key, uid) not in settings |
@@ -20,7 +20,7 b'' | |||||
20 |
|
20 | |||
21 | import logging |
|
21 | import logging | |
22 |
|
22 | |||
23 | from pyramid.httpexceptions import HTTPFound |
|
23 | from pyramid.httpexceptions import HTTPFound, HTTPNotFound | |
24 | from pyramid.view import view_config |
|
24 | from pyramid.view import view_config | |
25 | import formencode |
|
25 | import formencode | |
26 |
|
26 | |||
@@ -31,7 +31,7 b' from rhodecode.lib.auth import (' | |||||
31 | LoginRequired, HasRepoPermissionAnyDecorator, CSRFRequired) |
|
31 | LoginRequired, HasRepoPermissionAnyDecorator, CSRFRequired) | |
32 | from rhodecode.model.forms import IssueTrackerPatternsForm |
|
32 | from rhodecode.model.forms import IssueTrackerPatternsForm | |
33 | from rhodecode.model.meta import Session |
|
33 | from rhodecode.model.meta import Session | |
34 | from rhodecode.model.settings import IssueTrackerSettingsModel |
|
34 | from rhodecode.model.settings import IssueTrackerSettingsModel, SettingsModel | |
35 |
|
35 | |||
36 | log = logging.getLogger(__name__) |
|
36 | log = logging.getLogger(__name__) | |
37 |
|
37 | |||
@@ -64,7 +64,7 b' class RepoSettingsIssueTrackersView(Repo' | |||||
64 | @CSRFRequired() |
|
64 | @CSRFRequired() | |
65 | @view_config( |
|
65 | @view_config( | |
66 | route_name='edit_repo_issuetracker_test', request_method='POST', |
|
66 | route_name='edit_repo_issuetracker_test', request_method='POST', | |
67 |
|
|
67 | renderer='string', xhr=True) | |
68 | def repo_issuetracker_test(self): |
|
68 | def repo_issuetracker_test(self): | |
69 | return h.urlify_commit_message( |
|
69 | return h.urlify_commit_message( | |
70 | self.request.POST.get('test_text', ''), |
|
70 | self.request.POST.get('test_text', ''), | |
@@ -75,7 +75,7 b' class RepoSettingsIssueTrackersView(Repo' | |||||
75 | @CSRFRequired() |
|
75 | @CSRFRequired() | |
76 | @view_config( |
|
76 | @view_config( | |
77 | route_name='edit_repo_issuetracker_delete', request_method='POST', |
|
77 | route_name='edit_repo_issuetracker_delete', request_method='POST', | |
78 | renderer='rhodecode:templates/admin/repos/repo_edit.mako') |
|
78 | renderer='json_ext', xhr=True) | |
79 | def repo_issuetracker_delete(self): |
|
79 | def repo_issuetracker_delete(self): | |
80 | _ = self.request.translate |
|
80 | _ = self.request.translate | |
81 | uid = self.request.POST.get('uid') |
|
81 | uid = self.request.POST.get('uid') | |
@@ -85,10 +85,12 b' class RepoSettingsIssueTrackersView(Repo' | |||||
85 | except Exception: |
|
85 | except Exception: | |
86 | h.flash(_('Error occurred during deleting issue tracker entry'), |
|
86 | h.flash(_('Error occurred during deleting issue tracker entry'), | |
87 | category='error') |
|
87 | category='error') | |
88 | else: |
|
88 | raise HTTPNotFound() | |
89 | h.flash(_('Removed issue tracker entry'), category='success') |
|
89 | ||
90 | raise HTTPFound( |
|
90 | SettingsModel().invalidate_settings_cache() | |
91 | h.route_path('edit_repo_issuetracker', repo_name=self.db_repo_name)) |
|
91 | h.flash(_('Removed issue tracker entry.'), category='success') | |
|
92 | ||||
|
93 | return {'deleted': uid} | |||
92 |
|
94 | |||
93 | def _update_patterns(self, form, repo_settings): |
|
95 | def _update_patterns(self, form, repo_settings): | |
94 | for uid in form['delete_patterns']: |
|
96 | for uid in form['delete_patterns']: |
@@ -191,6 +191,24 b' table.dataTable {' | |||||
191 | padding-left: .65em; |
|
191 | padding-left: .65em; | |
192 | } |
|
192 | } | |
193 |
|
193 | |||
|
194 | &.td-issue-tracker-name { | |||
|
195 | width: 180px; | |||
|
196 | input { | |||
|
197 | width: 180px; | |||
|
198 | } | |||
|
199 | ||||
|
200 | } | |||
|
201 | ||||
|
202 | &.td-issue-tracker-regex { | |||
|
203 | white-space: nowrap; | |||
|
204 | ||||
|
205 | min-width: 300px; | |||
|
206 | input { | |||
|
207 | min-width: 300px; | |||
|
208 | } | |||
|
209 | ||||
|
210 | } | |||
|
211 | ||||
194 | &.td-url { |
|
212 | &.td-url { | |
195 | white-space: nowrap; |
|
213 | white-space: nowrap; | |
196 | } |
|
214 | } |
@@ -5,24 +5,101 b'' | |||||
5 | ## ${its.issue_tracker_settings_test(test_url)} |
|
5 | ## ${its.issue_tracker_settings_test(test_url)} | |
6 |
|
6 | |||
7 | <%def name="issue_tracker_settings_table(patterns, form_url, delete_url)"> |
|
7 | <%def name="issue_tracker_settings_table(patterns, form_url, delete_url)"> | |
|
8 | <% | |||
|
9 | # Name/desc, pattern, issue prefix | |||
|
10 | examples = [ | |||
|
11 | ( | |||
|
12 | ' ', | |||
|
13 | ' ', | |||
|
14 | ' ', | |||
|
15 | ' ' | |||
|
16 | ), | |||
|
17 | ||||
|
18 | ( | |||
|
19 | 'Redmine', | |||
|
20 | '(^#|\s#)(?P<issue_id>\d+)', | |||
|
21 | 'https://myissueserver.com/${repo}/issue/${issue_id}', | |||
|
22 | '' | |||
|
23 | ), | |||
|
24 | ||||
|
25 | ( | |||
|
26 | 'Redmine - Alternative', | |||
|
27 | '(?:issue-)(\d+)', | |||
|
28 | 'https://myissueserver.com/redmine/issue/${id}', | |||
|
29 | '' | |||
|
30 | ), | |||
|
31 | ||||
|
32 | ( | |||
|
33 | 'Redmine - Wiki', | |||
|
34 | '(?:wiki-)([a-zA-Z0-9]+)', | |||
|
35 | 'http://example.org/projects/${repo_name}/wiki/${id}', | |||
|
36 | 'wiki-' | |||
|
37 | ), | |||
|
38 | ||||
|
39 | ( | |||
|
40 | 'JIRA - All tickets', | |||
|
41 | '(^|\s\w+-\d+)', | |||
|
42 | 'https://myjira.com/browse/${id}', | |||
|
43 | '' | |||
|
44 | ), | |||
|
45 | ||||
|
46 | ( | |||
|
47 | 'JIRA - Project (JRA)', | |||
|
48 | '(?:(^|\s)(?P<issue_id>(?:JRA-|JRA-)(?:\d+)))', | |||
|
49 | 'https://myjira.com/${issue_id}', | |||
|
50 | '' | |||
|
51 | ), | |||
|
52 | ||||
|
53 | ( | |||
|
54 | 'Confluence WIKI', | |||
|
55 | '(?:conf-)([A-Z0-9]+)', | |||
|
56 | 'https://example.atlassian.net/display/wiki/${id}/${repo_name}', | |||
|
57 | 'CONF-', | |||
|
58 | ), | |||
|
59 | ||||
|
60 | ( | |||
|
61 | 'Pivotal Tracker', | |||
|
62 | '(?:pivot-)(?<project_id>\d+)-(?<story>\d+)', | |||
|
63 | 'https://www.pivotaltracker.com/s/projects/${project_id}/stories/${story}', | |||
|
64 | 'PIV-', | |||
|
65 | ), | |||
|
66 | ||||
|
67 | ( | |||
|
68 | 'Trello', | |||
|
69 | '(?:trello-)(?<card_id>[a-zA-Z0-9]+)', | |||
|
70 | 'https://trello.com/example.com/${card_id}', | |||
|
71 | 'TRELLO-', | |||
|
72 | ), | |||
|
73 | ] | |||
|
74 | %> | |||
|
75 | ||||
8 | <table class="rctable issuetracker"> |
|
76 | <table class="rctable issuetracker"> | |
9 | <tr> |
|
77 | <tr> | |
10 | <th>${_('Description')}</th> |
|
78 | <th>${_('Description')}</th> | |
11 | <th>${_('Pattern')}</th> |
|
79 | <th>${_('Pattern')}</th> | |
12 | <th>${_('Url')}</th> |
|
80 | <th>${_('Url')}</th> | |
13 | <th>${_('Prefix')}</th> |
|
81 | <th>${_('Extra Prefix')}</th> | |
14 | <th ></th> |
|
82 | <th ></th> | |
15 | </tr> |
|
83 | </tr> | |
16 | <tr> |
|
84 | % for name, pat, url, pref in examples: | |
17 | <td class="td-description issue-tracker-example">Example</td> |
|
85 | <tr class="it-examples" style="${'' if loop.index == 0 else 'display:none'}"> | |
18 |
<td class="td- |
|
86 | <td class="td-issue-tracker-name issue-tracker-example">${name}</td> | |
19 |
<td class="td- |
|
87 | <td class="td-regex issue-tracker-example">${pat}</td> | |
20 |
<td class="td- |
|
88 | <td class="td-url issue-tracker-example">${url}</td> | |
21 | <td class="issue-tracker-example"><a href="${h.route_url('enterprise_issue_tracker_settings')}" target="_blank">${_('Read more')}</a></td> |
|
89 | <td class="td-prefix issue-tracker-example">${pref}</td> | |
22 |
< |
|
90 | <td> | |
|
91 | % if loop.index == 0: | |||
|
92 | <a href="#showMore" onclick="$('.it-examples').toggle(); return false">${_('show examples')}</a> | |||
|
93 | % else: | |||
|
94 | <a href="#copyToInput" onclick="copyToInput(this, '${h.json.dumps(name)}', '${h.json.dumps(pat)}', '${h.json.dumps(url)}', '${h.json.dumps(pref)}'); return false">copy to input</a> | |||
|
95 | % endif | |||
|
96 | </td> | |||
|
97 | </tr> | |||
|
98 | % endfor | |||
|
99 | ||||
23 |
|
|
100 | %for uid, entry in patterns: | |
24 | <tr id="entry_${uid}"> |
|
101 | <tr id="entry_${uid}"> | |
25 |
<td class="td- |
|
102 | <td class="td-issue-tracker-name issuetracker_desc"> | |
26 | <span class="entry"> |
|
103 | <span class="entry"> | |
27 | ${entry.desc} |
|
104 | ${entry.desc} | |
28 | </span> |
|
105 | </span> | |
@@ -30,7 +107,7 b'' | |||||
30 | ${h.text('new_pattern_description_'+uid, class_='medium-inline', value=entry.desc or '')} |
|
107 | ${h.text('new_pattern_description_'+uid, class_='medium-inline', value=entry.desc or '')} | |
31 | </span> |
|
108 | </span> | |
32 | </td> |
|
109 | </td> | |
33 | <td class="td-regex issuetracker_pat"> |
|
110 | <td class="td-issue-tracker-regex issuetracker_pat"> | |
34 | <span class="entry"> |
|
111 | <span class="entry"> | |
35 | ${entry.pat} |
|
112 | ${entry.pat} | |
36 | </span> |
|
113 | </span> | |
@@ -95,13 +172,13 b'' | |||||
95 | if (confirm("${_('Confirm to remove this pattern:')} "+$(entry).data('desc'))) { |
|
172 | if (confirm("${_('Confirm to remove this pattern:')} "+$(entry).data('desc'))) { | |
96 | $.ajax({ |
|
173 | $.ajax({ | |
97 | type: "POST", |
|
174 | type: "POST", | |
98 |
url: "${delete_url}", |
|
175 | url: "${delete_url}", | |
99 | data: { |
|
176 | data: { | |
100 | 'csrf_token': CSRF_TOKEN, |
|
177 | 'csrf_token': CSRF_TOKEN, | |
101 | 'uid':$(entry).data('uid') |
|
178 | 'uid':$(entry).data('uid') | |
102 | }, |
|
179 | }, | |
103 | success: function(){ |
|
180 | success: function(){ | |
104 | location.reload(); |
|
181 | window.location.reload(); | |
105 | }, |
|
182 | }, | |
106 | error: function(data, textStatus, errorThrown){ |
|
183 | error: function(data, textStatus, errorThrown){ | |
107 | alert("Error while deleting entry.\nError code {0} ({1}). URL: {2}".format(data.status,data.statusText,$(entry)[0].url)); |
|
184 | alert("Error while deleting entry.\nError code {0} ({1}). URL: {2}".format(data.status,data.statusText,$(entry)[0].url)); | |
@@ -137,6 +214,24 b'' | |||||
137 | $('#add_pattern').on('click', function(e) { |
|
214 | $('#add_pattern').on('click', function(e) { | |
138 | addNewPatternInput(); |
|
215 | addNewPatternInput(); | |
139 | }); |
|
216 | }); | |
|
217 | ||||
|
218 | var copied = false; | |||
|
219 | copyToInput = function (elem, name, pat, url, pref) { | |||
|
220 | if (copied === false) { | |||
|
221 | addNewPatternInput(); | |||
|
222 | copied = true; | |||
|
223 | } | |||
|
224 | $(elem).hide(); | |||
|
225 | var load = function(text){ | |||
|
226 | return text.replace(/["]/g, "") | |||
|
227 | }; | |||
|
228 | $('#description_1').val(load(name)); | |||
|
229 | $('#pattern_1').val(load(pat)); | |||
|
230 | $('#url_1').val(load(url)); | |||
|
231 | $('#prefix_1').val(load(pref)); | |||
|
232 | ||||
|
233 | } | |||
|
234 | ||||
140 | </script> |
|
235 | </script> | |
141 | </%def> |
|
236 | </%def> | |
142 |
|
237 | |||
@@ -144,12 +239,12 b'' | |||||
144 | <table id="add-row-tmpl" style="display: none;"> |
|
239 | <table id="add-row-tmpl" style="display: none;"> | |
145 | <tbody> |
|
240 | <tbody> | |
146 | <tr class="new_pattern"> |
|
241 | <tr class="new_pattern"> | |
147 |
<td class="td- |
|
242 | <td class="td-issue-tracker-name issuetracker_desc"> | |
148 | <span class="entry"> |
|
243 | <span class="entry"> | |
149 |
|
|
244 | <input class="medium-inline" id="description_##UUID##" name="new_pattern_description_##UUID##" value="##DESCRIPTION##" type="text"> | |
150 | </span> |
|
245 | </span> | |
151 | </td> |
|
246 | </td> | |
152 | <td class="td-regex issuetracker_pat"> |
|
247 | <td class="td-issue-tracker-regex issuetracker_pat"> | |
153 | <span class="entry"> |
|
248 | <span class="entry"> | |
154 | <input class="medium-inline" id="pattern_##UUID##" name="new_pattern_pattern_##UUID##" placeholder="Pattern" |
|
249 | <input class="medium-inline" id="pattern_##UUID##" name="new_pattern_pattern_##UUID##" placeholder="Pattern" | |
155 | value="##PATTERN##" type="text"> |
|
250 | value="##PATTERN##" type="text"> | |
@@ -178,9 +273,14 b'' | |||||
178 | <div class="fields"> |
|
273 | <div class="fields"> | |
179 | <div class="field"> |
|
274 | <div class="field"> | |
180 | <div class='textarea-full'> |
|
275 | <div class='textarea-full'> | |
181 |
<textarea id="test_pattern_data" rows="1 |
|
276 | <textarea id="test_pattern_data" rows="12"> | |
182 | This is an example text for testing issue tracker patterns. |
|
277 | This is an example text for testing issue tracker patterns. | |
183 | This commit fixes ticket #451. |
|
278 | This commit fixes ticket #451 and ticket #910. | |
|
279 | Following tickets will get mentioned: | |||
|
280 | #123 | |||
|
281 | #456 | |||
|
282 | JRA-123 | |||
|
283 | JRA-456 | |||
184 | Open a pull request !101 to contribute ! |
|
284 | Open a pull request !101 to contribute ! | |
185 | Added tag v1.3.0 for commit 0f3b629be725 |
|
285 | Added tag v1.3.0 for commit 0f3b629be725 | |
186 |
|
286 |
General Comments 0
You need to be logged in to leave comments.
Login now