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

Last change on this file since 5886 was 5886, checked in by uli, 14 years ago

Add an applicant login view for regular applicants containers.
This is not finished yet. We will proceed step by step, adding tests
and functionality.

File size: 12.0 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, ac_series=None, ac_number=None, SUBMIT=None):
297        self.ac_series = ac_series
298        self.ac_number = ac_number
299        if SUBMIT is None:
300            return
301
302        if self.request.principal.id != 'zope.anybody':
303            print self.request.principal
304            # If record does not exist: create
305            # Then: redirect to record...
306            return
307        return
308
309#class AddApplicant(WAeUPAddFormPage):
310#    grok.context(IApplicantsContainer)
311#    grok.name('add')
312#    form_fields = grok.AutoFields(IApplicant)
313#    form_fields['fst_sit_results'].custom_widget = list_results_widget
314#    form_fields['passport'].custom_widget = EncodingImageFileWidget
315#    label = 'Add Applicant'
316#    title = 'Add Applicant'
317#    pnav = 1
318#
319#    @grok.action('Add applicant')
320#    def addApplicant(self, **data):
321#        from waeup.sirp.jambtables.applicants import Applicant
322#        applicant = Applicant()
323#        self.applyData(applicant, **data)
324#        # XXX: temporarily disabled.
325#        #self.context[applicant.reg_no] = applicant
326#        try:
327#            self.context[applicant.access_code] = applicant
328#        except KeyError:
329#            self.flash('The given access code is already in use!')
330#            return
331#        self.redirect(self.url(self.context))
332
333class DisplayApplicant(WAeUPDisplayFormPage):
334    grok.context(IApplicant)
335    grok.name('index')
336    form_fields = grok.AutoFields(IApplicant)
337    form_fields['fst_sit_results'].custom_widget = list_results_display_widget
338    #form_fields['passport'].custom_widget = PassportDisplayWidget
339    form_fields['passport'].custom_widget = ThumbnailWidget
340    label = 'Applicant'
341    title = 'Applicant'
342    pnav = 3
343
344class EditApplicant(WAeUPEditFormPage):
345    grok.context(IApplicant)
346    grok.name('edit')
347    form_fields = grok.AutoFields(IApplicantPDEEditData)
348    #form_fields['passport'].custom_widget = FileWidget
349    #form_fields['passport'].custom_widget = PassportWidget
350    form_fields['passport'].custom_widget = EncodingImageFileWidget
351    grok.template('form_edit_pde')
352
353    def update(self):
354        super(EditApplicant, self).update()
355        print self.request.form
356        return
357   
358    @property
359    def label(self):
360        # XXX: Use current/upcoming session
361        return 'Apply for Post UDE Screening Test (2009/2010)'
362    title = 'Edit Application'
363    pnav = 3
364
365    @grok.action('Save')
366    def save(self, **data):
367        self.applyData(self.context, **data)
368        self.context._p_changed = True
369        return
370
371    @grok.action('Final Submit')
372    def finalsubmit(self, **data):
373        self.applyData(self.context, **data)
374        self.context._p_changed = True
375        # XXX: Lock the form for editing...
376        return
Note: See TracBrowser for help on using the repository browser.