37 """ |
37 """ |
38 id = 'recipients_finder' |
38 id = 'recipients_finder' |
39 __select__ = yes() |
39 __select__ = yes() |
40 user_rql = ('Any X,E,A WHERE X is CWUser, X in_state S, S name "activated",' |
40 user_rql = ('Any X,E,A WHERE X is CWUser, X in_state S, S name "activated",' |
41 'X primary_email E, E address A') |
41 'X primary_email E, E address A') |
42 |
42 |
43 def recipients(self): |
43 def recipients(self): |
44 mode = self.config['default-recipients-mode'] |
44 mode = self.config['default-recipients-mode'] |
45 if mode == 'users': |
45 if mode == 'users': |
46 # use unsafe execute else we may don't have the right to see users |
46 # use unsafe execute else we may don't have the right to see users |
47 # to notify... |
47 # to notify... |
53 dests = zip(self.config['default-dest-addrs'], repeat(lang)) |
53 dests = zip(self.config['default-dest-addrs'], repeat(lang)) |
54 else: # mode == 'none' |
54 else: # mode == 'none' |
55 dests = [] |
55 dests = [] |
56 return dests |
56 return dests |
57 |
57 |
58 |
58 |
59 # hooks ####################################################################### |
59 # hooks ####################################################################### |
60 |
60 |
61 class RenderAndSendNotificationView(PreCommitOperation): |
61 class RenderAndSendNotificationView(PreCommitOperation): |
62 """delay rendering of notification view until precommit""" |
62 """delay rendering of notification view until precommit""" |
63 def precommit_event(self): |
63 def precommit_event(self): |
64 if self.view.rset[0][0] in self.session.query_data('pendingeids', ()): |
64 if self.view.rset[0][0] in self.session.query_data('pendingeids', ()): |
65 return # entity added and deleted in the same transaction |
65 return # entity added and deleted in the same transaction |
66 self.view.render_and_send(**getattr(self, 'viewargs', {})) |
66 self.view.render_and_send(**getattr(self, 'viewargs', {})) |
67 |
67 |
68 class StatusChangeHook(Hook): |
68 class StatusChangeHook(Hook): |
69 """notify when a workflowable entity has its state modified""" |
69 """notify when a workflowable entity has its state modified""" |
70 events = ('after_add_entity',) |
70 events = ('after_add_entity',) |
71 accepts = ('TrInfo',) |
71 accepts = ('TrInfo',) |
72 |
72 |
73 def call(self, session, entity): |
73 def call(self, session, entity): |
74 if not entity.from_state: # not a transition |
74 if not entity.from_state: # not a transition |
75 return |
75 return |
76 rset = entity.related('wf_info_for') |
76 rset = entity.related('wf_info_for') |
77 try: |
77 try: |
131 * set id and accepts attributes to match desired events and entity types |
131 * set id and accepts attributes to match desired events and entity types |
132 * set a content attribute to define the content of the email (unless you |
132 * set a content attribute to define the content of the email (unless you |
133 override call) |
133 override call) |
134 """ |
134 """ |
135 msgid_timestamp = True |
135 msgid_timestamp = True |
136 |
136 |
137 def recipients(self): |
137 def recipients(self): |
138 finder = self.vreg.select_component('recipients_finder', self.req, self.rset) |
138 finder = self.vreg.select_component('recipients_finder', self.req, self.rset) |
139 return finder.recipients() |
139 return finder.recipients() |
140 |
140 |
141 def subject(self): |
141 def subject(self): |
142 entity = self.entity(0, 0) |
142 entity = self.entity(0, 0) |
143 subject = self.req._(self.message) |
143 subject = self.req._(self.message) |
144 etype = entity.dc_type() |
144 etype = entity.dc_type() |
145 eid = entity.eid |
145 eid = entity.eid |
148 |
148 |
149 def user_login(self): |
149 def user_login(self): |
150 # req is actually a session (we are on the server side), and we have to |
150 # req is actually a session (we are on the server side), and we have to |
151 # prevent nested internal session |
151 # prevent nested internal session |
152 return self.req.actual_session().user.login |
152 return self.req.actual_session().user.login |
153 |
153 |
154 def context(self, **kwargs): |
154 def context(self, **kwargs): |
155 entity = self.entity(0, 0) |
155 entity = self.entity(0, 0) |
156 for key, val in kwargs.iteritems(): |
156 for key, val in kwargs.iteritems(): |
157 if val and isinstance(val, unicode) and val.strip(): |
157 if val and isinstance(val, unicode) and val.strip(): |
158 kwargs[key] = self.req._(val) |
158 kwargs[key] = self.req._(val) |
160 'eid': entity.eid, |
160 'eid': entity.eid, |
161 'etype': entity.dc_type(), |
161 'etype': entity.dc_type(), |
162 'url': entity.absolute_url(), |
162 'url': entity.absolute_url(), |
163 'title': entity.dc_long_title(),}) |
163 'title': entity.dc_long_title(),}) |
164 return kwargs |
164 return kwargs |
165 |
165 |
166 def cell_call(self, row, col=0, **kwargs): |
166 def cell_call(self, row, col=0, **kwargs): |
167 self.w(self.req._(self.content) % self.context(**kwargs)) |
167 self.w(self.req._(self.content) % self.context(**kwargs)) |
168 |
168 |
169 def construct_message_id(self, eid): |
169 def construct_message_id(self, eid): |
170 return construct_message_id(self.config.appid, eid, self.msgid_timestamp) |
170 return construct_message_id(self.config.appid, eid, self.msgid_timestamp) |
235 except: |
235 except: |
236 return None |
236 return None |
237 if appid != fromappid or host != gethostname(): |
237 if appid != fromappid or host != gethostname(): |
238 return None |
238 return None |
239 return values |
239 return values |
240 |
240 |
241 |
241 |
242 class StatusChangeMixIn(object): |
242 class StatusChangeMixIn(object): |
243 id = 'notif_status_change' |
243 id = 'notif_status_change' |
244 msgid_timestamp = True |
244 msgid_timestamp = True |
245 message = _('status changed') |
245 message = _('status changed') |
261 |
261 |
262 # XXX should be based on dc_title/dc_description, no? |
262 # XXX should be based on dc_title/dc_description, no? |
263 |
263 |
264 class ContentAddedView(NotificationView): |
264 class ContentAddedView(NotificationView): |
265 __abstract__ = True |
265 __abstract__ = True |
266 id = 'notif_after_add_entity' |
266 id = 'notif_after_add_entity' |
267 msgid_timestamp = False |
267 msgid_timestamp = False |
268 message = _('new') |
268 message = _('new') |
269 content = """ |
269 content = """ |
270 %(title)s |
270 %(title)s |
271 |
271 |
272 %(content)s |
272 %(content)s |
273 |
273 |
274 url: %(url)s |
274 url: %(url)s |
275 """ |
275 """ |
276 |
276 |
277 def context(self, **kwargs): |
277 def context(self, **kwargs): |
278 entity = self.entity(0, 0) |
278 entity = self.entity(0, 0) |
279 content = entity.printable_value(self.content_attr, format='text/plain') |
279 content = entity.printable_value(self.content_attr, format='text/plain') |
280 if content: |
280 if content: |
281 contentformat = getattr(entity, self.content_attr + '_format', 'text/rest') |
281 contentformat = getattr(entity, self.content_attr + '_format', 'text/rest') |
282 content = normalize_text(content, 80, rest=contentformat=='text/rest') |
282 content = normalize_text(content, 80, rest=contentformat=='text/rest') |
283 return super(ContentAddedView, self).context(content=content, **kwargs) |
283 return super(ContentAddedView, self).context(content=content, **kwargs) |
284 |
284 |
285 def subject(self): |
285 def subject(self): |
286 entity = self.entity(0, 0) |
286 entity = self.entity(0, 0) |
287 return u'%s #%s (%s)' % (self.req.__('New %s' % entity.e_schema), |
287 return u'%s #%s (%s)' % (self.req.__('New %s' % entity.e_schema), |
288 entity.eid, self.user_login()) |
288 entity.eid, self.user_login()) |
289 |
289 |
290 NormalizedTextView = class_renamed('NormalizedTextView', ContentAddedView) |
290 NormalizedTextView = class_renamed('NormalizedTextView', ContentAddedView) |
291 |
|
292 class CardAddedView(ContentAddedView): |
|
293 """get notified from new cards""" |
|
294 __select__ = implements('Card') |
|
295 content_attr = 'synopsis' |
|
296 |
|
297 |
|