source: main/waeup.sirp/trunk/src/waeup/sirp/applicants/browser.py @ 5936

Last change on this file since 5936 was 5928, checked in by Henrik Bettermann, 14 years ago

Fix AddApplicantsContainer? update method.

File size: 12.5 KB
Line 
1##
2## browser.py
3## Login : <uli@pu.smp.net>
4## Started on  Sun Jun 27 11:03:10 2010 Uli Fouquet
5## $Id$
6##
7## Copyright (C) 2010 Uli Fouquet
8## This program is free software; you can redistribute it and/or modify
9## it under the terms of the GNU General Public License as published by
10## the Free Software Foundation; either version 2 of the License, or
11## (at your option) any later version.
12##
13## This program is distributed in the hope that it will be useful,
14## but WITHOUT ANY WARRANTY; without even the implied warranty of
15## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16## GNU General Public License for more details.
17##
18## You should have received a copy of the GNU General Public License
19## along with this program; if not, write to the Free Software
20## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21##
22"""UI components for basic applicants and related components.
23"""
24import grok
25
26from datetime import datetime
27from hurry.jquery import jquery
28from hurry.jqueryui import jqueryui
29from zope.component import getUtility, getAllUtilitiesRegisteredFor
30from zope.formlib.widgets import FileWidget, DateWidget
31from waeup.sirp.browser import (
32    WAeUPPage, WAeUPEditFormPage, WAeUPAddFormPage,
33    WAeUPDisplayFormPage, NullValidator)
34from waeup.sirp.browser.pages import LoginPage
35from waeup.sirp.interfaces import IWAeUPObject
36from waeup.sirp.browser.resources import datepicker
37from waeup.sirp.browser.viewlets import (
38    AddActionButton, ManageActionButton, PrimaryNavTab,
39    )
40from waeup.sirp.browser.breadcrumbs import Breadcrumb
41from waeup.sirp.applicants import get_applicant_data, ResultEntry, Applicant
42from waeup.sirp.applicants.interfaces import (
43    IApplicant, IApplicantPrincipal, IApplicantPDEEditData,
44    IApplicantsRoot, IApplicantsContainer, IApplicantsContainerProvider,
45    )
46from waeup.sirp.widgets.passportwidget import (
47    PassportWidget, PassportDisplayWidget
48    )
49#from zope.formlib.objectwidget import ObjectWidget
50from zope.formlib.sequencewidget import ListSequenceWidget, SequenceDisplayWidget
51from zope.formlib.widget import CustomWidgetFactory
52from waeup.sirp.utils.helpers import ReST2HTML
53from waeup.sirp.widgets.objectwidget import (
54    WAeUPObjectWidget, WAeUPObjectDisplayWidget)
55from waeup.sirp.widgets.multilistwidget import (
56    MultiListWidget, MultiListDisplayWidget)
57from waeup.sirp.image.browser.widget import (
58    ThumbnailWidget, EncodingImageFileWidget,
59    )
60
61results_widget = CustomWidgetFactory(
62    WAeUPObjectWidget, ResultEntry)
63
64results_display_widget = CustomWidgetFactory(
65    WAeUPObjectDisplayWidget, ResultEntry)
66
67#list_results_widget = CustomWidgetFactory(
68#    ListSequenceWidget, subwidget=results_widget)
69
70list_results_widget = CustomWidgetFactory(
71    MultiListWidget, subwidget=results_widget)
72
73list_results_display_widget = CustomWidgetFactory(
74    MultiListDisplayWidget, subwidget=results_display_widget)
75
76#: A date widget that renders with CSS class `datepicker` thus
77#  enabling : the jQuery datepicker for this field if the form loaded
78#  the jQuery code.
79FriendlyDateWidget = CustomWidgetFactory(
80    DateWidget, cssClass='datepicker')
81
82class ApplicationsPage(WAeUPPage):
83    grok.context(IApplicantsRoot)
84    grok.name('index')
85    title = 'Applicants'
86    pnav = 3
87   
88    def getApplications(self):
89        """Get a list of all stored applicant containers.
90        """
91        for key, val in self.context.items():
92            url = self.url(val)
93            yield(dict(url=url, name=key, container=val))
94
95class ManageApplicantsRootActionButton(ManageActionButton):
96    grok.context(IApplicantsRoot)
97    grok.view(ApplicationsPage)
98    text = 'Manage applicant containers'
99
100class ApplicantsRootEditPage(WAeUPPage):
101    grok.context(IApplicantsRoot)
102    grok.name('manage')
103    grok.template('applicantsrooteditpage')
104    title = 'Edit applicants containers'
105    pnav = 3
106
107    def update(self, entries=None, DELETE=None, CANCEL=None):
108        if CANCEL is not None:
109            self.redirect(self.url(self.context))
110            return
111        if DELETE is None:
112            return
113        if entries is None:
114            return
115        if not isinstance(entries, list):
116            entries = [entries]
117        for name in entries:
118            del self.context[name]
119            self.flash('Deleted "%s"' % name)
120        return
121
122    def getApplications(self):
123        """Get a list of all stored applicant containers.
124        """
125        for key, val in self.context.items():
126            url = self.url(val)
127            yield(dict(url=url, name=key))
128
129class AddApplicantsContainerActionButton(AddActionButton):
130    grok.context(IApplicantsRoot)
131    grok.view(ApplicantsRootEditPage)
132    text = 'Add applicants container'
133
134class AddApplicantsContainer(WAeUPPage):
135    grok.context(IApplicantsRoot)
136    grok.name('add')
137    grok.template('addcontainer')
138    title = 'Add applicants container'
139    pnav = 3
140
141    def update(self, providername=None, name=None, title=None,
142               description=None, ADD=None, CANCEL=None):
143        if CANCEL is not None:
144            self.redirect(self.url(self.context))
145            return
146        if ADD is None:
147            return
148        if not name:
149            self.flash('Error: you must give a name')
150            return
151        if name in self.context.keys():
152            self.flash('A container of the given name already exists')
153            return
154        # Add new applicants container...
155        provider = getUtility(IApplicantsContainerProvider,
156                              name=providername)
157        container = provider.factory()
158        if title:
159            container.title = title
160        if description:
161            container.description = description
162        self.context[name] = container
163        self.flash('Added "%s".' % name)
164        self.redirect(self.url(self.context))
165        return
166       
167    def getContainerProviders(self):
168        """Get a list of applicants container providers.
169
170        Applicants container providers are named utilities that help
171        to create applicants containers of different types
172        (JAMB-based, non-JAMB-based, etc.).
173
174        The list returned contains dicts::
175
176          {'name': <utility_name>,
177           'provider': <provider instance>}
178
179        where `utility_name` is the name under which the respective
180        provider utility is registered and `provider` is the real
181        provider instance.
182
183        The `utility_name` can be used to lookup the utility anew (for
184        instance after submitting a form) and the `provider` instance
185        can be used to create new instances of the respective
186        applicants container type.
187        """
188        providers = getAllUtilitiesRegisteredFor(IApplicantsContainerProvider)
189        result = [
190            {'name': getattr(x, 'grokcore.component.directive.name'),
191             'provider': x}
192             for x in providers
193            ]
194        return result
195
196class ApplicantsRootBreadcrumb(Breadcrumb):
197    """A breadcrumb for applicantsroot.
198    """
199    grok.context(IApplicantsRoot)
200    title = u'Applicants'
201   
202class ApplicantsContainerBreadcrumb(Breadcrumb):
203    """A breadcrumb for applicantscontainers.
204    """
205    grok.context(IApplicantsContainer)
206
207class ApplicantsTab(PrimaryNavTab):
208    """Faculties-tab in primary navigation.
209    """
210    grok.context(IWAeUPObject)
211    grok.order(3)
212    grok.require('waeup.View')
213    grok.template('primarynavtab')
214
215    pnav = 3
216    tab_title = u'Applicants'
217
218    @property
219    def link_target(self):
220        return self.view.application_url('applicants')
221
222class ApplicantsContainerPage(WAeUPPage):
223    """The standard view for regular applicant containers.
224    """
225    grok.context(IApplicantsContainer)
226    grok.name('index')
227    pnav = 3
228   
229    @property
230    def title(self):
231        return "Applicants Container: %s" % getattr(
232            self.context, '__name__', 'unnamed')
233
234    @property
235    def label(self):
236        return self.title
237
238    def descriptionToHTML(self):
239        return ReST2HTML(self.context.description)
240
241class ManageApplicantsContainerActionButton(ManageActionButton):
242    grok.context(IApplicantsContainer)
243    grok.view(ApplicantsContainerPage)
244    text = 'Manage'
245
246
247class ManageApplicantsContainer(WAeUPEditFormPage):
248    grok.context(IApplicantsContainer)
249    grok.name('manage')
250    form_fields = grok.AutoFields(IApplicantsContainer)
251    # Use friendlier date widget...
252    form_fields['startdate'].custom_widget = FriendlyDateWidget
253    form_fields['enddate'].custom_widget = FriendlyDateWidget
254
255    @property
256    def title(self):
257        return "Manage applicants container: %s" % getattr(
258            self.context, '__name__', 'unnamed')
259   
260    @property
261    def label(self):
262        return self.title
263
264    pnav = 3
265
266    def update(self):
267        datepicker.need() # Enable jQuery datepicker in date fields.
268        return super(ManageApplicantsContainer, self).update()
269
270    @grok.action('Save')
271    def apply(self, **data):
272        self.applyData(self.context, **data)
273        self.flash('Data saved.')
274        return
275       
276    @grok.action('Back')
277    def cancel(self, **data):
278        self.redirect(self.url(self.context))
279        return
280
281class LoginApplicant(WAeUPPage):
282    grok.context(IApplicantsContainer)
283    grok.name('login')
284    grok.require('zope.Public')
285
286    title = u'Login'
287   
288    @property
289    def label(self):
290        return self.title
291
292    pnav = 3
293    prefix = u'APP'
294   
295    def update(self, SUBMIT=None):
296        self.ac_series = self.request.form.get('form.ac_series', None)
297        self.ac_number = self.request.form.get('form.ac_number', None)
298        if SUBMIT is None:
299            return
300
301        if self.request.principal.id == 'zope.anybody':
302            self.flash('Entered credentials are invalid')
303            return
304
305        if not IApplicantPrincipal.providedBy(self.request.principal):
306            # Don't care if user is already authenticated as non-applicant
307            return
308
309        pin = self.request.principal.access_code
310        if pin not in self.context.keys():
311            # Create applicant record
312            applicant = Applicant()
313            applicant.access_code = pin
314            self.context[pin] = applicant
315            # XXX: set owner role on created applicant
316
317        self.redirect(self.url(self.context[pin]))
318        return
319
320#class AddApplicant(WAeUPAddFormPage):
321#    grok.context(IApplicantsContainer)
322#    grok.name('add')
323#    form_fields = grok.AutoFields(IApplicant)
324#    form_fields['fst_sit_results'].custom_widget = list_results_widget
325#    form_fields['passport'].custom_widget = EncodingImageFileWidget
326#    label = 'Add Applicant'
327#    title = 'Add Applicant'
328#    pnav = 1
329#
330#    @grok.action('Add applicant')
331#    def addApplicant(self, **data):
332#        from waeup.sirp.jambtables.applicants import Applicant
333#        applicant = Applicant()
334#        self.applyData(applicant, **data)
335#        # XXX: temporarily disabled.
336#        #self.context[applicant.reg_no] = applicant
337#        try:
338#            self.context[applicant.access_code] = applicant
339#        except KeyError:
340#            self.flash('The given access code is already in use!')
341#            return
342#        self.redirect(self.url(self.context))
343
344class DisplayApplicant(WAeUPDisplayFormPage):
345    grok.context(IApplicant)
346    grok.name('index')
347    form_fields = grok.AutoFields(IApplicant)
348    form_fields['fst_sit_results'].custom_widget = list_results_display_widget
349    #form_fields['passport'].custom_widget = PassportDisplayWidget
350    form_fields['passport'].custom_widget = ThumbnailWidget
351    #form_fields['passport'].custom_widget = EncodingImageFileWidget
352    label = 'Applicant'
353    title = 'Applicant'
354    pnav = 3
355
356class EditApplicant(WAeUPEditFormPage):
357    grok.context(IApplicant)
358    grok.name('edit')
359    form_fields = grok.AutoFields(IApplicantPDEEditData)
360    #form_fields['passport'].custom_widget = FileWidget
361    #form_fields['passport'].custom_widget = PassportWidget
362    form_fields['passport'].custom_widget = EncodingImageFileWidget
363    grok.template('form_edit_pde')
364
365    def update(self):
366        super(EditApplicant, self).update()
367        print self.request.form
368        return
369   
370    @property
371    def label(self):
372        # XXX: Use current/upcoming session
373        return 'Apply for Post UDE Screening Test (2009/2010)'
374    title = 'Edit Application'
375    pnav = 3
376
377    @grok.action('Save')
378    def save(self, **data):
379        self.applyData(self.context, **data)
380        self.context._p_changed = True
381        return
382
383    @grok.action('Final Submit')
384    def finalsubmit(self, **data):
385        self.applyData(self.context, **data)
386        self.context._p_changed = True
387        # XXX: Lock the form for editing...
388        return
Note: See TracBrowser for help on using the repository browser.