##// END OF EJS Templates
emails: try to improve wording and layout - 1st iteration
Mads Kiilerich -
r3780:1de8abd9 beta
parent child Browse files
Show More
@@ -1,284 +1,285 b''
1 1 # -*- coding: utf-8 -*-
2 2 """
3 3 rhodecode.model.comment
4 4 ~~~~~~~~~~~~~~~~~~~~~~~
5 5
6 6 comments model for RhodeCode
7 7
8 8 :created_on: Nov 11, 2011
9 9 :author: marcink
10 10 :copyright: (C) 2011-2012 Marcin Kuzminski <marcin@python-works.com>
11 11 :license: GPLv3, see COPYING for more details.
12 12 """
13 13 # This program is free software: you can redistribute it and/or modify
14 14 # it under the terms of the GNU General Public License as published by
15 15 # the Free Software Foundation, either version 3 of the License, or
16 16 # (at your option) any later version.
17 17 #
18 18 # This program is distributed in the hope that it will be useful,
19 19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 21 # GNU General Public License for more details.
22 22 #
23 23 # You should have received a copy of the GNU General Public License
24 24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
25 25
26 26 import logging
27 27 import traceback
28 28
29 29 from pylons.i18n.translation import _
30 30 from sqlalchemy.util.compat import defaultdict
31 31
32 32 from rhodecode.lib.utils2 import extract_mentioned_users, safe_unicode
33 33 from rhodecode.lib import helpers as h
34 34 from rhodecode.model import BaseModel
35 35 from rhodecode.model.db import ChangesetComment, User, Repository, \
36 36 Notification, PullRequest
37 37 from rhodecode.model.notification import NotificationModel
38 38 from rhodecode.model.meta import Session
39 39
40 40 log = logging.getLogger(__name__)
41 41
42 42
43 43 class ChangesetCommentsModel(BaseModel):
44 44
45 45 cls = ChangesetComment
46 46
47 47 def __get_changeset_comment(self, changeset_comment):
48 48 return self._get_instance(ChangesetComment, changeset_comment)
49 49
50 50 def __get_pull_request(self, pull_request):
51 51 return self._get_instance(PullRequest, pull_request)
52 52
53 53 def _extract_mentions(self, s):
54 54 user_objects = []
55 55 for username in extract_mentioned_users(s):
56 56 user_obj = User.get_by_username(username, case_insensitive=True)
57 57 if user_obj:
58 58 user_objects.append(user_obj)
59 59 return user_objects
60 60
61 61 def _get_notification_data(self, repo, comment, user, comment_text,
62 62 line_no=None, revision=None, pull_request=None,
63 63 status_change=None, closing_pr=False):
64 64 """
65 65 Get notification data
66 66
67 67 :param comment_text:
68 68 :param line:
69 69 :returns: tuple (subj,body,recipients,notification_type,email_kwargs)
70 70 """
71 71 # make notification
72 72 body = comment_text # text of the comment
73 73 line = ''
74 74 if line_no:
75 75 line = _('on line %s') % line_no
76 76
77 77 #changeset
78 78 if revision:
79 79 notification_type = Notification.TYPE_CHANGESET_COMMENT
80 80 cs = repo.scm_instance.get_changeset(revision)
81 81 desc = "%s" % (cs.short_id)
82 82
83 83 _url = h.url('changeset_home',
84 84 repo_name=repo.repo_name,
85 85 revision=revision,
86 86 anchor='comment-%s' % comment.comment_id,
87 87 qualified=True,
88 88 )
89 89 subj = safe_unicode(
90 90 h.link_to('Re changeset: %(desc)s %(line)s' % \
91 91 {'desc': desc, 'line': line},
92 92 _url)
93 93 )
94 email_subject = 'User %s commented on changeset %s' % \
94 email_subject = '%s commented on changeset %s' % \
95 95 (user.username, h.short_id(revision))
96 96 # get the current participants of this changeset
97 97 recipients = ChangesetComment.get_users(revision=revision)
98 98 # add changeset author if it's in rhodecode system
99 99 cs_author = User.get_from_cs_author(cs.author)
100 100 if not cs_author:
101 101 #use repo owner if we cannot extract the author correctly
102 102 cs_author = repo.user
103 103 recipients += [cs_author]
104 104 email_kwargs = {
105 105 'status_change': status_change,
106 106 'cs_comment_user': h.person(user.email),
107 107 'cs_target_repo': h.url('summary_home', repo_name=repo.repo_name,
108 108 qualified=True),
109 109 'cs_comment_url': _url,
110 110 'raw_id': revision,
111 111 'message': cs.message
112 112 }
113 113 #pull request
114 114 elif pull_request:
115 115 notification_type = Notification.TYPE_PULL_REQUEST_COMMENT
116 116 desc = comment.pull_request.title
117 117 _url = h.url('pullrequest_show',
118 118 repo_name=pull_request.other_repo.repo_name,
119 119 pull_request_id=pull_request.pull_request_id,
120 120 anchor='comment-%s' % comment.comment_id,
121 121 qualified=True,
122 122 )
123 123 subj = safe_unicode(
124 124 h.link_to('Re pull request #%(pr_id)s: %(desc)s %(line)s' % \
125 125 {'desc': desc,
126 126 'pr_id': comment.pull_request.pull_request_id,
127 127 'line': line},
128 128 _url)
129 129 )
130 email_subject = 'User %s commented on pull request #%s' % \
130 email_subject = '%s commented on pull request #%s' % \
131 131 (user.username, comment.pull_request.pull_request_id)
132 132 # get the current participants of this pull request
133 133 recipients = ChangesetComment.get_users(pull_request_id=
134 134 pull_request.pull_request_id)
135 135 # add pull request author
136 136 recipients += [pull_request.author]
137 137
138 138 # add the reviewers to notification
139 139 recipients += [x.user for x in pull_request.reviewers]
140 140
141 141 #set some variables for email notification
142 142 email_kwargs = {
143 'pr_title': pull_request.title,
143 144 'pr_id': pull_request.pull_request_id,
144 145 'status_change': status_change,
145 146 'closing_pr': closing_pr,
146 147 'pr_comment_url': _url,
147 148 'pr_comment_user': h.person(user.email),
148 149 'pr_target_repo': h.url('summary_home',
149 150 repo_name=pull_request.other_repo.repo_name,
150 151 qualified=True)
151 152 }
152 153
153 154 return subj, body, recipients, notification_type, email_kwargs, email_subject
154 155
155 156 def create(self, text, repo, user, revision=None, pull_request=None,
156 157 f_path=None, line_no=None, status_change=None, closing_pr=False,
157 158 send_email=True):
158 159 """
159 160 Creates new comment for changeset or pull request.
160 161 IF status_change is not none this comment is associated with a
161 162 status change of changeset or changesets associated with pull request
162 163
163 164 :param text:
164 165 :param repo:
165 166 :param user:
166 167 :param revision:
167 168 :param pull_request:
168 169 :param f_path:
169 170 :param line_no:
170 171 :param status_change:
171 172 :param closing_pr:
172 173 :param send_email:
173 174 """
174 175 if not text:
175 176 log.warning('Missing text for comment, skipping...')
176 177 return
177 178
178 179 repo = self._get_repo(repo)
179 180 user = self._get_user(user)
180 181 comment = ChangesetComment()
181 182 comment.repo = repo
182 183 comment.author = user
183 184 comment.text = text
184 185 comment.f_path = f_path
185 186 comment.line_no = line_no
186 187
187 188 if revision:
188 189 comment.revision = revision
189 190 elif pull_request:
190 191 pull_request = self.__get_pull_request(pull_request)
191 192 comment.pull_request = pull_request
192 193 else:
193 194 raise Exception('Please specify revision or pull_request_id')
194 195
195 196 Session().add(comment)
196 197 Session().flush()
197 198
198 199 if send_email:
199 200 (subj, body, recipients, notification_type,
200 201 email_kwargs, email_subject) = self._get_notification_data(
201 202 repo, comment, user,
202 203 comment_text=text,
203 204 line_no=line_no,
204 205 revision=revision,
205 206 pull_request=pull_request,
206 207 status_change=status_change,
207 208 closing_pr=closing_pr)
208 209 # create notification objects, and emails
209 210 NotificationModel().create(
210 211 created_by=user, subject=subj, body=body,
211 212 recipients=recipients, type_=notification_type,
212 213 email_kwargs=email_kwargs, email_subject=email_subject
213 214 )
214 215
215 216 mention_recipients = set(self._extract_mentions(body))\
216 217 .difference(recipients)
217 218 if mention_recipients:
218 219 email_kwargs.update({'pr_mention': True})
219 220 subj = _('[Mention]') + ' ' + subj
220 221 NotificationModel().create(
221 222 created_by=user, subject=subj, body=body,
222 223 recipients=mention_recipients,
223 224 type_=notification_type,
224 225 email_kwargs=email_kwargs
225 226 )
226 227
227 228 return comment
228 229
229 230 def delete(self, comment):
230 231 """
231 232 Deletes given comment
232 233
233 234 :param comment_id:
234 235 """
235 236 comment = self.__get_changeset_comment(comment)
236 237 Session().delete(comment)
237 238
238 239 return comment
239 240
240 241 def get_comments(self, repo_id, revision=None, pull_request=None):
241 242 """
242 243 Get's main comments based on revision or pull_request_id
243 244
244 245 :param repo_id:
245 246 :param revision:
246 247 :param pull_request:
247 248 """
248 249
249 250 q = ChangesetComment.query()\
250 251 .filter(ChangesetComment.repo_id == repo_id)\
251 252 .filter(ChangesetComment.line_no == None)\
252 253 .filter(ChangesetComment.f_path == None)
253 254 if revision:
254 255 q = q.filter(ChangesetComment.revision == revision)
255 256 elif pull_request:
256 257 pull_request = self.__get_pull_request(pull_request)
257 258 q = q.filter(ChangesetComment.pull_request == pull_request)
258 259 else:
259 260 raise Exception('Please specify revision or pull_request')
260 261 q = q.order_by(ChangesetComment.created_on)
261 262 return q.all()
262 263
263 264 def get_inline_comments(self, repo_id, revision=None, pull_request=None):
264 265 q = Session().query(ChangesetComment)\
265 266 .filter(ChangesetComment.repo_id == repo_id)\
266 267 .filter(ChangesetComment.line_no != None)\
267 268 .filter(ChangesetComment.f_path != None)\
268 269 .order_by(ChangesetComment.comment_id.asc())\
269 270
270 271 if revision:
271 272 q = q.filter(ChangesetComment.revision == revision)
272 273 elif pull_request:
273 274 pull_request = self.__get_pull_request(pull_request)
274 275 q = q.filter(ChangesetComment.pull_request == pull_request)
275 276 else:
276 277 raise Exception('Please specify revision or pull_request_id')
277 278
278 279 comments = q.all()
279 280
280 281 paths = defaultdict(lambda: defaultdict(list))
281 282
282 283 for co in comments:
283 284 paths[co.f_path][co.line_no].append(co)
284 285 return paths.items()
@@ -1,17 +1,18 b''
1 1 ## -*- coding: utf-8 -*-
2 2 <%inherit file="main.html"/>
3 ##message from user goes here
4 <p>
5 ${cs_comment_user}: <br/>
3
4 <p>${_('URL')}: <a href="${cs_comment_url}">${cs_comment_url}</a></p>
5
6 <h4>${_('%s commented on a %s changeset.') % (cs_comment_user,cs_target_repo) |n}</h4>
7
8 <p>${_('Changeset')}: ${h.short_id(raw_id)}</p>
9 <p>${_('Description')}:<br/>
10 ${h.shorter(message, 256)}
11 </p>
12
13 %if status_change:
14 <p>${_('The changeset status was changed to')}: <b>${status_change}</b></p>
15 %endif
16 <p>${_('Comment')}:<br/>
6 17 ${body}
7 18 </p>
8 %if status_change:
9 <span>${_('New status')} -&gt; ${status_change}</span>
10 %endif
11 <div>${_('View this comment here')}: ${cs_comment_url}</div>
12
13 <pre>
14 ${_('Repo')}: ${cs_target_repo}
15 ${_('Changeset')}: ${h.short_id(raw_id)}
16 ${_('desc')}: ${h.shorter(message, 256)}
17 </pre>
@@ -1,11 +1,10 b''
1 1 ## -*- coding: utf-8 -*-
2 2 <%inherit file="main.html"/>
3 3
4 4 <h4>${_('Hello %s') % user}</h4>
5 <div>${_('We received a request to create a new password for your account.')}</div>
6 <div>${_('You can generate it by clicking following URL')}:</div>
5 <p>${_('We received a request to create a new password for your account.')}</p>
6 <p>${_('You can generate it by clicking following URL')}:</p>
7 7 <pre>
8 8 ${reset_url}
9 9 </pre>
10 <br/>
11 ${_("If you did not request new password please ignore this email.")}
10 <p>${_("Please ignore this email if you did not request a new password .")}</p>
@@ -1,18 +1,19 b''
1 1 ## -*- coding: utf-8 -*-
2 2 <%inherit file="main.html"/>
3 3
4 ${_('User %s opened pull request for repository %s and wants you to review changes.') % (('<b>%s</b>' % pr_user_created),pr_repo_url) |n}
5 <div>${_('View this pull request here')}: ${pr_url}</div>
6 <div>${_('title')}: ${pr_title}</div>
7 <div>${_('description')}:</div>
8 <p>
9 ${body}
10 </p>
4 <p>${_('URL')}: <a href="${pr_url}">${pr_url}</a></p>
5
6 <h4>${_('%s opened a pull request for repository %s and wants you to review changes.') % (pr_user_created,pr_repo_url) |n}</h4>
11 7
12 <div>${_('revisions for reviewing')}</div>
8 <p>${_('Title')}: <b>${pr_title}</b></p>
9 <p>${_('Description')}:</p>
10 <p style="white-space: pre-wrap;">${body}</p>
11
12 <p>${_('Changesets')}:</p>
13 13 <p style="white-space: pre-wrap;">
14 14 %for r,r_msg in pr_revisions:
15 15 <b>${h.short_id(r)}</b>:
16 16 ${h.shorter(r_msg, 256)}
17
17 18 %endfor
18 19 </p>
@@ -1,18 +1,17 b''
1 1 ## -*- coding: utf-8 -*-
2 2 <%inherit file="main.html"/>
3 ${_('Pull request #%s for repository %s') % (pr_id, pr_target_repo) |n}
4 ##message from user goes here
5 <p>
6 ${pr_comment_user}: <br/>
7 ${body}
8 </p>
9 <div>${_('View this comment here')}: ${pr_comment_url}</div>
3
4 <p>${_('URL')}: <a href="${pr_comment_url}">${pr_comment_url}</a></p>
5
6 <h4>${_('%s commented on pull request "%s"') % (pr_comment_user,pr_title) |n}</h4>
10 7
11 8 %if status_change:
12 9 %if closing_pr:
13 <span>${_('Closing pull request with status')} -&gt; ${status_change}</span>
10 <p>${_('Pull request was closed with status')}: <b>${status_change}</b></p>
14 11 %else:
15 <span>${_('New status')} -&gt; ${status_change}</span>
12 <p>${_('Pull request changed status')}: <b>${status_change}</b></p>
16 13 %endif
17 14 %endif
18 </p>
15
16 <p>${_('Comment')}:</p>
17 <p>${body}</p>
@@ -1,9 +1,6 b''
1 1 ## -*- coding: utf-8 -*-
2 2 <%inherit file="main.html"/>
3 3
4 ${_('A new user have registered in RhodeCode')}
5
6 4 ${body}
7 5
8
9 6 ${_('View this user here')}: ${registered_user_url}
General Comments 0
You need to be logged in to leave comments. Login now