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

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

Add views to manage applicants containers. These views/forms (we have
to get rid of one of these soon) make use of datepicker JS code.

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