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

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

Add breadcrumbs for ApplicantsRoot? and ApplicantsContainer?.

File size: 12.7 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, IApplicantContainerProvider,
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.widgets.objectwidget import (
53    WAeUPObjectWidget, WAeUPObjectDisplayWidget)
54from waeup.sirp.widgets.multilistwidget import (
55    MultiListWidget, MultiListDisplayWidget)
56from waeup.sirp.image.browser.widget import (
57    ThumbnailWidget, EncodingImageFileWidget,
58    )
59
60results_widget = CustomWidgetFactory(
61    WAeUPObjectWidget, ResultEntry)
62
63results_display_widget = CustomWidgetFactory(
64    WAeUPObjectDisplayWidget, ResultEntry)
65
66#list_results_widget = CustomWidgetFactory(
67#    ListSequenceWidget, subwidget=results_widget)
68
69list_results_widget = CustomWidgetFactory(
70    MultiListWidget, subwidget=results_widget)
71
72list_results_display_widget = CustomWidgetFactory(
73    MultiListDisplayWidget, subwidget=results_display_widget)
74
75#: A date widget that renders with CSS class `datepicker` thus
76#  enabling : the jQuery datepicker for this field if the form loaded
77#  the jQuery code.
78FriendlyDateWidget = CustomWidgetFactory(
79    DateWidget, cssClass='datepicker')
80
81class ApplicationsPage(WAeUPPage):
82    grok.context(IApplicantsRoot)
83    grok.name('index')
84    title = 'Applicants'
85    pnav = 3
86   
87    def getApplications(self):
88        """Get a list of all stored applicant containers.
89        """
90        for key, val in self.context.items():
91            url = self.url(val)
92            yield(dict(url=url, name=key))
93
94class ManageApplicantsRootActionButton(ManageActionButton):
95    grok.context(IApplicantsRoot)
96    grok.view(ApplicationsPage)
97    text = 'Manage applicant containers'
98
99class ApplicantsRootEditPage(WAeUPPage):
100    grok.context(IApplicantsRoot)
101    grok.name('manage')
102    grok.template('applicantsrooteditpage')
103    title = 'Edit applicants containers'
104    pnav = 3
105
106    def update(self, entries=None, DELETE=None, CANCEL=None):
107        if CANCEL is not None:
108            self.redirect(self.url(self.context))
109            return
110        if DELETE is None:
111            return
112        if entries is None:
113            return
114        if not isinstance(entries, list):
115            entries = [entries]
116        for name in entries:
117            del self.context[name]
118            self.flash('Deleted "%s"' % name)
119        return
120
121    def getApplications(self):
122        """Get a list of all stored applicant containers.
123        """
124        for key, val in self.context.items():
125            url = self.url(val)
126            yield(dict(url=url, name=key))
127
128class AddApplicantsContainerActionButton(AddActionButton):
129    grok.context(IApplicantsRoot)
130    grok.view(ApplicantsRootEditPage)
131    text = 'Add applicants container'
132
133class AddApplicantsContainer(WAeUPPage):
134    grok.context(IApplicantsRoot)
135    grok.name('add')
136    grok.template('addcontainer')
137    title = 'Add applicants container'
138    pnav = 3
139
140    def update(self, providername=None, name=None, title=None,
141               description=None, ADD=None, CANCEL=None):
142        if CANCEL is not None:
143            self.redirect(self.url(self.context))
144            return
145        if ADD is None:
146            return
147        if not name:
148            self.flash('Error: you must give a name')
149            return
150        if name in self.context.keys():
151            self.flash('A container of the given name already exists')
152            return
153        # Add new applicants container...
154        provider = getUtility(IApplicantContainerProvider,
155                              name=providername)
156        container = provider.factory()
157        if title:
158            container.title = title
159        if description:
160            container.description = description
161        self.context[name] = container
162        self.flash('Added "%s".' % name)
163        self.redirect(self.url(self.context))
164        return
165       
166    def getContainerProviders(self):
167        """Get a list of applicants container providers.
168
169        Applicants container providers are named utilities that help
170        to create applicants containers of different types
171        (JAMB-based, non-JAMB-based, etc.).
172
173        The list returned contains dicts::
174
175          {'name': <utility_name>,
176           'provider': <provider instance>}
177
178        where `utility_name` is the name under which the respective
179        provider utility is registered and `provider` is the real
180        provider instance.
181
182        The `utility_name` can be used to lookup the utility anew (for
183        instance after submitting a form) and the `provider` instance
184        can be used to create new instances of the respective
185        applicants container type.
186        """
187        providers = getAllUtilitiesRegisteredFor(IApplicantContainerProvider)
188        result = [
189            {'name': getattr(x, 'grokcore.component.directive.name'),
190             'provider': x}
191             for x in providers
192            ]
193        return result
194
195class ApplicantsRootBreadcrumb(Breadcrumb):
196    """A breadcrumb for applicantsroot.
197    """
198    grok.context(IApplicantsRoot)
199    title = u'Applicants'
200   
201class ApplicantsContainerBreadcrumb(Breadcrumb):
202    """A breadcrumb for applicantscontainers.
203    """
204    grok.context(IApplicantsContainer)
205
206class ApplicantsTab(PrimaryNavTab):
207    """Faculties-tab in primary navigation.
208    """
209    grok.context(IWAeUPObject)
210    grok.order(3)
211    grok.require('waeup.View')
212    grok.template('primarynavtab')
213
214    pnav = 3
215    tab_title = u'Applicants'
216
217    @property
218    def link_target(self):
219        return self.view.application_url('applicants')
220
221class ApplicantsContainerPage(WAeUPPage):
222    """The standard view for regular applicant containers.
223    """
224    grok.context(IApplicantsContainer)
225    grok.name('index')
226
227    @property
228    def title(self):
229        return "Applicants Container: %s" % getattr(
230            self.context, '__name__', 'unnamed')
231
232    @property
233    def label(self):
234        return self.title
235    pnav = 3
236
237class ManageApplicantsContainerActionButton(ManageActionButton):
238    grok.context(IApplicantsContainer)
239    grok.view(ApplicantsContainerPage)
240    text = 'Manage'
241
242class ApplicantsContainerEditPage(WAeUPPage):
243    """Manage/edit a container for regular applicants.
244    """
245    grok.context(IApplicantsContainer)
246    grok.name('manage')
247
248    @property
249    def title(self):
250        return "Manage applicants container: %s" % getattr(
251            self.context, '__name__', 'unnamed')
252   
253    @property
254    def label(self):
255        return self.title
256
257    pnav = 3
258
259    def update(self, CANCEL=None, SAVE=None,
260               title=None, description=None, startdate=None, enddate=None):
261        datepicker.need()
262
263        if CANCEL is not None:
264            self.redirect(self.url(self.context))
265            return
266        if SAVE is None:
267            return
268        self.context.title = title
269        self.context.description = description
270        try:
271            self.context.startdate = datetime.strptime(startdate, '%Y-%m-%d')
272        except ValueError:
273            pass
274        try:
275            self.context.enddate = datetime.strptime(enddate, '%Y-%m-%d')
276        except ValueError:
277            pass
278        self.flash('Data saved.')
279        return
280
281    def getFormattedDates(self):
282        """Returns a dict with formatted start- and enddate.
283
284        Returns dates of form ``YYYY-MM-DD`` based on the start and
285        enddates of the context container. The result dict has
286        format::
287
288          { 'start': '<YYYY-MM-DD>',
289            'end': '<YYYY-MM-DD>'}
290
291        Each value can also be ``''`` (empty string) if unset.
292        """
293        start = ''
294        if self.context.startdate is not None:
295            start = datetime.strftime(self.context.startdate, '%Y-%m-%d')
296        end = ''
297        if self.context.enddate is not None:
298            end = datetime.strftime(self.context.enddate, '%Y-%m-%d')
299        return {'start' : start, 'end' : end }
300
301
302class ManageApplicantsContainer(WAeUPEditFormPage):
303    grok.context(IApplicantsContainer)
304    grok.name('edit')
305    form_fields = grok.AutoFields(IApplicantsContainer)
306    # Use friendlier date widget...
307    form_fields['startdate'].custom_widget = FriendlyDateWidget
308    form_fields['enddate'].custom_widget = FriendlyDateWidget
309    label = 'Edit container'
310    title = label
311    pnav = 3
312
313    def update(self):
314        datepicker.need()
315        return super(ManageApplicantsContainer, self).update()
316
317    @grok.action('Apply')
318    def apply(self, **data):
319        self.applyData(self.context, **data)
320        self.flash('Data saved.')
321        return
322       
323    @grok.action('Back')
324    def cancel(self, **data):
325        self.redirect(self.url(self.context))
326        return
327   
328#class AddApplicant(WAeUPAddFormPage):
329#    grok.context(IApplicantContainer)
330#    grok.name('add')
331#    form_fields = grok.AutoFields(IApplicant)
332#    form_fields['fst_sit_results'].custom_widget = list_results_widget
333#    form_fields['passport'].custom_widget = EncodingImageFileWidget
334#    label = 'Add Applicant'
335#    title = 'Add Applicant'
336#    pnav = 1
337#
338#    @grok.action('Add applicant')
339#    def addApplicant(self, **data):
340#        from waeup.sirp.jambtables.applicants import Applicant
341#        applicant = Applicant()
342#        self.applyData(applicant, **data)
343#        # XXX: temporarily disabled.
344#        #self.context[applicant.reg_no] = applicant
345#        try:
346#            self.context[applicant.access_code] = applicant
347#        except KeyError:
348#            self.flash('The given access code is already in use!')
349#            return
350#        self.redirect(self.url(self.context))
351
352class DisplayApplicant(WAeUPDisplayFormPage):
353    grok.context(IApplicant)
354    grok.name('index')
355    form_fields = grok.AutoFields(IApplicant)
356    form_fields['fst_sit_results'].custom_widget = list_results_display_widget
357    #form_fields['passport'].custom_widget = PassportDisplayWidget
358    form_fields['passport'].custom_widget = ThumbnailWidget
359    label = 'Applicant'
360    title = 'Applicant'
361    pnav = 3
362
363class EditApplicant(WAeUPEditFormPage):
364    grok.context(IApplicant)
365    grok.name('edit')
366    form_fields = grok.AutoFields(IApplicantPDEEditData)
367    #form_fields['passport'].custom_widget = FileWidget
368    #form_fields['passport'].custom_widget = PassportWidget
369    form_fields['passport'].custom_widget = EncodingImageFileWidget
370    grok.template('form_edit_pde')
371
372    def update(self):
373        super(EditApplicant, self).update()
374        print self.request.form
375        return
376   
377    @property
378    def label(self):
379        # XXX: Use current/upcoming session
380        return 'Apply for Post UDE Screening Test (2009/2010)'
381    title = 'Edit Application'
382    pnav = 3
383
384    @grok.action('Save')
385    def save(self, **data):
386        self.applyData(self.context, **data)
387        self.context._p_changed = True
388        return
389
390    @grok.action('Final Submit')
391    def finalsubmit(self, **data):
392        self.applyData(self.context, **data)
393        self.context._p_changed = True
394        # XXX: Lock the form for editing...
395        return
Note: See TracBrowser for help on using the repository browser.