##// END OF EJS Templates
emails: improved styling, and fixed problems with some email clients...
ergo -
r4377:a2405083 stable
parent child Browse files
Show More
@@ -1,402 +1,419 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2016-2020 RhodeCode GmbH
3 # Copyright (C) 2016-2020 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
7 # (only), as published by the Free Software Foundation.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU Affero General Public License
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
16 #
17 # This program is dual-licensed. If you wish to learn more about the
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
20
21 import os
21 import os
22 import logging
22 import logging
23 import datetime
23 import datetime
24
24
25 from pyramid.view import view_config
25 from pyramid.view import view_config
26 from pyramid.renderers import render_to_response
26 from pyramid.renderers import render_to_response
27 from rhodecode.apps._base import BaseAppView
27 from rhodecode.apps._base import BaseAppView
28 from rhodecode.lib.celerylib import run_task, tasks
28 from rhodecode.lib.celerylib import run_task, tasks
29 from rhodecode.lib.utils2 import AttributeDict
29 from rhodecode.lib.utils2 import AttributeDict
30 from rhodecode.model.db import User
30 from rhodecode.model.db import User
31 from rhodecode.model.notification import EmailNotificationModel
31 from rhodecode.model.notification import EmailNotificationModel
32
32
33 log = logging.getLogger(__name__)
33 log = logging.getLogger(__name__)
34
34
35
35
36 class DebugStyleView(BaseAppView):
36 class DebugStyleView(BaseAppView):
37 def load_default_context(self):
37 def load_default_context(self):
38 c = self._get_local_tmpl_context()
38 c = self._get_local_tmpl_context()
39
39
40 return c
40 return c
41
41
42 @view_config(
42 @view_config(
43 route_name='debug_style_home', request_method='GET',
43 route_name='debug_style_home', request_method='GET',
44 renderer=None)
44 renderer=None)
45 def index(self):
45 def index(self):
46 c = self.load_default_context()
46 c = self.load_default_context()
47 c.active = 'index'
47 c.active = 'index'
48
48
49 return render_to_response(
49 return render_to_response(
50 'debug_style/index.html', self._get_template_context(c),
50 'debug_style/index.html', self._get_template_context(c),
51 request=self.request)
51 request=self.request)
52
52
53 @view_config(
53 @view_config(
54 route_name='debug_style_email', request_method='GET',
54 route_name='debug_style_email', request_method='GET',
55 renderer=None)
55 renderer=None)
56 @view_config(
56 @view_config(
57 route_name='debug_style_email_plain_rendered', request_method='GET',
57 route_name='debug_style_email_plain_rendered', request_method='GET',
58 renderer=None)
58 renderer=None)
59 def render_email(self):
59 def render_email(self):
60 c = self.load_default_context()
60 c = self.load_default_context()
61 email_id = self.request.matchdict['email_id']
61 email_id = self.request.matchdict['email_id']
62 c.active = 'emails'
62 c.active = 'emails'
63
63
64 pr = AttributeDict(
64 pr = AttributeDict(
65 pull_request_id=123,
65 pull_request_id=123,
66 title='digital_ocean: fix redis, elastic search start on boot, '
66 title='digital_ocean: fix redis, elastic search start on boot, '
67 'fix fd limits on supervisor, set postgres 11 version',
67 'fix fd limits on supervisor, set postgres 11 version',
68 description='''
68 description='''
69 Check if we should use full-topic or mini-topic.
69 Check if we should use full-topic or mini-topic.
70
70
71 - full topic produces some problems with merge states etc
71 - full topic produces some problems with merge states etc
72 - server-mini-topic needs probably tweeks.
72 - server-mini-topic needs probably tweeks.
73 ''',
73 ''',
74 repo_name='foobar',
74 repo_name='foobar',
75 source_ref_parts=AttributeDict(type='branch', name='fix-ticket-2000'),
75 source_ref_parts=AttributeDict(type='branch', name='fix-ticket-2000'),
76 target_ref_parts=AttributeDict(type='branch', name='master'),
76 target_ref_parts=AttributeDict(type='branch', name='master'),
77 )
77 )
78 target_repo = AttributeDict(repo_name='repo_group/target_repo')
78 target_repo = AttributeDict(repo_name='repo_group/target_repo')
79 source_repo = AttributeDict(repo_name='repo_group/source_repo')
79 source_repo = AttributeDict(repo_name='repo_group/source_repo')
80 user = User.get_by_username(self.request.GET.get('user')) or self._rhodecode_db_user
80 user = User.get_by_username(self.request.GET.get('user')) or self._rhodecode_db_user
81 # file/commit changes for PR update
81 # file/commit changes for PR update
82 commit_changes = AttributeDict({
82 commit_changes = AttributeDict({
83 'added': ['aaaaaaabbbbb', 'cccccccddddddd'],
83 'added': ['aaaaaaabbbbb', 'cccccccddddddd'],
84 'removed': ['eeeeeeeeeee'],
84 'removed': ['eeeeeeeeeee'],
85 })
85 })
86 file_changes = AttributeDict({
86 file_changes = AttributeDict({
87 'added': ['a/file1.md', 'file2.py'],
87 'added': ['a/file1.md', 'file2.py'],
88 'modified': ['b/modified_file.rst'],
88 'modified': ['b/modified_file.rst'],
89 'removed': ['.idea'],
89 'removed': ['.idea'],
90 })
90 })
91
91
92 exc_traceback = {
92 exc_traceback = {
93 'exc_utc_date': '2020-03-26T12:54:50.683281',
93 'exc_utc_date': '2020-03-26T12:54:50.683281',
94 'exc_id': 139638856342656,
94 'exc_id': 139638856342656,
95 'exc_timestamp': '1585227290.683288',
95 'exc_timestamp': '1585227290.683288',
96 'version': 'v1',
96 'version': 'v1',
97 'exc_message': 'Traceback (most recent call last):\n File "/nix/store/s43k2r9rysfbzmsjdqnxgzvvb7zjhkxb-python2.7-pyramid-1.10.4/lib/python2.7/site-packages/pyramid/tweens.py", line 41, in excview_tween\n response = handler(request)\n File "/nix/store/s43k2r9rysfbzmsjdqnxgzvvb7zjhkxb-python2.7-pyramid-1.10.4/lib/python2.7/site-packages/pyramid/router.py", line 148, in handle_request\n registry, request, context, context_iface, view_name\n File "/nix/store/s43k2r9rysfbzmsjdqnxgzvvb7zjhkxb-python2.7-pyramid-1.10.4/lib/python2.7/site-packages/pyramid/view.py", line 667, in _call_view\n response = view_callable(context, request)\n File "/nix/store/s43k2r9rysfbzmsjdqnxgzvvb7zjhkxb-python2.7-pyramid-1.10.4/lib/python2.7/site-packages/pyramid/config/views.py", line 188, in attr_view\n return view(context, request)\n File "/nix/store/s43k2r9rysfbzmsjdqnxgzvvb7zjhkxb-python2.7-pyramid-1.10.4/lib/python2.7/site-packages/pyramid/config/views.py", line 214, in predicate_wrapper\n return view(context, request)\n File "/nix/store/s43k2r9rysfbzmsjdqnxgzvvb7zjhkxb-python2.7-pyramid-1.10.4/lib/python2.7/site-packages/pyramid/viewderivers.py", line 401, in viewresult_to_response\n result = view(context, request)\n File "/nix/store/s43k2r9rysfbzmsjdqnxgzvvb7zjhkxb-python2.7-pyramid-1.10.4/lib/python2.7/site-packages/pyramid/viewderivers.py", line 132, in _class_view\n response = getattr(inst, attr)()\n File "/mnt/hgfs/marcink/workspace/rhodecode-enterprise-ce/rhodecode/apps/debug_style/views.py", line 355, in render_email\n template_type, **email_kwargs.get(email_id, {}))\n File "/mnt/hgfs/marcink/workspace/rhodecode-enterprise-ce/rhodecode/model/notification.py", line 402, in render_email\n body = email_template.render(None, **_kwargs)\n File "/mnt/hgfs/marcink/workspace/rhodecode-enterprise-ce/rhodecode/lib/partial_renderer.py", line 95, in render\n return self._render_with_exc(tmpl, args, kwargs)\n File "/mnt/hgfs/marcink/workspace/rhodecode-enterprise-ce/rhodecode/lib/partial_renderer.py", line 79, in _render_with_exc\n return render_func.render(*args, **kwargs)\n File "/nix/store/dakh34sxz4yfr435c0cwjz0sd6hnd5g3-python2.7-mako-1.1.0/lib/python2.7/site-packages/mako/template.py", line 476, in render\n return runtime._render(self, self.callable_, args, data)\n File "/nix/store/dakh34sxz4yfr435c0cwjz0sd6hnd5g3-python2.7-mako-1.1.0/lib/python2.7/site-packages/mako/runtime.py", line 883, in _render\n **_kwargs_for_callable(callable_, data)\n File "/nix/store/dakh34sxz4yfr435c0cwjz0sd6hnd5g3-python2.7-mako-1.1.0/lib/python2.7/site-packages/mako/runtime.py", line 920, in _render_context\n _exec_template(inherit, lclcontext, args=args, kwargs=kwargs)\n File "/nix/store/dakh34sxz4yfr435c0cwjz0sd6hnd5g3-python2.7-mako-1.1.0/lib/python2.7/site-packages/mako/runtime.py", line 947, in _exec_template\n callable_(context, *args, **kwargs)\n File "rhodecode_templates_email_templates_base_mako", line 63, in render_body\n File "rhodecode_templates_email_templates_exception_tracker_mako", line 43, in render_body\nAttributeError: \'str\' object has no attribute \'get\'\n',
97 'exc_message': 'Traceback (most recent call last):\n File "/nix/store/s43k2r9rysfbzmsjdqnxgzvvb7zjhkxb-python2.7-pyramid-1.10.4/lib/python2.7/site-packages/pyramid/tweens.py", line 41, in excview_tween\n response = handler(request)\n File "/nix/store/s43k2r9rysfbzmsjdqnxgzvvb7zjhkxb-python2.7-pyramid-1.10.4/lib/python2.7/site-packages/pyramid/router.py", line 148, in handle_request\n registry, request, context, context_iface, view_name\n File "/nix/store/s43k2r9rysfbzmsjdqnxgzvvb7zjhkxb-python2.7-pyramid-1.10.4/lib/python2.7/site-packages/pyramid/view.py", line 667, in _call_view\n response = view_callable(context, request)\n File "/nix/store/s43k2r9rysfbzmsjdqnxgzvvb7zjhkxb-python2.7-pyramid-1.10.4/lib/python2.7/site-packages/pyramid/config/views.py", line 188, in attr_view\n return view(context, request)\n File "/nix/store/s43k2r9rysfbzmsjdqnxgzvvb7zjhkxb-python2.7-pyramid-1.10.4/lib/python2.7/site-packages/pyramid/config/views.py", line 214, in predicate_wrapper\n return view(context, request)\n File "/nix/store/s43k2r9rysfbzmsjdqnxgzvvb7zjhkxb-python2.7-pyramid-1.10.4/lib/python2.7/site-packages/pyramid/viewderivers.py", line 401, in viewresult_to_response\n result = view(context, request)\n File "/nix/store/s43k2r9rysfbzmsjdqnxgzvvb7zjhkxb-python2.7-pyramid-1.10.4/lib/python2.7/site-packages/pyramid/viewderivers.py", line 132, in _class_view\n response = getattr(inst, attr)()\n File "/mnt/hgfs/marcink/workspace/rhodecode-enterprise-ce/rhodecode/apps/debug_style/views.py", line 355, in render_email\n template_type, **email_kwargs.get(email_id, {}))\n File "/mnt/hgfs/marcink/workspace/rhodecode-enterprise-ce/rhodecode/model/notification.py", line 402, in render_email\n body = email_template.render(None, **_kwargs)\n File "/mnt/hgfs/marcink/workspace/rhodecode-enterprise-ce/rhodecode/lib/partial_renderer.py", line 95, in render\n return self._render_with_exc(tmpl, args, kwargs)\n File "/mnt/hgfs/marcink/workspace/rhodecode-enterprise-ce/rhodecode/lib/partial_renderer.py", line 79, in _render_with_exc\n return render_func.render(*args, **kwargs)\n File "/nix/store/dakh34sxz4yfr435c0cwjz0sd6hnd5g3-python2.7-mako-1.1.0/lib/python2.7/site-packages/mako/template.py", line 476, in render\n return runtime._render(self, self.callable_, args, data)\n File "/nix/store/dakh34sxz4yfr435c0cwjz0sd6hnd5g3-python2.7-mako-1.1.0/lib/python2.7/site-packages/mako/runtime.py", line 883, in _render\n **_kwargs_for_callable(callable_, data)\n File "/nix/store/dakh34sxz4yfr435c0cwjz0sd6hnd5g3-python2.7-mako-1.1.0/lib/python2.7/site-packages/mako/runtime.py", line 920, in _render_context\n _exec_template(inherit, lclcontext, args=args, kwargs=kwargs)\n File "/nix/store/dakh34sxz4yfr435c0cwjz0sd6hnd5g3-python2.7-mako-1.1.0/lib/python2.7/site-packages/mako/runtime.py", line 947, in _exec_template\n callable_(context, *args, **kwargs)\n File "rhodecode_templates_email_templates_base_mako", line 63, in render_body\n File "rhodecode_templates_email_templates_exception_tracker_mako", line 43, in render_body\nAttributeError: \'str\' object has no attribute \'get\'\n',
98 'exc_type': 'AttributeError'
98 'exc_type': 'AttributeError'
99 }
99 }
100 email_kwargs = {
100 email_kwargs = {
101 'test': {},
101 'test': {},
102 'message': {
102 'message': {
103 'body': 'message body !'
103 'body': 'message body !'
104 },
104 },
105 'email_test': {
105 'email_test': {
106 'user': user,
106 'user': user,
107 'date': datetime.datetime.now(),
107 'date': datetime.datetime.now(),
108 },
108 },
109 'exception': {
109 'exception': {
110 'email_prefix': '[RHODECODE ERROR]',
110 'email_prefix': '[RHODECODE ERROR]',
111 'exc_id': exc_traceback['exc_id'],
111 'exc_id': exc_traceback['exc_id'],
112 'exc_url': 'http://server-url/{}'.format(exc_traceback['exc_id']),
112 'exc_url': 'http://server-url/{}'.format(exc_traceback['exc_id']),
113 'exc_type_name': 'NameError',
113 'exc_type_name': 'NameError',
114 'exc_traceback': exc_traceback,
114 'exc_traceback': exc_traceback,
115 },
115 },
116 'password_reset': {
116 'password_reset': {
117 'password_reset_url': 'http://example.com/reset-rhodecode-password/token',
117 'password_reset_url': 'http://example.com/reset-rhodecode-password/token',
118
118
119 'user': user,
119 'user': user,
120 'date': datetime.datetime.now(),
120 'date': datetime.datetime.now(),
121 'email': 'test@rhodecode.com',
121 'email': 'test@rhodecode.com',
122 'first_admin_email': User.get_first_super_admin().email
122 'first_admin_email': User.get_first_super_admin().email
123 },
123 },
124 'password_reset_confirmation': {
124 'password_reset_confirmation': {
125 'new_password': 'new-password-example',
125 'new_password': 'new-password-example',
126 'user': user,
126 'user': user,
127 'date': datetime.datetime.now(),
127 'date': datetime.datetime.now(),
128 'email': 'test@rhodecode.com',
128 'email': 'test@rhodecode.com',
129 'first_admin_email': User.get_first_super_admin().email
129 'first_admin_email': User.get_first_super_admin().email
130 },
130 },
131 'registration': {
131 'registration': {
132 'user': user,
132 'user': user,
133 'date': datetime.datetime.now(),
133 'date': datetime.datetime.now(),
134 },
134 },
135
135
136 'pull_request_comment': {
136 'pull_request_comment': {
137 'user': user,
137 'user': user,
138
138
139 'status_change': None,
139 'status_change': None,
140 'status_change_type': None,
140 'status_change_type': None,
141
141
142 'pull_request': pr,
142 'pull_request': pr,
143 'pull_request_commits': [],
143 'pull_request_commits': [],
144
144
145 'pull_request_target_repo': target_repo,
145 'pull_request_target_repo': target_repo,
146 'pull_request_target_repo_url': 'http://target-repo/url',
146 'pull_request_target_repo_url': 'http://target-repo/url',
147
147
148 'pull_request_source_repo': source_repo,
148 'pull_request_source_repo': source_repo,
149 'pull_request_source_repo_url': 'http://source-repo/url',
149 'pull_request_source_repo_url': 'http://source-repo/url',
150
150
151 'pull_request_url': 'http://localhost/pr1',
151 'pull_request_url': 'http://localhost/pr1',
152 'pr_comment_url': 'http://comment-url',
152 'pr_comment_url': 'http://comment-url',
153 'pr_comment_reply_url': 'http://comment-url#reply',
153 'pr_comment_reply_url': 'http://comment-url#reply',
154
154
155 'comment_file': None,
155 'comment_file': None,
156 'comment_line': None,
156 'comment_line': None,
157 'comment_type': 'note',
157 'comment_type': 'note',
158 'comment_body': 'This is my comment body. *I like !*',
158 'comment_body': 'This is my comment body. *I like !*',
159 'comment_id': 2048,
159 'comment_id': 2048,
160 'renderer_type': 'markdown',
160 'renderer_type': 'markdown',
161 'mention': True,
161 'mention': True,
162
162
163 },
163 },
164 'pull_request_comment+status': {
164 'pull_request_comment+status': {
165 'user': user,
165 'user': user,
166
166
167 'status_change': 'approved',
167 'status_change': 'approved',
168 'status_change_type': 'approved',
168 'status_change_type': 'approved',
169
169
170 'pull_request': pr,
170 'pull_request': pr,
171 'pull_request_commits': [],
171 'pull_request_commits': [],
172
172
173 'pull_request_target_repo': target_repo,
173 'pull_request_target_repo': target_repo,
174 'pull_request_target_repo_url': 'http://target-repo/url',
174 'pull_request_target_repo_url': 'http://target-repo/url',
175
175
176 'pull_request_source_repo': source_repo,
176 'pull_request_source_repo': source_repo,
177 'pull_request_source_repo_url': 'http://source-repo/url',
177 'pull_request_source_repo_url': 'http://source-repo/url',
178
178
179 'pull_request_url': 'http://localhost/pr1',
179 'pull_request_url': 'http://localhost/pr1',
180 'pr_comment_url': 'http://comment-url',
180 'pr_comment_url': 'http://comment-url',
181 'pr_comment_reply_url': 'http://comment-url#reply',
181 'pr_comment_reply_url': 'http://comment-url#reply',
182
182
183 'comment_type': 'todo',
183 'comment_type': 'todo',
184 'comment_file': None,
184 'comment_file': None,
185 'comment_line': None,
185 'comment_line': None,
186 'comment_body': '''
186 'comment_body': '''
187 I think something like this would be better
187 I think something like this would be better
188
188
189 ```py
189 ```py
190 // markdown renderer
190
191
191 def db():
192 def db():
192 global connection
193 global connection
193 return connection
194 return connection
194
195
195 ```
196 ```
196
197
197 ''',
198 ''',
198 'comment_id': 2048,
199 'comment_id': 2048,
199 'renderer_type': 'markdown',
200 'renderer_type': 'markdown',
200 'mention': True,
201 'mention': True,
201
202
202 },
203 },
203 'pull_request_comment+file': {
204 'pull_request_comment+file': {
204 'user': user,
205 'user': user,
205
206
206 'status_change': None,
207 'status_change': None,
207 'status_change_type': None,
208 'status_change_type': None,
208
209
209 'pull_request': pr,
210 'pull_request': pr,
210 'pull_request_commits': [],
211 'pull_request_commits': [],
211
212
212 'pull_request_target_repo': target_repo,
213 'pull_request_target_repo': target_repo,
213 'pull_request_target_repo_url': 'http://target-repo/url',
214 'pull_request_target_repo_url': 'http://target-repo/url',
214
215
215 'pull_request_source_repo': source_repo,
216 'pull_request_source_repo': source_repo,
216 'pull_request_source_repo_url': 'http://source-repo/url',
217 'pull_request_source_repo_url': 'http://source-repo/url',
217
218
218 'pull_request_url': 'http://localhost/pr1',
219 'pull_request_url': 'http://localhost/pr1',
219
220
220 'pr_comment_url': 'http://comment-url',
221 'pr_comment_url': 'http://comment-url',
221 'pr_comment_reply_url': 'http://comment-url#reply',
222 'pr_comment_reply_url': 'http://comment-url#reply',
222
223
223 'comment_file': 'rhodecode/model/get_flow_commits',
224 'comment_file': 'rhodecode/model/get_flow_commits',
224 'comment_line': 'o1210',
225 'comment_line': 'o1210',
225 'comment_type': 'todo',
226 'comment_type': 'todo',
226 'comment_body': '''
227 'comment_body': '''
227 I like this !
228 I like this !
228
229
229 But please check this code::
230 But please check this code
231
232 .. code-block:: javascript
233
234 // THIS IS RST CODE
235
236 this.createResolutionComment = function(commentId) {
237 // hide the trigger text
238 $('#resolve-comment-{0}'.format(commentId)).hide();
230
239
231 def main():
240 var comment = $('#comment-'+commentId);
232 print 'ok'
241 var commentData = comment.data();
242 if (commentData.commentInline) {
243 this.createComment(comment, commentId)
244 } else {
245 Rhodecode.comments.createGeneralComment('general', "$placeholder", commentId)
246 }
247
248 return false;
249 };
233
250
234 This should work better !
251 This should work better !
235 ''',
252 ''',
236 'comment_id': 2048,
253 'comment_id': 2048,
237 'renderer_type': 'rst',
254 'renderer_type': 'rst',
238 'mention': True,
255 'mention': True,
239
256
240 },
257 },
241
258
242 'pull_request_update': {
259 'pull_request_update': {
243 'updating_user': user,
260 'updating_user': user,
244
261
245 'status_change': None,
262 'status_change': None,
246 'status_change_type': None,
263 'status_change_type': None,
247
264
248 'pull_request': pr,
265 'pull_request': pr,
249 'pull_request_commits': [],
266 'pull_request_commits': [],
250
267
251 'pull_request_target_repo': target_repo,
268 'pull_request_target_repo': target_repo,
252 'pull_request_target_repo_url': 'http://target-repo/url',
269 'pull_request_target_repo_url': 'http://target-repo/url',
253
270
254 'pull_request_source_repo': source_repo,
271 'pull_request_source_repo': source_repo,
255 'pull_request_source_repo_url': 'http://source-repo/url',
272 'pull_request_source_repo_url': 'http://source-repo/url',
256
273
257 'pull_request_url': 'http://localhost/pr1',
274 'pull_request_url': 'http://localhost/pr1',
258
275
259 # update comment links
276 # update comment links
260 'pr_comment_url': 'http://comment-url',
277 'pr_comment_url': 'http://comment-url',
261 'pr_comment_reply_url': 'http://comment-url#reply',
278 'pr_comment_reply_url': 'http://comment-url#reply',
262 'ancestor_commit_id': 'f39bd443',
279 'ancestor_commit_id': 'f39bd443',
263 'added_commits': commit_changes.added,
280 'added_commits': commit_changes.added,
264 'removed_commits': commit_changes.removed,
281 'removed_commits': commit_changes.removed,
265 'changed_files': (file_changes.added + file_changes.modified + file_changes.removed),
282 'changed_files': (file_changes.added + file_changes.modified + file_changes.removed),
266 'added_files': file_changes.added,
283 'added_files': file_changes.added,
267 'modified_files': file_changes.modified,
284 'modified_files': file_changes.modified,
268 'removed_files': file_changes.removed,
285 'removed_files': file_changes.removed,
269 },
286 },
270
287
271 'cs_comment': {
288 'cs_comment': {
272 'user': user,
289 'user': user,
273 'commit': AttributeDict(idx=123, raw_id='a'*40, message='Commit message'),
290 'commit': AttributeDict(idx=123, raw_id='a'*40, message='Commit message'),
274 'status_change': None,
291 'status_change': None,
275 'status_change_type': None,
292 'status_change_type': None,
276
293
277 'commit_target_repo_url': 'http://foo.example.com/#comment1',
294 'commit_target_repo_url': 'http://foo.example.com/#comment1',
278 'repo_name': 'test-repo',
295 'repo_name': 'test-repo',
279 'comment_type': 'note',
296 'comment_type': 'note',
280 'comment_file': None,
297 'comment_file': None,
281 'comment_line': None,
298 'comment_line': None,
282 'commit_comment_url': 'http://comment-url',
299 'commit_comment_url': 'http://comment-url',
283 'commit_comment_reply_url': 'http://comment-url#reply',
300 'commit_comment_reply_url': 'http://comment-url#reply',
284 'comment_body': 'This is my comment body. *I like !*',
301 'comment_body': 'This is my comment body. *I like !*',
285 'comment_id': 2048,
302 'comment_id': 2048,
286 'renderer_type': 'markdown',
303 'renderer_type': 'markdown',
287 'mention': True,
304 'mention': True,
288 },
305 },
289 'cs_comment+status': {
306 'cs_comment+status': {
290 'user': user,
307 'user': user,
291 'commit': AttributeDict(idx=123, raw_id='a' * 40, message='Commit message'),
308 'commit': AttributeDict(idx=123, raw_id='a' * 40, message='Commit message'),
292 'status_change': 'approved',
309 'status_change': 'approved',
293 'status_change_type': 'approved',
310 'status_change_type': 'approved',
294
311
295 'commit_target_repo_url': 'http://foo.example.com/#comment1',
312 'commit_target_repo_url': 'http://foo.example.com/#comment1',
296 'repo_name': 'test-repo',
313 'repo_name': 'test-repo',
297 'comment_type': 'note',
314 'comment_type': 'note',
298 'comment_file': None,
315 'comment_file': None,
299 'comment_line': None,
316 'comment_line': None,
300 'commit_comment_url': 'http://comment-url',
317 'commit_comment_url': 'http://comment-url',
301 'commit_comment_reply_url': 'http://comment-url#reply',
318 'commit_comment_reply_url': 'http://comment-url#reply',
302 'comment_body': '''
319 'comment_body': '''
303 Hello **world**
320 Hello **world**
304
321
305 This is a multiline comment :)
322 This is a multiline comment :)
306
323
307 - list
324 - list
308 - list2
325 - list2
309 ''',
326 ''',
310 'comment_id': 2048,
327 'comment_id': 2048,
311 'renderer_type': 'markdown',
328 'renderer_type': 'markdown',
312 'mention': True,
329 'mention': True,
313 },
330 },
314 'cs_comment+file': {
331 'cs_comment+file': {
315 'user': user,
332 'user': user,
316 'commit': AttributeDict(idx=123, raw_id='a' * 40, message='Commit message'),
333 'commit': AttributeDict(idx=123, raw_id='a' * 40, message='Commit message'),
317 'status_change': None,
334 'status_change': None,
318 'status_change_type': None,
335 'status_change_type': None,
319
336
320 'commit_target_repo_url': 'http://foo.example.com/#comment1',
337 'commit_target_repo_url': 'http://foo.example.com/#comment1',
321 'repo_name': 'test-repo',
338 'repo_name': 'test-repo',
322
339
323 'comment_type': 'note',
340 'comment_type': 'note',
324 'comment_file': 'test-file.py',
341 'comment_file': 'test-file.py',
325 'comment_line': 'n100',
342 'comment_line': 'n100',
326
343
327 'commit_comment_url': 'http://comment-url',
344 'commit_comment_url': 'http://comment-url',
328 'commit_comment_reply_url': 'http://comment-url#reply',
345 'commit_comment_reply_url': 'http://comment-url#reply',
329 'comment_body': 'This is my comment body. *I like !*',
346 'comment_body': 'This is my comment body. *I like !*',
330 'comment_id': 2048,
347 'comment_id': 2048,
331 'renderer_type': 'markdown',
348 'renderer_type': 'markdown',
332 'mention': True,
349 'mention': True,
333 },
350 },
334
351
335 'pull_request': {
352 'pull_request': {
336 'user': user,
353 'user': user,
337 'pull_request': pr,
354 'pull_request': pr,
338 'pull_request_commits': [
355 'pull_request_commits': [
339 ('472d1df03bf7206e278fcedc6ac92b46b01c4e21', '''\
356 ('472d1df03bf7206e278fcedc6ac92b46b01c4e21', '''\
340 my-account: moved email closer to profile as it's similar data just moved outside.
357 my-account: moved email closer to profile as it's similar data just moved outside.
341 '''),
358 '''),
342 ('cbfa3061b6de2696c7161ed15ba5c6a0045f90a7', '''\
359 ('cbfa3061b6de2696c7161ed15ba5c6a0045f90a7', '''\
343 users: description edit fixes
360 users: description edit fixes
344
361
345 - tests
362 - tests
346 - added metatags info
363 - added metatags info
347 '''),
364 '''),
348 ],
365 ],
349
366
350 'pull_request_target_repo': target_repo,
367 'pull_request_target_repo': target_repo,
351 'pull_request_target_repo_url': 'http://target-repo/url',
368 'pull_request_target_repo_url': 'http://target-repo/url',
352
369
353 'pull_request_source_repo': source_repo,
370 'pull_request_source_repo': source_repo,
354 'pull_request_source_repo_url': 'http://source-repo/url',
371 'pull_request_source_repo_url': 'http://source-repo/url',
355
372
356 'pull_request_url': 'http://code.rhodecode.com/_pull-request/123',
373 'pull_request_url': 'http://code.rhodecode.com/_pull-request/123',
357 }
374 }
358
375
359 }
376 }
360
377
361 template_type = email_id.split('+')[0]
378 template_type = email_id.split('+')[0]
362 (c.subject, c.headers, c.email_body,
379 (c.subject, c.headers, c.email_body,
363 c.email_body_plaintext) = EmailNotificationModel().render_email(
380 c.email_body_plaintext) = EmailNotificationModel().render_email(
364 template_type, **email_kwargs.get(email_id, {}))
381 template_type, **email_kwargs.get(email_id, {}))
365
382
366 test_email = self.request.GET.get('email')
383 test_email = self.request.GET.get('email')
367 if test_email:
384 if test_email:
368 recipients = [test_email]
385 recipients = [test_email]
369 run_task(tasks.send_email, recipients, c.subject,
386 run_task(tasks.send_email, recipients, c.subject,
370 c.email_body_plaintext, c.email_body)
387 c.email_body_plaintext, c.email_body)
371
388
372 if self.request.matched_route.name == 'debug_style_email_plain_rendered':
389 if self.request.matched_route.name == 'debug_style_email_plain_rendered':
373 template = 'debug_style/email_plain_rendered.mako'
390 template = 'debug_style/email_plain_rendered.mako'
374 else:
391 else:
375 template = 'debug_style/email.mako'
392 template = 'debug_style/email.mako'
376 return render_to_response(
393 return render_to_response(
377 template, self._get_template_context(c),
394 template, self._get_template_context(c),
378 request=self.request)
395 request=self.request)
379
396
380 @view_config(
397 @view_config(
381 route_name='debug_style_template', request_method='GET',
398 route_name='debug_style_template', request_method='GET',
382 renderer=None)
399 renderer=None)
383 def template(self):
400 def template(self):
384 t_path = self.request.matchdict['t_path']
401 t_path = self.request.matchdict['t_path']
385 c = self.load_default_context()
402 c = self.load_default_context()
386 c.active = os.path.splitext(t_path)[0]
403 c.active = os.path.splitext(t_path)[0]
387 c.came_from = ''
404 c.came_from = ''
388 c.email_types = {
405 c.email_types = {
389 'cs_comment+file': {},
406 'cs_comment+file': {},
390 'cs_comment+status': {},
407 'cs_comment+status': {},
391
408
392 'pull_request_comment+file': {},
409 'pull_request_comment+file': {},
393 'pull_request_comment+status': {},
410 'pull_request_comment+status': {},
394
411
395 'pull_request_update': {},
412 'pull_request_update': {},
396 }
413 }
397 c.email_types.update(EmailNotificationModel.email_types)
414 c.email_types.update(EmailNotificationModel.email_types)
398
415
399 return render_to_response(
416 return render_to_response(
400 'debug_style/' + t_path, self._get_template_context(c),
417 'debug_style/' + t_path, self._get_template_context(c),
401 request=self.request)
418 request=self.request)
402
419
@@ -1,603 +1,642 b''
1 ## -*- coding: utf-8 -*-
1 ## -*- coding: utf-8 -*-
2
2
3 ## helpers
3 ## helpers
4 <%def name="tag_button(text, tag_type=None)">
4 <%def name="tag_button(text, tag_type=None)">
5 <%
5 <%
6 color_scheme = {
6 color_scheme = {
7 'default': 'border:1px solid #979797;color:#666666;background-color:#f9f9f9',
7 'default': 'border:1px solid #979797;color:#666666;background-color:#f9f9f9',
8 'approved': 'border:1px solid #0ac878;color:#0ac878;background-color:#f9f9f9',
8 'approved': 'border:1px solid #0ac878;color:#0ac878;background-color:#f9f9f9',
9 'rejected': 'border:1px solid #e85e4d;color:#e85e4d;background-color:#f9f9f9',
9 'rejected': 'border:1px solid #e85e4d;color:#e85e4d;background-color:#f9f9f9',
10 'under_review': 'border:1px solid #ffc854;color:#ffc854;background-color:#f9f9f9',
10 'under_review': 'border:1px solid #ffc854;color:#ffc854;background-color:#f9f9f9',
11 }
11 }
12
12
13 css_style = ';'.join([
13 css_style = ';'.join([
14 'display:inline',
14 'display:inline',
15 'border-radius:2px',
15 'border-radius:2px',
16 'font-size:12px',
16 'font-size:12px',
17 'padding:.2em',
17 'padding:.2em',
18 ])
18 ])
19
19
20 %>
20 %>
21 <pre style="${css_style}; ${color_scheme.get(tag_type, color_scheme['default'])}">${text}</pre>
21 <pre style="${css_style}; ${color_scheme.get(tag_type, color_scheme['default'])}">${text}</pre>
22 </%def>
22 </%def>
23
23
24 <%def name="status_text(text, tag_type=None)">
24 <%def name="status_text(text, tag_type=None)">
25 <%
25 <%
26 color_scheme = {
26 color_scheme = {
27 'default': 'color:#666666',
27 'default': 'color:#666666',
28 'approved': 'color:#0ac878',
28 'approved': 'color:#0ac878',
29 'rejected': 'color:#e85e4d',
29 'rejected': 'color:#e85e4d',
30 'under_review': 'color:#ffc854',
30 'under_review': 'color:#ffc854',
31 }
31 }
32 %>
32 %>
33 <span style="font-weight:bold;font-size:12px;padding:.2em;${color_scheme.get(tag_type, color_scheme['default'])}">${text}</span>
33 <span style="font-weight:bold;font-size:12px;padding:.2em;${color_scheme.get(tag_type, color_scheme['default'])}">${text}</span>
34 </%def>
34 </%def>
35
35
36 <%def name="gravatar_img(email, size=16)">
36 <%def name="gravatar_img(email, size=16)">
37 <%
37 <%
38 css_style = ';'.join([
38 css_style = ';'.join([
39 'padding: 0',
39 'padding: 0',
40 'margin: -4px 0',
40 'margin: -4px 0',
41 'border-radius: 50%',
41 'border-radius: 50%',
42 'box-sizing: content-box',
42 'box-sizing: content-box',
43 'display: inline',
43 'display: inline',
44 'line-height: 1em',
44 'line-height: 1em',
45 'min-width: 16px',
45 'min-width: 16px',
46 'min-height: 16px',
46 'min-height: 16px',
47 ])
47 ])
48 %>
48 %>
49
49
50 <img alt="gravatar" style="${css_style}" src="${h.gravatar_url(email, size)}" height="${size}" width="${size}">
50 <img alt="gravatar" style="${css_style}" src="${h.gravatar_url(email, size)}" height="${size}" width="${size}">
51 </%def>
51 </%def>
52
52
53 <%def name="link_css()">\
53 <%def name="link_css()">\
54 <%
54 <%
55 css_style = ';'.join([
55 css_style = ';'.join([
56 'color:#427cc9',
56 'color:#427cc9',
57 'text-decoration:none',
57 'text-decoration:none',
58 'cursor:pointer'
58 'cursor:pointer'
59 ])
59 ])
60 %>\
60 %>\
61 ${css_style}\
61 ${css_style}\
62 </%def>
62 </%def>
63
63
64 ## Constants
64 ## Constants
65 <%
65 <%
66 text_regular = "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell, 'Helvetica Neue', Helvetica, sans-serif"
66 text_regular = "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell, 'Helvetica Neue', Helvetica, sans-serif"
67 text_monospace = "'Menlo', 'Liberation Mono', 'Consolas', 'DejaVu Sans Mono', 'Ubuntu Mono', 'Courier New', 'andale mono', 'lucida console', monospace"
67 text_monospace = "'Menlo', 'Liberation Mono', 'Consolas', 'DejaVu Sans Mono', 'Ubuntu Mono', 'Courier New', 'andale mono', 'lucida console', monospace"
68
68
69 %>
69 %>
70
70
71 ## headers we additionally can set for email
71 ## headers we additionally can set for email
72 <%def name="headers()" filter="n,trim"></%def>
72 <%def name="headers()" filter="n,trim"></%def>
73
73
74 <%def name="plaintext_footer()" filter="trim">
74 <%def name="plaintext_footer()" filter="trim">
75 ${_('This is a notification from RhodeCode.')} ${instance_url}
75 ${_('This is a notification from RhodeCode.')} ${instance_url}
76 </%def>
76 </%def>
77
77
78 <%def name="body_plaintext()" filter="n,trim">
78 <%def name="body_plaintext()" filter="n,trim">
79 ## this example is not called itself but overridden in each template
79 ## this example is not called itself but overridden in each template
80 ## the plaintext_footer should be at the bottom of both html and text emails
80 ## the plaintext_footer should be at the bottom of both html and text emails
81 ${self.plaintext_footer()}
81 ${self.plaintext_footer()}
82 </%def>
82 </%def>
83
83
84 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
84 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
85 <html xmlns="http://www.w3.org/1999/xhtml">
85 <html xmlns="http://www.w3.org/1999/xhtml">
86 <head>
86 <head>
87 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
87 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
88 <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
88 <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
89 <title>${self.subject()}</title>
89 <title>${self.subject()}</title>
90 <style type="text/css">
90 <style type="text/css">
91 /* Based on The MailChimp Reset INLINE: Yes. */
91 /* Based on The MailChimp Reset INLINE: Yes. */
92 #outlook a {
92 #outlook a {
93 padding: 0;
93 padding: 0;
94 }
94 }
95
95
96 /* Force Outlook to provide a "view in browser" menu link. */
96 /* Force Outlook to provide a "view in browser" menu link. */
97 body {
97 body {
98 width: 100% !important;
98 width: 100% !important;
99 -webkit-text-size-adjust: 100%;
99 -webkit-text-size-adjust: 100%;
100 -ms-text-size-adjust: 100%;
100 -ms-text-size-adjust: 100%;
101 margin: 0;
101 margin: 0;
102 padding: 0;
102 padding: 0;
103 font-family: ${text_regular|n};
103 font-family: ${text_regular|n};
104 color: #000000;
104 }
105 }
105
106
106 /* Prevent Webkit and Windows Mobile platforms from changing default font sizes.*/
107 /* Prevent Webkit and Windows Mobile platforms from changing default font sizes.*/
107 .ExternalClass {
108 .ExternalClass {
108 width: 100%;
109 width: 100%;
109 }
110 }
110
111
111 /* Force Hotmail to display emails at full width */
112 /* Force Hotmail to display emails at full width */
112 .ExternalClass, .ExternalClass p, .ExternalClass span, .ExternalClass font, .ExternalClass td, .ExternalClass div {
113 .ExternalClass, .ExternalClass p, .ExternalClass span, .ExternalClass font, .ExternalClass td, .ExternalClass div {
113 line-height: 100%;
114 line-height: 100%;
114 }
115 }
115
116
116 /* Forces Hotmail to display normal line spacing. More on that: http://www.emailonacid.com/forum/viewthread/43/ */
117 /* Forces Hotmail to display normal line spacing. More on that: http://www.emailonacid.com/forum/viewthread/43/ */
117 #backgroundTable {
118 #backgroundTable {
118 margin: 0;
119 margin: 0;
119 padding: 0;
120 padding: 0;
120 line-height: 100% !important;
121 line-height: 100% !important;
121 }
122 }
122
123
123 /* End reset */
124 /* End reset */
124
125
125 /* defaults for images*/
126 /* defaults for images*/
126 img {
127 img {
127 outline: none;
128 outline: none;
128 text-decoration: none;
129 text-decoration: none;
129 -ms-interpolation-mode: bicubic;
130 -ms-interpolation-mode: bicubic;
130 }
131 }
131
132
132 a img {
133 a img {
133 border: none;
134 border: none;
134 }
135 }
135
136
136 .image_fix {
137 .image_fix {
137 display: block;
138 display: block;
138 }
139 }
139
140
140 body {
141 body {
141 line-height: 1.2em;
142 line-height: 1.2em;
142 }
143 }
143
144
144 p {
145 p {
145 margin: 0 0 20px;
146 margin: 0 0 20px;
146 }
147 }
147
148
148 h1, h2, h3, h4, h5, h6 {
149 h1, h2, h3, h4, h5, h6 {
149 color: #323232 !important;
150 color: #323232 !important;
150 }
151 }
151
152
152 a {
153 a {
153 color: #427cc9;
154 color: #427cc9;
154 text-decoration: none;
155 text-decoration: none;
155 outline: none;
156 outline: none;
156 cursor: pointer;
157 cursor: pointer;
157 }
158 }
158
159
159 a:focus {
160 a:focus {
160 outline: none;
161 outline: none;
161 }
162 }
162
163
163 a:hover {
164 a:hover {
164 color: #305b91;
165 color: #305b91;
165 }
166 }
166
167
167 h1 a, h2 a, h3 a, h4 a, h5 a, h6 a {
168 h1 a, h2 a, h3 a, h4 a, h5 a, h6 a {
168 color: #427cc9 !important;
169 color: #427cc9 !important;
169 text-decoration: none !important;
170 text-decoration: none !important;
170 }
171 }
171
172
172 h1 a:active, h2 a:active, h3 a:active, h4 a:active, h5 a:active, h6 a:active {
173 h1 a:active, h2 a:active, h3 a:active, h4 a:active, h5 a:active, h6 a:active {
173 color: #305b91 !important;
174 color: #305b91 !important;
174 }
175 }
175
176
176 h1 a:visited, h2 a:visited, h3 a:visited, h4 a:visited, h5 a:visited, h6 a:visited {
177 h1 a:visited, h2 a:visited, h3 a:visited, h4 a:visited, h5 a:visited, h6 a:visited {
177 color: #305b91 !important;
178 color: #305b91 !important;
178 }
179 }
179
180
180 table {
181 table {
181 font-size: 13px;
182 font-size: 13px;
182 border-collapse: collapse;
183 border-collapse: collapse;
183 mso-table-lspace: 0pt;
184 mso-table-lspace: 0pt;
184 mso-table-rspace: 0pt;
185 mso-table-rspace: 0pt;
185 }
186 }
186
187
187 table tr {
188 table tr {
188 display: table-row;
189 display: table-row;
189 vertical-align: inherit;
190 vertical-align: inherit;
190 border-color: inherit;
191 border-color: inherit;
191 border-spacing: 0 3px;
192 border-spacing: 0 3px;
192 }
193 }
193
194
194 table td {
195 table td {
195 padding: .65em 1em .65em 0;
196 padding: .65em 1em .65em 0;
196 border-collapse: collapse;
197 border-collapse: collapse;
197 vertical-align: top;
198 vertical-align: top;
198 text-align: left;
199 text-align: left;
199 }
200 }
200
201
201 input {
202 input {
202 display: inline;
203 display: inline;
203 border-radius: 2px;
204 border-radius: 2px;
204 border: 1px solid #dbd9da;
205 border: 1px solid #dbd9da;
205 padding: .5em;
206 padding: .5em;
206 }
207 }
207
208
208 input:focus {
209 input:focus {
209 outline: 1px solid #979797
210 outline: 1px solid #979797
210 }
211 }
211
212
212 code {
213 code {
213 font-family: ${text_monospace|n};
214 font-family: ${text_monospace|n};
215 white-space: pre-line !important;
216 color: #000000;
217 }
218
219 ul.changes-ul {
220 list-style: none;
221 list-style-type: none;
222 padding: 0;
223 margin: 10px 0;
224 }
225 ul.changes-ul li {
226 list-style: none;
227 list-style-type: none;
228 margin: 2px 0;
214 }
229 }
215
230
216 @media only screen and (-webkit-min-device-pixel-ratio: 2) {
231 @media only screen and (-webkit-min-device-pixel-ratio: 2) {
217 /* Put your iPhone 4g styles in here */
232 /* Put your iPhone 4g styles in here */
218 }
233 }
219
234
220 /* Android targeting */
235 /* Android targeting */
221 @media only screen and (-webkit-device-pixel-ratio:.75){
236 @media only screen and (-webkit-device-pixel-ratio:.75){
222 /* Put CSS for low density (ldpi) Android layouts in here */
237 /* Put CSS for low density (ldpi) Android layouts in here */
223 }
238 }
224 @media only screen and (-webkit-device-pixel-ratio:1){
239 @media only screen and (-webkit-device-pixel-ratio:1){
225 /* Put CSS for medium density (mdpi) Android layouts in here */
240 /* Put CSS for medium density (mdpi) Android layouts in here */
226 }
241 }
227 @media only screen and (-webkit-device-pixel-ratio:1.5){
242 @media only screen and (-webkit-device-pixel-ratio:1.5){
228 /* Put CSS for high density (hdpi) Android layouts in here */
243 /* Put CSS for high density (hdpi) Android layouts in here */
229 }
244 }
230 /* end Android targeting */
245 /* end Android targeting */
231
246
232 /** MARKDOWN styling **/
247 /** MARKDOWN styling **/
233 div.markdown-block {
248 div.markdown-block {
234 clear: both;
249 clear: both;
235 overflow: hidden;
250 overflow: hidden;
236 margin: 0;
251 margin: 0;
237 padding: 3px 5px 3px
252 padding: 3px 5px 3px
238 }
253 }
239
254
240 div.markdown-block h1, div.markdown-block h2, div.markdown-block h3, div.markdown-block h4, div.markdown-block h5, div.markdown-block h6 {
255 div.markdown-block h1,
256 div.markdown-block h2,
257 div.markdown-block h3,
258 div.markdown-block h4,
259 div.markdown-block h5,
260 div.markdown-block h6 {
241 border-bottom: none !important;
261 border-bottom: none !important;
242 padding: 0 !important;
262 padding: 0 !important;
243 overflow: visible !important
263 overflow: visible !important
244 }
264 }
245
265
246 div.markdown-block h1, div.markdown-block h2 {
266 div.markdown-block h1,
267 div.markdown-block h2 {
247 border-bottom: 1px #e6e5e5 solid !important
268 border-bottom: 1px #e6e5e5 solid !important
248 }
269 }
249
270
250 div.markdown-block h1 {
271 div.markdown-block h1 {
251 font-size: 32px;
272 font-size: 32px;
252 margin: 15px 0 15px 0 !important;
273 margin: 15px 0 15px 0 !important;
253 padding-bottom: 5px !important
274 padding-bottom: 5px !important
254 }
275 }
255
276
256 div.markdown-block h2 {
277 div.markdown-block h2 {
257 font-size: 24px !important;
278 font-size: 24px !important;
258 margin: 34px 0 10px 0 !important;
279 margin: 34px 0 10px 0 !important;
259 padding-top: 15px !important;
280 padding-top: 15px !important;
260 padding-bottom: 8px !important
281 padding-bottom: 8px !important
261 }
282 }
262
283
263 div.markdown-block h3 {
284 div.markdown-block h3 {
264 font-size: 18px !important;
285 font-size: 18px !important;
265 margin: 30px 0 8px 0 !important;
286 margin: 30px 0 8px 0 !important;
266 padding-bottom: 2px !important
287 padding-bottom: 2px !important
267 }
288 }
268
289
269 div.markdown-block h4 {
290 div.markdown-block h4 {
270 font-size: 13px !important;
291 font-size: 13px !important;
271 margin: 18px 0 3px 0 !important
292 margin: 18px 0 3px 0 !important
272 }
293 }
273
294
274 div.markdown-block h5 {
295 div.markdown-block h5 {
275 font-size: 12px !important;
296 font-size: 12px !important;
276 margin: 15px 0 3px 0 !important
297 margin: 15px 0 3px 0 !important
277 }
298 }
278
299
279 div.markdown-block h6 {
300 div.markdown-block h6 {
280 font-size: 12px;
301 font-size: 12px;
281 color: #777777;
302 color: #777777;
282 margin: 15px 0 3px 0 !important
303 margin: 15px 0 3px 0 !important
283 }
304 }
284
305
285 div.markdown-block hr {
306 div.markdown-block hr {
286 border: 0;
307 border: 0;
287 color: #e6e5e5;
308 color: #e6e5e5;
288 background-color: #e6e5e5;
309 background-color: #e6e5e5;
289 height: 3px;
310 height: 3px;
290 margin-bottom: 13px
311 margin-bottom: 13px
291 }
312 }
292
313
293 div.markdown-block ol, div.markdown-block ul, div.markdown-block p, div.markdown-block blockquote, div.markdown-block dl, div.markdown-block li, div.markdown-block table {
314 div.markdown-block ol,
315 div.markdown-block ul,
316 div.markdown-block p,
317 div.markdown-block blockquote,
318 div.markdown-block dl,
319 div.markdown-block li,
320 div.markdown-block table {
294 margin: 3px 0 13px 0 !important;
321 margin: 3px 0 13px 0 !important;
295 color: #424242 !important;
322 color: #424242 !important;
296 font-size: 13px !important;
323 font-size: 13px !important;
297 font-family: ${text_regular|n};
324 font-family: ${text_regular|n};
298 font-weight: normal !important;
325 font-weight: normal !important;
299 overflow: visible !important;
326 overflow: visible !important;
300 line-height: 140% !important
327 line-height: 140% !important
301 }
328 }
302
329
303 div.markdown-block pre {
330 div.markdown-block pre {
304 margin: 3px 0 13px 0 !important;
331 margin: 3px 0 13px 0 !important;
305 padding: .5em;
332 padding: .5em;
306 color: #424242 !important;
333 color: #424242 !important;
307 font-size: 13px !important;
334 font-size: 13px !important;
308 overflow: visible !important;
335 overflow: visible !important;
309 line-height: 140% !important;
336 line-height: 140% !important;
310 background-color: #F5F5F5
337 background-color: #F5F5F5
311 }
338 }
312
339
313 div.markdown-block img {
340 div.markdown-block img {
314 border-style: none;
341 border-style: none;
315 background-color: #fff;
342 background-color: #fff;
316 padding-right: 20px;
343 padding-right: 20px;
317 max-width: 100%
344 max-width: 100%
318 }
345 }
319
346
320 div.markdown-block strong {
347 div.markdown-block strong {
321 font-weight: 600;
348 font-weight: 600;
322 margin: 0
349 margin: 0
323 }
350 }
324
351
325 div.markdown-block ul.checkbox, div.markdown-block ol.checkbox {
352 div.markdown-block ul.checkbox, div.markdown-block ol.checkbox {
326 padding-left: 20px !important;
353 padding-left: 20px !important;
327 margin-top: 0 !important;
354 margin-top: 0 !important;
328 margin-bottom: 18px !important
355 margin-bottom: 18px !important
329 }
356 }
330
357
331 div.markdown-block ul, div.markdown-block ol {
358 div.markdown-block ul, div.markdown-block ol {
332 padding-left: 30px !important;
359 padding-left: 30px !important;
333 margin-top: 0 !important;
360 margin-top: 0 !important;
334 margin-bottom: 18px !important
361 margin-bottom: 18px !important
335 }
362 }
336
363
337 div.markdown-block ul.checkbox li, div.markdown-block ol.checkbox li {
364 div.markdown-block ul.checkbox li, div.markdown-block ol.checkbox li {
338 list-style: none !important;
365 list-style: none !important;
339 margin: 6px !important;
366 margin: 6px !important;
340 padding: 0 !important
367 padding: 0 !important
341 }
368 }
342
369
343 div.markdown-block ul li, div.markdown-block ol li {
370 div.markdown-block ul li, div.markdown-block ol li {
344 list-style: disc !important;
371 list-style: disc !important;
345 margin: 6px !important;
372 margin: 6px !important;
346 padding: 0 !important
373 padding: 0 !important
347 }
374 }
348
375
349 div.markdown-block ol li {
376 div.markdown-block ol li {
350 list-style: decimal !important
377 list-style: decimal !important
351 }
378 }
352
379
353 div.markdown-block #message {
380 div.markdown-block #message {
354 -webkit-border-radius: 2px;
381 -webkit-border-radius: 2px;
355 -moz-border-radius: 2px;
382 -moz-border-radius: 2px;
356 border-radius: 2px;
383 border-radius: 2px;
357 border: 1px solid #dbd9da;
384 border: 1px solid #dbd9da;
358 display: block;
385 display: block;
359 width: 100%;
386 width: 100%;
360 height: 60px;
387 height: 60px;
361 margin: 6px 0
388 margin: 6px 0
362 }
389 }
363
390
364 div.markdown-block button, div.markdown-block #ws {
391 div.markdown-block button, div.markdown-block #ws {
365 font-size: 13px;
392 font-size: 13px;
366 padding: 4px 6px;
393 padding: 4px 6px;
367 -webkit-border-radius: 2px;
394 -webkit-border-radius: 2px;
368 -moz-border-radius: 2px;
395 -moz-border-radius: 2px;
369 border-radius: 2px;
396 border-radius: 2px;
370 border: 1px solid #dbd9da;
397 border: 1px solid #dbd9da;
371 background-color: #eeeeee
398 background-color: #eeeeee
372 }
399 }
373
400
374 div.markdown-block code, div.markdown-block pre, div.markdown-block #ws, div.markdown-block #message {
401 div.markdown-block code,
402 div.markdown-block pre,
403 div.markdown-block #ws,
404 div.markdown-block #message {
375 font-family: ${text_monospace|n};
405 font-family: ${text_monospace|n};
376 font-size: 11px;
406 font-size: 11px;
377 -webkit-border-radius: 2px;
407 -webkit-border-radius: 2px;
378 -moz-border-radius: 2px;
408 -moz-border-radius: 2px;
379 border-radius: 2px;
409 border-radius: 2px;
380 background-color: white;
410 background-color: #FFFFFF;
381 color: #7E7F7F
411 color: #7E7F7F
382 }
412 }
383
413
384 div.markdown-block code {
414 div.markdown-block code {
385 border: 1px solid #eeeeee;
415 border: 1px solid #7E7F7F;
386 margin: 0 2px;
416 margin: 0 2px;
387 padding: 0 5px
417 padding: 0 5px
388 }
418 }
389
419
390 div.markdown-block pre {
420 div.markdown-block pre {
391 border: 1px solid #dbd9da;
421 border: 1px solid #7E7F7F;
392 overflow: auto;
422 overflow: auto;
393 padding: .5em;
423 padding: .5em;
394 background-color: #F5F5F5
424 background-color: #FFFFFF;
395 }
425 }
396
426
397 div.markdown-block pre > code {
427 div.markdown-block pre > code {
398 border: 0;
428 border: 0;
399 margin: 0;
429 margin: 0;
400 padding: 0
430 padding: 0
401 }
431 }
402
432
403 div.rst-block {
433 div.rst-block {
404 clear: both;
434 clear: both;
405 overflow: hidden;
435 overflow: hidden;
406 margin: 0;
436 margin: 0;
407 padding: 3px 5px 3px
437 padding: 3px 5px 3px
408 }
438 }
409
439
410 div.rst-block h2 {
440 div.rst-block h2 {
411 font-weight: normal
441 font-weight: normal
412 }
442 }
413
443
414 div.rst-block h1, div.rst-block h2, div.rst-block h3, div.rst-block h4, div.rst-block h5, div.rst-block h6 {
444 div.rst-block h1,
445 div.rst-block h2,
446 div.rst-block h3,
447 div.rst-block h4,
448 div.rst-block h5,
449 div.rst-block h6 {
415 border-bottom: 0 !important;
450 border-bottom: 0 !important;
416 margin: 0 !important;
451 margin: 0 !important;
417 padding: 0 !important;
452 padding: 0 !important;
418 line-height: 1.5em !important
453 line-height: 1.5em !important
419 }
454 }
420
455
421 div.rst-block h1:first-child {
456 div.rst-block h1:first-child {
422 padding-top: .25em !important
457 padding-top: .25em !important
423 }
458 }
424
459
425 div.rst-block h2, div.rst-block h3 {
460 div.rst-block h2, div.rst-block h3 {
426 margin: 1em 0 !important
461 margin: 1em 0 !important
427 }
462 }
428
463
429 div.rst-block h1, div.rst-block h2 {
464 div.rst-block h1, div.rst-block h2 {
430 border-bottom: 1px #e6e5e5 solid !important
465 border-bottom: 1px #e6e5e5 solid !important
431 }
466 }
432
467
433 div.rst-block h2 {
468 div.rst-block h2 {
434 margin-top: 1.5em !important;
469 margin-top: 1.5em !important;
435 padding-top: .5em !important
470 padding-top: .5em !important
436 }
471 }
437
472
438 div.rst-block p {
473 div.rst-block p {
439 color: black !important;
474 color: black !important;
440 margin: 1em 0 !important;
475 margin: 1em 0 !important;
441 line-height: 1.5em !important
476 line-height: 1.5em !important
442 }
477 }
443
478
444 div.rst-block ul {
479 div.rst-block ul {
445 list-style: disc !important;
480 list-style: disc !important;
446 margin: 1em 0 1em 2em !important;
481 margin: 1em 0 1em 2em !important;
447 clear: both
482 clear: both
448 }
483 }
449
484
450 div.rst-block ol {
485 div.rst-block ol {
451 list-style: decimal;
486 list-style: decimal;
452 margin: 1em 0 1em 2em !important
487 margin: 1em 0 1em 2em !important
453 }
488 }
454
489
455 div.rst-block pre, div.rst-block code {
490 div.rst-block pre, div.rst-block code {
456 font: 12px "Bitstream Vera Sans Mono", "Courier", monospace
491 font: 12px "Bitstream Vera Sans Mono", "Courier", monospace
457 }
492 }
458
493
459 div.rst-block code {
494 div.rst-block code {
460 font-size: 12px !important;
495 font-size: 12px !important;
461 background-color: ghostWhite !important;
496 background-color: ghostWhite !important;
462 color: #444 !important;
497 color: #444 !important;
463 padding: 0 .2em !important;
498 padding: 0 .2em !important;
464 border: 1px solid #dedede !important
499 border: 1px solid #7E7F7F !important
465 }
500 }
466
501
467 div.rst-block pre code {
502 div.rst-block pre code {
468 padding: 0 !important;
503 padding: 0 !important;
469 font-size: 12px !important;
504 font-size: 12px !important;
470 background-color: #eee !important;
505 background-color: #eee !important;
471 border: none !important
506 border: none !important
472 }
507 }
473
508
474 div.rst-block pre {
509 div.rst-block pre {
475 margin: 1em 0;
510 margin: 1em 0;
476 padding: 15px;
511 padding: 15px;
477 border: 1px solid #eeeeee;
512 border: 1px solid #7E7F7F;
478 -webkit-border-radius: 2px;
513 -webkit-border-radius: 2px;
479 -moz-border-radius: 2px;
514 -moz-border-radius: 2px;
480 border-radius: 2px;
515 border-radius: 2px;
481 overflow: auto;
516 overflow: auto;
482 font-size: 12px;
517 font-size: 12px;
483 color: #444;
518 color: #444;
484 background-color: #F5F5F5
519 background-color: #FFFFFF;
520 }
521
522 .clear-both {
523 clear:both;
485 }
524 }
486
525
487 /*elasticmatch is custom rhodecode tag*/
526 /*elasticmatch is custom rhodecode tag*/
488 .codehilite .c-ElasticMatch {
527 .codehilite .c-ElasticMatch {
489 background-color: #faffa6;
528 background-color: #faffa6;
490 padding: 0.2em;
529 padding: 0.2em;
491 }
530 }
492
531
493 .codehilite .c-ElasticMatch { background-color: #faffa6; padding: 0.2em;}
532 .codehilite .c-ElasticMatch { background-color: #faffa6; padding: 0.2em;}
494 .codehilite .hll { background-color: #ffffcc }
533 .codehilite .hll { background-color: #ffffcc }
495 .codehilite .c { color: #408080; font-style: italic } /* Comment */
534 .codehilite .c { color: #408080; font-style: italic } /* Comment */
496 .codehilite .err { border: none } /* Error */
535 .codehilite .err { border: none } /* Error */
497 .codehilite .k { color: #008000; font-weight: bold } /* Keyword */
536 .codehilite .k { color: #008000; font-weight: bold } /* Keyword */
498 .codehilite .o { color: #666666 } /* Operator */
537 .codehilite .o { color: #666666 } /* Operator */
499 .codehilite .ch { color: #408080; font-style: italic } /* Comment.Hashbang */
538 .codehilite .ch { color: #408080; font-style: italic } /* Comment.Hashbang */
500 .codehilite .cm { color: #408080; font-style: italic } /* Comment.Multiline */
539 .codehilite .cm { color: #408080; font-style: italic } /* Comment.Multiline */
501 .codehilite .cp { color: #BC7A00 } /* Comment.Preproc */
540 .codehilite .cp { color: #BC7A00 } /* Comment.Preproc */
502 .codehilite .cpf { color: #408080; font-style: italic } /* Comment.PreprocFile */
541 .codehilite .cpf { color: #408080; font-style: italic } /* Comment.PreprocFile */
503 .codehilite .c1 { color: #408080; font-style: italic } /* Comment.Single */
542 .codehilite .c1 { color: #408080; font-style: italic } /* Comment.Single */
504 .codehilite .cs { color: #408080; font-style: italic } /* Comment.Special */
543 .codehilite .cs { color: #408080; font-style: italic } /* Comment.Special */
505 .codehilite .gd { color: #A00000 } /* Generic.Deleted */
544 .codehilite .gd { color: #A00000 } /* Generic.Deleted */
506 .codehilite .ge { font-style: italic } /* Generic.Emph */
545 .codehilite .ge { font-style: italic } /* Generic.Emph */
507 .codehilite .gr { color: #FF0000 } /* Generic.Error */
546 .codehilite .gr { color: #FF0000 } /* Generic.Error */
508 .codehilite .gh { color: #000080; font-weight: bold } /* Generic.Heading */
547 .codehilite .gh { color: #000080; font-weight: bold } /* Generic.Heading */
509 .codehilite .gi { color: #00A000 } /* Generic.Inserted */
548 .codehilite .gi { color: #00A000 } /* Generic.Inserted */
510 .codehilite .go { color: #888888 } /* Generic.Output */
549 .codehilite .go { color: #888888 } /* Generic.Output */
511 .codehilite .gp { color: #000080; font-weight: bold } /* Generic.Prompt */
550 .codehilite .gp { color: #000080; font-weight: bold } /* Generic.Prompt */
512 .codehilite .gs { font-weight: bold } /* Generic.Strong */
551 .codehilite .gs { font-weight: bold } /* Generic.Strong */
513 .codehilite .gu { color: #800080; font-weight: bold } /* Generic.Subheading */
552 .codehilite .gu { color: #800080; font-weight: bold } /* Generic.Subheading */
514 .codehilite .gt { color: #0044DD } /* Generic.Traceback */
553 .codehilite .gt { color: #0044DD } /* Generic.Traceback */
515 .codehilite .kc { color: #008000; font-weight: bold } /* Keyword.Constant */
554 .codehilite .kc { color: #008000; font-weight: bold } /* Keyword.Constant */
516 .codehilite .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */
555 .codehilite .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */
517 .codehilite .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */
556 .codehilite .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */
518 .codehilite .kp { color: #008000 } /* Keyword.Pseudo */
557 .codehilite .kp { color: #008000 } /* Keyword.Pseudo */
519 .codehilite .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */
558 .codehilite .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */
520 .codehilite .kt { color: #B00040 } /* Keyword.Type */
559 .codehilite .kt { color: #B00040 } /* Keyword.Type */
521 .codehilite .m { color: #666666 } /* Literal.Number */
560 .codehilite .m { color: #666666 } /* Literal.Number */
522 .codehilite .s { color: #BA2121 } /* Literal.String */
561 .codehilite .s { color: #BA2121 } /* Literal.String */
523 .codehilite .na { color: #7D9029 } /* Name.Attribute */
562 .codehilite .na { color: #7D9029 } /* Name.Attribute */
524 .codehilite .nb { color: #008000 } /* Name.Builtin */
563 .codehilite .nb { color: #008000 } /* Name.Builtin */
525 .codehilite .nc { color: #0000FF; font-weight: bold } /* Name.Class */
564 .codehilite .nc { color: #0000FF; font-weight: bold } /* Name.Class */
526 .codehilite .no { color: #880000 } /* Name.Constant */
565 .codehilite .no { color: #880000 } /* Name.Constant */
527 .codehilite .nd { color: #AA22FF } /* Name.Decorator */
566 .codehilite .nd { color: #AA22FF } /* Name.Decorator */
528 .codehilite .ni { color: #999999; font-weight: bold } /* Name.Entity */
567 .codehilite .ni { color: #999999; font-weight: bold } /* Name.Entity */
529 .codehilite .ne { color: #D2413A; font-weight: bold } /* Name.Exception */
568 .codehilite .ne { color: #D2413A; font-weight: bold } /* Name.Exception */
530 .codehilite .nf { color: #0000FF } /* Name.Function */
569 .codehilite .nf { color: #0000FF } /* Name.Function */
531 .codehilite .nl { color: #A0A000 } /* Name.Label */
570 .codehilite .nl { color: #A0A000 } /* Name.Label */
532 .codehilite .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */
571 .codehilite .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */
533 .codehilite .nt { color: #008000; font-weight: bold } /* Name.Tag */
572 .codehilite .nt { color: #008000; font-weight: bold } /* Name.Tag */
534 .codehilite .nv { color: #19177C } /* Name.Variable */
573 .codehilite .nv { color: #19177C } /* Name.Variable */
535 .codehilite .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */
574 .codehilite .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */
536 .codehilite .w { color: #bbbbbb } /* Text.Whitespace */
575 .codehilite .w { color: #bbbbbb } /* Text.Whitespace */
537 .codehilite .mb { color: #666666 } /* Literal.Number.Bin */
576 .codehilite .mb { color: #666666 } /* Literal.Number.Bin */
538 .codehilite .mf { color: #666666 } /* Literal.Number.Float */
577 .codehilite .mf { color: #666666 } /* Literal.Number.Float */
539 .codehilite .mh { color: #666666 } /* Literal.Number.Hex */
578 .codehilite .mh { color: #666666 } /* Literal.Number.Hex */
540 .codehilite .mi { color: #666666 } /* Literal.Number.Integer */
579 .codehilite .mi { color: #666666 } /* Literal.Number.Integer */
541 .codehilite .mo { color: #666666 } /* Literal.Number.Oct */
580 .codehilite .mo { color: #666666 } /* Literal.Number.Oct */
542 .codehilite .sa { color: #BA2121 } /* Literal.String.Affix */
581 .codehilite .sa { color: #BA2121 } /* Literal.String.Affix */
543 .codehilite .sb { color: #BA2121 } /* Literal.String.Backtick */
582 .codehilite .sb { color: #BA2121 } /* Literal.String.Backtick */
544 .codehilite .sc { color: #BA2121 } /* Literal.String.Char */
583 .codehilite .sc { color: #BA2121 } /* Literal.String.Char */
545 .codehilite .dl { color: #BA2121 } /* Literal.String.Delimiter */
584 .codehilite .dl { color: #BA2121 } /* Literal.String.Delimiter */
546 .codehilite .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */
585 .codehilite .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */
547 .codehilite .s2 { color: #BA2121 } /* Literal.String.Double */
586 .codehilite .s2 { color: #BA2121 } /* Literal.String.Double */
548 .codehilite .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */
587 .codehilite .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */
549 .codehilite .sh { color: #BA2121 } /* Literal.String.Heredoc */
588 .codehilite .sh { color: #BA2121 } /* Literal.String.Heredoc */
550 .codehilite .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */
589 .codehilite .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */
551 .codehilite .sx { color: #008000 } /* Literal.String.Other */
590 .codehilite .sx { color: #008000 } /* Literal.String.Other */
552 .codehilite .sr { color: #BB6688 } /* Literal.String.Regex */
591 .codehilite .sr { color: #BB6688 } /* Literal.String.Regex */
553 .codehilite .s1 { color: #BA2121 } /* Literal.String.Single */
592 .codehilite .s1 { color: #BA2121 } /* Literal.String.Single */
554 .codehilite .ss { color: #19177C } /* Literal.String.Symbol */
593 .codehilite .ss { color: #19177C } /* Literal.String.Symbol */
555 .codehilite .bp { color: #008000 } /* Name.Builtin.Pseudo */
594 .codehilite .bp { color: #008000 } /* Name.Builtin.Pseudo */
556 .codehilite .fm { color: #0000FF } /* Name.Function.Magic */
595 .codehilite .fm { color: #0000FF } /* Name.Function.Magic */
557 .codehilite .vc { color: #19177C } /* Name.Variable.Class */
596 .codehilite .vc { color: #19177C } /* Name.Variable.Class */
558 .codehilite .vg { color: #19177C } /* Name.Variable.Global */
597 .codehilite .vg { color: #19177C } /* Name.Variable.Global */
559 .codehilite .vi { color: #19177C } /* Name.Variable.Instance */
598 .codehilite .vi { color: #19177C } /* Name.Variable.Instance */
560 .codehilite .vm { color: #19177C } /* Name.Variable.Magic */
599 .codehilite .vm { color: #19177C } /* Name.Variable.Magic */
561 .codehilite .il { color: #666666 } /* Literal.Number.Integer.Long */
600 .codehilite .il { color: #666666 } /* Literal.Number.Integer.Long */
562
601
563 </style>
602 </style>
564
603
565 </head>
604 </head>
566 <body>
605 <body>
567
606
568 <div>
607 <div>
569 <!-- Wrapper/Container Table: Use a wrapper table to control the width and the background color consistently of your email. Use this approach instead of setting attributes on the body tag. -->
608 <!-- Wrapper/Container Table: Use a wrapper table to control the width and the background color consistently of your email. Use this approach instead of setting attributes on the body tag. -->
570 <table cellpadding="0" cellspacing="0" border="0" id="backgroundTable" align="left" style="margin:1%;width:97%;padding:0;font-family:${text_regular|n};font-weight:100;border:1px solid #dbd9da">
609 <table cellpadding="0" cellspacing="0" border="0" id="backgroundTable" align="left" style="margin:1%;width:97%;padding:0;font-family:${text_regular|n};font-weight:100;border:1px solid #dbd9da">
571 <tr>
610 <tr>
572 <td valign="top" style="padding:0;">
611 <td valign="top" style="padding:0;">
573 <table cellpadding="0" cellspacing="0" border="0" align="left" width="100%">
612 <table cellpadding="0" cellspacing="0" border="0" align="left" width="100%">
574 <tr>
613 <tr>
575 <td style="width:100%;padding:10px 15px;background-color:#202020" valign="top">
614 <td style="width:100%;padding:10px 15px;background-color:#202020" valign="top">
576 <a style="color:#eeeeee;text-decoration:none;" href="${instance_url}">
615 <a style="color:#eeeeee;text-decoration:none;" href="${instance_url}">
577 ${_('RhodeCode')}
616 ${_('RhodeCode')}
578 % if rhodecode_instance_name:
617 % if rhodecode_instance_name:
579 - ${rhodecode_instance_name}
618 - ${rhodecode_instance_name}
580 % endif
619 % endif
581 </a>
620 </a>
582 </td>
621 </td>
583 </tr>
622 </tr>
584 <tr>
623 <tr style="background-color: #fff">
585 <td style="padding:15px;" valign="top">${self.body()}</td>
624 <td style="padding:15px;" valign="top">${self.body()}</td>
586 </tr>
625 </tr>
587 </table>
626 </table>
588 </td>
627 </td>
589 </tr>
628 </tr>
590 </table>
629 </table>
591 <!-- End of wrapper table -->
630 <!-- End of wrapper table -->
592 </div>
631 </div>
593
632
594 <div style="width:100%; clear: both; height: 1px">&nbsp;</div>
633 <div style="width:100%; clear: both; height: 1px">&nbsp;</div>
595
634
596 <div style="margin-left:1%;font-weight:100;font-size:11px;color:#666666;text-decoration:none;font-family:${text_monospace};">
635 <div style="margin-left:1%;font-weight:100;font-size:11px;color:#666666;text-decoration:none;font-family:${text_monospace};">
597 ${_('This is a notification from RhodeCode.')}
636 ${_('This is a notification from RhodeCode.')}
598 <a style="font-weight:100;font-size:11px;color:#666666;text-decoration:none;font-family:${text_monospace};" href="${instance_url}">
637 <a style="font-weight:100;font-size:11px;color:#666666;text-decoration:none;font-family:${text_monospace};" href="${instance_url}">
599 ${instance_url}
638 ${instance_url}
600 </a>
639 </a>
601 </div>
640 </div>
602 </body>
641 </body>
603 </html>
642 </html>
@@ -1,170 +1,172 b''
1 ## -*- coding: utf-8 -*-
1 ## -*- coding: utf-8 -*-
2 <%inherit file="base.mako"/>
2 <%inherit file="base.mako"/>
3 <%namespace name="base" file="base.mako"/>
3 <%namespace name="base" file="base.mako"/>
4
4
5 ## EMAIL SUBJECT
5 ## EMAIL SUBJECT
6 <%def name="subject()" filter="n,trim,whitespace_filter">
6 <%def name="subject()" filter="n,trim,whitespace_filter">
7 <%
7 <%
8 data = {
8 data = {
9 'user': '@'+h.person(user),
9 'user': '@'+h.person(user),
10 'repo_name': repo_name,
10 'repo_name': repo_name,
11 'status': status_change,
11 'status': status_change,
12 'comment_file': comment_file,
12 'comment_file': comment_file,
13 'comment_line': comment_line,
13 'comment_line': comment_line,
14 'comment_type': comment_type,
14 'comment_type': comment_type,
15 'comment_id': comment_id,
15 'comment_id': comment_id,
16
16
17 'commit_id': h.show_id(commit),
17 'commit_id': h.show_id(commit),
18 }
18 }
19 %>
19 %>
20
20
21
21
22 % if comment_file:
22 % if comment_file:
23 ${(_('[mention]') if mention else '')} ${_('{user} left a {comment_type} on file `{comment_file}` in commit `{commit_id}`').format(**data)} ${_('in the `{repo_name}` repository').format(**data) |n}
23 ${(_('[mention]') if mention else '')} ${_('{user} left a {comment_type} on file `{comment_file}` in commit `{commit_id}`').format(**data)} ${_('in the `{repo_name}` repository').format(**data) |n}
24 % else:
24 % else:
25 % if status_change:
25 % if status_change:
26 ${(_('[mention]') if mention else '')} ${_('[status: {status}] {user} left a {comment_type} on commit `{commit_id}`').format(**data) |n} ${_('in the `{repo_name}` repository').format(**data) |n}
26 ${(_('[mention]') if mention else '')} ${_('[status: {status}] {user} left a {comment_type} on commit `{commit_id}`').format(**data) |n} ${_('in the `{repo_name}` repository').format(**data) |n}
27 % else:
27 % else:
28 ${(_('[mention]') if mention else '')} ${_('{user} left a {comment_type} on commit `{commit_id}`').format(**data) |n} ${_('in the `{repo_name}` repository').format(**data) |n}
28 ${(_('[mention]') if mention else '')} ${_('{user} left a {comment_type} on commit `{commit_id}`').format(**data) |n} ${_('in the `{repo_name}` repository').format(**data) |n}
29 % endif
29 % endif
30 % endif
30 % endif
31
31
32 </%def>
32 </%def>
33
33
34 ## PLAINTEXT VERSION OF BODY
34 ## PLAINTEXT VERSION OF BODY
35 <%def name="body_plaintext()" filter="n,trim">
35 <%def name="body_plaintext()" filter="n,trim">
36 <%
36 <%
37 data = {
37 data = {
38 'user': h.person(user),
38 'user': h.person(user),
39 'repo_name': repo_name,
39 'repo_name': repo_name,
40 'status': status_change,
40 'status': status_change,
41 'comment_file': comment_file,
41 'comment_file': comment_file,
42 'comment_line': comment_line,
42 'comment_line': comment_line,
43 'comment_type': comment_type,
43 'comment_type': comment_type,
44 'comment_id': comment_id,
44 'comment_id': comment_id,
45
45
46 'commit_id': h.show_id(commit),
46 'commit_id': h.show_id(commit),
47 }
47 }
48 %>
48 %>
49
49
50 * ${_('Comment link')}: ${commit_comment_url}
50 * ${_('Comment link')}: ${commit_comment_url}
51
51
52 %if status_change:
52 %if status_change:
53 * ${_('Commit status')}: ${_('Status was changed to')}: *${status_change}*
53 * ${_('Commit status')}: ${_('Status was changed to')}: *${status_change}*
54
54
55 %endif
55 %endif
56 * ${_('Commit')}: ${h.show_id(commit)}
56 * ${_('Commit')}: ${h.show_id(commit)}
57
57
58 * ${_('Commit message')}: ${commit.message}
58 * ${_('Commit message')}: ${commit.message}
59
59
60 %if comment_file:
60 %if comment_file:
61 * ${_('File: {comment_file} on line {comment_line}').format(**data)}
61 * ${_('File: {comment_file} on line {comment_line}').format(**data)}
62
62
63 %endif
63 %endif
64 % if comment_type == 'todo':
64 % if comment_type == 'todo':
65 ${('Inline' if comment_file else 'General')} ${_('`TODO` number')} ${comment_id}:
65 ${('Inline' if comment_file else 'General')} ${_('`TODO` number')} ${comment_id}:
66 % else:
66 % else:
67 ${('Inline' if comment_file else 'General')} ${_('`Note` number')} ${comment_id}:
67 ${('Inline' if comment_file else 'General')} ${_('`Note` number')} ${comment_id}:
68 % endif
68 % endif
69
69
70 ${comment_body |n, trim}
70 ${comment_body |n, trim}
71
71
72 ---
72 ---
73 ${self.plaintext_footer()}
73 ${self.plaintext_footer()}
74 </%def>
74 </%def>
75
75
76
76
77 <%
77 <%
78 data = {
78 data = {
79 'user': h.person(user),
79 'user': h.person(user),
80 'comment_file': comment_file,
80 'comment_file': comment_file,
81 'comment_line': comment_line,
81 'comment_line': comment_line,
82 'comment_type': comment_type,
82 'comment_type': comment_type,
83 'comment_id': comment_id,
83 'comment_id': comment_id,
84 'renderer_type': renderer_type or 'plain',
84 'renderer_type': renderer_type or 'plain',
85
85
86 'repo': commit_target_repo_url,
86 'repo': commit_target_repo_url,
87 'repo_name': repo_name,
87 'repo_name': repo_name,
88 'commit_id': h.show_id(commit),
88 'commit_id': h.show_id(commit),
89 }
89 }
90 %>
90 %>
91
91
92 ## header
92 <table style="text-align:left;vertical-align:middle;width: 100%">
93 <table style="text-align:left;vertical-align:middle;width: 100%">
93 <tr>
94 <tr>
94 <td style="width:100%;border-bottom:1px solid #dbd9da;">
95 <td style="width:100%;border-bottom:1px solid #dbd9da;">
95
96
96 <h4 style="margin: 0">
97 <div style="margin: 0; font-weight: bold">
97 <div style="margin-bottom: 4px">
98 <div class="clear-both" style="margin-bottom: 4px">
98 <span style="color:#7E7F7F">@${h.person(user.username)}</span>
99 <span style="color:#7E7F7F">@${h.person(user.username)}</span>
99 ${_('left a')}
100 ${_('left a')}
100 <a href="${commit_comment_url}" style="${base.link_css()}">
101 <a href="${commit_comment_url}" style="${base.link_css()}">
101 % if comment_file:
102 % if comment_file:
102 ${_('{comment_type} on file `{comment_file}` in commit.').format(**data)}
103 ${_('{comment_type} on file `{comment_file}` in commit.').format(**data)}
103 % else:
104 % else:
104 ${_('{comment_type} on commit.').format(**data) |n}
105 ${_('{comment_type} on commit.').format(**data) |n}
105 % endif
106 % endif
106 </a>
107 </a>
107 </div>
108 </div>
108 <div style="margin-top: 10px"></div>
109 <div style="margin-top: 10px"></div>
109 ${_('Commit')} <code>${data['commit_id']}</code> ${_('of repository')}: ${data['repo_name']}
110 ${_('Commit')} <code>${data['commit_id']}</code> ${_('of repository')}: ${data['repo_name']}
110 </h4>
111 </div>
111
112
112 </td>
113 </td>
113 </tr>
114 </tr>
114
115
115 </table>
116 </table>
116
117 <div class="clear-both"></div>
118 ## main body
117 <table style="text-align:left;vertical-align:middle;width: 100%">
119 <table style="text-align:left;vertical-align:middle;width: 100%">
118
120
119 ## spacing def
121 ## spacing def
120 <tr>
122 <tr>
121 <td style="width: 130px"></td>
123 <td style="width: 130px"></td>
122 <td></td>
124 <td></td>
123 </tr>
125 </tr>
124
126
125 % if status_change:
127 % if status_change:
126 <tr>
128 <tr>
127 <td style="padding-right:20px;">${_('Commit Status')}:</td>
129 <td style="padding-right:20px;">${_('Commit Status')}:</td>
128 <td>
130 <td>
129 ${_('Status was changed to')}: ${base.status_text(status_change, tag_type=status_change_type)}
131 ${_('Status was changed to')}: ${base.status_text(status_change, tag_type=status_change_type)}
130 </td>
132 </td>
131 </tr>
133 </tr>
132 % endif
134 % endif
133
135
134 <tr>
136 <tr>
135 <td style="padding-right:20px;">${_('Commit')}:</td>
137 <td style="padding-right:20px;">${_('Commit')}:</td>
136 <td>
138 <td>
137 <a href="${commit_comment_url}" style="${base.link_css()}">${h.show_id(commit)}</a>
139 <a href="${commit_comment_url}" style="${base.link_css()}">${h.show_id(commit)}</a>
138 </td>
140 </td>
139 </tr>
141 </tr>
140 <tr>
142 <tr>
141 <td style="padding-right:20px;">${_('Commit message')}:</td>
143 <td style="padding-right:20px;">${_('Commit message')}:</td>
142 <td style="white-space:pre-wrap">${h.urlify_commit_message(commit.message, repo_name)}</td>
144 <td style="white-space:pre-wrap">${h.urlify_commit_message(commit.message, repo_name)}</td>
143 </tr>
145 </tr>
144
146
145 % if comment_file:
147 % if comment_file:
146 <tr>
148 <tr>
147 <td style="padding-right:20px;">${_('File')}:</td>
149 <td style="padding-right:20px;">${_('File')}:</td>
148 <td><a href="${commit_comment_url}" style="${base.link_css()}">${_('`{comment_file}` on line {comment_line}').format(**data)}</a></td>
150 <td><a href="${commit_comment_url}" style="${base.link_css()}">${_('`{comment_file}` on line {comment_line}').format(**data)}</a></td>
149 </tr>
151 </tr>
150 % endif
152 % endif
151
153
152 <tr style="border-bottom:1px solid #dbd9da;">
154 <tr style="border-bottom:1px solid #dbd9da;">
153 <td colspan="2" style="padding-right:20px;">
155 <td colspan="2" style="padding-right:20px;">
154 % if comment_type == 'todo':
156 % if comment_type == 'todo':
155 ${('Inline' if comment_file else 'General')} ${_('`TODO` number')} ${comment_id}:
157 ${('Inline' if comment_file else 'General')} ${_('`TODO` number')} ${comment_id}:
156 % else:
158 % else:
157 ${('Inline' if comment_file else 'General')} ${_('`Note` number')} ${comment_id}:
159 ${('Inline' if comment_file else 'General')} ${_('`Note` number')} ${comment_id}:
158 % endif
160 % endif
159 </td>
161 </td>
160 </tr>
162 </tr>
161
163
162 <tr>
164 <tr>
163 <td colspan="2" style="background: #F7F7F7">${h.render(comment_body, renderer=data['renderer_type'], mentions=True)}</td>
165 <td colspan="2" style="background: #F7F7F7">${h.render(comment_body, renderer=data['renderer_type'], mentions=True)}</td>
164 </tr>
166 </tr>
165
167
166 <tr>
168 <tr>
167 <td><a href="${commit_comment_reply_url}">${_('Reply')}</a></td>
169 <td><a href="${commit_comment_reply_url}">${_('Reply')}</a></td>
168 <td></td>
170 <td></td>
169 </tr>
171 </tr>
170 </table>
172 </table>
@@ -1,201 +1,203 b''
1 ## -*- coding: utf-8 -*-
1 ## -*- coding: utf-8 -*-
2 <%inherit file="base.mako"/>
2 <%inherit file="base.mako"/>
3 <%namespace name="base" file="base.mako"/>
3 <%namespace name="base" file="base.mako"/>
4
4
5 ## EMAIL SUBJECT
5 ## EMAIL SUBJECT
6 <%def name="subject()" filter="n,trim,whitespace_filter">
6 <%def name="subject()" filter="n,trim,whitespace_filter">
7 <%
7 <%
8 data = {
8 data = {
9 'user': '@'+h.person(user),
9 'user': '@'+h.person(user),
10 'repo_name': repo_name,
10 'repo_name': repo_name,
11 'status': status_change,
11 'status': status_change,
12 'comment_file': comment_file,
12 'comment_file': comment_file,
13 'comment_line': comment_line,
13 'comment_line': comment_line,
14 'comment_type': comment_type,
14 'comment_type': comment_type,
15 'comment_id': comment_id,
15 'comment_id': comment_id,
16
16
17 'pr_title': pull_request.title,
17 'pr_title': pull_request.title,
18 'pr_id': pull_request.pull_request_id,
18 'pr_id': pull_request.pull_request_id,
19 }
19 }
20 %>
20 %>
21
21
22
22
23 % if comment_file:
23 % if comment_file:
24 ${(_('[mention]') if mention else '')} ${_('{user} left a {comment_type} on file `{comment_file}` in pull request !{pr_id}: "{pr_title}"').format(**data) |n}
24 ${(_('[mention]') if mention else '')} ${_('{user} left a {comment_type} on file `{comment_file}` in pull request !{pr_id}: "{pr_title}"').format(**data) |n}
25 % else:
25 % else:
26 % if status_change:
26 % if status_change:
27 ${(_('[mention]') if mention else '')} ${_('[status: {status}] {user} left a {comment_type} on pull request !{pr_id}: "{pr_title}"').format(**data) |n}
27 ${(_('[mention]') if mention else '')} ${_('[status: {status}] {user} left a {comment_type} on pull request !{pr_id}: "{pr_title}"').format(**data) |n}
28 % else:
28 % else:
29 ${(_('[mention]') if mention else '')} ${_('{user} left a {comment_type} on pull request !{pr_id}: "{pr_title}"').format(**data) |n}
29 ${(_('[mention]') if mention else '')} ${_('{user} left a {comment_type} on pull request !{pr_id}: "{pr_title}"').format(**data) |n}
30 % endif
30 % endif
31 % endif
31 % endif
32
32
33 </%def>
33 </%def>
34
34
35 ## PLAINTEXT VERSION OF BODY
35 ## PLAINTEXT VERSION OF BODY
36 <%def name="body_plaintext()" filter="n,trim">
36 <%def name="body_plaintext()" filter="n,trim">
37 <%
37 <%
38 data = {
38 data = {
39 'user': h.person(user),
39 'user': h.person(user),
40 'repo_name': repo_name,
40 'repo_name': repo_name,
41 'status': status_change,
41 'status': status_change,
42 'comment_file': comment_file,
42 'comment_file': comment_file,
43 'comment_line': comment_line,
43 'comment_line': comment_line,
44 'comment_type': comment_type,
44 'comment_type': comment_type,
45 'comment_id': comment_id,
45 'comment_id': comment_id,
46
46
47 'pr_title': pull_request.title,
47 'pr_title': pull_request.title,
48 'pr_id': pull_request.pull_request_id,
48 'pr_id': pull_request.pull_request_id,
49 'source_ref_type': pull_request.source_ref_parts.type,
49 'source_ref_type': pull_request.source_ref_parts.type,
50 'source_ref_name': pull_request.source_ref_parts.name,
50 'source_ref_name': pull_request.source_ref_parts.name,
51 'target_ref_type': pull_request.target_ref_parts.type,
51 'target_ref_type': pull_request.target_ref_parts.type,
52 'target_ref_name': pull_request.target_ref_parts.name,
52 'target_ref_name': pull_request.target_ref_parts.name,
53 'source_repo': pull_request_source_repo.repo_name,
53 'source_repo': pull_request_source_repo.repo_name,
54 'target_repo': pull_request_target_repo.repo_name,
54 'target_repo': pull_request_target_repo.repo_name,
55 'source_repo_url': pull_request_source_repo_url,
55 'source_repo_url': pull_request_source_repo_url,
56 'target_repo_url': pull_request_target_repo_url,
56 'target_repo_url': pull_request_target_repo_url,
57 }
57 }
58 %>
58 %>
59
59
60 * ${_('Comment link')}: ${pr_comment_url}
60 * ${_('Comment link')}: ${pr_comment_url}
61
61
62 * ${_('Pull Request')}: !${pull_request.pull_request_id}
62 * ${_('Pull Request')}: !${pull_request.pull_request_id}
63
63
64 * ${h.literal(_('Commit flow: {source_ref_type}:{source_ref_name} of {source_repo_url} into {target_ref_type}:{target_ref_name} of {target_repo_url}').format(**data))}
64 * ${h.literal(_('Commit flow: {source_ref_type}:{source_ref_name} of {source_repo_url} into {target_ref_type}:{target_ref_name} of {target_repo_url}').format(**data))}
65
65
66 %if status_change and not closing_pr:
66 %if status_change and not closing_pr:
67 * ${_('{user} submitted pull request !{pr_id} status: *{status}*').format(**data)}
67 * ${_('{user} submitted pull request !{pr_id} status: *{status}*').format(**data)}
68
68
69 %elif status_change and closing_pr:
69 %elif status_change and closing_pr:
70 * ${_('{user} submitted pull request !{pr_id} status: *{status} and closed*').format(**data)}
70 * ${_('{user} submitted pull request !{pr_id} status: *{status} and closed*').format(**data)}
71
71
72 %endif
72 %endif
73 %if comment_file:
73 %if comment_file:
74 * ${_('File: {comment_file} on line {comment_line}').format(**data)}
74 * ${_('File: {comment_file} on line {comment_line}').format(**data)}
75
75
76 %endif
76 %endif
77 % if comment_type == 'todo':
77 % if comment_type == 'todo':
78 ${('Inline' if comment_file else 'General')} ${_('`TODO` number')} ${comment_id}:
78 ${('Inline' if comment_file else 'General')} ${_('`TODO` number')} ${comment_id}:
79 % else:
79 % else:
80 ${('Inline' if comment_file else 'General')} ${_('`Note` number')} ${comment_id}:
80 ${('Inline' if comment_file else 'General')} ${_('`Note` number')} ${comment_id}:
81 % endif
81 % endif
82
82
83 ${comment_body |n, trim}
83 ${comment_body |n, trim}
84
84
85 ---
85 ---
86 ${self.plaintext_footer()}
86 ${self.plaintext_footer()}
87 </%def>
87 </%def>
88
88
89
89
90 <%
90 <%
91 data = {
91 data = {
92 'user': h.person(user),
92 'user': h.person(user),
93 'comment_file': comment_file,
93 'comment_file': comment_file,
94 'comment_line': comment_line,
94 'comment_line': comment_line,
95 'comment_type': comment_type,
95 'comment_type': comment_type,
96 'comment_id': comment_id,
96 'comment_id': comment_id,
97 'renderer_type': renderer_type or 'plain',
97 'renderer_type': renderer_type or 'plain',
98
98
99 'pr_title': pull_request.title,
99 'pr_title': pull_request.title,
100 'pr_id': pull_request.pull_request_id,
100 'pr_id': pull_request.pull_request_id,
101 'status': status_change,
101 'status': status_change,
102 'source_ref_type': pull_request.source_ref_parts.type,
102 'source_ref_type': pull_request.source_ref_parts.type,
103 'source_ref_name': pull_request.source_ref_parts.name,
103 'source_ref_name': pull_request.source_ref_parts.name,
104 'target_ref_type': pull_request.target_ref_parts.type,
104 'target_ref_type': pull_request.target_ref_parts.type,
105 'target_ref_name': pull_request.target_ref_parts.name,
105 'target_ref_name': pull_request.target_ref_parts.name,
106 'source_repo': pull_request_source_repo.repo_name,
106 'source_repo': pull_request_source_repo.repo_name,
107 'target_repo': pull_request_target_repo.repo_name,
107 'target_repo': pull_request_target_repo.repo_name,
108 'source_repo_url': h.link_to(pull_request_source_repo.repo_name, pull_request_source_repo_url),
108 'source_repo_url': h.link_to(pull_request_source_repo.repo_name, pull_request_source_repo_url),
109 'target_repo_url': h.link_to(pull_request_target_repo.repo_name, pull_request_target_repo_url),
109 'target_repo_url': h.link_to(pull_request_target_repo.repo_name, pull_request_target_repo_url),
110 }
110 }
111 %>
111 %>
112
112
113 ## header
113 <table style="text-align:left;vertical-align:middle;width: 100%">
114 <table style="text-align:left;vertical-align:middle;width: 100%">
114 <tr>
115 <tr>
115 <td style="width:100%;border-bottom:1px solid #dbd9da;">
116 <td style="width:100%;border-bottom:1px solid #dbd9da;">
116
117
117 <h4 style="margin: 0">
118 <div style="margin: 0; font-weight: bold">
118 <div style="margin-bottom: 4px">
119 <div class="clear-both" style="margin-bottom: 4px">
119 <span style="color:#7E7F7F">@${h.person(user.username)}</span>
120 <span style="color:#7E7F7F">@${h.person(user.username)}</span>
120 ${_('left a')}
121 ${_('left a')}
121 <a href="${pr_comment_url}" style="${base.link_css()}">
122 <a href="${pr_comment_url}" style="${base.link_css()}">
122 % if comment_file:
123 % if comment_file:
123 ${_('{comment_type} on file `{comment_file}` in pull request.').format(**data)}
124 ${_('{comment_type} on file `{comment_file}` in pull request.').format(**data)}
124 % else:
125 % else:
125 ${_('{comment_type} on pull request.').format(**data) |n}
126 ${_('{comment_type} on pull request.').format(**data) |n}
126 % endif
127 % endif
127 </a>
128 </a>
128 </div>
129 </div>
129 <div style="margin-top: 10px"></div>
130 <div style="margin-top: 10px"></div>
130 ${_('Pull request')} <code>!${data['pr_id']}: ${data['pr_title']}</code>
131 ${_('Pull request')} <code>!${data['pr_id']}: ${data['pr_title']}</code>
131 </h4>
132 </div>
132
133
133 </td>
134 </td>
134 </tr>
135 </tr>
135
136
136 </table>
137 </table>
137
138 <div class="clear-both"></div>
139 ## main body
138 <table style="text-align:left;vertical-align:middle;width: 100%">
140 <table style="text-align:left;vertical-align:middle;width: 100%">
139
141
140 ## spacing def
142 ## spacing def
141 <tr>
143 <tr>
142 <td style="width: 130px"></td>
144 <td style="width: 130px"></td>
143 <td></td>
145 <td></td>
144 </tr>
146 </tr>
145
147
146 % if status_change:
148 % if status_change:
147 <tr>
149 <tr>
148 <td style="padding-right:20px;">${_('Review Status')}:</td>
150 <td style="padding-right:20px;">${_('Review Status')}:</td>
149 <td>
151 <td>
150 % if closing_pr:
152 % if closing_pr:
151 ${_('Closed pull request with status')}: ${base.status_text(status_change, tag_type=status_change_type)}
153 ${_('Closed pull request with status')}: ${base.status_text(status_change, tag_type=status_change_type)}
152 % else:
154 % else:
153 ${_('Submitted review status')}: ${base.status_text(status_change, tag_type=status_change_type)}
155 ${_('Submitted review status')}: ${base.status_text(status_change, tag_type=status_change_type)}
154 % endif
156 % endif
155 </td>
157 </td>
156 </tr>
158 </tr>
157 % endif
159 % endif
158 <tr>
160 <tr>
159 <td style="padding-right:20px;">${_('Pull request')}:</td>
161 <td style="padding-right:20px;">${_('Pull request')}:</td>
160 <td>
162 <td>
161 <a href="${pull_request_url}" style="${base.link_css()}">
163 <a href="${pull_request_url}" style="${base.link_css()}">
162 !${pull_request.pull_request_id}
164 !${pull_request.pull_request_id}
163 </a>
165 </a>
164 </td>
166 </td>
165 </tr>
167 </tr>
166
168
167 <tr>
169 <tr>
168 <td style="padding-right:20px;line-height:20px;">${_('Commit Flow')}:</td>
170 <td style="padding-right:20px;line-height:20px;">${_('Commit Flow')}:</td>
169 <td style="line-height:20px;">
171 <td style="line-height:20px;">
170 <code>${'{}:{}'.format(data['source_ref_type'], pull_request.source_ref_parts.name)}</code> ${_('of')} ${data['source_repo_url']}
172 <code>${'{}:{}'.format(data['source_ref_type'], pull_request.source_ref_parts.name)}</code> ${_('of')} ${data['source_repo_url']}
171 &rarr;
173 &rarr;
172 <code>${'{}:{}'.format(data['target_ref_type'], pull_request.target_ref_parts.name)}</code> ${_('of')} ${data['target_repo_url']}
174 <code>${'{}:{}'.format(data['target_ref_type'], pull_request.target_ref_parts.name)}</code> ${_('of')} ${data['target_repo_url']}
173 </td>
175 </td>
174 </tr>
176 </tr>
175
177
176 % if comment_file:
178 % if comment_file:
177 <tr>
179 <tr>
178 <td style="padding-right:20px;">${_('File')}:</td>
180 <td style="padding-right:20px;">${_('File')}:</td>
179 <td><a href="${pr_comment_url}" style="${base.link_css()}">${_('`{comment_file}` on line {comment_line}').format(**data)}</a></td>
181 <td><a href="${pr_comment_url}" style="${base.link_css()}">${_('`{comment_file}` on line {comment_line}').format(**data)}</a></td>
180 </tr>
182 </tr>
181 % endif
183 % endif
182
184
183 <tr style="border-bottom:1px solid #dbd9da;">
185 <tr style="border-bottom:1px solid #dbd9da;">
184 <td colspan="2" style="padding-right:20px;">
186 <td colspan="2" style="padding-right:20px;">
185 % if comment_type == 'todo':
187 % if comment_type == 'todo':
186 ${('Inline' if comment_file else 'General')} ${_('`TODO` number')} ${comment_id}:
188 ${('Inline' if comment_file else 'General')} ${_('`TODO` number')} ${comment_id}:
187 % else:
189 % else:
188 ${('Inline' if comment_file else 'General')} ${_('`Note` number')} ${comment_id}:
190 ${('Inline' if comment_file else 'General')} ${_('`Note` number')} ${comment_id}:
189 % endif
191 % endif
190 </td>
192 </td>
191 </tr>
193 </tr>
192
194
193 <tr>
195 <tr>
194 <td colspan="2" style="background: #F7F7F7">${h.render(comment_body, renderer=data['renderer_type'], mentions=True)}</td>
196 <td colspan="2" style="background: #F7F7F7">${h.render(comment_body, renderer=data['renderer_type'], mentions=True)}</td>
195 </tr>
197 </tr>
196
198
197 <tr>
199 <tr>
198 <td><a href="${pr_comment_reply_url}">${_('Reply')}</a></td>
200 <td><a href="${pr_comment_reply_url}">${_('Reply')}</a></td>
199 <td></td>
201 <td></td>
200 </tr>
202 </tr>
201 </table>
203 </table>
@@ -1,143 +1,144 b''
1 ## -*- coding: utf-8 -*-
1 ## -*- coding: utf-8 -*-
2 <%inherit file="base.mako"/>
2 <%inherit file="base.mako"/>
3 <%namespace name="base" file="base.mako"/>
3 <%namespace name="base" file="base.mako"/>
4
4
5 ## EMAIL SUBJECT
5 ## EMAIL SUBJECT
6 <%def name="subject()" filter="n,trim,whitespace_filter">
6 <%def name="subject()" filter="n,trim,whitespace_filter">
7 <%
7 <%
8 data = {
8 data = {
9 'user': '@'+h.person(user),
9 'user': '@'+h.person(user),
10 'pr_id': pull_request.pull_request_id,
10 'pr_id': pull_request.pull_request_id,
11 'pr_title': pull_request.title,
11 'pr_title': pull_request.title,
12 }
12 }
13 %>
13 %>
14
14
15 ${_('{user} requested a pull request review. !{pr_id}: "{pr_title}"').format(**data) |n}
15 ${_('{user} requested a pull request review. !{pr_id}: "{pr_title}"').format(**data) |n}
16 </%def>
16 </%def>
17
17
18 ## PLAINTEXT VERSION OF BODY
18 ## PLAINTEXT VERSION OF BODY
19 <%def name="body_plaintext()" filter="n,trim">
19 <%def name="body_plaintext()" filter="n,trim">
20 <%
20 <%
21 data = {
21 data = {
22 'user': h.person(user),
22 'user': h.person(user),
23 'pr_id': pull_request.pull_request_id,
23 'pr_id': pull_request.pull_request_id,
24 'pr_title': pull_request.title,
24 'pr_title': pull_request.title,
25 'source_ref_type': pull_request.source_ref_parts.type,
25 'source_ref_type': pull_request.source_ref_parts.type,
26 'source_ref_name': pull_request.source_ref_parts.name,
26 'source_ref_name': pull_request.source_ref_parts.name,
27 'target_ref_type': pull_request.target_ref_parts.type,
27 'target_ref_type': pull_request.target_ref_parts.type,
28 'target_ref_name': pull_request.target_ref_parts.name,
28 'target_ref_name': pull_request.target_ref_parts.name,
29 'repo_url': pull_request_source_repo_url,
29 'repo_url': pull_request_source_repo_url,
30 'source_repo': pull_request_source_repo.repo_name,
30 'source_repo': pull_request_source_repo.repo_name,
31 'target_repo': pull_request_target_repo.repo_name,
31 'target_repo': pull_request_target_repo.repo_name,
32 'source_repo_url': pull_request_source_repo_url,
32 'source_repo_url': pull_request_source_repo_url,
33 'target_repo_url': pull_request_target_repo_url,
33 'target_repo_url': pull_request_target_repo_url,
34 }
34 }
35 %>
35 %>
36
36
37 * ${_('Pull Request link')}: ${pull_request_url}
37 * ${_('Pull Request link')}: ${pull_request_url}
38
38
39 * ${h.literal(_('Commit flow: {source_ref_type}:{source_ref_name} of {source_repo_url} into {target_ref_type}:{target_ref_name} of {target_repo_url}').format(**data))}
39 * ${h.literal(_('Commit flow: {source_ref_type}:{source_ref_name} of {source_repo_url} into {target_ref_type}:{target_ref_name} of {target_repo_url}').format(**data))}
40
40
41 * ${_('Title')}: ${pull_request.title}
41 * ${_('Title')}: ${pull_request.title}
42
42
43 * ${_('Description')}:
43 * ${_('Description')}:
44
44
45 ${pull_request.description | trim}
45 ${pull_request.description | trim}
46
46
47
47
48 * ${_ungettext('Commit (%(num)s)', 'Commits (%(num)s)', len(pull_request_commits) ) % {'num': len(pull_request_commits)}}:
48 * ${_ungettext('Commit (%(num)s)', 'Commits (%(num)s)', len(pull_request_commits) ) % {'num': len(pull_request_commits)}}:
49
49
50 % for commit_id, message in pull_request_commits:
50 % for commit_id, message in pull_request_commits:
51 - ${h.short_id(commit_id)}
51 - ${h.short_id(commit_id)}
52 ${h.chop_at_smart(message, '\n', suffix_if_chopped='...')}
52 ${h.chop_at_smart(message, '\n', suffix_if_chopped='...')}
53
53
54 % endfor
54 % endfor
55
55
56 ---
56 ---
57 ${self.plaintext_footer()}
57 ${self.plaintext_footer()}
58 </%def>
58 </%def>
59 <%
59 <%
60 data = {
60 data = {
61 'user': h.person(user),
61 'user': h.person(user),
62 'pr_id': pull_request.pull_request_id,
62 'pr_id': pull_request.pull_request_id,
63 'pr_title': pull_request.title,
63 'pr_title': pull_request.title,
64 'source_ref_type': pull_request.source_ref_parts.type,
64 'source_ref_type': pull_request.source_ref_parts.type,
65 'source_ref_name': pull_request.source_ref_parts.name,
65 'source_ref_name': pull_request.source_ref_parts.name,
66 'target_ref_type': pull_request.target_ref_parts.type,
66 'target_ref_type': pull_request.target_ref_parts.type,
67 'target_ref_name': pull_request.target_ref_parts.name,
67 'target_ref_name': pull_request.target_ref_parts.name,
68 'repo_url': pull_request_source_repo_url,
68 'repo_url': pull_request_source_repo_url,
69 'source_repo': pull_request_source_repo.repo_name,
69 'source_repo': pull_request_source_repo.repo_name,
70 'target_repo': pull_request_target_repo.repo_name,
70 'target_repo': pull_request_target_repo.repo_name,
71 'source_repo_url': h.link_to(pull_request_source_repo.repo_name, pull_request_source_repo_url),
71 'source_repo_url': h.link_to(pull_request_source_repo.repo_name, pull_request_source_repo_url),
72 'target_repo_url': h.link_to(pull_request_target_repo.repo_name, pull_request_target_repo_url),
72 'target_repo_url': h.link_to(pull_request_target_repo.repo_name, pull_request_target_repo_url),
73 }
73 }
74 %>
74 %>
75
75 ## header
76 <table style="text-align:left;vertical-align:middle;width: 100%">
76 <table style="text-align:left;vertical-align:middle;width: 100%">
77 <tr>
77 <tr>
78 <td style="width:100%;border-bottom:1px solid #dbd9da;">
78 <td style="width:100%;border-bottom:1px solid #dbd9da;">
79
79
80 <h4 style="margin: 0">
80 <div style="margin: 0; font-weight: bold">
81 <div style="margin-bottom: 4px">
81 <div class="clear-both" class="clear-both" style="margin-bottom: 4px">
82 <span style="color:#7E7F7F">@${h.person(user.username)}</span>
82 <span style="color:#7E7F7F">@${h.person(user.username)}</span>
83 ${_('requested a')}
83 ${_('requested a')}
84 <a href="${pull_request_url}" style="${base.link_css()}">
84 <a href="${pull_request_url}" style="${base.link_css()}">
85 ${_('pull request review.').format(**data) }
85 ${_('pull request review.').format(**data) }
86 </a>
86 </a>
87 </div>
87 </div>
88 <div style="margin-top: 10px"></div>
88 <div style="margin-top: 10px"></div>
89 ${_('Pull request')} <code>!${data['pr_id']}: ${data['pr_title']}</code>
89 ${_('Pull request')} <code>!${data['pr_id']}: ${data['pr_title']}</code>
90 </h4>
90 </div>
91
91
92 </td>
92 </td>
93 </tr>
93 </tr>
94
94
95 </table>
95 </table>
96
96 <div class="clear-both"></div>
97 ## main body
97 <table style="text-align:left;vertical-align:middle;width: 100%">
98 <table style="text-align:left;vertical-align:middle;width: 100%">
98 ## spacing def
99 ## spacing def
99 <tr>
100 <tr>
100 <td style="width: 130px"></td>
101 <td style="width: 130px"></td>
101 <td></td>
102 <td></td>
102 </tr>
103 </tr>
103
104
104 <tr>
105 <tr>
105 <td style="padding-right:20px;">${_('Pull request')}:</td>
106 <td style="padding-right:20px;">${_('Pull request')}:</td>
106 <td>
107 <td>
107 <a href="${pull_request_url}" style="${base.link_css()}">
108 <a href="${pull_request_url}" style="${base.link_css()}">
108 !${pull_request.pull_request_id}
109 !${pull_request.pull_request_id}
109 </a>
110 </a>
110 </td>
111 </td>
111 </tr>
112 </tr>
112
113
113 <tr>
114 <tr>
114 <td style="padding-right:20px;line-height:20px;">${_('Commit Flow')}:</td>
115 <td style="padding-right:20px;line-height:20px;">${_('Commit Flow')}:</td>
115 <td style="line-height:20px;">
116 <td style="line-height:20px;">
116 <code>${'{}:{}'.format(data['source_ref_type'], pull_request.source_ref_parts.name)}</code> ${_('of')} ${data['source_repo_url']}
117 <code>${'{}:{}'.format(data['source_ref_type'], pull_request.source_ref_parts.name)}</code> ${_('of')} ${data['source_repo_url']}
117 &rarr;
118 &rarr;
118 <code>${'{}:{}'.format(data['target_ref_type'], pull_request.target_ref_parts.name)}</code> ${_('of')} ${data['target_repo_url']}
119 <code>${'{}:{}'.format(data['target_ref_type'], pull_request.target_ref_parts.name)}</code> ${_('of')} ${data['target_repo_url']}
119 </td>
120 </td>
120 </tr>
121 </tr>
121
122
122 <tr>
123 <tr>
123 <td style="padding-right:20px;">${_('Description')}:</td>
124 <td style="padding-right:20px;">${_('Description')}:</td>
124 <td style="white-space:pre-wrap"><code>${pull_request.description | trim}</code></td>
125 <td style="white-space:pre-wrap"><code>${pull_request.description | trim}</code></td>
125 </tr>
126 </tr>
126 <tr>
127 <tr>
127 <td style="padding-right:20px;">${_ungettext('Commit (%(num)s)', 'Commits (%(num)s)', len(pull_request_commits)) % {'num': len(pull_request_commits)}}:</td>
128 <td style="padding-right:20px;">${_ungettext('Commit (%(num)s)', 'Commits (%(num)s)', len(pull_request_commits)) % {'num': len(pull_request_commits)}}:</td>
128 <td></td>
129 <td></td>
129 </tr>
130 </tr>
130
131
131 <tr>
132 <tr>
132 <td colspan="2">
133 <td colspan="2">
133 <ol style="margin:0 0 0 1em;padding:0;text-align:left;">
134 <ol style="margin:0 0 0 1em;padding:0;text-align:left;">
134 % for commit_id, message in pull_request_commits:
135 % for commit_id, message in pull_request_commits:
135 <li style="margin:0 0 1em;">
136 <li style="margin:0 0 1em;">
136 <pre style="margin:0 0 .5em"><a href="${h.route_path('repo_commit', repo_name=pull_request_source_repo.repo_name, commit_id=commit_id)}" style="${base.link_css()}">${h.short_id(commit_id)}</a></pre>
137 <pre style="margin:0 0 .5em"><a href="${h.route_path('repo_commit', repo_name=pull_request_source_repo.repo_name, commit_id=commit_id)}" style="${base.link_css()}">${h.short_id(commit_id)}</a></pre>
137 ${h.chop_at_smart(message, '\n', suffix_if_chopped='...')}
138 ${h.chop_at_smart(message, '\n', suffix_if_chopped='...')}
138 </li>
139 </li>
139 % endfor
140 % endfor
140 </ol>
141 </ol>
141 </td>
142 </td>
142 </tr>
143 </tr>
143 </table>
144 </table>
@@ -1,164 +1,170 b''
1 ## -*- coding: utf-8 -*-
1 ## -*- coding: utf-8 -*-
2 <%inherit file="base.mako"/>
2 <%inherit file="base.mako"/>
3 <%namespace name="base" file="base.mako"/>
3 <%namespace name="base" file="base.mako"/>
4
4
5 ## EMAIL SUBJECT
5 ## EMAIL SUBJECT
6 <%def name="subject()" filter="n,trim,whitespace_filter">
6 <%def name="subject()" filter="n,trim,whitespace_filter">
7 <%
7 <%
8 data = {
8 data = {
9 'updating_user': '@'+h.person(updating_user),
9 'updating_user': '@'+h.person(updating_user),
10 'pr_id': pull_request.pull_request_id,
10 'pr_id': pull_request.pull_request_id,
11 'pr_title': pull_request.title,
11 'pr_title': pull_request.title,
12 }
12 }
13 %>
13 %>
14
14
15 ${_('{updating_user} updated pull request. !{pr_id}: "{pr_title}"').format(**data) |n}
15 ${_('{updating_user} updated pull request. !{pr_id}: "{pr_title}"').format(**data) |n}
16 </%def>
16 </%def>
17
17
18 ## PLAINTEXT VERSION OF BODY
18 ## PLAINTEXT VERSION OF BODY
19 <%def name="body_plaintext()" filter="n,trim">
19 <%def name="body_plaintext()" filter="n,trim">
20 <%
20 <%
21 data = {
21 data = {
22 'updating_user': h.person(updating_user),
22 'updating_user': h.person(updating_user),
23 'pr_id': pull_request.pull_request_id,
23 'pr_id': pull_request.pull_request_id,
24 'pr_title': pull_request.title,
24 'pr_title': pull_request.title,
25 'source_ref_type': pull_request.source_ref_parts.type,
25 'source_ref_type': pull_request.source_ref_parts.type,
26 'source_ref_name': pull_request.source_ref_parts.name,
26 'source_ref_name': pull_request.source_ref_parts.name,
27 'target_ref_type': pull_request.target_ref_parts.type,
27 'target_ref_type': pull_request.target_ref_parts.type,
28 'target_ref_name': pull_request.target_ref_parts.name,
28 'target_ref_name': pull_request.target_ref_parts.name,
29 'repo_url': pull_request_source_repo_url,
29 'repo_url': pull_request_source_repo_url,
30 'source_repo': pull_request_source_repo.repo_name,
30 'source_repo': pull_request_source_repo.repo_name,
31 'target_repo': pull_request_target_repo.repo_name,
31 'target_repo': pull_request_target_repo.repo_name,
32 'source_repo_url': pull_request_source_repo_url,
32 'source_repo_url': pull_request_source_repo_url,
33 'target_repo_url': pull_request_target_repo_url,
33 'target_repo_url': pull_request_target_repo_url,
34 }
34 }
35 %>
35 %>
36
36
37 * ${_('Pull Request link')}: ${pull_request_url}
37 * ${_('Pull Request link')}: ${pull_request_url}
38
38
39 * ${h.literal(_('Commit flow: {source_ref_type}:{source_ref_name} of {source_repo_url} into {target_ref_type}:{target_ref_name} of {target_repo_url}').format(**data))}
39 * ${h.literal(_('Commit flow: {source_ref_type}:{source_ref_name} of {source_repo_url} into {target_ref_type}:{target_ref_name} of {target_repo_url}').format(**data))}
40
40
41 * ${_('Title')}: ${pull_request.title}
41 * ${_('Title')}: ${pull_request.title}
42
42
43 * ${_('Description')}:
43 * ${_('Description')}:
44
44
45 ${pull_request.description | trim}
45 ${pull_request.description | trim}
46
46
47 * Changed commits:
47 * Changed commits:
48
48
49 - Added: ${len(added_commits)}
49 - Added: ${len(added_commits)}
50 - Removed: ${len(removed_commits)}
50 - Removed: ${len(removed_commits)}
51
51
52 * Changed files:
52 * Changed files:
53
53
54 %if not changed_files:
54 %if not changed_files:
55 No file changes found
55 No file changes found
56 %else:
56 %else:
57 %for file_name in added_files:
57 %for file_name in added_files:
58 - A `${file_name}`
58 - A `${file_name}`
59 %endfor
59 %endfor
60 %for file_name in modified_files:
60 %for file_name in modified_files:
61 - M `${file_name}`
61 - M `${file_name}`
62 %endfor
62 %endfor
63 %for file_name in removed_files:
63 %for file_name in removed_files:
64 - R `${file_name}`
64 - R `${file_name}`
65 %endfor
65 %endfor
66 %endif
66 %endif
67
67
68 ---
68 ---
69 ${self.plaintext_footer()}
69 ${self.plaintext_footer()}
70 </%def>
70 </%def>
71 <%
71 <%
72 data = {
72 data = {
73 'updating_user': h.person(updating_user),
73 'updating_user': h.person(updating_user),
74 'pr_id': pull_request.pull_request_id,
74 'pr_id': pull_request.pull_request_id,
75 'pr_title': pull_request.title,
75 'pr_title': pull_request.title,
76 'source_ref_type': pull_request.source_ref_parts.type,
76 'source_ref_type': pull_request.source_ref_parts.type,
77 'source_ref_name': pull_request.source_ref_parts.name,
77 'source_ref_name': pull_request.source_ref_parts.name,
78 'target_ref_type': pull_request.target_ref_parts.type,
78 'target_ref_type': pull_request.target_ref_parts.type,
79 'target_ref_name': pull_request.target_ref_parts.name,
79 'target_ref_name': pull_request.target_ref_parts.name,
80 'repo_url': pull_request_source_repo_url,
80 'repo_url': pull_request_source_repo_url,
81 'source_repo': pull_request_source_repo.repo_name,
81 'source_repo': pull_request_source_repo.repo_name,
82 'target_repo': pull_request_target_repo.repo_name,
82 'target_repo': pull_request_target_repo.repo_name,
83 'source_repo_url': h.link_to(pull_request_source_repo.repo_name, pull_request_source_repo_url),
83 'source_repo_url': h.link_to(pull_request_source_repo.repo_name, pull_request_source_repo_url),
84 'target_repo_url': h.link_to(pull_request_target_repo.repo_name, pull_request_target_repo_url),
84 'target_repo_url': h.link_to(pull_request_target_repo.repo_name, pull_request_target_repo_url),
85 }
85 }
86 %>
86 %>
87
87
88 ## header
88 <table style="text-align:left;vertical-align:middle;width: 100%">
89 <table style="text-align:left;vertical-align:middle;width: 100%">
89 <tr>
90 <tr>
90 <td style="width:100%;border-bottom:1px solid #dbd9da;">
91 <td style="width:100%;border-bottom:1px solid #dbd9da;">
91
92
92 <h4 style="margin: 0">
93 <div style="margin: 0; font-weight: bold">
93 <div style="margin-bottom: 4px">
94 <div class="clear-both" style="margin-bottom: 4px">
94 <span style="color:#7E7F7F">@${h.person(updating_user.username)}</span>
95 <span style="color:#7E7F7F">@${h.person(updating_user.username)}</span>
95 ${_('updated')}
96 ${_('updated')}
96 <a href="${pull_request_url}" style="${base.link_css()}">
97 <a href="${pull_request_url}" style="${base.link_css()}">
97 ${_('pull request.').format(**data) }
98 ${_('pull request.').format(**data) }
98 </a>
99 </a>
99 </div>
100 </div>
100 <div style="margin-top: 10px"></div>
101 <div style="margin-top: 10px"></div>
101 ${_('Pull request')} <code>!${data['pr_id']}: ${data['pr_title']}</code>
102 ${_('Pull request')} <code>!${data['pr_id']}: ${data['pr_title']}</code>
102 </h4>
103 </div>
103
104
104 </td>
105 </td>
105 </tr>
106 </tr>
106
107
107 </table>
108 </table>
108
109 <div class="clear-both"></div>
110 ## main body
109 <table style="text-align:left;vertical-align:middle;width: 100%">
111 <table style="text-align:left;vertical-align:middle;width: 100%">
110 ## spacing def
112 ## spacing def
111 <tr>
113 <tr>
112 <td style="width: 130px"></td>
114 <td style="width: 130px"></td>
113 <td></td>
115 <td></td>
114 </tr>
116 </tr>
115
117
116 <tr>
118 <tr>
117 <td style="padding-right:20px;">${_('Pull request')}:</td>
119 <td style="padding-right:20px;">${_('Pull request')}:</td>
118 <td>
120 <td>
119 <a href="${pull_request_url}" style="${base.link_css()}">
121 <a href="${pull_request_url}" style="${base.link_css()}">
120 !${pull_request.pull_request_id}
122 !${pull_request.pull_request_id}
121 </a>
123 </a>
122 </td>
124 </td>
123 </tr>
125 </tr>
124
126
125 <tr>
127 <tr>
126 <td style="padding-right:20px;line-height:20px;">${_('Commit Flow')}:</td>
128 <td style="padding-right:20px;line-height:20px;">${_('Commit Flow')}:</td>
127 <td style="line-height:20px;">
129 <td style="line-height:20px;">
128 <code>${'{}:{}'.format(data['source_ref_type'], pull_request.source_ref_parts.name)}</code> ${_('of')} ${data['source_repo_url']}
130 <code>${'{}:{}'.format(data['source_ref_type'], pull_request.source_ref_parts.name)}</code> ${_('of')} ${data['source_repo_url']}
129 &rarr;
131 &rarr;
130 <code>${'{}:{}'.format(data['target_ref_type'], pull_request.target_ref_parts.name)}</code> ${_('of')} ${data['target_repo_url']}
132 <code>${'{}:{}'.format(data['target_ref_type'], pull_request.target_ref_parts.name)}</code> ${_('of')} ${data['target_repo_url']}
131 </td>
133 </td>
132 </tr>
134 </tr>
133
135
134 <tr>
136 <tr>
135 <td style="padding-right:20px;">${_('Description')}:</td>
137 <td style="padding-right:20px;">${_('Description')}:</td>
136 <td style="white-space:pre-wrap"><code>${pull_request.description | trim}</code></td>
138 <td style="white-space:pre-wrap"><code>${pull_request.description | trim}</code></td>
137 </tr>
139 </tr>
138 <tr>
140 <tr>
139 <td style="padding-right:20px;">${_('Changes')}:</td>
141 <td style="padding-right:20px;">${_('Changes')}:</td>
140 <td style="white-space:pre-line">\
142 <td>
141 <strong>Changed commits:</strong>
143 <strong>Changed commits:</strong>
142
144 <ul class="changes-ul">
143 - Added: ${len(added_commits)}
145 <li>- Added: ${len(added_commits)}</li>
144 - Removed: ${len(removed_commits)}
146 <li>- Removed: ${len(removed_commits)}</li>
147 </ul>
145
148
146 <strong>Changed files:</strong>
149 <strong>Changed files:</strong>
150 <ul class="changes-ul">
147
151
148 %if not changed_files:
152 %if not changed_files:
149 No file changes found
153 <li>No file changes found</li>
150 %else:
154 %else:
151 %for file_name in added_files:
155 %for file_name in added_files:
152 - A <a href="${pull_request_url + '#a_' + h.FID(ancestor_commit_id, file_name)}">${file_name}</a>
156 <li>- A <a href="${pull_request_url + '#a_' + h.FID(ancestor_commit_id, file_name)}">${file_name}</a></li>
153 %endfor
157 %endfor
154 %for file_name in modified_files:
158 %for file_name in modified_files:
155 - M <a href="${pull_request_url + '#a_' + h.FID(ancestor_commit_id, file_name)}">${file_name}</a>
159 <li>- M <a href="${pull_request_url + '#a_' + h.FID(ancestor_commit_id, file_name)}">${file_name}</a></li>
156 %endfor
160 %endfor
157 %for file_name in removed_files:
161 %for file_name in removed_files:
158 - R <a href="${pull_request_url + '#a_' + h.FID(ancestor_commit_id, file_name)}">${file_name}</a>
162 <li>- R <a href="${pull_request_url + '#a_' + h.FID(ancestor_commit_id, file_name)}">${file_name}</a></li>
159 %endfor
163 %endfor
160 %endif
164 %endif
165
166 </ul>
161 </td>
167 </td>
162 </tr>
168 </tr>
163
169
164 </table>
170 </table>
@@ -1,59 +1,60 b''
1 ## -*- coding: utf-8 -*-
1 ## -*- coding: utf-8 -*-
2 <%inherit file="base.mako"/>
2 <%inherit file="base.mako"/>
3 <%namespace name="base" file="base.mako"/>
3 <%namespace name="base" file="base.mako"/>
4
4
5 <%def name="subject()" filter="n,trim,whitespace_filter">
5 <%def name="subject()" filter="n,trim,whitespace_filter">
6 RhodeCode new user registration: ${user.username}
6 RhodeCode new user registration: ${user.username}
7 </%def>
7 </%def>
8
8
9 <%def name="body_plaintext()" filter="n,trim">
9 <%def name="body_plaintext()" filter="n,trim">
10
10
11 A new user `${user.username}` has registered on ${h.format_date(date)}
11 A new user `${user.username}` has registered on ${h.format_date(date)}
12
12
13 - Username: ${user.username}
13 - Username: ${user.username}
14 - Full Name: ${user.first_name} ${user.last_name}
14 - Full Name: ${user.first_name} ${user.last_name}
15 - Email: ${user.email}
15 - Email: ${user.email}
16 - Profile link: ${h.route_url('user_profile', username=user.username)}
16 - Profile link: ${h.route_url('user_profile', username=user.username)}
17
17
18 ---
18 ---
19 ${self.plaintext_footer()}
19 ${self.plaintext_footer()}
20 </%def>
20 </%def>
21
21
22
22 ## header
23 <table style="text-align:left;vertical-align:middle;width: 100%">
23 <table style="text-align:left;vertical-align:middle;width: 100%">
24 <tr>
24 <tr>
25 <td style="width:100%;border-bottom:1px solid #dbd9da;">
25 <td style="width:100%;border-bottom:1px solid #dbd9da;">
26 <h4 style="margin: 0">
26 <h4 style="margin: 0">
27 <a href="${h.route_url('user_profile', username=user.username)}" style="${base.link_css()}">
27 <a href="${h.route_url('user_profile', username=user.username)}" style="${base.link_css()}">
28 ${_('New user {user} has registered on {date}').format(user=user.username, date=h.format_date(date))}
28 ${_('New user {user} has registered on {date}').format(user=user.username, date=h.format_date(date))}
29 </a>
29 </a>
30 </h4>
30 </h4>
31 </td>
31 </td>
32 </tr>
32 </tr>
33 </table>
33 </table>
34
34 <div class="clear-both"></div>
35 ## main body
35 <table style="text-align:left;vertical-align:middle;width: 100%">
36 <table style="text-align:left;vertical-align:middle;width: 100%">
36 ## spacing def
37 ## spacing def
37 <tr>
38 <tr>
38 <td style="width: 130px"></td>
39 <td style="width: 130px"></td>
39 <td></td>
40 <td></td>
40 </tr>
41 </tr>
41 <tr>
42 <tr>
42 <td style="padding-right:20px;padding-top:20px;">${_('Username')}:</td>
43 <td style="padding-right:20px;padding-top:20px;">${_('Username')}:</td>
43 <td style="line-height:1;padding-top:20px;">${user.username}</td>
44 <td style="line-height:1;padding-top:20px;">${user.username}</td>
44 </tr>
45 </tr>
45 <tr>
46 <tr>
46 <td style="padding-right:20px;">${_('Full Name')}:</td>
47 <td style="padding-right:20px;">${_('Full Name')}:</td>
47 <td>${user.first_name} ${user.last_name}</td>
48 <td>${user.first_name} ${user.last_name}</td>
48 </tr>
49 </tr>
49 <tr>
50 <tr>
50 <td style="padding-right:20px;">${_('Email')}:</td>
51 <td style="padding-right:20px;">${_('Email')}:</td>
51 <td>${user.email}</td>
52 <td>${user.email}</td>
52 </tr>
53 </tr>
53 <tr>
54 <tr>
54 <td style="padding-right:20px;">${_('Profile')}:</td>
55 <td style="padding-right:20px;">${_('Profile')}:</td>
55 <td>
56 <td>
56 <a href="${h.route_url('user_profile', username=user.username)}">${h.route_url('user_profile', username=user.username)}</a>
57 <a href="${h.route_url('user_profile', username=user.username)}">${h.route_url('user_profile', username=user.username)}</a>
57 </td>
58 </td>
58 </tr>
59 </tr>
59 </table>
60 </table>
General Comments 0
You need to be logged in to leave comments. Login now