# HG changeset patch # User Marcin Kuzminski # Date 2011-11-20 21:26:55 # Node ID f23828b00b21cbf4b66a4022e083229cf9a9a008 # Parent 8cb7f5c4d494777ef461b4bbc4d6371f6756119c notification fixes and improvements diff --git a/rhodecode/model/comment.py b/rhodecode/model/comment.py --- a/rhodecode/model/comment.py +++ b/rhodecode/model/comment.py @@ -28,8 +28,9 @@ import logging import traceback from rhodecode.model import BaseModel -from rhodecode.model.db import ChangesetComment +from rhodecode.model.db import ChangesetComment, User, Notification from sqlalchemy.util.compat import defaultdict +from rhodecode.model.notification import NotificationModel log = logging.getLogger(__name__) @@ -60,6 +61,17 @@ class ChangesetCommentsModel(BaseModel): self.sa.add(comment) self.sa.commit() + + # make notification + usr = User.get(user_id) + subj = 'User %s commented on %s' % (usr.username, revision) + body = text + recipients = ChangesetComment.get_users(revision=revision) + NotificationModel().create(created_by=user_id, subject=subj, + body = body, recipients = recipients, + type_ = Notification.TYPE_CHANGESET_COMMENT) + + return comment def delete(self, comment_id): diff --git a/rhodecode/model/db.py b/rhodecode/model/db.py --- a/rhodecode/model/db.py +++ b/rhodecode/model/db.py @@ -1109,18 +1109,40 @@ class ChangesetComment(Base, BaseModel): text = Column('text', Unicode(25000), nullable=False) modified_at = Column('modified_at', DateTime(), nullable=False, default=datetime.datetime.now) - author = relationship('User') + author = relationship('User', lazy='joined') repo = relationship('Repository') + @classmethod + def get_users(cls, revision): + """ + Returns user associated with this changesetComment. ie those + who actually commented + + :param cls: + :param revision: + """ + return Session.query(User)\ + .filter(cls.revision == revision)\ + .join(ChangesetComment.author).all() + + class Notification(Base, BaseModel): __tablename__ = 'notifications' __table_args__ = ({'extend_existing':True}) + + TYPE_CHANGESET_COMMENT = 'cs_comment' + TYPE_MESSAGE = 'message' + TYPE_MENTION = 'mention' + notification_id = Column('notification_id', Integer(), nullable=False, primary_key=True) subject = Column('subject', Unicode(512), nullable=True) body = Column('body', Unicode(50000), nullable=True) + created_by = Column("created_by", Integer(), ForeignKey('users.user_id'), nullable=True) created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now) + type_ = Column('type', Unicode(256)) + create_by_user = relationship('User') user_notifications = relationship('UserNotification', primaryjoin = 'Notification.notification_id==UserNotification.notification_id', cascade = "all, delete, delete-orphan") @@ -1131,10 +1153,15 @@ class Notification(Base, BaseModel): .filter(UserNotification.notification == self).all()] @classmethod - def create(cls, subject, body, recipients): + def create(cls, created_by, subject, body, recipients, type_=None): + if type_ is None: + type_ = Notification.TYPE_MESSAGE + notification = cls() + notification.create_by_user = created_by notification.subject = subject notification.body = body + notification.type_ = type_ Session.add(notification) for u in recipients: u.notifications.append(notification) @@ -1143,10 +1170,12 @@ class Notification(Base, BaseModel): class UserNotification(Base, BaseModel): __tablename__ = 'user_to_notification' - __table_args__ = ({'extend_existing':True}) + __table_args__ = (UniqueConstraint('user_id', 'notification_id'), + {'extend_existing':True}) user_to_notification_id = Column("user_to_notification_id", Integer(), nullable=False, unique=True, primary_key=True) user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None) notification_id = Column("notification_id", Integer(), ForeignKey('notifications.notification_id'), nullable=False) + read = Column('read', Boolean, default=False) sent_on = Column('sent_on', DateTime(timezone=False), nullable=True, unique=None) user = relationship('User', single_parent=True, lazy="joined") diff --git a/rhodecode/model/notification.py b/rhodecode/model/notification.py --- a/rhodecode/model/notification.py +++ b/rhodecode/model/notification.py @@ -38,18 +38,43 @@ from rhodecode.model.db import Notificat class NotificationModel(BaseModel): - def create(self, subject, body, recipients): + def create(self, created_by, subject, body, recipients, + type_=Notification.TYPE_MESSAGE): + """ + + Creates notification of given type + + :param created_by: int, str or User instance. User who created this + notification + :param subject: + :param body: + :param recipients: list of int, str or User objects + :param type_: type of notification + """ if not getattr(recipients, '__iter__', False): raise Exception('recipients must be a list of iterable') - for x in recipients: - if not isinstance(x, User): - raise Exception('recipient is not instance of %s got %s' % \ - (User, type(x))) + created_by_obj = created_by + if not isinstance(created_by, User): + created_by_obj = User.get(created_by) - Notification.create(subject, body, recipients) + recipients_objs = [] + for u in recipients: + if isinstance(u, User): + recipients_objs.append(u) + elif isinstance(u, basestring): + recipients_objs.append(User.get_by_username(username=u)) + elif isinstance(u, int): + recipients_objs.append(User.get(u)) + else: + raise Exception('Unsupported recipient must be one of int,' + 'str or User object') + + Notification.create(created_by=created_by_obj, subject=subject, + body = body, recipients = recipients_objs, + type_=type_) def get_for_user(self, user_id): diff --git a/rhodecode/public/css/diff.css b/rhodecode/public/css/diff.css --- a/rhodecode/public/css/diff.css +++ b/rhodecode/public/css/diff.css @@ -7,6 +7,9 @@ div.diffblock { line-height: 100%; /* new */ line-height: 125%; + -webkit-border-radius: 6px 6px 0px 0px; + -moz-border-radius: 6px 6px 0px 0px; + border-radius: 6px 6px 0px 0px; } div.diffblock.margined{ @@ -19,8 +22,9 @@ div.diffblock .code-header{ padding:10px 0 10px 0; } div.diffblock .code-header div{ - margin-left:25px; + margin-left:10px; font-weight: bold; + font-size: 14px; } div.diffblock .code-body{ background: #FFFFFF; diff --git a/rhodecode/templates/admin/users/notifications.html b/rhodecode/templates/admin/users/notifications.html --- a/rhodecode/templates/admin/users/notifications.html +++ b/rhodecode/templates/admin/users/notifications.html @@ -18,11 +18,21 @@
${self.breadcrumbs()} +
- % for notification in c.notifications: - ${notification.title} + % if c.notifications: + %for notification in c.notifications: +
+

${notification.subject}

+
${h.rst(notification.body)}
+
+ %endfor %else:
${_('No notifications here yet')}
- %endfor + %endif diff --git a/rhodecode/templates/changeset/changeset.html b/rhodecode/templates/changeset/changeset.html --- a/rhodecode/templates/changeset/changeset.html +++ b/rhodecode/templates/changeset/changeset.html @@ -34,12 +34,12 @@
- ${_('Changeset')} - r${c.changeset.revision}:${h.short_id(c.changeset.raw_id)} - » ${h.link_to(_('raw diff'), + ${h.link_to(_('raw diff'), h.url('raw_changeset_home',repo_name=c.repo_name,revision=c.changeset.raw_id,diff='show'))} » ${h.link_to(_('download diff'), h.url('raw_changeset_home',repo_name=c.repo_name,revision=c.changeset.raw_id,diff='download'))} -
+
${len(c.comments)} comment(s) (${c.inline_cnt} ${_('inline')})
+