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

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

ApplicantsContainerProvider? not ApplicantContainerProvider?

File size: 12.7 KB
RevLine 
[5273]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##
[5824]22"""UI components for basic applicants and related components.
[5273]23"""
24import grok
25
[5837]26from datetime import datetime
27from hurry.jquery import jquery
28from hurry.jqueryui import jqueryui
[5822]29from zope.component import getUtility, getAllUtilitiesRegisteredFor
[5844]30from zope.formlib.widgets import FileWidget, DateWidget
[5273]31from waeup.sirp.browser import (
32    WAeUPPage, WAeUPEditFormPage, WAeUPAddFormPage,
33    WAeUPDisplayFormPage, NullValidator)
[5442]34from waeup.sirp.browser.pages import LoginPage
[5320]35from waeup.sirp.interfaces import IWAeUPObject
[5837]36from waeup.sirp.browser.resources import datepicker
[5828]37from waeup.sirp.browser.viewlets import (
38    AddActionButton, ManageActionButton, PrimaryNavTab,
39    )
[5845]40from waeup.sirp.browser.breadcrumbs import Breadcrumb
[5806]41from waeup.sirp.applicants import get_applicant_data, ResultEntry
[5758]42from waeup.sirp.applicants.interfaces import (
[5822]43    IApplicant, IApplicantPrincipal, IApplicantPDEEditData,
[5846]44    IApplicantsRoot, IApplicantsContainer, IApplicantsContainerProvider,
[5822]45    )
[5686]46from waeup.sirp.widgets.passportwidget import (
47    PassportWidget, PassportDisplayWidget
48    )
[5273]49#from zope.formlib.objectwidget import ObjectWidget
50from zope.formlib.sequencewidget import ListSequenceWidget, SequenceDisplayWidget
51from zope.formlib.widget import CustomWidgetFactory
[5303]52from waeup.sirp.widgets.objectwidget import (
[5301]53    WAeUPObjectWidget, WAeUPObjectDisplayWidget)
[5303]54from waeup.sirp.widgets.multilistwidget import (
[5273]55    MultiListWidget, MultiListDisplayWidget)
[5686]56from waeup.sirp.image.browser.widget import (
57    ThumbnailWidget, EncodingImageFileWidget,
58    )
[5320]59
[5273]60results_widget = CustomWidgetFactory(
[5301]61    WAeUPObjectWidget, ResultEntry)
[5273]62
63results_display_widget = CustomWidgetFactory(
[5301]64    WAeUPObjectDisplayWidget, ResultEntry)
[5273]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
[5844]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
[5822]81class ApplicationsPage(WAeUPPage):
82    grok.context(IApplicantsRoot)
83    grok.name('index')
84    title = 'Applicants'
[5843]85    pnav = 3
[5822]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))
[5273]93
[5828]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'
[5843]104    pnav = 3
[5828]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
[5822]128class AddApplicantsContainerActionButton(AddActionButton):
129    grok.context(IApplicantsRoot)
[5828]130    grok.view(ApplicantsRootEditPage)
[5822]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'
[5843]138    pnav = 3
[5822]139
[5828]140    def update(self, providername=None, name=None, title=None,
141               description=None, ADD=None, CANCEL=None):
[5822]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...
[5846]154        provider = getUtility(IApplicantsContainerProvider,
[5822]155                              name=providername)
156        container = provider.factory()
[5828]157        if title:
158            container.title = title
159        if description:
160            container.description = description
[5822]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):
[5825]167        """Get a list of applicants container providers.
[5822]168
[5825]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        """
[5846]187        providers = getAllUtilitiesRegisteredFor(IApplicantsContainerProvider)
[5822]188        result = [
189            {'name': getattr(x, 'grokcore.component.directive.name'),
190             'provider': x}
191             for x in providers
192            ]
193        return result
[5828]194
[5845]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)
[5828]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
[5843]214    pnav = 3
[5828]215    tab_title = u'Applicants'
216
217    @property
218    def link_target(self):
219        return self.view.application_url('applicants')
220
[5830]221class ApplicantsContainerPage(WAeUPPage):
222    """The standard view for regular applicant containers.
223    """
224    grok.context(IApplicantsContainer)
225    grok.name('index')
[5828]226
[5837]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
[5843]235    pnav = 3
[5830]236
[5832]237class ManageApplicantsContainerActionButton(ManageActionButton):
238    grok.context(IApplicantsContainer)
239    grok.view(ApplicantsContainerPage)
240    text = 'Manage'
241
242class ApplicantsContainerEditPage(WAeUPPage):
[5837]243    """Manage/edit a container for regular applicants.
244    """
[5832]245    grok.context(IApplicantsContainer)
246    grok.name('manage')
247
[5837]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
[5843]257    pnav = 3
[5832]258
[5837]259    def update(self, CANCEL=None, SAVE=None,
260               title=None, description=None, startdate=None, enddate=None):
261        datepicker.need()
[5832]262
[5837]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)
[5844]306    # Use friendlier date widget...
307    form_fields['startdate'].custom_widget = FriendlyDateWidget
308    form_fields['enddate'].custom_widget = FriendlyDateWidget
[5837]309    label = 'Edit container'
310    title = label
[5845]311    pnav = 3
[5837]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   
[5758]328#class AddApplicant(WAeUPAddFormPage):
[5846]329#    grok.context(IApplicantsContainer)
[5758]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))
[5273]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
[5686]357    #form_fields['passport'].custom_widget = PassportDisplayWidget
358    form_fields['passport'].custom_widget = ThumbnailWidget
[5273]359    label = 'Applicant'
360    title = 'Applicant'
[5843]361    pnav = 3
[5273]362
363class EditApplicant(WAeUPEditFormPage):
364    grok.context(IApplicant)
365    grok.name('edit')
[5484]366    form_fields = grok.AutoFields(IApplicantPDEEditData)
[5686]367    #form_fields['passport'].custom_widget = FileWidget
368    #form_fields['passport'].custom_widget = PassportWidget
369    form_fields['passport'].custom_widget = EncodingImageFileWidget
[5488]370    grok.template('form_edit_pde')
[5484]371
[5686]372    def update(self):
373        super(EditApplicant, self).update()
374        print self.request.form
375        return
376   
[5484]377    @property
378    def label(self):
379        # XXX: Use current/upcoming session
380        return 'Apply for Post UDE Screening Test (2009/2010)'
[5273]381    title = 'Edit Application'
[5845]382    pnav = 3
[5273]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
[5484]390    @grok.action('Final Submit')
391    def finalsubmit(self, **data):
[5273]392        self.applyData(self.context, **data)
[5484]393        self.context._p_changed = True
394        # XXX: Lock the form for editing...
[5273]395        return
Note: See TracBrowser for help on using the repository browser.