##// END OF EJS Templates
notification fixes and improvements
marcink -
r1703:f23828b0 beta
parent child Browse files
Show More
@@ -28,8 +28,9 import logging
28 28 import traceback
29 29
30 30 from rhodecode.model import BaseModel
31 from rhodecode.model.db import ChangesetComment
31 from rhodecode.model.db import ChangesetComment, User, Notification
32 32 from sqlalchemy.util.compat import defaultdict
33 from rhodecode.model.notification import NotificationModel
33 34
34 35 log = logging.getLogger(__name__)
35 36
@@ -60,6 +61,17 class ChangesetCommentsModel(BaseModel):
60 61
61 62 self.sa.add(comment)
62 63 self.sa.commit()
64
65 # make notification
66 usr = User.get(user_id)
67 subj = 'User %s commented on %s' % (usr.username, revision)
68 body = text
69 recipients = ChangesetComment.get_users(revision=revision)
70 NotificationModel().create(created_by=user_id, subject=subj,
71 body = body, recipients = recipients,
72 type_ = Notification.TYPE_CHANGESET_COMMENT)
73
74
63 75 return comment
64 76
65 77 def delete(self, comment_id):
@@ -1109,18 +1109,40 class ChangesetComment(Base, BaseModel):
1109 1109 text = Column('text', Unicode(25000), nullable=False)
1110 1110 modified_at = Column('modified_at', DateTime(), nullable=False, default=datetime.datetime.now)
1111 1111
1112 author = relationship('User')
1112 author = relationship('User', lazy='joined')
1113 1113 repo = relationship('Repository')
1114 1114
1115 1115
1116 @classmethod
1117 def get_users(cls, revision):
1118 """
1119 Returns user associated with this changesetComment. ie those
1120 who actually commented
1121
1122 :param cls:
1123 :param revision:
1124 """
1125 return Session.query(User)\
1126 .filter(cls.revision == revision)\
1127 .join(ChangesetComment.author).all()
1128
1129
1116 1130 class Notification(Base, BaseModel):
1117 1131 __tablename__ = 'notifications'
1118 1132 __table_args__ = ({'extend_existing':True})
1133
1134 TYPE_CHANGESET_COMMENT = 'cs_comment'
1135 TYPE_MESSAGE = 'message'
1136 TYPE_MENTION = 'mention'
1137
1119 1138 notification_id = Column('notification_id', Integer(), nullable=False, primary_key=True)
1120 1139 subject = Column('subject', Unicode(512), nullable=True)
1121 1140 body = Column('body', Unicode(50000), nullable=True)
1141 created_by = Column("created_by", Integer(), ForeignKey('users.user_id'), nullable=True)
1122 1142 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1143 type_ = Column('type', Unicode(256))
1123 1144
1145 create_by_user = relationship('User')
1124 1146 user_notifications = relationship('UserNotification',
1125 1147 primaryjoin = 'Notification.notification_id==UserNotification.notification_id',
1126 1148 cascade = "all, delete, delete-orphan")
@@ -1131,10 +1153,15 class Notification(Base, BaseModel):
1131 1153 .filter(UserNotification.notification == self).all()]
1132 1154
1133 1155 @classmethod
1134 def create(cls, subject, body, recipients):
1156 def create(cls, created_by, subject, body, recipients, type_=None):
1157 if type_ is None:
1158 type_ = Notification.TYPE_MESSAGE
1159
1135 1160 notification = cls()
1161 notification.create_by_user = created_by
1136 1162 notification.subject = subject
1137 1163 notification.body = body
1164 notification.type_ = type_
1138 1165 Session.add(notification)
1139 1166 for u in recipients:
1140 1167 u.notifications.append(notification)
@@ -1143,10 +1170,12 class Notification(Base, BaseModel):
1143 1170
1144 1171 class UserNotification(Base, BaseModel):
1145 1172 __tablename__ = 'user_to_notification'
1146 __table_args__ = ({'extend_existing':True})
1173 __table_args__ = (UniqueConstraint('user_id', 'notification_id'),
1174 {'extend_existing':True})
1147 1175 user_to_notification_id = Column("user_to_notification_id", Integer(), nullable=False, unique=True, primary_key=True)
1148 1176 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
1149 1177 notification_id = Column("notification_id", Integer(), ForeignKey('notifications.notification_id'), nullable=False)
1178 read = Column('read', Boolean, default=False)
1150 1179 sent_on = Column('sent_on', DateTime(timezone=False), nullable=True, unique=None)
1151 1180
1152 1181 user = relationship('User', single_parent=True, lazy="joined")
@@ -38,18 +38,43 from rhodecode.model.db import Notificat
38 38
39 39 class NotificationModel(BaseModel):
40 40
41 def create(self, subject, body, recipients):
41 def create(self, created_by, subject, body, recipients,
42 type_=Notification.TYPE_MESSAGE):
43 """
44
45 Creates notification of given type
46
47 :param created_by: int, str or User instance. User who created this
48 notification
49 :param subject:
50 :param body:
51 :param recipients: list of int, str or User objects
52 :param type_: type of notification
53 """
42 54
43 55 if not getattr(recipients, '__iter__', False):
44 56 raise Exception('recipients must be a list of iterable')
45 57
46 for x in recipients:
47 if not isinstance(x, User):
48 raise Exception('recipient is not instance of %s got %s' % \
49 (User, type(x)))
58 created_by_obj = created_by
59 if not isinstance(created_by, User):
60 created_by_obj = User.get(created_by)
50 61
51 62
52 Notification.create(subject, body, recipients)
63 recipients_objs = []
64 for u in recipients:
65 if isinstance(u, User):
66 recipients_objs.append(u)
67 elif isinstance(u, basestring):
68 recipients_objs.append(User.get_by_username(username=u))
69 elif isinstance(u, int):
70 recipients_objs.append(User.get(u))
71 else:
72 raise Exception('Unsupported recipient must be one of int,'
73 'str or User object')
74
75 Notification.create(created_by=created_by_obj, subject=subject,
76 body = body, recipients = recipients_objs,
77 type_=type_)
53 78
54 79
55 80 def get_for_user(self, user_id):
@@ -7,6 +7,9 div.diffblock {
7 7 line-height: 100%;
8 8 /* new */
9 9 line-height: 125%;
10 -webkit-border-radius: 6px 6px 0px 0px;
11 -moz-border-radius: 6px 6px 0px 0px;
12 border-radius: 6px 6px 0px 0px;
10 13 }
11 14
12 15 div.diffblock.margined{
@@ -19,8 +22,9 div.diffblock .code-header{
19 22 padding:10px 0 10px 0;
20 23 }
21 24 div.diffblock .code-header div{
22 margin-left:25px;
25 margin-left:10px;
23 26 font-weight: bold;
27 font-size: 14px;
24 28 }
25 29 div.diffblock .code-body{
26 30 background: #FFFFFF;
@@ -18,11 +18,21
18 18 <!-- box / title -->
19 19 <div class="title">
20 20 ${self.breadcrumbs()}
21 <ul class="links">
22 <li>
23 <span style="text-transform: uppercase;"><a href="#">${_('Compose message')}</a></span>
24 </li>
25 </ul>
21 26 </div>
22 % for notification in c.notifications:
23 ${notification.title}
27 % if c.notifications:
28 %for notification in c.notifications:
29 <div class="table">
30 <h4>${notification.subject}</h4>
31 <div>${h.rst(notification.body)}</div>
32 </div>
33 %endfor
24 34 %else:
25 35 <div class="table">${_('No notifications here yet')}</div>
26 %endfor
36 %endif
27 37 </div>
28 38 </%def>
@@ -34,12 +34,12
34 34 <div class="diffblock">
35 35 <div class="code-header">
36 36 <div>
37 ${_('Changeset')} - r${c.changeset.revision}:${h.short_id(c.changeset.raw_id)}
38 &raquo; <span>${h.link_to(_('raw diff'),
37 <span>${h.link_to(_('raw diff'),
39 38 h.url('raw_changeset_home',repo_name=c.repo_name,revision=c.changeset.raw_id,diff='show'))}</span>
40 39 &raquo; <span>${h.link_to(_('download diff'),
41 40 h.url('raw_changeset_home',repo_name=c.repo_name,revision=c.changeset.raw_id,diff='download'))}</span>
42 </div>
41 <div class="comments-number" style="float:right;padding-right:5px">${len(c.comments)} comment(s) (${c.inline_cnt} ${_('inline')})</div>
42 </div>
43 43 </div>
44 44 </div>
45 45 <div id="changeset_content">
General Comments 0
You need to be logged in to leave comments. Login now