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

Last change on this file since 5905 was 5905, checked in by uli, 13 years ago

Preliminary code for adding new applicants in case new applicant
logged in for the first time.

File size: 12.6 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
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        container.name = name
159        if title:
160            container.title = title
161        if description:
162            container.description = description
163        self.context[name] = container
164        self.flash('Added "%s".' % name)
165        self.redirect(self.url(self.context))
166        return
167       
168    def getContainerProviders(self):
169        """Get a list of applicants container providers.
170
171        Applicants container providers are named utilities that help
172        to create applicants containers of different types
173        (JAMB-based, non-JAMB-based, etc.).
174
175        The list returned contains dicts::
176
177          {'name': <utility_name>,
178           'provider': <provider instance>}
179
180        where `utility_name` is the name under which the respective
181        provider utility is registered and `provider` is the real
182        provider instance.
183
184        The `utility_name` can be used to lookup the utility anew (for
185        instance after submitting a form) and the `provider` instance
186        can be used to create new instances of the respective
187        applicants container type.
188        """
189        providers = getAllUtilitiesRegisteredFor(IApplicantsContainerProvider)
190        result = [
191            {'name': getattr(x, 'grokcore.component.directive.name'),
192             'provider': x}
193             for x in providers
194            ]
195        return result
196
197class ApplicantsRootBreadcrumb(Breadcrumb):
198    """A breadcrumb for applicantsroot.
199    """
200    grok.context(IApplicantsRoot)
201    title = u'Applicants'
202   
203class ApplicantsContainerBreadcrumb(Breadcrumb):
204    """A breadcrumb for applicantscontainers.
205    """
206    grok.context(IApplicantsContainer)
207
208class ApplicantsTab(PrimaryNavTab):
209    """Faculties-tab in primary navigation.
210    """
211    grok.context(IWAeUPObject)
212    grok.order(3)
213    grok.require('waeup.View')
214    grok.template('primarynavtab')
215
216    pnav = 3
217    tab_title = u'Applicants'
218
219    @property
220    def link_target(self):
221        return self.view.application_url('applicants')
222
223class ApplicantsContainerPage(WAeUPPage):
224    """The standard view for regular applicant containers.
225    """
226    grok.context(IApplicantsContainer)
227    grok.name('index')
228    pnav = 3
229   
230    @property
231    def title(self):
232        return "Applicants Container: %s" % getattr(
233            self.context, '__name__', 'unnamed')
234
235    @property
236    def label(self):
237        return self.title
238
239    def descriptionToHTML(self):
240        return ReST2HTML(self.context.description)
241
242class ManageApplicantsContainerActionButton(ManageActionButton):
243    grok.context(IApplicantsContainer)
244    grok.view(ApplicantsContainerPage)
245    text = 'Manage'
246
247
248class ManageApplicantsContainer(WAeUPEditFormPage):
249    grok.context(IApplicantsContainer)
250    grok.name('manage')
251    form_fields = grok.AutoFields(IApplicantsContainer)
252    # Use friendlier date widget...
253    form_fields['startdate'].custom_widget = FriendlyDateWidget
254    form_fields['enddate'].custom_widget = FriendlyDateWidget
255
256    @property
257    def title(self):
258        return "Manage applicants container: %s" % getattr(
259            self.context, '__name__', 'unnamed')
260   
261    @property
262    def label(self):
263        return self.title
264
265    pnav = 3
266
267    def update(self):
268        datepicker.need() # Enable jQuery datepicker in date fields.
269        return super(ManageApplicantsContainer, self).update()
270
271    @grok.action('Save')
272    def apply(self, **data):
273        self.applyData(self.context, **data)
274        self.flash('Data saved.')
275        return
276       
277    @grok.action('Back')
278    def cancel(self, **data):
279        self.redirect(self.url(self.context))
280        return
281
282class LoginApplicant(WAeUPPage):
283    grok.context(IApplicantsContainer)
284    grok.name('login')
285    grok.require('zope.Public')
286
287    title = u'Login'
288   
289    @property
290    def label(self):
291        return self.title
292
293    pnav = 3
294    prefix = u'APP'
295   
296    def update(self, SUBMIT=None):
297        self.ac_series = self.request.form.get('form.ac_series', None)
298        self.ac_number = self.request.form.get('form.ac_number', None)
299        if SUBMIT is None:
300            return
301
302        if self.request.principal.id == 'zope.anybody':
303            self.flash('Entered credentials are invalid')
304            return
305
306        if not IApplicantPrincipal.providedBy(self.request.principal):
307            # Don't care if user is already authenticated as non-applicant
308            return
309
310        pin = self.request.principal.access_code
311        if pin not in self.context.keys():
312            # Create applicant record
313            self.flash("CREATE APPLICANT")
314            return
315            raise("Create APPLICANT")
316            applicant = Applicant()
317            applicant.access_code = pin
318            self.context[pin] = applicant
319            # XXX: set owner role on created applicant
320
321        self.redirect(self.url(self.context[pin]))
322        return
323
324#class AddApplicant(WAeUPAddFormPage):
325#    grok.context(IApplicantsContainer)
326#    grok.name('add')
327#    form_fields = grok.AutoFields(IApplicant)
328#    form_fields['fst_sit_results'].custom_widget = list_results_widget
329#    form_fields['passport'].custom_widget = EncodingImageFileWidget
330#    label = 'Add Applicant'
331#    title = 'Add Applicant'
332#    pnav = 1
333#
334#    @grok.action('Add applicant')
335#    def addApplicant(self, **data):
336#        from waeup.sirp.jambtables.applicants import Applicant
337#        applicant = Applicant()
338#        self.applyData(applicant, **data)
339#        # XXX: temporarily disabled.
340#        #self.context[applicant.reg_no] = applicant
341#        try:
342#            self.context[applicant.access_code] = applicant
343#        except KeyError:
344#            self.flash('The given access code is already in use!')
345#            return
346#        self.redirect(self.url(self.context))
347
348class DisplayApplicant(WAeUPDisplayFormPage):
349    grok.context(IApplicant)
350    grok.name('index')
351    form_fields = grok.AutoFields(IApplicant)
352    form_fields['fst_sit_results'].custom_widget = list_results_display_widget
353    #form_fields['passport'].custom_widget = PassportDisplayWidget
354    form_fields['passport'].custom_widget = ThumbnailWidget
355    label = 'Applicant'
356    title = 'Applicant'
357    pnav = 3
358
359class EditApplicant(WAeUPEditFormPage):
360    grok.context(IApplicant)
361    grok.name('edit')
362    form_fields = grok.AutoFields(IApplicantPDEEditData)
363    #form_fields['passport'].custom_widget = FileWidget
364    #form_fields['passport'].custom_widget = PassportWidget
365    form_fields['passport'].custom_widget = EncodingImageFileWidget
366    grok.template('form_edit_pde')
367
368    def update(self):
369        super(EditApplicant, self).update()
370        print self.request.form
371        return
372   
373    @property
374    def label(self):
375        # XXX: Use current/upcoming session
376        return 'Apply for Post UDE Screening Test (2009/2010)'
377    title = 'Edit Application'
378    pnav = 3
379
380    @grok.action('Save')
381    def save(self, **data):
382        self.applyData(self.context, **data)
383        self.context._p_changed = True
384        return
385
386    @grok.action('Final Submit')
387    def finalsubmit(self, **data):
388        self.applyData(self.context, **data)
389        self.context._p_changed = True
390        # XXX: Lock the form for editing...
391        return
Note: See TracBrowser for help on using the repository browser.