changeset 1703:f23828b00b21 beta

notification fixes and improvements
author Marcin Kuzminski <marcin@python-works.com>
date Sun, 20 Nov 2011 22:26:55 +0200
parents 8cb7f5c4d494
children 3efc47f59639
files rhodecode/model/comment.py rhodecode/model/db.py rhodecode/model/notification.py rhodecode/public/css/diff.css rhodecode/templates/admin/users/notifications.html rhodecode/templates/changeset/changeset.html
diffstat 6 files changed, 97 insertions(+), 17 deletions(-) [+]
line wrap: on
line diff
--- a/rhodecode/model/comment.py	Sun Nov 20 01:53:00 2011 +0200
+++ b/rhodecode/model/comment.py	Sun Nov 20 22:26:55 2011 +0200
@@ -28,8 +28,9 @@
 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 @@
 
             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):
--- a/rhodecode/model/db.py	Sun Nov 20 01:53:00 2011 +0200
+++ b/rhodecode/model/db.py	Sun Nov 20 22:26:55 2011 +0200
@@ -1109,18 +1109,40 @@
     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 @@
                 .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 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")
--- a/rhodecode/model/notification.py	Sun Nov 20 01:53:00 2011 +0200
+++ b/rhodecode/model/notification.py	Sun Nov 20 22:26:55 2011 +0200
@@ -38,18 +38,43 @@
 
 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):
--- a/rhodecode/public/css/diff.css	Sun Nov 20 01:53:00 2011 +0200
+++ b/rhodecode/public/css/diff.css	Sun Nov 20 22:26:55 2011 +0200
@@ -7,6 +7,9 @@
     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 @@
 	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;
--- a/rhodecode/templates/admin/users/notifications.html	Sun Nov 20 01:53:00 2011 +0200
+++ b/rhodecode/templates/admin/users/notifications.html	Sun Nov 20 22:26:55 2011 +0200
@@ -18,11 +18,21 @@
     <!-- box / title -->
     <div class="title">
         ${self.breadcrumbs()}       
+        <ul class="links">
+            <li>
+              <span style="text-transform: uppercase;"><a href="#">${_('Compose message')}</a></span>
+            </li>          
+        </ul>            
     </div>
-    % for notification in c.notifications:
-        ${notification.title}
+    % if c.notifications:
+      %for notification in c.notifications:
+          <div class="table">
+            <h4>${notification.subject}</h4>
+            <div>${h.rst(notification.body)}</div>
+          </div>
+      %endfor
     %else:
         <div class="table">${_('No notifications here yet')}</div>
-    %endfor
+    %endif
 </div>    
 </%def>  
--- a/rhodecode/templates/changeset/changeset.html	Sun Nov 20 01:53:00 2011 +0200
+++ b/rhodecode/templates/changeset/changeset.html	Sun Nov 20 22:26:55 2011 +0200
@@ -34,12 +34,12 @@
 		<div class="diffblock">
 			<div class="code-header">
 				<div>
-				${_('Changeset')} - r${c.changeset.revision}:${h.short_id(c.changeset.raw_id)}
-				 &raquo; <span>${h.link_to(_('raw diff'),
+                <span>${h.link_to(_('raw diff'),
 				h.url('raw_changeset_home',repo_name=c.repo_name,revision=c.changeset.raw_id,diff='show'))}</span>
 				 &raquo; <span>${h.link_to(_('download diff'),
 				h.url('raw_changeset_home',repo_name=c.repo_name,revision=c.changeset.raw_id,diff='download'))}</span>
-				</div>
+				<div class="comments-number" style="float:right;padding-right:5px">${len(c.comments)} comment(s) (${c.inline_cnt} ${_('inline')})</div>
+                </div>
 			</div>
 		</div>
 	    <div id="changeset_content">