Révision e008d4d6
Ajouté par Frédéric Péters il y a plus de 10 ans
extra/modules/admin.ptl | ||
---|---|---|
1 |
import os |
|
2 |
|
|
3 |
from quixote import get_publisher, redirect |
|
4 |
from quixote.directory import Directory |
|
5 |
|
|
6 |
import wcs.admin.root |
|
7 |
import wcs.root |
|
8 |
from wcs.admin.menu import * |
|
9 |
from wcs.roles import get_user_roles |
|
10 |
|
|
11 |
from qommon import errors, get_cfg |
|
12 |
from qommon.form import * |
|
13 |
|
|
14 |
from wcs.formdef import FormDef |
|
15 |
from wcs.categories import Category |
|
16 |
|
|
17 |
from events import get_default_event_tags |
|
18 |
import re |
|
19 |
from abelium_domino_ui import AbeliumDominoDirectory |
|
20 |
|
|
21 |
class AdminRootDirectory(wcs.admin.root.RootDirectory): |
|
22 |
def __init__(self): |
|
23 |
self._q_exports = wcs.admin.root.RootDirectory._q_exports |
|
24 |
self.menu_items[-1] = ('/', N_('Au Quotidien')) |
|
25 |
|
|
26 |
def _q_index [html] (self): |
|
27 |
from wcs.admin.menu import html_top |
|
28 |
html_top('/') |
|
29 |
'<p>' |
|
30 |
_('Welcome on Au Quotidien administration interface') |
|
31 |
'</p>' |
|
32 |
# XXX: add links to documentation, "this is based on w.c.s., a free |
|
33 |
# software project", etc. |
|
34 |
|
|
35 |
class PanelDirectory(Directory): |
|
36 |
_q_exports = ['', 'update', 'announces', 'permissions', 'event_keywords', |
|
37 |
'announce_themes', 'drupal', 'ezldap', 'strongbox', 'clicrdv', 'domino'] |
|
38 |
label = N_('Control Panel') |
|
39 |
|
|
40 |
domino = AbeliumDominoDirectory() |
|
41 |
|
|
42 |
def _q_index [html] (self): |
|
43 |
html_top('panel', _('Control Panel')) |
|
44 |
get_response().breadcrumb.append(('panel', _('Control Panel'))) |
|
45 |
|
|
46 |
'<ul>' |
|
47 |
'<li><a href="announces">%s</a></li>' % _('Announces Options') |
|
48 |
'<li><a href="permissions">%s</a></li>' % _('Permissions') |
|
49 |
'<li><a href="event_keywords">%s</a></li>' % _('Event Keywords') |
|
50 |
'<li><a href="announce_themes">%s</a></li>' % _('Announce Themes') |
|
51 |
if get_publisher().has_site_option('drupal'): |
|
52 |
'<li><a href="drupal">%s</a></li>' % _('Drupal Integration') |
|
53 |
if get_publisher().has_site_option('ezldap'): |
|
54 |
'<li><a href="ezldap">%s</a></li>' % _('eZ publish / LDAP Integration') |
|
55 |
if get_publisher().has_site_option('strongbox'): |
|
56 |
'<li><a href="strongbox">%s</a></li>' % _('Strongbox Support') |
|
57 |
if get_publisher().has_site_option('clicrdv'): |
|
58 |
'<li><a href="clicrdv">%s</a></li>' % _('ClicRDV Integration') |
|
59 |
if get_publisher().has_site_option('domino'): |
|
60 |
'<li><a href="domino">%s</a></li>' % _('Abelium Domino Integration') |
|
61 |
'</ul>' |
|
62 |
|
|
63 |
def _verify_mask(self, form): |
|
64 |
if form.is_submitted(): |
|
65 |
if not re.match("[0-9Xx]*$", form.get('mobile_mask') or ''): |
|
66 |
form.set_error('mobile_mask', _('Invalid value')) |
|
67 |
else: |
|
68 |
string_value = form.get_widget('mobile_mask').value |
|
69 |
if string_value: |
|
70 |
form.get_widget('mobile_mask').value = string_value.upper() |
|
71 |
|
|
72 |
def announces [html] (self): |
|
73 |
announces_cfg = get_cfg('announces', {}) |
|
74 |
sms_cfg = get_cfg('sms', {}) |
|
75 |
form = Form(enctype='multipart/form-data') |
|
76 |
hint = "" |
|
77 |
if sms_cfg.get('mode','') in ("none",""): |
|
78 |
hint = htmltext(_('You must also <a href="%s">configure your SMS provider</a>') % "../settings/sms") |
|
79 |
|
|
80 |
form.add(CheckboxWidget, 'sms_support', title = _('SMS support'), |
|
81 |
hint = hint, value = announces_cfg.get('sms_support', 0)) |
|
82 |
form.add(StringWidget, 'mobile_mask', title = _('Mask for mobile numbers'), |
|
83 |
hint = _('example: 06XXXXXXXX'), |
|
84 |
value = announces_cfg.get('mobile_mask','')) |
|
85 |
form.add_submit('submit', _('Submit')) |
|
86 |
form.add_submit('cancel', _('Cancel')) |
|
87 |
|
|
88 |
self._verify_mask(form) |
|
89 |
|
|
90 |
if form.get_widget('cancel').parse(): |
|
91 |
return redirect('.') |
|
92 |
|
|
93 |
if not form.is_submitted() or form.has_errors(): |
|
94 |
get_response().breadcrumb.append(('panel', _('Control Panel'))) |
|
95 |
get_response().breadcrumb.append(('announces', _('Announces Options'))) |
|
96 |
html_top('panel', _('Announces Options')) |
|
97 |
'<h2>%s</h2>' % _('Announces Options') |
|
98 |
form.render() |
|
99 |
else: |
|
100 |
from wcs.admin.settings import cfg_submit |
|
101 |
cfg_submit(form, 'announces', ('sms_support','mobile_mask')) |
|
102 |
return redirect('.') |
|
103 |
|
|
104 |
def permissions [html] (self): |
|
105 |
permissions_cfg = get_cfg('aq-permissions', {}) |
|
106 |
form = Form(enctype='multipart/form-data') |
|
107 |
form.add(SingleSelectWidget, 'forms', title = _('Admin role for forms'), |
|
108 |
value = permissions_cfg.get('forms', None), |
|
109 |
options = [(None, _('Nobody'))] + get_user_roles()) |
|
110 |
form.add(SingleSelectWidget, 'events', title = _('Admin role for events'), |
|
111 |
value = permissions_cfg.get('events', None), |
|
112 |
options = [(None, _('Nobody'))] + get_user_roles()) |
|
113 |
form.add(SingleSelectWidget, 'links', title = _('Admin role for links'), |
|
114 |
value = permissions_cfg.get('links', None), |
|
115 |
options = [(None, _('Nobody'))] + get_user_roles()) |
|
116 |
form.add(SingleSelectWidget, 'announces', title = _('Admin role for announces'), |
|
117 |
value = permissions_cfg.get('announces', None), |
|
118 |
options = [(None, _('Nobody'))] + get_user_roles()) |
|
119 |
form.add(SingleSelectWidget, 'payments', title = _('Admin role for payments'), |
|
120 |
value = permissions_cfg.get('payments', None), |
|
121 |
options = [(None, _('Nobody'))] + get_user_roles()) |
|
122 |
form.add(SingleSelectWidget, 'strongbox', title = _('Admin role for strongbox'), |
|
123 |
value = permissions_cfg.get('strongbox', None), |
|
124 |
options = [(None, _('Nobody'))] + get_user_roles()) |
|
125 |
form.add_submit('submit', _('Submit')) |
|
126 |
form.add_submit('cancel', _('Cancel')) |
|
127 |
|
|
128 |
if form.get_widget('cancel').parse(): |
|
129 |
return redirect('.') |
|
130 |
|
|
131 |
if not form.is_submitted() or form.has_errors(): |
|
132 |
get_response().breadcrumb.append(('panel', _('Control Panel'))) |
|
133 |
get_response().breadcrumb.append(('permissions', _('Permissions'))) |
|
134 |
html_top('panel', _('Permissions')) |
|
135 |
'<h2>%s</h2>' % _('Permissions') |
|
136 |
form.render() |
|
137 |
else: |
|
138 |
from wcs.admin.settings import cfg_submit |
|
139 |
cfg_submit(form, 'aq-permissions', |
|
140 |
('forms', 'events', 'links', 'announces', 'payments', 'strongbox')) |
|
141 |
return redirect('.') |
|
142 |
|
|
143 |
|
|
144 |
def event_keywords [html] (self): |
|
145 |
misc_cfg = get_cfg('misc', {}) |
|
146 |
form = Form(enctype='multipart/form-data') |
|
147 |
form.add(WidgetList, 'event_tags', title = _('Event Keywords'), |
|
148 |
value = misc_cfg.get('event_tags', get_default_event_tags()), |
|
149 |
elemnt_type = StringWidget, |
|
150 |
add_element_label = _('Add Keyword'), |
|
151 |
element_kwargs = {str('render_br'): False, str('size'): 30}) |
|
152 |
|
|
153 |
form.add_submit('submit', _('Submit')) |
|
154 |
form.add_submit('cancel', _('Cancel')) |
|
155 |
|
|
156 |
if form.get_widget('cancel').parse(): |
|
157 |
return redirect('.') |
|
158 |
|
|
159 |
if not form.is_submitted() or form.has_errors(): |
|
160 |
get_response().breadcrumb.append(('panel', _('Control Panel'))) |
|
161 |
get_response().breadcrumb.append(('event_keywords', _('Event Keywords'))) |
|
162 |
html_top('panel', _('Event Keywords')) |
|
163 |
'<h2>%s</h2>' % _('Event Keywords') |
|
164 |
form.render() |
|
165 |
else: |
|
166 |
from wcs.admin.settings import cfg_submit |
|
167 |
cfg_submit(form, 'misc', ('event_tags',)) |
|
168 |
return redirect('.') |
|
169 |
|
|
170 |
def announce_themes [html] (self): |
|
171 |
misc_cfg = get_cfg('misc', {}) |
|
172 |
form = Form(enctype='multipart/form-data') |
|
173 |
form.add(WidgetList, 'announce_themes', title = _('Announce Themes'), |
|
174 |
value = misc_cfg.get('announce_themes', []), |
|
175 |
elemnt_type = StringWidget, |
|
176 |
add_element_label = _('Add Theme'), |
|
177 |
element_kwargs = {str('render_br'): False, str('size'): 30}) |
|
178 |
|
|
179 |
form.add_submit('submit', _('Submit')) |
|
180 |
form.add_submit('cancel', _('Cancel')) |
|
181 |
|
|
182 |
if form.get_widget('cancel').parse(): |
|
183 |
return redirect('.') |
|
184 |
|
|
185 |
if not form.is_submitted() or form.has_errors(): |
|
186 |
get_response().breadcrumb.append(('panel', _('Control Panel'))) |
|
187 |
get_response().breadcrumb.append(('announce_themes', _('Announce Themes'))) |
|
188 |
html_top('panel', _('Announce Themes')) |
|
189 |
'<h2>%s</h2>' % _('Announce Themes') |
|
190 |
form.render() |
|
191 |
else: |
|
192 |
from wcs.admin.settings import cfg_submit |
|
193 |
cfg_submit(form, 'misc', ('announce_themes',)) |
|
194 |
return redirect('.') |
|
195 |
|
|
196 |
def drupal [html] (self): |
|
197 |
if not get_publisher().has_site_option('drupal'): |
|
198 |
raise errors.TraversalError() |
|
199 |
misc_cfg = get_cfg('misc', {}) |
|
200 |
form = Form(enctype='multipart/form-data') |
|
201 |
form.add(StringWidget, 'aq-drupal-ip', title=_('IP Address of Drupal'), |
|
202 |
value=misc_cfg.get('aq-drupal-ip'), required=False, |
|
203 |
hint=_('Empty for disabled authentication')) |
|
204 |
|
|
205 |
form.add_submit('submit', _('Submit')) |
|
206 |
form.add_submit('cancel', _('Cancel')) |
|
207 |
|
|
208 |
if form.get_widget('cancel').parse(): |
|
209 |
return redirect('.') |
|
210 |
|
|
211 |
if not form.is_submitted() or form.has_errors(): |
|
212 |
get_response().breadcrumb.append(('panel', _('Control Panel'))) |
|
213 |
get_response().breadcrumb.append(('drupal', _('Drupal Integration'))) |
|
214 |
html_top('panel', _('Drupal Integration')) |
|
215 |
'<h2>%s</h2>' % _('Drupal Integration') |
|
216 |
form.render() |
|
217 |
else: |
|
218 |
from wcs.admin.settings import cfg_submit |
|
219 |
cfg_submit(form, 'misc', ('aq-drupal-ip',)) |
|
220 |
return redirect('.') |
|
221 |
|
|
222 |
def ezldap [html] (self): |
|
223 |
if not get_publisher().has_site_option('ezldap'): |
|
224 |
raise errors.TraversalError() |
|
225 |
misc_cfg = get_cfg('misc', {}) |
|
226 |
form = Form(enctype='multipart/form-data') |
|
227 |
form.add(StringWidget, 'aq-ezldap-url', title=_('LDAP URL'), |
|
228 |
value=misc_cfg.get('aq-ezldap-url'), required=False, |
|
229 |
hint=_('Empty to disable eZ/LDAP support')) |
|
230 |
form.add(StringWidget, 'aq-ezldap-binddn', title=_('LDAP Admin Bind DN'), |
|
231 |
value=misc_cfg.get('aq-ezldap-binddn'), required=False) |
|
232 |
form.add(PasswordWidget, 'aq-ezldap-bindpassword', title=_('LDAP Admin Bind Password'), |
|
233 |
value=misc_cfg.get('aq-ezldap-bindpassword'), required=False) |
|
234 |
form.add(StringWidget, 'aq-ezldap-basedn', title=_('LDAP Base DN'), |
|
235 |
value=misc_cfg.get('aq-ezldap-basedn'), required=False) |
|
236 |
form.add(StringWidget, 'aq-ezldap-dntemplate', title=_('LDAP DN Template'), |
|
237 |
value=misc_cfg.get('aq-ezldap-dntemplate'), required=False) |
|
238 |
form.add(StringWidget, 'aq-ezldap-ip', title=_('Use Auth-DN header only from this IP'), |
|
239 |
value=misc_cfg.get('aq-ezldap-ip'), required=False, |
|
240 |
hint=_('Empty to disable IP filtering')) |
|
241 |
|
|
242 |
form.add_submit('submit', _('Submit')) |
|
243 |
form.add_submit('cancel', _('Cancel')) |
|
244 |
|
|
245 |
if form.get_widget('cancel').parse(): |
|
246 |
return redirect('.') |
|
247 |
|
|
248 |
if not form.is_submitted() or form.has_errors(): |
|
249 |
get_response().breadcrumb.append(('panel', _('Control Panel'))) |
|
250 |
get_response().breadcrumb.append(('ezldap', _('eZ publish / LDAP Integration'))) |
|
251 |
html_top('panel', _('eZ publish / LDAP Integration')) |
|
252 |
'<h2>%s</h2>' % _('eZ publish / LDAP Integration') |
|
253 |
form.render() |
|
254 |
else: |
|
255 |
from wcs.admin.settings import cfg_submit |
|
256 |
cfg_submit(form, 'misc', ('aq-ezldap-url', |
|
257 |
'aq-ezldap-binddn', 'aq-ezldap-bindpassword', |
|
258 |
'aq-ezldap-basedn', 'aq-ezldap-dntemplate', |
|
259 |
'aq-ezldap-ip')) |
|
260 |
return redirect('.') |
|
261 |
|
|
262 |
def strongbox [html] (self): |
|
263 |
if not get_publisher().has_site_option('strongbox'): |
|
264 |
raise errors.TraversalError() |
|
265 |
misc_cfg = get_cfg('misc', {}) |
|
266 |
form = Form(enctype='multipart/form-data') |
|
267 |
form.add(CheckboxWidget, 'aq-strongbox', title=_('Strongbox Support'), |
|
268 |
value=misc_cfg.get('aq-strongbox'), required=False) |
|
269 |
|
|
270 |
form.add_submit('submit', _('Submit')) |
|
271 |
form.add_submit('cancel', _('Cancel')) |
|
272 |
|
|
273 |
if form.get_widget('cancel').parse(): |
|
274 |
return redirect('.') |
|
275 |
|
|
276 |
if not form.is_submitted() or form.has_errors(): |
|
277 |
get_response().breadcrumb.append(('panel', _('Control Panel'))) |
|
278 |
get_response().breadcrumb.append(('strongbox', _('Strongbox Support'))) |
|
279 |
html_top('panel', _('Strongbox Support')) |
|
280 |
'<h2>%s</h2>' % _('Strongbox Support') |
|
281 |
form.render() |
|
282 |
else: |
|
283 |
from wcs.admin.settings import cfg_submit |
|
284 |
cfg_submit(form, 'misc', ('aq-strongbox',)) |
|
285 |
return redirect('.') |
|
286 |
|
|
287 |
def clicrdv [html] (self): |
|
288 |
if not get_publisher().has_site_option('clicrdv'): |
|
289 |
raise errors.TraversalError() |
|
290 |
misc_cfg = get_cfg('misc', {}) |
|
291 |
form = Form(enctype='multipart/form-data') |
|
292 |
form.add(SingleSelectWidget, 'aq-clicrdv-server', title=_('ClicRDV Server'), |
|
293 |
value=misc_cfg.get('aq-clicrdv-server', 'sandbox.clicrdv.com'), required=True, |
|
294 |
options=[(str('www.clicrdv.com'), _('Production Server')), |
|
295 |
(str('sandbox.clicrdv.com'), _('Sandbox Server'))]) |
|
296 |
form.add(StringWidget, 'aq-clicrdv-api-key', title=_('API Key'), |
|
297 |
value=misc_cfg.get('aq-clicrdv-api-key'), required=False, |
|
298 |
size=40, hint=_('Empty to disable ClicRDV support')) |
|
299 |
form.add(StringWidget, 'aq-clicrdv-api-username', title=_('Username'), |
|
300 |
value=misc_cfg.get('aq-clicrdv-api-username'), required=False) |
|
301 |
form.add(StringWidget, 'aq-clicrdv-api-password', title=_('Password'), |
|
302 |
value=misc_cfg.get('aq-clicrdv-api-password'), required=False) |
|
303 |
|
|
304 |
form.add_submit('submit', _('Submit')) |
|
305 |
form.add_submit('cancel', _('Cancel')) |
|
306 |
|
|
307 |
if form.get_widget('cancel').parse(): |
|
308 |
return redirect('.') |
|
309 |
|
|
310 |
if not form.is_submitted() or form.has_errors(): |
|
311 |
get_response().breadcrumb.append(('panel', _('Control Panel'))) |
|
312 |
get_response().breadcrumb.append(('clicrdv', _('ClicRDV Integration'))) |
|
313 |
html_top('panel', _('ClicRDV Integration')) |
|
314 |
'<h2>%s</h2>' % _('ClicRDV Integration') |
|
315 |
form.render() |
|
316 |
_('Available Interventions: ') |
|
317 |
try: |
|
318 |
from clicrdv import get_all_intervention_sets |
|
319 |
intervention_sets = get_all_intervention_sets() |
|
320 |
'<ul>' |
|
321 |
for s in intervention_sets: |
|
322 |
'<li><strong>clicrdv_get_interventions_in_set(%s)</strong> - %s' % (s['id'], s['name']) |
|
323 |
'<ul>' |
|
324 |
for n, intervention in s['interventions']: |
|
325 |
'<li>%s (id: %s)</li>' % (intervention, n) |
|
326 |
'</ul></li>' |
|
327 |
'</ul>' |
|
328 |
except Exception, e: |
|
329 |
'<p>' |
|
330 |
_('Cannot access to ClicRDV service') |
|
331 |
' (%s)</p>' % str(e) |
|
332 |
else: |
|
333 |
from wcs.admin.settings import cfg_submit |
|
334 |
cfg_submit(form, 'misc', ('aq-clicrdv-server', |
|
335 |
'aq-clicrdv-api-key', |
|
336 |
'aq-clicrdv-api-username', |
|
337 |
'aq-clicrdv-api-password')) |
|
338 |
return redirect('.') |
|
339 |
|
|
340 |
|
|
341 |
AdminRootDirectory.register_page('panel', PanelDirectory()) |
|
342 |
|
|
343 |
import categories_admin |
|
344 |
|
extra/modules/admin.py | ||
---|---|---|
1 |
import os |
|
2 |
|
|
3 |
from quixote import get_publisher, redirect |
|
4 |
from quixote.directory import Directory |
|
5 |
from quixote.html import htmltext, TemplateIO |
|
6 |
|
|
7 |
import wcs.admin.root |
|
8 |
import wcs.root |
|
9 |
from wcs.admin.menu import * |
|
10 |
from wcs.roles import get_user_roles |
|
11 |
|
|
12 |
from qommon import errors, get_cfg |
|
13 |
from qommon.form import * |
|
14 |
|
|
15 |
from wcs.formdef import FormDef |
|
16 |
from wcs.categories import Category |
|
17 |
|
|
18 |
from events import get_default_event_tags |
|
19 |
import re |
|
20 |
from abelium_domino_ui import AbeliumDominoDirectory |
|
21 |
|
|
22 |
class AdminRootDirectory(wcs.admin.root.RootDirectory): |
|
23 |
def __init__(self): |
|
24 |
self._q_exports = wcs.admin.root.RootDirectory._q_exports |
|
25 |
self.menu_items[-1] = ('/', N_('Au Quotidien')) |
|
26 |
|
|
27 |
def _q_index(self): |
|
28 |
from wcs.admin.menu import html_top |
|
29 |
html_top('/') |
|
30 |
r = TemplateIO(html=True) |
|
31 |
r += htmltext('<p>%s</p>') % _('Welcome on Au Quotidien administration interface') |
|
32 |
# XXX: add links to documentation, "this is based on w.c.s., a free |
|
33 |
# software project", etc. |
|
34 |
return r.getvalue() |
|
35 |
|
|
36 |
|
|
37 |
class PanelDirectory(Directory): |
|
38 |
_q_exports = ['', 'update', 'announces', 'permissions', 'event_keywords', |
|
39 |
'announce_themes', 'drupal', 'ezldap', 'strongbox', 'clicrdv', 'domino'] |
|
40 |
label = N_('Control Panel') |
|
41 |
|
|
42 |
domino = AbeliumDominoDirectory() |
|
43 |
|
|
44 |
def _q_index(self): |
|
45 |
html_top('panel', _('Control Panel')) |
|
46 |
get_response().breadcrumb.append(('panel', _('Control Panel'))) |
|
47 |
|
|
48 |
r = TemplateIO(html=True) |
|
49 |
r += htmltext('<ul>') |
|
50 |
r += htmltext('<li><a href="announces">%s</a></li>') % _('Announces Options') |
|
51 |
r += htmltext('<li><a href="permissions">%s</a></li>') % _('Permissions') |
|
52 |
r += htmltext('<li><a href="event_keywords">%s</a></li>') % _('Event Keywords') |
|
53 |
r += htmltext('<li><a href="announce_themes">%s</a></li>') % _('Announce Themes') |
|
54 |
if get_publisher().has_site_option('drupal'): |
|
55 |
r += htmltext('<li><a href="drupal">%s</a></li>') % _('Drupal Integration') |
|
56 |
if get_publisher().has_site_option('ezldap'): |
|
57 |
r += htmltext('<li><a href="ezldap">%s</a></li>') % _('eZ publish / LDAP Integration') |
|
58 |
if get_publisher().has_site_option('strongbox'): |
|
59 |
r += htmltext('<li><a href="strongbox">%s</a></li>') % _('Strongbox Support') |
|
60 |
if get_publisher().has_site_option('clicrdv'): |
|
61 |
r += htmltext('<li><a href="clicrdv">%s</a></li>') % _('ClicRDV Integration') |
|
62 |
if get_publisher().has_site_option('domino'): |
|
63 |
r += htmltext('<li><a href="domino">%s</a></li>') % _('Abelium Domino Integration') |
|
64 |
r += htmltext('</ul>') |
|
65 |
return r.getvalue() |
|
66 |
|
|
67 |
def _verify_mask(self, form): |
|
68 |
if form.is_submitted(): |
|
69 |
if not re.match("[0-9Xx]*$", form.get('mobile_mask') or ''): |
|
70 |
form.set_error('mobile_mask', _('Invalid value')) |
|
71 |
else: |
|
72 |
string_value = form.get_widget('mobile_mask').value |
|
73 |
if string_value: |
|
74 |
form.get_widget('mobile_mask').value = string_value.upper() |
|
75 |
|
|
76 |
def announces(self): |
|
77 |
announces_cfg = get_cfg('announces', {}) |
|
78 |
sms_cfg = get_cfg('sms', {}) |
|
79 |
form = Form(enctype='multipart/form-data') |
|
80 |
hint = "" |
|
81 |
if sms_cfg.get('mode','') in ("none",""): |
|
82 |
hint = htmltext(_('You must also <a href="%s">configure your SMS provider</a>') % "../settings/sms") |
|
83 |
|
|
84 |
form.add(CheckboxWidget, 'sms_support', title = _('SMS support'), |
|
85 |
hint = hint, value = announces_cfg.get('sms_support', 0)) |
|
86 |
form.add(StringWidget, 'mobile_mask', title = _('Mask for mobile numbers'), |
|
87 |
hint = _('example: 06XXXXXXXX'), |
|
88 |
value = announces_cfg.get('mobile_mask','')) |
|
89 |
form.add_submit('submit', _('Submit')) |
|
90 |
form.add_submit('cancel', _('Cancel')) |
|
91 |
|
|
92 |
self._verify_mask(form) |
|
93 |
|
|
94 |
if form.get_widget('cancel').parse(): |
|
95 |
return redirect('.') |
|
96 |
|
|
97 |
if not form.is_submitted() or form.has_errors(): |
|
98 |
get_response().breadcrumb.append(('panel', _('Control Panel'))) |
|
99 |
get_response().breadcrumb.append(('announces', _('Announces Options'))) |
|
100 |
html_top('panel', _('Announces Options')) |
|
101 |
r = TemplateIO(html=True) |
|
102 |
r += htmltext('<h2>%s</h2>') % _('Announces Options') |
|
103 |
r += form.render() |
|
104 |
return r.getvalue() |
|
105 |
else: |
|
106 |
from wcs.admin.settings import cfg_submit |
|
107 |
cfg_submit(form, 'announces', ('sms_support','mobile_mask')) |
|
108 |
return redirect('.') |
|
109 |
|
|
110 |
def permissions(self): |
|
111 |
permissions_cfg = get_cfg('aq-permissions', {}) |
|
112 |
form = Form(enctype='multipart/form-data') |
|
113 |
form.add(SingleSelectWidget, 'forms', title = _('Admin role for forms'), |
|
114 |
value = permissions_cfg.get('forms', None), |
|
115 |
options = [(None, _('Nobody'))] + get_user_roles()) |
|
116 |
form.add(SingleSelectWidget, 'events', title = _('Admin role for events'), |
|
117 |
value = permissions_cfg.get('events', None), |
|
118 |
options = [(None, _('Nobody'))] + get_user_roles()) |
|
119 |
form.add(SingleSelectWidget, 'links', title = _('Admin role for links'), |
|
120 |
value = permissions_cfg.get('links', None), |
|
121 |
options = [(None, _('Nobody'))] + get_user_roles()) |
|
122 |
form.add(SingleSelectWidget, 'announces', title = _('Admin role for announces'), |
|
123 |
value = permissions_cfg.get('announces', None), |
|
124 |
options = [(None, _('Nobody'))] + get_user_roles()) |
|
125 |
form.add(SingleSelectWidget, 'payments', title = _('Admin role for payments'), |
|
126 |
value = permissions_cfg.get('payments', None), |
|
127 |
options = [(None, _('Nobody'))] + get_user_roles()) |
|
128 |
form.add(SingleSelectWidget, 'strongbox', title = _('Admin role for strongbox'), |
|
129 |
value = permissions_cfg.get('strongbox', None), |
|
130 |
options = [(None, _('Nobody'))] + get_user_roles()) |
|
131 |
form.add_submit('submit', _('Submit')) |
|
132 |
form.add_submit('cancel', _('Cancel')) |
|
133 |
|
|
134 |
if form.get_widget('cancel').parse(): |
|
135 |
return redirect('.') |
|
136 |
|
|
137 |
if not form.is_submitted() or form.has_errors(): |
|
138 |
get_response().breadcrumb.append(('panel', _('Control Panel'))) |
|
139 |
get_response().breadcrumb.append(('permissions', _('Permissions'))) |
|
140 |
html_top('panel', _('Permissions')) |
|
141 |
r = TemplateIO(html=True) |
|
142 |
r += htmltext('<h2>%s</h2>') % _('Permissions') |
|
143 |
r += form.render() |
|
144 |
return r.getvalue() |
|
145 |
else: |
|
146 |
from wcs.admin.settings import cfg_submit |
|
147 |
cfg_submit(form, 'aq-permissions', |
|
148 |
('forms', 'events', 'links', 'announces', 'payments', 'strongbox')) |
|
149 |
return redirect('.') |
|
150 |
|
|
151 |
def event_keywords(self): |
|
152 |
misc_cfg = get_cfg('misc', {}) |
|
153 |
form = Form(enctype='multipart/form-data') |
|
154 |
form.add(WidgetList, 'event_tags', title = _('Event Keywords'), |
|
155 |
value = misc_cfg.get('event_tags', get_default_event_tags()), |
|
156 |
elemnt_type = StringWidget, |
|
157 |
add_element_label = _('Add Keyword'), |
|
158 |
element_kwargs = {str('render_br'): False, str('size'): 30}) |
|
159 |
|
|
160 |
form.add_submit('submit', _('Submit')) |
|
161 |
form.add_submit('cancel', _('Cancel')) |
|
162 |
|
|
163 |
if form.get_widget('cancel').parse(): |
|
164 |
return redirect('.') |
|
165 |
|
|
166 |
if not form.is_submitted() or form.has_errors(): |
|
167 |
get_response().breadcrumb.append(('panel', _('Control Panel'))) |
|
168 |
get_response().breadcrumb.append(('event_keywords', _('Event Keywords'))) |
|
169 |
html_top('panel', _('Event Keywords')) |
|
170 |
r = TemplateIO(html=True) |
|
171 |
r += htmltext('<h2>%s</h2>') % _('Event Keywords') |
|
172 |
r += form.render() |
|
173 |
return r.getvalue() |
|
174 |
else: |
|
175 |
from wcs.admin.settings import cfg_submit |
|
176 |
cfg_submit(form, 'misc', ('event_tags',)) |
|
177 |
return redirect('.') |
|
178 |
|
|
179 |
def announce_themes(self): |
|
180 |
misc_cfg = get_cfg('misc', {}) |
|
181 |
form = Form(enctype='multipart/form-data') |
|
182 |
form.add(WidgetList, 'announce_themes', title = _('Announce Themes'), |
|
183 |
value = misc_cfg.get('announce_themes', []), |
|
184 |
elemnt_type = StringWidget, |
|
185 |
add_element_label = _('Add Theme'), |
|
186 |
element_kwargs = {str('render_br'): False, str('size'): 30}) |
|
187 |
|
|
188 |
form.add_submit('submit', _('Submit')) |
|
189 |
form.add_submit('cancel', _('Cancel')) |
|
190 |
|
|
191 |
if form.get_widget('cancel').parse(): |
|
192 |
return redirect('.') |
|
193 |
|
|
194 |
if not form.is_submitted() or form.has_errors(): |
|
195 |
get_response().breadcrumb.append(('panel', _('Control Panel'))) |
|
196 |
get_response().breadcrumb.append(('announce_themes', _('Announce Themes'))) |
|
197 |
html_top('panel', _('Announce Themes')) |
|
198 |
r = TemplateIO(html=True) |
|
199 |
r += htmltext('<h2>%s</h2>') % _('Announce Themes') |
|
200 |
r += form.render() |
|
201 |
return r.getvalue() |
|
202 |
else: |
|
203 |
from wcs.admin.settings import cfg_submit |
|
204 |
cfg_submit(form, 'misc', ('announce_themes',)) |
|
205 |
return redirect('.') |
|
206 |
|
|
207 |
def drupal(self): |
|
208 |
if not get_publisher().has_site_option('drupal'): |
|
209 |
raise errors.TraversalError() |
|
210 |
misc_cfg = get_cfg('misc', {}) |
|
211 |
form = Form(enctype='multipart/form-data') |
|
212 |
form.add(StringWidget, 'aq-drupal-ip', title=_('IP Address of Drupal'), |
|
213 |
value=misc_cfg.get('aq-drupal-ip'), required=False, |
|
214 |
hint=_('Empty for disabled authentication')) |
|
215 |
|
|
216 |
form.add_submit('submit', _('Submit')) |
|
217 |
form.add_submit('cancel', _('Cancel')) |
|
218 |
|
|
219 |
if form.get_widget('cancel').parse(): |
|
220 |
return redirect('.') |
|
221 |
|
|
222 |
if not form.is_submitted() or form.has_errors(): |
|
223 |
get_response().breadcrumb.append(('panel', _('Control Panel'))) |
|
224 |
get_response().breadcrumb.append(('drupal', _('Drupal Integration'))) |
|
225 |
html_top('panel', _('Drupal Integration')) |
|
226 |
r = TemplateIO(html=True) |
|
227 |
r += htmltext('<h2>%s</h2>') % _('Drupal Integration') |
|
228 |
r += form.render() |
|
229 |
return r.getvalue() |
|
230 |
else: |
|
231 |
from wcs.admin.settings import cfg_submit |
|
232 |
cfg_submit(form, 'misc', ('aq-drupal-ip',)) |
|
233 |
return redirect('.') |
|
234 |
|
|
235 |
def ezldap(self): |
|
236 |
if not get_publisher().has_site_option('ezldap'): |
|
237 |
raise errors.TraversalError() |
|
238 |
misc_cfg = get_cfg('misc', {}) |
|
239 |
form = Form(enctype='multipart/form-data') |
|
240 |
form.add(StringWidget, 'aq-ezldap-url', title=_('LDAP URL'), |
|
241 |
value=misc_cfg.get('aq-ezldap-url'), required=False, |
|
242 |
hint=_('Empty to disable eZ/LDAP support')) |
|
243 |
form.add(StringWidget, 'aq-ezldap-binddn', title=_('LDAP Admin Bind DN'), |
|
244 |
value=misc_cfg.get('aq-ezldap-binddn'), required=False) |
|
245 |
form.add(PasswordWidget, 'aq-ezldap-bindpassword', title=_('LDAP Admin Bind Password'), |
|
246 |
value=misc_cfg.get('aq-ezldap-bindpassword'), required=False) |
|
247 |
form.add(StringWidget, 'aq-ezldap-basedn', title=_('LDAP Base DN'), |
|
248 |
value=misc_cfg.get('aq-ezldap-basedn'), required=False) |
|
249 |
form.add(StringWidget, 'aq-ezldap-dntemplate', title=_('LDAP DN Template'), |
|
250 |
value=misc_cfg.get('aq-ezldap-dntemplate'), required=False) |
|
251 |
form.add(StringWidget, 'aq-ezldap-ip', title=_('Use Auth-DN header only from this IP'), |
|
252 |
value=misc_cfg.get('aq-ezldap-ip'), required=False, |
|
253 |
hint=_('Empty to disable IP filtering')) |
|
254 |
|
|
255 |
form.add_submit('submit', _('Submit')) |
|
256 |
form.add_submit('cancel', _('Cancel')) |
|
257 |
|
|
258 |
if form.get_widget('cancel').parse(): |
|
259 |
return redirect('.') |
|
260 |
|
|
261 |
if not form.is_submitted() or form.has_errors(): |
|
262 |
get_response().breadcrumb.append(('panel', _('Control Panel'))) |
|
263 |
get_response().breadcrumb.append(('ezldap', _('eZ publish / LDAP Integration'))) |
|
264 |
html_top('panel', _('eZ publish / LDAP Integration')) |
|
265 |
r = TemplateIO(html=True) |
|
266 |
r += htmltext('<h2>%s</h2>') % _('eZ publish / LDAP Integration') |
|
267 |
r += form.render() |
|
268 |
return r.getvalue() |
|
269 |
else: |
|
270 |
from wcs.admin.settings import cfg_submit |
|
271 |
cfg_submit(form, 'misc', ('aq-ezldap-url', |
|
272 |
'aq-ezldap-binddn', 'aq-ezldap-bindpassword', |
|
273 |
'aq-ezldap-basedn', 'aq-ezldap-dntemplate', |
|
274 |
'aq-ezldap-ip')) |
|
275 |
return redirect('.') |
|
276 |
|
|
277 |
def strongbox(self): |
|
278 |
if not get_publisher().has_site_option('strongbox'): |
|
279 |
raise errors.TraversalError() |
|
280 |
misc_cfg = get_cfg('misc', {}) |
|
281 |
form = Form(enctype='multipart/form-data') |
|
282 |
form.add(CheckboxWidget, 'aq-strongbox', title=_('Strongbox Support'), |
|
283 |
value=misc_cfg.get('aq-strongbox'), required=False) |
|
284 |
|
|
285 |
form.add_submit('submit', _('Submit')) |
|
286 |
form.add_submit('cancel', _('Cancel')) |
|
287 |
|
|
288 |
if form.get_widget('cancel').parse(): |
|
289 |
return redirect('.') |
|
290 |
|
|
291 |
if not form.is_submitted() or form.has_errors(): |
|
292 |
get_response().breadcrumb.append(('panel', _('Control Panel'))) |
|
293 |
get_response().breadcrumb.append(('strongbox', _('Strongbox Support'))) |
|
294 |
html_top('panel', _('Strongbox Support')) |
|
295 |
r = TemplateIO(html=True) |
|
296 |
r += htmltext('<h2>%s</h2>') % _('Strongbox Support') |
|
297 |
r += form.render() |
|
298 |
return r.getvalue() |
|
299 |
else: |
|
300 |
from wcs.admin.settings import cfg_submit |
|
301 |
cfg_submit(form, 'misc', ('aq-strongbox',)) |
|
302 |
return redirect('.') |
|
303 |
|
|
304 |
def clicrdv(self): |
|
305 |
if not get_publisher().has_site_option('clicrdv'): |
|
306 |
raise errors.TraversalError() |
|
307 |
misc_cfg = get_cfg('misc', {}) |
|
308 |
form = Form(enctype='multipart/form-data') |
|
309 |
form.add(SingleSelectWidget, 'aq-clicrdv-server', title=_('ClicRDV Server'), |
|
310 |
value=misc_cfg.get('aq-clicrdv-server', 'sandbox.clicrdv.com'), required=True, |
|
311 |
options=[(str('www.clicrdv.com'), _('Production Server')), |
|
312 |
(str('sandbox.clicrdv.com'), _('Sandbox Server'))]) |
|
313 |
form.add(StringWidget, 'aq-clicrdv-api-key', title=_('API Key'), |
|
314 |
value=misc_cfg.get('aq-clicrdv-api-key'), required=False, |
|
315 |
size=40, hint=_('Empty to disable ClicRDV support')) |
|
316 |
form.add(StringWidget, 'aq-clicrdv-api-username', title=_('Username'), |
|
317 |
value=misc_cfg.get('aq-clicrdv-api-username'), required=False) |
|
318 |
form.add(StringWidget, 'aq-clicrdv-api-password', title=_('Password'), |
|
319 |
value=misc_cfg.get('aq-clicrdv-api-password'), required=False) |
|
320 |
|
|
321 |
form.add_submit('submit', _('Submit')) |
|
322 |
form.add_submit('cancel', _('Cancel')) |
|
323 |
|
|
324 |
if form.get_widget('cancel').parse(): |
|
325 |
return redirect('.') |
|
326 |
|
|
327 |
if not form.is_submitted() or form.has_errors(): |
|
328 |
get_response().breadcrumb.append(('panel', _('Control Panel'))) |
|
329 |
get_response().breadcrumb.append(('clicrdv', _('ClicRDV Integration'))) |
|
330 |
html_top('panel', _('ClicRDV Integration')) |
|
331 |
r = TemplateIO(html=True) |
|
332 |
r += htmltext('<h2>%s</h2>') % _('ClicRDV Integration') |
|
333 |
r += form.render() |
|
334 |
r += htmltext('<p>%s</p>') % _('Available Interventions: ') |
|
335 |
try: |
|
336 |
from clicrdv import get_all_intervention_sets |
|
337 |
intervention_sets = get_all_intervention_sets() |
|
338 |
r += htmltext('<ul>') |
|
339 |
for s in intervention_sets: |
|
340 |
r += htmltext('<li><strong>clicrdv_get_interventions_in_set(%s)</strong> - %s') % ( |
|
341 |
s['id'], s['name']) |
|
342 |
r += htmltext('<ul>') |
|
343 |
for n, intervention in s['interventions']: |
|
344 |
r += htmltext('<li>%s (id: %s)</li>') % (intervention, n) |
|
345 |
r += htmltext('</ul></li>') |
|
346 |
r += htmltext('</ul>') |
|
347 |
except Exception, e: |
|
348 |
r += htmltext('<p>%s (%s)</p>') % ( |
|
349 |
_('Cannot access to ClicRDV service'), str(e)) |
|
350 |
return r.getvalue() |
|
351 |
else: |
|
352 |
from wcs.admin.settings import cfg_submit |
|
353 |
cfg_submit(form, 'misc', ('aq-clicrdv-server', |
|
354 |
'aq-clicrdv-api-key', |
|
355 |
'aq-clicrdv-api-username', |
|
356 |
'aq-clicrdv-api-password')) |
|
357 |
return redirect('.') |
|
358 |
|
|
359 |
|
|
360 |
AdminRootDirectory.register_page('panel', PanelDirectory()) |
|
361 |
|
|
362 |
import categories_admin |
|
363 |
|
extra/modules/agenda.ptl | ||
---|---|---|
1 |
import time |
|
2 |
import datetime |
|
3 |
from sets import Set |
|
4 |
|
|
5 |
from quixote.directory import Directory |
|
6 |
from quixote import get_publisher, get_request, redirect, get_session, get_response |
|
7 |
|
|
8 |
from qommon import misc, template, errors, get_cfg |
|
9 |
from qommon.form import * |
|
10 |
|
|
11 |
from events import Event, RemoteCalendar, get_default_event_tags |
|
12 |
|
|
13 |
|
|
14 |
class TagDirectory(Directory): |
|
15 |
def _q_lookup(self, component): |
|
16 |
events = Event.select() |
|
17 |
for remote_calendar in RemoteCalendar.select(): |
|
18 |
if remote_calendar.events: |
|
19 |
events.extend(remote_calendar.events) |
|
20 |
self.events = [x for x in events if component in (x.keywords or [])] |
|
21 |
self.events.sort(lambda x,y: cmp(x.date_start, y.date_start)) |
|
22 |
self.tag = component |
|
23 |
return self.display_events() |
|
24 |
|
|
25 |
def display_events [html] (self): |
|
26 |
template.html_top(_('Agenda')) |
|
27 |
if len(self.events) > 1: |
|
28 |
'<p id="nb-events">' |
|
29 |
_('%(nb)d events with %(keyword)s keyword') % { |
|
30 |
'nb': len(self.events), |
|
31 |
'keyword': self.tag |
|
32 |
} |
|
33 |
'</p>' |
|
34 |
|
|
35 |
if self.events: |
|
36 |
'<dl id="events">' |
|
37 |
for ev in self.events: |
|
38 |
ev.as_html_dt_dd() |
|
39 |
'</dl>' |
|
40 |
else: |
|
41 |
'<p id="nb-events">' |
|
42 |
_('No event registered with the %s keyword.') % self.tag |
|
43 |
'</p>' |
|
44 |
|
|
45 |
|
|
46 |
class AgendaDirectory(Directory): |
|
47 |
_q_exports = ['', 'icalendar', 'tag', 'atom', 'filter'] |
|
48 |
|
|
49 |
year = None |
|
50 |
month = None |
|
51 |
|
|
52 |
tag = TagDirectory() |
|
53 |
|
|
54 |
def _q_traverse(self, path): |
|
55 |
get_response().breadcrumb.append(('agenda/', _('Agenda'))) |
|
56 |
self.year, self.month = time.localtime()[:2] |
|
57 |
if len(path) >= 1 and path[0].isdigit(): |
|
58 |
self.year, self.month = (None, None) |
|
59 |
self.year = int(path[0]) |
|
60 |
get_response().breadcrumb.append(('%s/' % self.year, self.year)) |
|
61 |
path = path[1:] |
|
62 |
if len(path) >= 1 and path[0] in [str(x) for x in range(1, 13)]: |
|
63 |
self.month = int(path[0]) |
|
64 |
get_response().breadcrumb.append(('%s/' % self.month, |
|
65 |
misc.get_month_name(self.month))) |
|
66 |
path = path[1:] |
|
67 |
if len(path) == 0: |
|
68 |
return redirect(get_request().get_path() + '/') |
|
69 |
return Directory._q_traverse(self, path) |
|
70 |
|
|
71 |
def _q_index [html] (self): |
|
72 |
if self.month: |
|
73 |
self.display_month_links() |
|
74 |
self.display_month() |
|
75 |
else: |
|
76 |
return redirect('..') |
|
77 |
|
|
78 |
def display_month [html] (self): |
|
79 |
template.html_top(_('Agenda')) |
|
80 |
events = Event.select() |
|
81 |
remote_cal = get_request().form.get('cal') |
|
82 |
if remote_cal != 'local': |
|
83 |
if remote_cal: |
|
84 |
try: |
|
85 |
events = RemoteCalendar.get(remote_cal).events |
|
86 |
except KeyError: |
|
87 |
raise errors.TraversalError() |
|
88 |
if not events: |
|
89 |
events = [] |
|
90 |
else: |
|
91 |
for remote_calendar in RemoteCalendar.select(): |
|
92 |
if remote_calendar.events: |
|
93 |
events.extend(remote_calendar.events) |
|
94 |
events = [x for x in events if x.in_month(self.year, self.month)] |
|
95 |
events.sort(lambda x,y: cmp(x.date_start, y.date_start)) |
|
96 |
|
|
97 |
if events: |
|
98 |
if len(events) > 1: |
|
99 |
'<p id="nb-events">' |
|
100 |
_('%(nb)d events for %(month_name)s %(year)s') % { |
|
101 |
'nb': len(events), |
|
102 |
'month_name': misc.get_month_name(self.month), |
|
103 |
'year': self.year} |
|
104 |
'</p>' |
|
105 |
|
|
106 |
'<dl id="events">' |
|
107 |
for ev in events: |
|
108 |
ev.as_html_dt_dd() |
|
109 |
'</dl>' |
|
110 |
else: |
|
111 |
'<p id="nb-events">' |
|
112 |
_('No event registered for the month of %s.') % '%s %s' % ( |
|
113 |
misc.get_month_name(self.month), self.year) |
|
114 |
'</p>' |
|
115 |
|
|
116 |
root_url = get_publisher().get_root_url() |
|
117 |
'<div id="agenda-subs">' |
|
118 |
'<p>' |
|
119 |
_('You can subscribe to this calendar:') |
|
120 |
'</p>' |
|
121 |
'<ul>' |
|
122 |
' <li><a href="%sagenda/icalendar" id="par_ical">%s</a></li>' % (root_url, _('iCalendar')) |
|
123 |
' <li><a href="%sagenda/atom" id="par_rss">%s</a></li>' % (root_url, _('Feed')) |
|
124 |
'</ul>' |
|
125 |
'</div>' |
|
126 |
|
|
127 |
def display_month_links [html] (self): |
|
128 |
today = datetime.date(*(time.localtime()[:2] + (1,))) |
|
129 |
'<ul id="month-links">' |
|
130 |
for i in range(12): |
|
131 |
'<li>' |
|
132 |
if (today.year, today.month) == (self.year, self.month): |
|
133 |
'<strong>' |
|
134 |
'%s %s' % (misc.get_month_name(today.month), today.year) |
|
135 |
'</strong>' |
|
136 |
else: |
|
137 |
root_url = get_publisher().get_root_url() |
|
138 |
'<a href="%sagenda/%s/%s/">' % (root_url, today.year, today.month) |
|
139 |
'%s %s' % (misc.get_month_name(today.month), today.year) |
|
140 |
'</a>' |
|
141 |
'</li>' |
|
142 |
today += datetime.timedelta(31) |
|
143 |
'</ul>' |
|
144 |
|
|
145 |
def display_remote_calendars [html] (self): |
|
146 |
remote_calendars = [x for x in RemoteCalendar.select() if x.label] |
|
147 |
if not remote_calendars: |
|
148 |
return |
|
149 |
remote_calendars.sort(lambda x,y: cmp(x.label, y.label)) |
|
150 |
'<p class="tags">' |
|
151 |
remote_cal = get_request().form.get('cal') |
|
152 |
agenda_root_url = get_publisher().get_root_url() + 'agenda/' |
|
153 |
if remote_cal: |
|
154 |
'<a href="%s">%s</a> ' % (agenda_root_url, _('All')) |
|
155 |
else: |
|
156 |
'<strong><a href="%s">%s</a></strong> ' % (agenda_root_url, _('All')) |
|
157 |
if remote_cal != 'local': |
|
158 |
'<a href="%s?cal=local">%s</a> ' % (agenda_root_url, _('Local')) |
|
159 |
else: |
|
160 |
'<strong><a href="%s?cal=local">%s</a></strong> ' % (agenda_root_url, _('Local')) |
|
161 |
for cal in remote_calendars: |
|
162 |
if remote_cal == str(cal.id): |
|
163 |
'<strong><a href="%s?cal=%s">%s</a></strong> ' % (agenda_root_url, cal.id, cal.label) |
|
164 |
else: |
|
165 |
'<a href="%s?cal=%s">%s</a> ' % (agenda_root_url, cal.id, cal.label) |
|
166 |
'</p>' |
|
167 |
|
|
168 |
def icalendar(self): |
|
169 |
if not Event.keys(): |
|
170 |
raise errors.TraversalError() |
|
171 |
response = get_response() |
|
172 |
response.set_content_type('text/calendar', 'utf-8') |
|
173 |
vcal = Event.as_vcalendar() |
|
174 |
if type(vcal) is unicode: |
|
175 |
return vcal.encode('utf-8') |
|
176 |
else: |
|
177 |
return vcal |
|
178 |
|
|
179 |
def atom [plain] (self): |
|
180 |
response = get_response() |
|
181 |
response.set_content_type('application/atom+xml') |
|
182 |
|
|
183 |
from pyatom import pyatom |
|
184 |
xmldoc = pyatom.XMLDoc() |
|
185 |
feed = pyatom.Feed() |
|
186 |
xmldoc.root_element = feed |
|
187 |
feed.title = get_cfg('misc', {}).get('sitename', 'Au Quotidien') + ' - ' + _('Agenda') |
|
188 |
feed.id = get_request().get_url() |
|
189 |
|
|
190 |
author_email = get_cfg('emails', {}).get('reply_to') |
|
191 |
if not author_email: |
|
192 |
author_email = get_cfg('emails', {}).get('from') |
|
193 |
if author_email: |
|
194 |
feed.authors.append(pyatom.Author(author_email)) |
|
195 |
|
|
196 |
feed.links.append(pyatom.Link(get_request().get_url(1) + '/')) |
|
197 |
|
|
198 |
year, month = time.localtime()[:2] |
|
199 |
nyear, nmonth = year, month+1 |
|
200 |
if nmonth > 12: |
|
201 |
nyear, nmonth = nyear+1, 1 |
|
202 |
|
|
203 |
events = [x for x in Event.select() if x.in_month(year, month) or x.in_month(nyear, nmonth)] |
|
204 |
events.sort(lambda x,y: cmp(x.date_start, y.date_start)) |
|
205 |
events.reverse() |
|
206 |
|
|
207 |
for item in events: |
|
208 |
entry = item.get_atom_entry() |
|
209 |
if entry is not None: |
|
210 |
feed.entries.append(entry) |
|
211 |
|
|
212 |
str(feed) |
|
213 |
|
|
214 |
def filter [html] (self, no_event=False): |
|
215 |
template.html_top(_('Agenda')) |
|
216 |
tags = get_cfg('misc', {}).get('event_tags') |
|
217 |
if not tags: |
|
218 |
tags = get_default_event_tags() |
|
219 |
remote_calendars = [x for x in RemoteCalendar.select() if x.label] |
|
220 |
|
|
221 |
form = Form(enctype='multipart/form-data') |
|
222 |
if tags and remote_calendars: |
|
223 |
form.widgets.append(HtmlWidget('<table id="agenda-filter"><tr><td>')) |
|
224 |
if tags: |
|
225 |
form.add(CheckboxesWidget, 'tags', title = _('Tags'), |
|
226 |
elements = [(x,x) for x in tags], |
|
227 |
inline = False) |
|
228 |
if tags and remote_calendars: |
|
229 |
form.widgets.append(HtmlWidget('</td><td>')) |
|
230 |
if remote_calendars: |
|
231 |
remote_calendars.sort(lambda x,y: cmp(x.label, y.label)) |
|
232 |
form.add(CheckboxesWidget, 'calendars', title = _('Calendars'), |
|
233 |
elements = [('local', _('Local'))] + [(x.id, x.label) for x in remote_calendars], |
|
234 |
inline = False) |
|
235 |
if tags and remote_calendars: |
|
236 |
form.widgets.append(HtmlWidget('</td></tr></table>')) |
|
237 |
|
|
238 |
form.add_submit('submit', _('Submit')) |
|
239 |
form.add_submit('cancel', _('Cancel')) |
|
240 |
if form.get_widget('cancel').parse(): |
|
241 |
return redirect('.') |
|
242 |
|
|
243 |
if no_event or not form.is_submitted(): |
|
244 |
if no_event: |
|
245 |
'<p id="nb-events">' |
|
246 |
_('No events matching the filter.') |
|
247 |
'</p>' |
|
248 |
form.render() |
|
249 |
else: |
|
250 |
return self.filter_submitted(form, tags, remote_calendars) |
|
251 |
|
|
252 |
def filter_submitted [html] (self, form, tags, remote_calendars): |
|
253 |
if remote_calendars: |
|
254 |
selected_remote_calendars = form.get_widget('calendars').parse() |
|
255 |
events = [] |
|
256 |
for remote_calendar in selected_remote_calendars: |
|
257 |
if remote_calendar == 'local': |
|
258 |
events.extend(Event.select()) |
|
259 |
else: |
|
260 |
try: |
|
261 |
events.extend(RemoteCalendar.get(remote_calendar).events) |
|
262 |
except KeyError: |
|
263 |
pass |
|
264 |
else: |
|
265 |
events = Event.select() |
|
266 |
|
|
267 |
events = [x for x in events if x.after_today()] |
|
268 |
|
|
269 |
if tags: |
|
270 |
selected_tags = Set(form.get_widget('tags').parse()) |
|
271 |
if selected_tags and len(selected_tags) != len(tags): |
|
272 |
events = [x for x in events if Set(x.keywords).intersection(selected_tags)] |
|
273 |
|
|
274 |
events.sort(lambda x,y: cmp(x.date_start, y.date_start)) |
|
275 |
|
|
276 |
if len(events) > 1: |
|
277 |
'<p id="nb-events">' |
|
278 |
_('%(nb)d events') % {'nb': len(events)} |
|
279 |
'</p>' |
|
280 |
|
|
281 |
if events: |
|
282 |
'<dl id="events">' |
|
283 |
for ev in events: |
|
284 |
ev.as_html_dt_dd() |
|
285 |
'</dl>' |
|
286 |
else: |
|
287 |
return self.filter(no_event=True) |
extra/modules/agenda.py | ||
---|---|---|
1 |
import time |
|
2 |
import datetime |
|
3 |
from sets import Set |
|
4 |
|
|
5 |
from quixote.directory import Directory |
|
6 |
from quixote import get_publisher, get_request, redirect, get_session, get_response |
|
7 |
from quixote.html import htmltext, TemplateIO |
|
8 |
|
|
9 |
from qommon import misc, template, errors, get_cfg |
|
10 |
from qommon.form import * |
|
11 |
|
|
12 |
from events import Event, RemoteCalendar, get_default_event_tags |
|
13 |
|
|
14 |
|
|
15 |
class TagDirectory(Directory): |
|
16 |
def _q_lookup(self, component): |
|
17 |
events = Event.select() |
|
18 |
for remote_calendar in RemoteCalendar.select(): |
|
19 |
if remote_calendar.events: |
|
20 |
events.extend(remote_calendar.events) |
|
21 |
self.events = [x for x in events if component in (x.keywords or [])] |
|
22 |
self.events.sort(lambda x,y: cmp(x.date_start, y.date_start)) |
|
23 |
self.tag = component |
|
24 |
return self.display_events() |
|
25 |
|
|
26 |
def display_events(self): |
|
27 |
template.html_top(_('Agenda')) |
|
28 |
r = TemplateIO(html=True) |
|
29 |
if len(self.events) > 1: |
|
30 |
r += htmltext('<p id="nb-events">') |
|
31 |
r += _('%(nb)d events with %(keyword)s keyword') % { |
|
32 |
'nb': len(self.events), |
|
33 |
'keyword': self.tag |
|
34 |
} |
|
35 |
r += htmltext('</p>') |
|
36 |
|
|
37 |
if self.events: |
|
38 |
r += htmltext('<dl id="events">') |
|
39 |
for ev in self.events: |
|
40 |
r += htmltext(ev.as_html_dt_dd()) |
|
41 |
r += htmltext('</dl>') |
|
42 |
else: |
|
43 |
r += htmltext('<p id="nb-events">') |
|
44 |
r += _('No event registered with the %s keyword.') % self.tag |
|
45 |
r += htmltext('</p>') |
|
46 |
return r.getvalue() |
|
47 |
|
|
48 |
|
|
49 |
class AgendaDirectory(Directory): |
|
50 |
_q_exports = ['', 'icalendar', 'tag', 'atom', 'filter'] |
|
51 |
|
|
52 |
year = None |
|
53 |
month = None |
|
54 |
|
|
55 |
tag = TagDirectory() |
|
56 |
|
|
57 |
def _q_traverse(self, path): |
|
58 |
get_response().breadcrumb.append(('agenda/', _('Agenda'))) |
|
59 |
self.year, self.month = time.localtime()[:2] |
|
60 |
if len(path) >= 1 and path[0].isdigit(): |
|
61 |
self.year, self.month = (None, None) |
|
62 |
self.year = int(path[0]) |
|
63 |
get_response().breadcrumb.append(('%s/' % self.year, self.year)) |
|
64 |
path = path[1:] |
|
65 |
if len(path) >= 1 and path[0] in [str(x) for x in range(1, 13)]: |
|
66 |
self.month = int(path[0]) |
|
67 |
get_response().breadcrumb.append(('%s/' % self.month, |
|
68 |
misc.get_month_name(self.month))) |
|
69 |
path = path[1:] |
|
70 |
if len(path) == 0: |
|
71 |
return redirect(get_request().get_path() + '/') |
|
72 |
return Directory._q_traverse(self, path) |
|
73 |
|
|
74 |
def _q_index(self): |
|
75 |
if self.month: |
|
76 |
r = TemplateIO(html=True) |
|
77 |
r += htmltext(self.display_month_links()) |
|
78 |
r += htmltext(self.display_month()) |
|
79 |
return r.getvalue() |
|
80 |
else: |
|
81 |
return redirect('..') |
|
82 |
|
|
83 |
def display_month(self): |
|
84 |
template.html_top(_('Agenda')) |
|
85 |
events = Event.select() |
|
86 |
remote_cal = get_request().form.get('cal') |
|
87 |
if remote_cal != 'local': |
|
88 |
if remote_cal: |
|
89 |
try: |
|
90 |
events = RemoteCalendar.get(remote_cal).events |
|
91 |
except KeyError: |
|
92 |
raise errors.TraversalError() |
|
93 |
if not events: |
|
94 |
events = [] |
|
95 |
else: |
|
96 |
for remote_calendar in RemoteCalendar.select(): |
|
97 |
if remote_calendar.events: |
|
98 |
events.extend(remote_calendar.events) |
|
99 |
events = [x for x in events if x.in_month(self.year, self.month)] |
|
100 |
events.sort(lambda x,y: cmp(x.date_start, y.date_start)) |
|
101 |
|
|
102 |
r = TemplateIO(html=True) |
|
103 |
if events: |
|
104 |
if len(events) > 1: |
|
105 |
r += htmltrxt('<p id="nb-events">') |
|
106 |
r += _('%(nb)d events for %(month_name)s %(year)s') % { |
|
107 |
'nb': len(events), |
|
108 |
'month_name': misc.get_month_name(self.month), |
|
109 |
'year': self.year} |
|
110 |
r += htmltext('</p>') |
|
111 |
|
|
112 |
r += htmltext('<dl id="events">') |
|
113 |
for ev in events: |
|
114 |
r += htmltext(ev.as_html_dt_dd()) |
|
115 |
r += htmltext('</dl>') |
|
116 |
else: |
|
117 |
r += htmltext('<p id="nb-events">') |
|
118 |
r += _('No event registered for the month of %s.') % '%s %s' % ( |
|
119 |
misc.get_month_name(self.month), self.year) |
|
120 |
r += htmltext('</p>') |
|
121 |
|
|
122 |
root_url = get_publisher().get_root_url() |
|
123 |
r += htmltext('<div id="agenda-subs">') |
|
124 |
r += htmltext('<p>') |
|
125 |
r += _('You can subscribe to this calendar:') |
|
126 |
r += htmltext('</p>') |
|
127 |
r += htmltext('<ul>') |
|
128 |
r += htmltext(' <li><a href="%sagenda/icalendar" id="par_ical">%s</a></li>') % ( |
|
129 |
root_url, _('iCalendar')) |
|
130 |
r += htmltext(' <li><a href="%sagenda/atom" id="par_rss">%s</a></li>') % ( |
|
131 |
root_url, _('Feed')) |
|
132 |
r += htmltext('</ul>') |
|
133 |
r += htmltext('</div>') |
|
134 |
return r.getvalue() |
|
135 |
|
|
136 |
def display_month_links(self): |
|
137 |
today = datetime.date(*(time.localtime()[:2] + (1,))) |
|
138 |
r = TemplateIO(html=True) |
|
139 |
r += htmltext('<ul id="month-links">') |
|
140 |
for i in range(12): |
|
141 |
r += htmltext('<li>') |
|
142 |
if (today.year, today.month) == (self.year, self.month): |
|
143 |
r += htmltext('<strong>') |
|
144 |
r += '%s %s' % (misc.get_month_name(today.month), today.year) |
|
145 |
r += htmltext('</strong>') |
|
146 |
else: |
|
147 |
root_url = get_publisher().get_root_url() |
|
148 |
r += htmltext('<a href="%sagenda/%s/%s/">') % (root_url, today.year, today.month) |
|
149 |
r += '%s %s' % (misc.get_month_name(today.month), today.year) |
|
150 |
r += htmltext('</a>') |
|
151 |
r += htmltext('</li>') |
|
152 |
today += datetime.timedelta(31) |
|
153 |
r += htmltext('</ul>') |
|
154 |
return r.getvalue() |
|
155 |
|
|
156 |
def display_remote_calendars(self): |
|
157 |
r = TemplateIO(html=True) |
|
158 |
remote_calendars = [x for x in RemoteCalendar.select() if x.label] |
|
159 |
if not remote_calendars: |
|
160 |
return |
|
161 |
remote_calendars.sort(lambda x,y: cmp(x.label, y.label)) |
|
162 |
r += htmltext('<p class="tags">') |
|
163 |
remote_cal = get_request().form.get('cal') |
|
164 |
agenda_root_url = get_publisher().get_root_url() + 'agenda/' |
|
165 |
if remote_cal: |
|
166 |
r += htmltext('<a href="%s">%s</a> ') % (agenda_root_url, _('All')) |
|
167 |
else: |
|
168 |
r += htmltext('<strong><a href="%s">%s</a></strong> ') % (agenda_root_url, _('All')) |
|
169 |
if remote_cal != 'local': |
|
170 |
r += htmltext('<a href="%s?cal=local">%s</a> ') % (agenda_root_url, _('Local')) |
|
171 |
else: |
|
172 |
r += htmltext('<strong><a href="%s?cal=local">%s</a></strong> ') % (agenda_root_url, _('Local')) |
|
173 |
for cal in remote_calendars: |
|
174 |
if remote_cal == str(cal.id): |
|
175 |
r += htmltext('<strong><a href="%s?cal=%s">%s</a></strong> ') % ( |
|
176 |
agenda_root_url, cal.id, cal.label) |
|
177 |
else: |
|
178 |
r += htmltext('<a href="%s?cal=%s">%s</a> ') % (agenda_root_url, cal.id, cal.label) |
|
179 |
r += htmltext('</p>') |
|
180 |
return r.getvalue() |
|
181 |
|
|
182 |
def icalendar(self): |
|
183 |
if not Event.keys(): |
|
184 |
raise errors.TraversalError() |
|
185 |
response = get_response() |
|
186 |
response.set_content_type('text/calendar', 'utf-8') |
|
187 |
vcal = Event.as_vcalendar() |
|
188 |
if type(vcal) is unicode: |
|
189 |
return vcal.encode('utf-8') |
|
190 |
else: |
|
191 |
return vcal |
|
192 |
|
|
193 |
def atom(self): |
|
194 |
response = get_response() |
|
195 |
response.set_content_type('application/atom+xml') |
|
196 |
|
|
197 |
from pyatom import pyatom |
|
198 |
xmldoc = pyatom.XMLDoc() |
|
199 |
feed = pyatom.Feed() |
|
200 |
xmldoc.root_element = feed |
|
201 |
feed.title = get_cfg('misc', {}).get('sitename', 'Au Quotidien') + ' - ' + _('Agenda') |
|
202 |
feed.id = get_request().get_url() |
|
203 |
|
|
204 |
author_email = get_cfg('emails', {}).get('reply_to') |
|
205 |
if not author_email: |
|
206 |
author_email = get_cfg('emails', {}).get('from') |
|
207 |
if author_email: |
|
208 |
feed.authors.append(pyatom.Author(author_email)) |
|
209 |
|
|
210 |
feed.links.append(pyatom.Link(get_request().get_url(1) + '/')) |
|
211 |
|
|
212 |
year, month = time.localtime()[:2] |
|
213 |
nyear, nmonth = year, month+1 |
|
214 |
if nmonth > 12: |
|
215 |
nyear, nmonth = nyear+1, 1 |
|
216 |
|
|
217 |
events = [x for x in Event.select() if x.in_month(year, month) or x.in_month(nyear, nmonth)] |
|
218 |
events.sort(lambda x,y: cmp(x.date_start, y.date_start)) |
|
219 |
events.reverse() |
|
220 |
|
|
221 |
for item in events: |
|
222 |
entry = item.get_atom_entry() |
|
223 |
if entry is not None: |
|
224 |
feed.entries.append(entry) |
|
225 |
|
|
226 |
return str(feed) |
|
227 |
|
|
228 |
def filter(self, no_event=False): |
|
229 |
template.html_top(_('Agenda')) |
|
230 |
tags = get_cfg('misc', {}).get('event_tags') |
|
231 |
if not tags: |
|
232 |
tags = get_default_event_tags() |
|
233 |
remote_calendars = [x for x in RemoteCalendar.select() if x.label] |
|
234 |
|
|
235 |
form = Form(enctype='multipart/form-data') |
|
236 |
if tags and remote_calendars: |
|
237 |
form.widgets.append(HtmlWidget('<table id="agenda-filter"><tr><td>')) |
|
238 |
if tags: |
|
239 |
form.add(CheckboxesWidget, 'tags', title = _('Tags'), |
|
240 |
elements = [(x,x) for x in tags], |
|
241 |
inline = False) |
|
242 |
if tags and remote_calendars: |
|
243 |
form.widgets.append(HtmlWidget('</td><td>')) |
|
244 |
if remote_calendars: |
|
245 |
remote_calendars.sort(lambda x,y: cmp(x.label, y.label)) |
|
246 |
form.add(CheckboxesWidget, 'calendars', title = _('Calendars'), |
|
247 |
elements = [('local', _('Local'))] + [(x.id, x.label) for x in remote_calendars], |
|
248 |
inline = False) |
|
249 |
if tags and remote_calendars: |
|
250 |
form.widgets.append(HtmlWidget('</td></tr></table>')) |
|
251 |
|
|
252 |
form.add_submit('submit', _('Submit')) |
|
253 |
form.add_submit('cancel', _('Cancel')) |
|
254 |
if form.get_widget('cancel').parse(): |
|
255 |
return redirect('.') |
|
256 |
|
|
257 |
if no_event or not form.is_submitted(): |
|
258 |
r = TemplateIO(html=True) |
|
259 |
if no_event: |
|
260 |
r += htmltext('<p id="nb-events">') |
|
261 |
r += _('No events matching the filter.') |
|
262 |
r += htmltext('</p>') |
|
263 |
r += form.render() |
|
264 |
return r.getvalue() |
|
265 |
else: |
|
266 |
return self.filter_submitted(form, tags, remote_calendars) |
|
267 |
|
|
268 |
def filter_submitted(self, form, tags, remote_calendars): |
|
269 |
if remote_calendars: |
|
270 |
selected_remote_calendars = form.get_widget('calendars').parse() |
|
271 |
events = [] |
|
272 |
for remote_calendar in selected_remote_calendars: |
|
273 |
if remote_calendar == 'local': |
|
274 |
events.extend(Event.select()) |
|
275 |
else: |
|
276 |
try: |
|
277 |
events.extend(RemoteCalendar.get(remote_calendar).events) |
|
278 |
except KeyError: |
|
279 |
pass |
|
280 |
else: |
|
281 |
events = Event.select() |
|
282 |
|
|
283 |
events = [x for x in events if x.after_today()] |
|
284 |
|
|
285 |
if tags: |
|
286 |
selected_tags = Set(form.get_widget('tags').parse()) |
|
287 |
if selected_tags and len(selected_tags) != len(tags): |
|
288 |
events = [x for x in events if Set(x.keywords).intersection(selected_tags)] |
|
289 |
|
|
290 |
events.sort(lambda x,y: cmp(x.date_start, y.date_start)) |
|
291 |
|
|
292 |
r = TemplateIO(html=True) |
|
293 |
|
|
294 |
if len(events) > 1: |
|
295 |
r += htmltext('<p id="nb-events">') |
|
296 |
r += htmltext(_('%(nb)d events')) % {'nb': len(events)} |
|
297 |
r += htmltext('</p>') |
|
298 |
|
|
299 |
if events: |
|
300 |
r += htmltext('<dl id="events">') |
|
301 |
for ev in events: |
|
302 |
r += htmltext(ev.as_html_dt_dd()) |
|
303 |
r += htmltext('</dl>') |
|
304 |
return r.getvalue() |
|
305 |
else: |
|
306 |
return self.filter(no_event=True) |
extra/modules/announces_ui.ptl | ||
---|---|---|
1 |
from quixote import get_request, get_response, get_session, redirect |
|
2 |
from quixote.directory import Directory, AccessControlled |
|
3 |
|
|
4 |
import wcs |
|
5 |
from wcs.backoffice.menu import * |
|
6 |
|
|
7 |
from qommon import errors |
|
8 |
from qommon.form import * |
|
9 |
from qommon.afterjobs import AfterJob |
|
10 |
|
|
11 |
from announces import Announce, AnnounceSubscription |
|
12 |
|
|
13 |
|
|
14 |
class SubscriptionDirectory(Directory): |
|
15 |
_q_exports = ['delete_email', "delete_sms"] |
|
16 |
|
|
17 |
def __init__(self, subscription): |
|
18 |
self.subscription = subscription |
|
19 |
|
|
20 |
def delete_email [html] (self): |
|
21 |
form = Form(enctype='multipart/form-data') |
|
22 |
form.widgets.append(HtmlWidget('<p>%s</p>' % _( |
|
23 |
'You are about to delete this subscription.'))) |
|
24 |
form.add_submit('submit', _('Submit')) |
|
25 |
form.add_submit('cancel', _('Cancel')) |
|
26 |
if form.get_submit() == 'cancel': |
|
27 |
return redirect('..') |
|
28 |
if not form.is_submitted() or form.has_errors(): |
|
29 |
get_response().breadcrumb.append(('delete', _('Delete'))) |
|
30 |
html_top('announces', title = _('Delete Subscription')) |
|
31 |
'<h2>%s</h2>' % _('Deleting Subscription') |
|
32 |
form.render() |
|
33 |
else: |
|
34 |
self.subscription.remove("email") |
|
35 |
return redirect('..') |
|
36 |
|
|
37 |
def delete_sms [html] (self): |
|
38 |
form = Form(enctype='multipart/form-data') |
|
39 |
form.widgets.append(HtmlWidget('<p>%s</p>' % _( |
|
40 |
'You are about to delete this subscription.'))) |
|
41 |
form.add_submit('submit', _('Submit')) |
|
42 |
form.add_submit('cancel', _('Cancel')) |
|
43 |
if form.get_submit() == 'cancel': |
|
44 |
return redirect('..') |
|
45 |
if not form.is_submitted() or form.has_errors(): |
|
46 |
get_response().breadcrumb.append(('delete', _('Delete'))) |
|
47 |
html_top('announces', title = _('Delete Subscription')) |
|
48 |
'<h2>%s</h2>' % _('Deleting Subscription') |
|
49 |
form.render() |
|
50 |
else: |
|
51 |
self.subscription.remove("sms") |
|
52 |
return redirect('..') |
|
53 |
|
|
54 |
|
|
55 |
class SubscriptionsDirectory(Directory): |
|
56 |
_q_exports = [''] |
|
57 |
|
|
58 |
def _q_traverse(self, path): |
|
59 |
get_response().breadcrumb.append(('subscriptions', _('Subscriptions'))) |
|
60 |
return Directory._q_traverse(self, path) |
|
61 |
|
|
62 |
def _q_index [html] (self): |
|
63 |
html_top('announces', _('Announces Subscribers')) |
|
64 |
|
|
65 |
'<h2>%s</h2>' % _('Announces Subscribers') |
|
66 |
|
|
67 |
subscribers = AnnounceSubscription.select() |
|
68 |
'<ul class="biglist" id="subscribers-list">' |
|
69 |
for l in subscribers: |
|
70 |
if l.email: |
|
71 |
if l.enabled is False: |
|
72 |
'<li class="disabled">' |
|
73 |
else: |
|
74 |
'<li>' |
|
75 |
'<strong class="label">' |
|
76 |
if l.user: |
|
77 |
l.user.display_name |
|
78 |
elif l.email: |
|
79 |
l.email |
|
80 |
'</strong>' |
|
81 |
'<p class="details">' |
|
82 |
if l.user: |
|
83 |
l.user.email |
|
84 |
'</p>' |
|
85 |
'<p class="commands">' |
|
86 |
command_icon('%s/delete_email' % l.id, 'remove', popup = True) |
|
87 |
'</p></li>' |
|
88 |
'</li>' |
|
89 |
if l.sms: |
|
90 |
if l.enabled_sms is False: |
|
91 |
'<li class="disabled">' |
|
92 |
else: |
|
93 |
'<li>' |
|
94 |
'<strong class="label">' |
|
95 |
if l.user: |
|
96 |
l.user.display_name |
|
97 |
elif l.email: |
|
98 |
l.email |
|
99 |
'</strong>' |
|
100 |
'<p class="details">' |
|
101 |
l.sms |
|
102 |
'</p>' |
|
103 |
'<p class="commands">' |
|
104 |
command_icon('%s/delete_sms' % l.id, 'remove', popup = True) |
|
105 |
'</p></li>' |
|
106 |
'</li>' |
|
107 |
'</ul>' |
|
108 |
|
|
109 |
def _q_lookup(self, component): |
|
110 |
try: |
|
111 |
sub = AnnounceSubscription.get(component) |
|
112 |
except KeyError: |
|
113 |
raise errors.TraversalError() |
|
114 |
get_response().breadcrumb.append((str(sub.id), str(sub.id))) |
|
115 |
return SubscriptionDirectory(sub) |
|
116 |
|
|
117 |
def listing(self): |
|
118 |
return redirect('.') |
|
119 |
|
|
120 |
class AnnounceDirectory(Directory): |
|
121 |
_q_exports = ['', 'edit', 'delete', 'email', 'sms'] |
|
122 |
|
|
123 |
def __init__(self, announce): |
|
124 |
self.announce = announce |
|
125 |
|
|
126 |
def _q_index [html] (self): |
|
127 |
form = Form(enctype='multipart/form-data') |
|
128 |
get_response().filter['sidebar'] = self.get_sidebar() |
|
129 |
|
|
130 |
if self.announce.sent_by_email_time is None: |
|
131 |
form.add_submit('email', _('Send email')) |
|
132 |
|
|
133 |
announces_cfg = get_cfg('announces', {}) |
|
134 |
if announces_cfg.get('sms_support', 0) and self.announce.sent_by_sms_time is None: |
|
135 |
form.add_submit('sms', _('Send SMS')) |
|
136 |
|
|
137 |
if form.get_submit() == 'edit': |
|
138 |
return redirect('edit') |
|
139 |
if form.get_submit() == 'delete': |
|
140 |
return redirect('delete') |
|
141 |
if form.get_submit() == 'email': |
|
142 |
return redirect('email') |
|
143 |
if form.get_submit() == 'sms': |
|
144 |
return redirect('sms') |
|
145 |
|
|
146 |
html_top('announces', title = _('Announce: %s') % self.announce.title) |
|
147 |
'<h2>%s</h2>' % _('Announce: %s') % self.announce.title |
|
148 |
'<div class="bo-block">' |
|
149 |
'<p>' |
|
150 |
self.announce.text |
|
151 |
'</p>' |
|
152 |
'</div>' |
|
153 |
|
|
154 |
if form.get_submit_widgets(): |
|
155 |
form.render() |
|
156 |
|
|
157 |
def get_sidebar [html] (self): |
|
158 |
'<ul>' |
|
159 |
'<li><a href="edit">%s</a></li>' % _('Edit') |
|
160 |
'<li><a href="delete">%s</a></li>' % _('Delete') |
|
161 |
'</ul>' |
|
162 |
|
|
163 |
def email [html] (self): |
|
164 |
if get_request().form.get('job'): |
|
165 |
try: |
|
166 |
job = AfterJob.get(get_request().form.get('job')) |
|
167 |
except KeyError: |
|
168 |
return redirect('..') |
|
169 |
html_top('announces', title = _('Announce: %s') % self.announce.title) |
|
170 |
get_response().add_javascript(['jquery.js', 'afterjob.js']) |
|
171 |
'<dl class="job-status">' |
|
172 |
'<dt>' |
|
173 |
_(job.label) |
|
174 |
'</dt>' |
|
175 |
'<dd>' |
|
176 |
'<span class="afterjob" id="%s">' % job.id |
|
177 |
_(job.status) |
|
178 |
'</span>' |
|
179 |
'</dd>' |
|
180 |
'</dl>' |
|
181 |
|
|
182 |
'<div class="done">' |
|
183 |
'<a href="../">%s</a>' % _('Back') |
|
184 |
'</div>' |
|
185 |
|
|
186 |
else: |
|
187 |
job = get_response().add_after_job( |
|
188 |
str(N_('Sending emails for announce')), |
|
189 |
self.announce.email) |
|
190 |
return redirect('email?job=%s' % job.id) |
|
191 |
|
|
192 |
def sms [html] (self): |
|
193 |
if get_request().form.get('job'): |
|
194 |
try: |
|
195 |
job = AfterJob.get(get_request().form.get('job')) |
|
196 |
except KeyError: |
|
197 |
return redirect('..') |
|
198 |
html_top('announces', title = _('Announce: %s') % self.announce.title) |
|
199 |
get_response().add_javascript(['jquery.js', 'afterjob.js']) |
|
200 |
'<dl class="job-status">' |
|
201 |
'<dt>' |
|
202 |
_(job.label) |
|
203 |
'</dt>' |
|
204 |
'<dd>' |
|
205 |
'<span class="afterjob" id="%s">' % job.id |
|
206 |
_(job.status) |
|
207 |
'</span>' |
|
208 |
'</dd>' |
|
209 |
'</dl>' |
|
210 |
|
|
211 |
'<div class="done">' |
|
212 |
'<a href="../">%s</a>' % _('Back') |
|
213 |
'</div>' |
|
214 |
|
|
215 |
else: |
|
216 |
job = get_response().add_after_job( |
|
217 |
str(N_('Sending sms for announce')), |
|
218 |
self.announce.sms) |
|
219 |
return redirect('sms?job=%s' % job.id) |
|
220 |
|
|
221 |
def edit [html] (self): |
|
222 |
form = self.form() |
|
223 |
if form.get_submit() == 'cancel': |
|
224 |
return redirect('.') |
|
225 |
|
|
226 |
if form.is_submitted() and not form.has_errors(): |
|
227 |
self.submit(form) |
|
228 |
return redirect('..') |
|
229 |
|
|
230 |
html_top('announces', title = _('Edit Announce: %s') % self.announce.title) |
|
231 |
'<h2>%s</h2>' % _('Edit Announce: %s') % self.announce.title |
|
232 |
form.render() |
|
233 |
|
|
234 |
|
|
235 |
def form(self): |
|
236 |
form = Form(enctype='multipart/form-data') |
|
237 |
form.add(StringWidget, 'title', title = _('Title'), required = True, |
|
238 |
value = self.announce.title) |
|
239 |
if self.announce.publication_time: |
|
240 |
pub_time = time.strftime(misc.date_format(), self.announce.publication_time) |
|
241 |
else: |
|
242 |
pub_time = None |
|
243 |
form.add(DateWidget, 'publication_time', title = _('Publication Time'), |
|
244 |
value = pub_time) |
|
245 |
if self.announce.expiration_time: |
|
246 |
exp_time = time.strftime(misc.date_format(), self.announce.expiration_time) |
|
247 |
else: |
|
248 |
exp_time = None |
|
249 |
form.add(DateWidget, 'expiration_time', title = _('Expiration Time'), |
|
250 |
value = exp_time) |
|
251 |
form.add(TextWidget, 'text', title = _('Text'), required = True, |
|
252 |
value = self.announce.text, rows = 10, cols = 70) |
|
253 |
if get_cfg('misc', {}).get('announce_themes'): |
|
254 |
form.add(SingleSelectWidget, 'theme', title = _('Announce Theme'), |
|
255 |
value = self.announce.theme, |
|
256 |
options = get_cfg('misc', {}).get('announce_themes')) |
|
257 |
form.add(CheckboxWidget, 'hidden', title = _('Hidden'), |
|
258 |
value = self.announce.hidden) |
|
259 |
form.add_submit('submit', _('Submit')) |
|
260 |
form.add_submit('cancel', _('Cancel')) |
|
261 |
return form |
|
262 |
|
|
263 |
def submit(self, form): |
|
264 |
for k in ('title', 'text', 'hidden', 'theme'): |
|
265 |
widget = form.get_widget(k) |
|
266 |
if widget: |
|
267 |
setattr(self.announce, k, widget.parse()) |
|
268 |
for k in ('publication_time', 'expiration_time'): |
|
269 |
widget = form.get_widget(k) |
|
270 |
if widget: |
|
271 |
wid_time = widget.parse() |
|
272 |
if wid_time: |
|
273 |
setattr(self.announce, k, time.strptime(wid_time, misc.date_format())) |
|
274 |
else: |
|
275 |
setattr(self.announce, k, None) |
|
276 |
self.announce.store() |
|
277 |
|
|
278 |
def delete [html] (self): |
|
279 |
form = Form(enctype='multipart/form-data') |
|
280 |
form.widgets.append(HtmlWidget('<p>%s</p>' % _( |
|
281 |
'You are about to irrevocably delete this announce.'))) |
|
282 |
form.add_submit('submit', _('Submit')) |
|
283 |
form.add_submit('cancel', _('Cancel')) |
|
284 |
if form.get_submit() == 'cancel': |
|
285 |
return redirect('..') |
|
286 |
if not form.is_submitted() or form.has_errors(): |
|
287 |
get_response().breadcrumb.append(('delete', _('Delete'))) |
|
288 |
html_top('announces', title = _('Delete Announce')) |
|
289 |
'<h2>%s</h2>' % _('Deleting Announce: %s') % self.announce.title |
|
290 |
form.render() |
|
291 |
else: |
|
292 |
self.announce.remove_self() |
|
293 |
return redirect('..') |
|
294 |
|
|
295 |
|
|
296 |
|
|
297 |
class AnnouncesDirectory(AccessControlled, Directory): |
|
298 |
_q_exports = ['', 'new', 'listing', 'subscriptions', 'update_order', 'log'] |
|
299 |
label = N_('Announces') |
|
300 |
|
|
301 |
subscriptions = SubscriptionsDirectory() |
|
302 |
|
|
303 |
def _q_access(self): |
|
304 |
user = get_request().user |
|
305 |
if not user: |
|
306 |
raise errors.AccessUnauthorizedError() |
|
307 |
admin_role = get_cfg('aq-permissions', {}).get('announces', None) |
|
308 |
if not (user.is_admin or admin_role in (user.roles or [])): |
|
309 |
raise errors.AccessForbiddenError( |
|
310 |
public_msg = _('You are not allowed to access Announces Management'), |
|
311 |
location_hint = 'backoffice') |
|
312 |
|
|
313 |
get_response().breadcrumb.append(('announces/', _('Announces'))) |
|
314 |
|
|
315 |
|
|
316 |
def _q_index [html] (self): |
|
317 |
html_top('announces', _('Announces')) |
|
318 |
|
|
319 |
'<ul id="main-actions">' |
|
320 |
' <li><a class="new-item" href="new">%s</a></li>' % _('New') |
|
321 |
' <li><a href="subscriptions/">%s</a></li>' % _('Subscriptions') |
|
322 |
' <li><a href="log">%s</a></li>' % _('Log') |
|
323 |
'</ul>' |
|
324 |
|
|
325 |
announces = Announce.select() |
|
326 |
announces.sort(lambda x,y: cmp(x.publication_time or x.modification_time, |
|
327 |
y.publication_time or y.modification_time)) |
|
328 |
announces.reverse() |
|
329 |
|
|
330 |
'<ul class="biglist" id="announces-list">' |
|
331 |
for l in announces: |
|
332 |
announce_id = l.id |
|
333 |
if l.hidden: |
|
334 |
'<li class="disabled" class="biglistitem" id="itemId_%s">' % announce_id |
|
335 |
else: |
|
336 |
'<li class="biglistitem" id="itemId_%s">' % announce_id |
|
337 |
'<strong class="label"><a href="%s/">%s</a></strong>' % (l.id, l.title) |
|
338 |
if l.publication_time: |
|
339 |
'<p class="details">' |
|
340 |
time.strftime(misc.date_format(), l.publication_time) |
|
341 |
'</p>' |
|
342 |
'</li>' |
|
343 |
'</ul>' |
|
344 |
|
|
345 |
def log [html] (self): |
|
346 |
announces = Announce.select() |
|
347 |
log = [] |
|
348 |
for l in announces: |
|
349 |
if l.publication_time: |
|
350 |
log.append((l.publication_time, _('Publication'), l)) |
|
351 |
if l.sent_by_email_time: |
|
352 |
log.append((l.sent_by_email_time, _('Email'), l)) |
|
353 |
if l.sent_by_sms_time: |
|
354 |
log.append((l.sent_by_sms_time, _('SMS'), l)) |
|
355 |
log.sort() |
|
356 |
|
|
357 |
get_response().breadcrumb.append(('log', _('Log'))) |
|
358 |
html_top('announces', title = _('Log')) |
|
359 |
|
|
360 |
'<table>' |
|
361 |
'<thead>' |
|
362 |
'<tr>' |
|
363 |
'<th>%s</th>' % _('Time') |
|
364 |
'<th>%s</th>' % _('Type') |
|
365 |
'<td></td>' |
|
366 |
'</tr>' |
|
367 |
'</thead>' |
|
368 |
'<tbody>' |
|
369 |
for log_time, log_type, log_announce in log: |
|
370 |
'<tr>' |
|
371 |
'<td>' |
|
372 |
misc.localstrftime(log_time) |
|
373 |
'</td>' |
|
374 |
'<td>' |
|
375 |
log_type |
|
376 |
'</td>' |
|
377 |
'<td>' |
|
378 |
'<a href="%s">%s</a>' % (log_announce.id, log_announce.title) |
|
379 |
'</td>' |
|
380 |
'</tr>' |
|
381 |
'</tbody>' |
|
382 |
'</table>' |
|
383 |
|
|
384 |
|
|
385 |
def update_order(self): |
|
386 |
request = get_request() |
|
387 |
new_order = request.form['order'].strip(';').split(';') |
|
388 |
announces = Announce.select() |
|
389 |
dict = {} |
|
390 |
for l in announces: |
|
391 |
dict[str(l.id)] = l |
|
392 |
for i, o in enumerate(new_order): |
|
393 |
dict[o].position = i + 1 |
|
394 |
dict[o].store() |
|
395 |
return 'ok' |
|
396 |
|
|
397 |
|
|
398 |
def new [html] (self): |
|
399 |
announce = Announce() |
|
400 |
announce.publication_time = time.gmtime() |
|
401 |
announce_ui = AnnounceDirectory(announce) |
|
402 |
|
|
403 |
form = announce_ui.form() |
|
404 |
if form.get_submit() == 'cancel': |
|
405 |
return redirect('.') |
|
406 |
|
|
407 |
if form.is_submitted() and not form.has_errors(): |
|
408 |
announce_ui.submit(form) |
|
409 |
return redirect('%s/' % announce_ui.announce.id) |
|
410 |
|
|
411 |
get_response().breadcrumb.append(('new', _('New Announce'))) |
|
412 |
html_top('announces', title = _('New Announce')) |
|
413 |
'<h2>%s</h2>' % _('New Announce') |
|
414 |
form.render() |
|
415 |
|
|
416 |
def _q_lookup(self, component): |
|
417 |
try: |
|
418 |
announce = Announce.get(component) |
|
419 |
except KeyError: |
|
420 |
raise errors.TraversalError() |
|
421 |
get_response().breadcrumb.append((str(announce.id), announce.title)) |
|
422 |
return AnnounceDirectory(announce) |
|
423 |
|
|
424 |
def listing(self): |
|
425 |
return redirect('.') |
|
426 |
|
extra/modules/announces_ui.py | ||
---|---|---|
1 |
from quixote import get_request, get_response, get_session, redirect |
|
2 |
from quixote.directory import Directory, AccessControlled |
|
3 |
from quixote.html import htmltext, TemplateIO |
|
4 |
|
|
5 |
import wcs |
|
6 |
from wcs.backoffice.menu import * |
|
7 |
|
|
8 |
from qommon import errors |
|
9 |
from qommon.form import * |
|
10 |
from qommon.afterjobs import AfterJob |
|
11 |
|
|
12 |
from announces import Announce, AnnounceSubscription |
|
13 |
|
|
14 |
|
|
15 |
class SubscriptionDirectory(Directory): |
|
16 |
_q_exports = ['delete_email', "delete_sms"] |
|
17 |
|
|
18 |
def __init__(self, subscription): |
|
19 |
self.subscription = subscription |
|
20 |
|
|
21 |
def delete_email(self): |
|
22 |
form = Form(enctype='multipart/form-data') |
|
23 |
form.widgets.append(HtmlWidget('<p>%s</p>' % _( |
|
24 |
'You are about to delete this subscription.'))) |
|
25 |
form.add_submit('submit', _('Submit')) |
|
26 |
form.add_submit('cancel', _('Cancel')) |
|
27 |
if form.get_submit() == 'cancel': |
|
28 |
return redirect('..') |
|
29 |
if not form.is_submitted() or form.has_errors(): |
|
30 |
get_response().breadcrumb.append(('delete', _('Delete'))) |
|
31 |
html_top('announces', title = _('Delete Subscription')) |
|
32 |
r = TemplateIO(html=True) |
|
33 |
r += htmltext('<h2>%s</h2>') % _('Deleting Subscription') |
|
34 |
r += form.render() |
|
35 |
return r.getvalue() |
|
36 |
else: |
|
37 |
self.subscription.remove("email") |
|
38 |
return redirect('..') |
|
39 |
|
|
40 |
def delete_sms(self): |
|
41 |
form = Form(enctype='multipart/form-data') |
|
42 |
form.widgets.append(HtmlWidget('<p>%s</p>' % _( |
|
43 |
'You are about to delete this subscription.'))) |
|
44 |
form.add_submit('submit', _('Submit')) |
|
45 |
form.add_submit('cancel', _('Cancel')) |
|
46 |
if form.get_submit() == 'cancel': |
|
47 |
return redirect('..') |
|
48 |
if not form.is_submitted() or form.has_errors(): |
|
49 |
get_response().breadcrumb.append(('delete', _('Delete'))) |
|
50 |
html_top('announces', title = _('Delete Subscription')) |
|
51 |
r = TemplateIO(html=True) |
|
52 |
r += htmltext('<h2>%s</h2>') % _('Deleting Subscription') |
|
53 |
r += form.render() |
|
54 |
return r.getvalue() |
|
55 |
else: |
|
56 |
self.subscription.remove("sms") |
|
57 |
return redirect('..') |
|
58 |
|
|
59 |
|
|
60 |
class SubscriptionsDirectory(Directory): |
|
61 |
_q_exports = [''] |
|
62 |
|
|
63 |
def _q_traverse(self, path): |
|
64 |
get_response().breadcrumb.append(('subscriptions', _('Subscriptions'))) |
|
65 |
return Directory._q_traverse(self, path) |
|
66 |
|
|
67 |
def _q_index(self): |
|
68 |
html_top('announces', _('Announces Subscribers')) |
|
69 |
r = TemplateIO(html=True) |
|
70 |
|
|
71 |
r += htmltext('<h2>%s</h2>') % _('Announces Subscribers') |
|
72 |
|
|
73 |
subscribers = AnnounceSubscription.select() |
|
74 |
r += htmltext('<ul class="biglist" id="subscribers-list">') |
|
75 |
for l in subscribers: |
|
76 |
if l.email: |
|
77 |
if l.enabled is False: |
|
78 |
r += htmltext('<li class="disabled">') |
|
79 |
else: |
|
80 |
r += htmltext('<li>') |
|
81 |
r += htmltext('<strong class="label">') |
|
82 |
if l.user: |
|
83 |
r += l.user.display_name |
|
84 |
elif l.email: |
|
85 |
r += l.email |
|
86 |
r += htmltext('</strong>') |
|
87 |
r += htmltext('<p class="details">') |
|
88 |
if l.user: |
|
89 |
r += l.user.email |
|
90 |
r += htmltext('</p>') |
|
91 |
r += htmltext('<p class="commands">') |
|
92 |
r += command_icon('%s/delete_email' % l.id, 'remove', popup = True) |
|
93 |
r += htmltext('</p></li>') |
|
94 |
r += htmltext('</li>') |
|
95 |
if l.sms: |
|
96 |
if l.enabled_sms is False: |
|
97 |
r += htmltext('<li class="disabled">') |
|
98 |
else: |
|
99 |
r += htmltext('<li>') |
|
100 |
r += htmltext('<strong class="label">') |
|
101 |
if l.user: |
|
102 |
r += l.user.display_name |
|
103 |
elif l.email: |
|
104 |
r += l.email |
|
105 |
r += htmltext('</strong>') |
|
106 |
r += htmltext('<p class="details">') |
|
107 |
r += l.sms |
|
108 |
r += htmltext('</p>') |
|
109 |
r += htmltext('<p class="commands">') |
|
110 |
r += command_icon('%s/delete_sms' % l.id, 'remove', popup = True) |
|
111 |
r += htmltext('</p></li>') |
|
112 |
r += htmltext('</li>') |
|
113 |
r += htmltext('</ul>') |
|
114 |
return r.getvalue() |
|
115 |
|
|
116 |
def _q_lookup(self, component): |
|
117 |
try: |
|
118 |
sub = AnnounceSubscription.get(component) |
|
119 |
except KeyError: |
|
120 |
raise errors.TraversalError() |
|
121 |
get_response().breadcrumb.append((str(sub.id), str(sub.id))) |
|
122 |
return SubscriptionDirectory(sub) |
|
123 |
|
|
124 |
def listing(self): |
|
125 |
return redirect('.') |
|
126 |
|
|
127 |
class AnnounceDirectory(Directory): |
|
128 |
_q_exports = ['', 'edit', 'delete', 'email', 'sms'] |
|
129 |
|
|
130 |
def __init__(self, announce): |
|
131 |
self.announce = announce |
|
132 |
|
|
133 |
def _q_index(self): |
|
134 |
form = Form(enctype='multipart/form-data') |
|
135 |
get_response().filter['sidebar'] = self.get_sidebar() |
|
136 |
|
|
137 |
if self.announce.sent_by_email_time is None: |
|
138 |
form.add_submit('email', _('Send email')) |
|
139 |
|
|
140 |
announces_cfg = get_cfg('announces', {}) |
|
141 |
if announces_cfg.get('sms_support', 0) and self.announce.sent_by_sms_time is None: |
|
142 |
form.add_submit('sms', _('Send SMS')) |
|
143 |
|
|
144 |
if form.get_submit() == 'edit': |
|
145 |
return redirect('edit') |
|
146 |
if form.get_submit() == 'delete': |
|
147 |
return redirect('delete') |
|
148 |
if form.get_submit() == 'email': |
|
149 |
return redirect('email') |
|
150 |
if form.get_submit() == 'sms': |
|
151 |
return redirect('sms') |
|
152 |
|
|
153 |
html_top('announces', title = _('Announce: %s') % self.announce.title) |
|
154 |
r = TemplateIO(html=True) |
|
155 |
r += htmltext('<h2>%s</h2>') % _('Announce: %s') % self.announce.title |
|
156 |
r += htmltext('<div class="bo-block">') |
|
157 |
r += htmltext('<p>') |
|
158 |
r += self.announce.text |
|
159 |
r += htmltext('</p>') |
|
160 |
r += htmltext('</div>') |
|
161 |
|
|
162 |
if form.get_submit_widgets(): |
|
163 |
r += form.render() |
|
164 |
|
|
165 |
return r.getvalue() |
|
166 |
|
|
167 |
def get_sidebar(self): |
|
168 |
r = TemplateIO(html=True) |
|
169 |
r += htmltext('<ul>') |
|
170 |
r += htmltext('<li><a href="edit">%s</a></li>') % _('Edit') |
|
171 |
r += htmltext('<li><a href="delete">%s</a></li>') % _('Delete') |
|
172 |
r += htmltext('</ul>') |
|
173 |
return r.getvalue() |
|
174 |
|
|
175 |
def email(self): |
|
176 |
if get_request().form.get('job'): |
|
177 |
try: |
|
178 |
job = AfterJob.get(get_request().form.get('job')) |
|
179 |
except KeyError: |
|
180 |
return redirect('..') |
|
181 |
html_top('announces', title = _('Announce: %s') % self.announce.title) |
|
182 |
r = TemplateIO(html=True) |
|
183 |
get_response().add_javascript(['jquery.js', 'afterjob.js']) |
|
184 |
r += htmltext('<dl class="job-status">') |
|
185 |
r += htmltext('<dt>') |
|
186 |
r += _(job.label) |
|
187 |
r += htmltext('</dt>') |
|
188 |
r += htmltext('<dd>') |
|
189 |
r += htmltext('<span class="afterjob" id="%s">') % job.id |
|
190 |
r += _(job.status) |
|
191 |
r += htmltext('</span>') |
|
192 |
r += htmltext('</dd>') |
|
193 |
r += htmltext('</dl>') |
|
194 |
|
|
195 |
r += htmltext('<div class="done">') |
|
196 |
r += htmltext('<a href="../">%s</a>') % _('Back') |
|
197 |
r += htmltext('</div>') |
|
198 |
|
|
199 |
return r.getvalue() |
|
200 |
else: |
|
201 |
job = get_response().add_after_job( |
|
202 |
str(N_('Sending emails for announce')), |
|
203 |
self.announce.email) |
|
204 |
return redirect('email?job=%s' % job.id) |
|
205 |
|
|
206 |
def sms(self): |
|
207 |
if get_request().form.get('job'): |
|
208 |
try: |
|
209 |
job = AfterJob.get(get_request().form.get('job')) |
|
210 |
except KeyError: |
|
211 |
return redirect('..') |
|
212 |
html_top('announces', title = _('Announce: %s') % self.announce.title) |
|
213 |
get_response().add_javascript(['jquery.js', 'afterjob.js']) |
|
214 |
r = TemplateIO(html=True) |
|
215 |
r += htmltext('<dl class="job-status">') |
|
216 |
r += htmltext('<dt>') |
|
217 |
r += _(job.label) |
|
218 |
r += htmltext('</dt>') |
|
219 |
r += htmltext('<dd>') |
|
220 |
r += htmltext('<span class="afterjob" id="%s">') % job.id |
|
221 |
r += _(job.status) |
|
222 |
r += htmltext('</span>') |
|
223 |
r += htmltext('</dd>') |
|
224 |
r += htmltext('</dl>') |
|
225 |
|
|
226 |
r += htmltext('<div class="done">') |
|
227 |
r += htmltext('<a href="../">%s</a>') % _('Back') |
|
228 |
r += htmltext('</div>') |
|
229 |
|
|
230 |
return r.getvalue() |
|
231 |
else: |
|
232 |
job = get_response().add_after_job( |
|
233 |
str(N_('Sending sms for announce')), |
|
234 |
self.announce.sms) |
|
235 |
return redirect('sms?job=%s' % job.id) |
|
236 |
|
|
237 |
def edit(self): |
|
238 |
form = self.form() |
|
239 |
if form.get_submit() == 'cancel': |
|
240 |
return redirect('.') |
|
241 |
|
|
242 |
if form.is_submitted() and not form.has_errors(): |
|
243 |
self.submit(form) |
|
244 |
return redirect('..') |
|
245 |
|
|
246 |
html_top('announces', title = _('Edit Announce: %s') % self.announce.title) |
|
247 |
r = TemplateIO(html=True) |
|
248 |
r += htmltext('<h2>%s</h2>') % _('Edit Announce: %s') % self.announce.title |
|
249 |
r += form.render() |
|
250 |
return r.getvalue() |
|
251 |
|
|
252 |
def form(self): |
|
253 |
form = Form(enctype='multipart/form-data') |
|
254 |
form.add(StringWidget, 'title', title = _('Title'), required = True, |
|
255 |
value = self.announce.title) |
|
256 |
if self.announce.publication_time: |
|
257 |
pub_time = time.strftime(misc.date_format(), self.announce.publication_time) |
|
258 |
else: |
|
259 |
pub_time = None |
|
260 |
form.add(DateWidget, 'publication_time', title = _('Publication Time'), |
|
261 |
value = pub_time) |
|
262 |
if self.announce.expiration_time: |
|
263 |
exp_time = time.strftime(misc.date_format(), self.announce.expiration_time) |
|
264 |
else: |
|
265 |
exp_time = None |
|
266 |
form.add(DateWidget, 'expiration_time', title = _('Expiration Time'), |
|
267 |
value = exp_time) |
|
268 |
form.add(TextWidget, 'text', title = _('Text'), required = True, |
|
269 |
value = self.announce.text, rows = 10, cols = 70) |
|
270 |
if get_cfg('misc', {}).get('announce_themes'): |
|
271 |
form.add(SingleSelectWidget, 'theme', title = _('Announce Theme'), |
|
272 |
value = self.announce.theme, |
|
273 |
options = get_cfg('misc', {}).get('announce_themes')) |
|
274 |
form.add(CheckboxWidget, 'hidden', title = _('Hidden'), |
|
275 |
value = self.announce.hidden) |
|
276 |
form.add_submit('submit', _('Submit')) |
|
277 |
form.add_submit('cancel', _('Cancel')) |
|
278 |
return form |
|
279 |
|
|
280 |
def submit(self, form): |
|
281 |
for k in ('title', 'text', 'hidden', 'theme'): |
|
282 |
widget = form.get_widget(k) |
|
283 |
if widget: |
|
284 |
setattr(self.announce, k, widget.parse()) |
|
285 |
for k in ('publication_time', 'expiration_time'): |
|
286 |
widget = form.get_widget(k) |
|
287 |
if widget: |
|
288 |
wid_time = widget.parse() |
|
289 |
if wid_time: |
|
290 |
setattr(self.announce, k, time.strptime(wid_time, misc.date_format())) |
|
291 |
else: |
|
292 |
setattr(self.announce, k, None) |
|
293 |
self.announce.store() |
|
294 |
|
|
295 |
def delete(self): |
|
296 |
form = Form(enctype='multipart/form-data') |
|
297 |
form.widgets.append(HtmlWidget('<p>%s</p>' % _( |
|
298 |
'You are about to irrevocably delete this announce.'))) |
|
299 |
form.add_submit('submit', _('Submit')) |
|
300 |
form.add_submit('cancel', _('Cancel')) |
|
301 |
if form.get_submit() == 'cancel': |
|
302 |
return redirect('..') |
|
303 |
if not form.is_submitted() or form.has_errors(): |
|
304 |
get_response().breadcrumb.append(('delete', _('Delete'))) |
|
305 |
html_top('announces', title = _('Delete Announce')) |
|
306 |
r = TemplateIO(html=True) |
|
307 |
r += htmltext('<h2>%s</h2>') % _('Deleting Announce: %s') % self.announce.title |
|
308 |
r += form.render() |
|
309 |
return r.getvalue() |
|
310 |
else: |
|
311 |
self.announce.remove_self() |
|
312 |
return redirect('..') |
|
313 |
|
|
314 |
|
|
315 |
class AnnouncesDirectory(AccessControlled, Directory): |
|
316 |
_q_exports = ['', 'new', 'listing', 'subscriptions', 'update_order', 'log'] |
|
317 |
label = N_('Announces') |
|
318 |
|
|
319 |
subscriptions = SubscriptionsDirectory() |
|
320 |
|
|
321 |
def _q_access(self): |
|
322 |
user = get_request().user |
|
323 |
if not user: |
|
324 |
raise errors.AccessUnauthorizedError() |
|
325 |
admin_role = get_cfg('aq-permissions', {}).get('announces', None) |
|
326 |
if not (user.is_admin or admin_role in (user.roles or [])): |
|
327 |
raise errors.AccessForbiddenError( |
|
328 |
public_msg = _('You are not allowed to access Announces Management'), |
|
329 |
location_hint = 'backoffice') |
|
330 |
|
|
331 |
get_response().breadcrumb.append(('announces/', _('Announces'))) |
|
332 |
|
|
333 |
def _q_index(self): |
|
334 |
html_top('announces', _('Announces')) |
|
335 |
r = TemplateIO(html=True) |
|
336 |
|
|
337 |
r += htmltext('<ul id="main-actions">') |
|
338 |
r += htmltext(' <li><a class="new-item" href="new">%s</a></li>') % _('New') |
|
339 |
r += htmltext(' <li><a href="subscriptions/">%s</a></li>') % _('Subscriptions') |
|
340 |
r += htmltext(' <li><a href="log">%s</a></li>') % _('Log') |
|
341 |
r += htmltext('</ul>') |
|
342 |
|
|
343 |
announces = Announce.select() |
|
344 |
announces.sort(lambda x,y: cmp(x.publication_time or x.modification_time, |
|
345 |
y.publication_time or y.modification_time)) |
|
346 |
announces.reverse() |
|
347 |
|
|
348 |
r += htmltext('<ul class="biglist" id="announces-list">') |
|
349 |
for l in announces: |
|
350 |
announce_id = l.id |
|
351 |
if l.hidden: |
|
352 |
r += htmltext('<li class="disabled" class="biglistitem" id="itemId_%s">') % announce_id |
|
353 |
else: |
|
354 |
r += htmltext('<li class="biglistitem" id="itemId_%s">') % announce_id |
|
355 |
r += htmltext('<strong class="label"><a href="%s/">%s</a></strong>') % (l.id, l.title) |
|
356 |
if l.publication_time: |
|
357 |
r += htmltext('<p class="details">') |
|
358 |
r += time.strftime(misc.date_format(), l.publication_time) |
|
359 |
r += htmltext('</p>') |
|
360 |
r += htmltext('</li>') |
|
361 |
r += htmltext('</ul>') |
|
362 |
return r.getvalue() |
|
363 |
|
|
364 |
def log(self): |
|
365 |
announces = Announce.select() |
|
366 |
log = [] |
|
367 |
for l in announces: |
|
368 |
if l.publication_time: |
|
369 |
log.append((l.publication_time, _('Publication'), l)) |
|
370 |
if l.sent_by_email_time: |
|
371 |
log.append((l.sent_by_email_time, _('Email'), l)) |
|
372 |
if l.sent_by_sms_time: |
|
373 |
log.append((l.sent_by_sms_time, _('SMS'), l)) |
|
374 |
log.sort() |
|
375 |
|
|
376 |
get_response().breadcrumb.append(('log', _('Log'))) |
|
377 |
html_top('announces', title = _('Log')) |
|
378 |
r = TemplateIO(html=True) |
|
379 |
|
|
380 |
r += htmltext('<table>') |
|
381 |
r += htmltext('<thead>') |
|
382 |
r += htmltext('<tr>') |
|
383 |
r += htmltext('<th>%s</th>') % _('Time') |
|
384 |
r += htmltext('<th>%s</th>') % _('Type') |
|
385 |
r += htmltext('<td></td>') |
|
386 |
r += htmltext('</tr>') |
|
387 |
r += htmltext('</thead>') |
|
388 |
r += htmltext('<tbody>') |
|
389 |
for log_time, log_type, log_announce in log: |
|
390 |
r += htmltext('<tr>') |
|
391 |
r += htmltext('<td>') |
|
392 |
r += misc.localstrftime(log_time) |
|
393 |
r += htmltext('</td>') |
|
394 |
r += htmltext('<td>') |
|
395 |
r += log_type |
|
396 |
r += htmltext('</td>') |
|
397 |
r += htmltext('<td>') |
|
398 |
r += htmltext('<a href="%s">%s</a>') % (log_announce.id, log_announce.title) |
|
399 |
r += htmltext('</td>') |
|
400 |
r += htmltext('</tr>') |
|
401 |
r += htmltext('</tbody>') |
|
402 |
r += htmltext('</table>') |
|
403 |
return r.getvalue() |
|
404 |
|
|
405 |
def update_order(self): |
|
406 |
request = get_request() |
|
407 |
new_order = request.form['order'].strip(';').split(';') |
|
408 |
announces = Announce.select() |
|
409 |
dict = {} |
|
410 |
for l in announces: |
|
411 |
dict[str(l.id)] = l |
|
412 |
for i, o in enumerate(new_order): |
|
413 |
dict[o].position = i + 1 |
|
414 |
dict[o].store() |
|
415 |
return 'ok' |
|
416 |
|
|
417 |
def new(self): |
|
418 |
announce = Announce() |
|
419 |
announce.publication_time = time.gmtime() |
|
420 |
announce_ui = AnnounceDirectory(announce) |
|
421 |
|
|
422 |
form = announce_ui.form() |
|
423 |
if form.get_submit() == 'cancel': |
|
424 |
return redirect('.') |
|
425 |
|
|
426 |
if form.is_submitted() and not form.has_errors(): |
|
427 |
announce_ui.submit(form) |
|
428 |
return redirect('%s/' % announce_ui.announce.id) |
|
429 |
|
|
430 |
get_response().breadcrumb.append(('new', _('New Announce'))) |
|
431 |
html_top('announces', title = _('New Announce')) |
|
432 |
r = TemplateIO(html=True) |
|
433 |
r += htmltext('<h2>%s</h2>') % _('New Announce') |
|
434 |
r += form.render() |
|
435 |
return r.getvalue() |
|
436 |
|
|
437 |
def _q_lookup(self, component): |
|
438 |
try: |
|
439 |
announce = Announce.get(component) |
|
440 |
except KeyError: |
|
441 |
raise errors.TraversalError() |
|
442 |
get_response().breadcrumb.append((str(announce.id), announce.title)) |
|
443 |
return AnnounceDirectory(announce) |
|
444 |
|
|
445 |
def listing(self): |
|
446 |
return redirect('.') |
|
447 |
|
Formats disponibles : Unified diff
convert admin/agenda/announces_ui from ptl to py (#3930)