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

Last change on this file since 5841 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
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
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.applicants import get_applicant_data, ResultEntry
41from waeup.sirp.applicants.interfaces import (
42    IApplicant, IApplicantPrincipal, IApplicantPDEEditData,
43    IApplicantsRoot, IApplicantsContainer, IApplicantContainerProvider,
44    )
45from waeup.sirp.widgets.passportwidget import (
46    PassportWidget, PassportDisplayWidget
47    )
48#from zope.formlib.objectwidget import ObjectWidget
49from zope.formlib.sequencewidget import ListSequenceWidget, SequenceDisplayWidget
50from zope.formlib.widget import CustomWidgetFactory
51from waeup.sirp.widgets.objectwidget import (
52    WAeUPObjectWidget, WAeUPObjectDisplayWidget)
53from waeup.sirp.widgets.multilistwidget import (
54    MultiListWidget, MultiListDisplayWidget)
55from waeup.sirp.image.browser.widget import (
56    ThumbnailWidget, EncodingImageFileWidget,
57    )
58
59results_widget = CustomWidgetFactory(
60    WAeUPObjectWidget, ResultEntry)
61
62results_display_widget = CustomWidgetFactory(
63    WAeUPObjectDisplayWidget, ResultEntry)
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
74class ApplicationsPage(WAeUPPage):
75    grok.context(IApplicantsRoot)
76    grok.name('index')
77    title = 'Applicants'
78    pnav = 2
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))
86
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
121class AddApplicantsContainerActionButton(AddActionButton):
122    grok.context(IApplicantsRoot)
123    grok.view(ApplicantsRootEditPage)
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'
131    pnav = 2
132
133    def update(self, providername=None, name=None, title=None,
134               description=None, ADD=None, CANCEL=None):
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()
150        if title:
151            container.title = title
152        if description:
153            container.description = description
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):
160        """Get a list of applicants container providers.
161
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        """
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
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
204class ApplicantsContainerPage(WAeUPPage):
205    """The standard view for regular applicant containers.
206    """
207    grok.context(IApplicantsContainer)
208    grok.name('index')
209
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
218    pnav = 2
219
220class ManageApplicantsContainerActionButton(ManageActionButton):
221    grok.context(IApplicantsContainer)
222    grok.view(ApplicantsContainerPage)
223    text = 'Manage'
224
225class ApplicantsContainerEditPage(WAeUPPage):
226    """Manage/edit a container for regular applicants.
227    """
228    grok.context(IApplicantsContainer)
229    grok.name('manage')
230
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
240    pnav = 2
241
242    def update(self, CANCEL=None, SAVE=None,
243               title=None, description=None, startdate=None, enddate=None):
244        datepicker.need()
245
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   
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))
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
337    #form_fields['passport'].custom_widget = PassportDisplayWidget
338    form_fields['passport'].custom_widget = ThumbnailWidget
339    label = 'Applicant'
340    title = 'Applicant'
341    pnav = 2
342
343class EditApplicant(WAeUPEditFormPage):
344    grok.context(IApplicant)
345    grok.name('edit')
346    form_fields = grok.AutoFields(IApplicantPDEEditData)
347    #form_fields['passport'].custom_widget = FileWidget
348    #form_fields['passport'].custom_widget = PassportWidget
349    form_fields['passport'].custom_widget = EncodingImageFileWidget
350    grok.template('form_edit_pde')
351
352    def update(self):
353        super(EditApplicant, self).update()
354        print self.request.form
355        return
356   
357    @property
358    def label(self):
359        # XXX: Use current/upcoming session
360        return 'Apply for Post UDE Screening Test (2009/2010)'
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
370    @grok.action('Final Submit')
371    def finalsubmit(self, **data):
372        self.applyData(self.context, **data)
373        self.context._p_changed = True
374        # XXX: Lock the form for editing...
375        return
Note: See TracBrowser for help on using the repository browser.