##// END OF EJS Templates
html: move "Submit a bug" to make it more clear that it is for RhodeCode, not the repo...
html: move "Submit a bug" to make it more clear that it is for RhodeCode, not the repo RhodeCode _could_ contain a bug tracker and this link _could_ be for filing bugs for the hosted projects. Moving the link to the RhodeCode info makes it more clear that it is for RhodeCode bugs. The server instance is however something local, not directly related to the upstream.

File last commit:

r3654:ec635494 beta
r3779:e61a656b beta
Show More
notification.py
281 lines | 10.3 KiB | text/x-python | PythonLexer
#302 - basic notification system, models+tests
r1702 # -*- coding: utf-8 -*-
"""
rhodecode.model.notification
docs update
r1839 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#302 - basic notification system, models+tests
r1702
Model for notifications
pep8ify
r1800
#302 - basic notification system, models+tests
r1702 :created_on: Nov 20, 2011
:author: marcink
2012 copyrights
r1824 :copyright: (C) 2010-2012 Marcin Kuzminski <marcin@python-works.com>
#302 - basic notification system, models+tests
r1702 :license: GPLv3, see COPYING for more details.
"""
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
Notification fixes...
r1717 import os
#302 - basic notification system, models+tests
r1702 import logging
import traceback
added template context into Notification templates
r3423 from pylons import tmpl_context as c
#302 - basic notification system, models+tests
r1702 from pylons.i18n.translation import _
- refactoring to overcome poor usage of global pylons config...
r1723 import rhodecode
Notification fixes...
r1717 from rhodecode.lib import helpers as h
#302 - basic notification system, models+tests
r1702 from rhodecode.model import BaseModel
from rhodecode.model.db import Notification, User, UserNotification
notifications changes...
r3430 from rhodecode.model.meta import Session
#302 - basic notification system, models+tests
r1702
Notification system improvements...
r1712 log = logging.getLogger(__name__)
#302 - basic notification system, models+tests
r1702
notification to commit author + gardening
r1716
#302 - basic notification system, models+tests
r1702 class NotificationModel(BaseModel):
Added associated classes into child models
r2522 cls = Notification
Notification system improvements...
r1712 def __get_notification(self, notification):
if isinstance(notification, Notification):
return notification
Mysql fixes...
r2149 elif isinstance(notification, (int, long)):
Notification system improvements...
r1712 return Notification.get(notification)
else:
if notification:
Mysql fixes...
r2149 raise Exception('notification must be int, long or Instance'
Notification system improvements...
r1712 ' of Notification got %s' % type(notification))
implements #222 registration feedback...
r1731 def create(self, created_by, subject, body, recipients=None,
type_=Notification.TYPE_MESSAGE, with_email=True,
notifications changes...
r3430 email_kwargs={}, email_subject=None):
notification fixes and improvements
r1703 """
pep8ify
r1800
notification fixes and improvements
r1703 Creates notification of given type
pep8ify
r1800
notification fixes and improvements
r1703 :param created_by: int, str or User instance. User who created this
notification
:param subject:
:param body:
auto white-space removal
r1818 :param recipients: list of int, str or User objects, when None
implements #222 registration feedback...
r1731 is given send to all admins
notification fixes and improvements
r1703 :param type_: type of notification
implements #222 registration feedback...
r1731 :param with_email: send email with this notification
:param email_kwargs: additional dict to pass as args to email template
notifications changes...
r3430 :param email_subject: use given subject as email subject
notification fixes and improvements
r1703 """
#235 forking page repo group selection...
r1722 from rhodecode.lib.celerylib import tasks, run_task
#302 - basic notification system, models+tests
r1702
implements #222 registration feedback...
r1731 if recipients and not getattr(recipients, '__iter__', False):
Mads Kiilerich
fix a couple of typos
r3270 raise Exception('recipients must be a list or iterable')
#302 - basic notification system, models+tests
r1702
Share common getter functions in base model, and remove duplicated functions from other models
r2432 created_by_obj = self._get_user(created_by)
#302 - basic notification system, models+tests
r1702
implements #222 registration feedback...
r1731 if recipients:
recipients_objs = []
for u in recipients:
Share common getter functions in base model, and remove duplicated functions from other models
r2432 obj = self._get_user(u)
implements #222 registration feedback...
r1731 if obj:
recipients_objs.append(obj)
recipients_objs = set(recipients_objs)
code garden
r2077 log.debug('sending notifications %s to %s' % (
type_, recipients_objs)
)
implements #222 registration feedback...
r1731 else:
# empty recipients means to all admins
recipients_objs = User.query().filter(User.admin == True).all()
code garden
r2077 log.debug('sending notifications %s to admins: %s' % (
type_, recipients_objs)
)
notif = Notification.create(
created_by=created_by_obj, subject=subject,
body=body, recipients=recipients_objs, type_=type_
)
Notification fixes...
r1717
Mads Kiilerich
follow Python conventions for boolean values...
r3625 if not with_email:
implements #222 registration feedback...
r1731 return notif
Don't send emails to person who comment on changeset
r2387 #don't send email to person who created this comment
rec_objs = set(recipients_objs).difference(set([created_by_obj]))
# send email with notification to all other participants
for rec in rec_objs:
notifications changes...
r3430 if not email_subject:
notification model should only send html emails not generating multipart ones
r3448 email_subject = NotificationModel()\
.make_description(notif, show_age=False)
implements #222 registration feedback...
r1731 type_ = type_
notification model should only send html emails not generating multipart ones
r3448 email_body = None # we set body to none, we just send HTML emails
Add changeset status change into emails
r2296 ## this is passed into template
pep8ify
r1800 kwargs = {'subject': subject, 'body': h.rst_w_mentions(body)}
implements #222 registration feedback...
r1731 kwargs.update(email_kwargs)
Notification fixes...
r1717 email_body_html = EmailNotificationModel()\
implements #222 registration feedback...
r1731 .get_email_tmpl(type_, **kwargs)
Use __unicode__ instead of __repr__ in models.
r2156
#235 forking page repo group selection...
r1722 run_task(tasks.send_email, rec.email, email_subject, email_body,
Notification fixes...
r1717 email_body_html)
return notif
#302 - basic notification system, models+tests
r1702
Tests updates, Session refactoring
r1713 def delete(self, user, notification):
# we don't want to remove actual notification just the assignment
Notification system improvements...
r1712 try:
Tests updates, Session refactoring
r1713 notification = self.__get_notification(notification)
Share common getter functions in base model, and remove duplicated functions from other models
r2432 user = self._get_user(user)
Tests updates, Session refactoring
r1713 if notification and user:
Notification fixes...
r1717 obj = UserNotification.query()\
.filter(UserNotification.user == user)\
.filter(UserNotification.notification
== notification)\
.one()
notifications changes...
r3430 Session().delete(obj)
Notification system improvements...
r1712 return True
except Exception:
log.error(traceback.format_exc())
raise
#302 - basic notification system, models+tests
r1702
Added pull requests filter into notification inbox....
r2433 def get_for_user(self, user, filter_=None):
"""
Get mentions for given user, filter them if filter dict is given
:param user:
:param filter:
"""
Share common getter functions in base model, and remove duplicated functions from other models
r2432 user = self._get_user(user)
Added pull requests filter into notification inbox....
r2433
q = UserNotification.query()\
.filter(UserNotification.user == user)\
.join((Notification, UserNotification.notification_id ==
Notification.notification_id))
if filter_:
Added filtering on inbox by comments
r2503 q = q.filter(Notification.type_.in_(filter_))
#302 - basic notification system, models+tests
r1702
Added pull requests filter into notification inbox....
r2433 return q.all()
added mark as read for single notifications
r2610 def mark_read(self, user, notification):
try:
notification = self.__get_notification(notification)
user = self._get_user(user)
if notification and user:
obj = UserNotification.query()\
.filter(UserNotification.user == user)\
.filter(UserNotification.notification
== notification)\
.one()
obj.read = True
notifications changes...
r3430 Session().add(obj)
added mark as read for single notifications
r2610 return True
except Exception:
log.error(traceback.format_exc())
raise
Added pull requests filter into notification inbox....
r2433 def mark_all_read_for_user(self, user, filter_=None):
Share common getter functions in base model, and remove duplicated functions from other models
r2432 user = self._get_user(user)
Added pull requests filter into notification inbox....
r2433 q = UserNotification.query()\
.filter(UserNotification.user == user)\
Implemented initial code-review status of changesets
r2217 .filter(UserNotification.read == False)\
Added pull requests filter into notification inbox....
r2433 .join((Notification, UserNotification.notification_id ==
Notification.notification_id))
if filter_:
Added filtering on inbox by comments
r2503 q = q.filter(Notification.type_.in_(filter_))
Added pull requests filter into notification inbox....
r2433
# this is a little inefficient but sqlalchemy doesn't support
# update on joined tables :(
for obj in q.all():
obj.read = True
notifications changes...
r3430 Session().add(obj)
mark all read button for notifications
r1791
Tests updates, Session refactoring
r1713 def get_unread_cnt_for_user(self, user):
Share common getter functions in base model, and remove duplicated functions from other models
r2432 user = self._get_user(user)
#302 - basic notification system, models+tests
r1702 return UserNotification.query()\
Notification system improvements...
r1712 .filter(UserNotification.read == False)\
Tests updates, Session refactoring
r1713 .filter(UserNotification.user == user).count()
#302 - basic notification system, models+tests
r1702
Tests updates, Session refactoring
r1713 def get_unread_for_user(self, user):
Share common getter functions in base model, and remove duplicated functions from other models
r2432 user = self._get_user(user)
#302 - basic notification system, models+tests
r1702 return [x.notification for x in UserNotification.query()\
Notification system improvements...
r1712 .filter(UserNotification.read == False)\
Tests updates, Session refactoring
r1713 .filter(UserNotification.user == user).all()]
Notification system improvements...
r1712
def get_user_notification(self, user, notification):
Share common getter functions in base model, and remove duplicated functions from other models
r2432 user = self._get_user(user)
Notification system improvements...
r1712 notification = self.__get_notification(notification)
return UserNotification.query()\
.filter(UserNotification.notification == notification)\
.filter(UserNotification.user == user).scalar()
Notification fixes...
r1717 def make_description(self, notification, show_age=True):
Notification system improvements...
r1712 """
Creates a human readable description based on properties
of notification object
"""
- added commenting to pull requests...
r2443 #alias
_n = notification
code garden
r2082 _map = {
Mads Kiilerich
Fix a lot of casings - use standard casing in most places
r3654 _n.TYPE_CHANGESET_COMMENT: _('%(user)s commented on changeset at %(when)s'),
_n.TYPE_MESSAGE: _('%(user)s sent message at %(when)s'),
_n.TYPE_MENTION: _('%(user)s mentioned you at %(when)s'),
_n.TYPE_REGISTRATION: _('%(user)s registered in RhodeCode at %(when)s'),
_n.TYPE_PULL_REQUEST: _('%(user)s opened new pull request at %(when)s'),
_n.TYPE_PULL_REQUEST_COMMENT: _('%(user)s commented on pull request at %(when)s')
code garden
r2082 }
Mads Kiilerich
Fix a lot of casings - use standard casing in most places
r3654 tmpl = _map[notification.type_]
implements #222 registration feedback...
r1731
Notification fixes...
r1717 if show_age:
when = h.age(notification.created_on)
else:
Format datetime in notifications according to unified function
r2445 when = h.fmt_date(notification.created_on)
Use __unicode__ instead of __repr__ in models.
r2156
Mads Kiilerich
Fix a lot of casings - use standard casing in most places
r3654 return tmpl % dict(
code garden
r2082 user=notification.created_by_user.username,
Mads Kiilerich
Fix a lot of casings - use standard casing in most places
r3654 when=when,
)
Notification fixes...
r1717
class EmailNotificationModel(BaseModel):
test fixes
r1732 TYPE_CHANGESET_COMMENT = Notification.TYPE_CHANGESET_COMMENT
Mads Kiilerich
fix a couple of typos
r3270 TYPE_PASSWORD_RESET = 'password_link'
test fixes
r1732 TYPE_REGISTRATION = Notification.TYPE_REGISTRATION
Added basic models for saving open pull requests...
r2434 TYPE_PULL_REQUEST = Notification.TYPE_PULL_REQUEST
part2 of pull-request notification improvements
r2802 TYPE_PULL_REQUEST_COMMENT = Notification.TYPE_PULL_REQUEST_COMMENT
Notification fixes...
r1717 TYPE_DEFAULT = 'default'
def __init__(self):
- refactoring to overcome poor usage of global pylons config...
r1723 self._template_root = rhodecode.CONFIG['pylons.paths']['templates'][0]
self._tmpl_lookup = rhodecode.CONFIG['pylons.app_globals'].mako_lookup
Notification fixes...
r1717
self.email_types = {
code garden
r2082 self.TYPE_CHANGESET_COMMENT: 'email_templates/changeset_comment.html',
self.TYPE_PASSWORD_RESET: 'email_templates/password_reset.html',
self.TYPE_REGISTRATION: 'email_templates/registration.html',
Nicer email notifications about pull-request
r2799 self.TYPE_DEFAULT: 'email_templates/default.html',
self.TYPE_PULL_REQUEST: 'email_templates/pull_request.html',
part2 of pull-request notification improvements
r2802 self.TYPE_PULL_REQUEST_COMMENT: 'email_templates/pull_request_comment.html',
Notification fixes...
r1717 }
def get_email_tmpl(self, type_, **kwargs):
"""
return generated template for email based on given type
auto white-space removal
r1818
Notification fixes...
r1717 :param type_:
"""
- refactoring to overcome poor usage of global pylons config...
r1723
test fixes
r1732 base = self.email_types.get(type_, self.email_types[self.TYPE_DEFAULT])
- refactoring to overcome poor usage of global pylons config...
r1723 email_template = self._tmpl_lookup.get_template(base)
fixes #691: Notifications for pull requests: move link to pull request to the top...
r3121 # translator and helpers inject
_kwargs = {'_': _,
added template context into Notification templates
r3423 'h': h,
'c': c}
Notification fixes...
r1717 _kwargs.update(kwargs)
log.debug('rendering tmpl %s with kwargs %s' % (base, _kwargs))
return email_template.render(**_kwargs)