Projet

Général

Profil

« Précédent | Suivant » 

Révision e008d4d6

Ajouté par Frédéric Péters il y a plus de 10 ans

convert admin/agenda/announces_ui from ptl to py (#3930)

Voir les différences:

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