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

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

Also save name attribute. Otherwise the breadcrumb remains empty.

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, 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.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(IApplicantsContainerProvider,
155                              name=providername)
156        container = provider.factory()
157        container.name = name
158        if title:
159            container.title = title
160        if description:
161            container.description = description
162        self.context[name] = container
163        self.flash('Added "%s".' % name)
164        self.redirect(self.url(self.context))
165        return
166       
167    def getContainerProviders(self):
168        """Get a list of applicants container providers.
169
170        Applicants container providers are named utilities that help
171        to create applicants containers of different types
172        (JAMB-based, non-JAMB-based, etc.).
173
174        The list returned contains dicts::
175
176          {'name': <utility_name>,
177           'provider': <provider instance>}
178
179        where `utility_name` is the name under which the respective
180        provider utility is registered and `provider` is the real
181        provider instance.
182
183        The `utility_name` can be used to lookup the utility anew (for
184        instance after submitting a form) and the `provider` instance
185        can be used to create new instances of the respective
186        applicants container type.
187        """
188        providers = getAllUtilitiesRegisteredFor(IApplicantsContainerProvider)
189        result = [
190            {'name': getattr(x, 'grokcore.component.directive.name'),
191             'provider': x}
192             for x in providers
193            ]
194        return result
195
196class ApplicantsRootBreadcrumb(Breadcrumb):
197    """A breadcrumb for applicantsroot.
198    """
199    grok.context(IApplicantsRoot)
200    title = u'Applicants'
201   
202class ApplicantsContainerBreadcrumb(Breadcrumb):
203    """A breadcrumb for applicantscontainers.
204    """
205    grok.context(IApplicantsContainer)
206
207class ApplicantsTab(PrimaryNavTab):
208    """Faculties-tab in primary navigation.
209    """
210    grok.context(IWAeUPObject)
211    grok.order(3)
212    grok.require('waeup.View')
213    grok.template('primarynavtab')
214
215    pnav = 3
216    tab_title = u'Applicants'
217
218    @property
219    def link_target(self):
220        return self.view.application_url('applicants')
221
222class ApplicantsContainerPage(WAeUPPage):
223    """The standard view for regular applicant containers.
224    """
225    grok.context(IApplicantsContainer)
226    grok.name('index')
227
228    @property
229    def title(self):
230        return "Applicants Container: %s" % getattr(
231            self.context, '__name__', 'unnamed')
232
233    @property
234    def label(self):
235        return self.title
236    pnav = 3
237
238class ManageApplicantsContainerActionButton(ManageActionButton):
239    grok.context(IApplicantsContainer)
240    grok.view(ApplicantsContainerPage)
241    text = 'Manage'
242
243class ApplicantsContainerEditPage(WAeUPPage):
244    """Manage/edit a container for regular applicants.
245    """
246    grok.context(IApplicantsContainer)
247    grok.name('manage')
248
249    @property
250    def title(self):
251        return "Manage applicants container: %s" % getattr(
252            self.context, '__name__', 'unnamed')
253   
254    @property
255    def label(self):
256        return self.title
257
258    pnav = 3
259
260    def update(self, CANCEL=None, SAVE=None,
261               title=None, description=None, startdate=None, enddate=None):
262        datepicker.need()
263
264        if CANCEL is not None:
265            self.redirect(self.url(self.context))
266            return
267        if SAVE is None:
268            return
269        self.context.title = title
270        self.context.description = description
271        try:
272            self.context.startdate = datetime.strptime(startdate, '%Y-%m-%d')
273        except ValueError:
274            pass
275        try:
276            self.context.enddate = datetime.strptime(enddate, '%Y-%m-%d')
277        except ValueError:
278            pass
279        self.flash('Data saved.')
280        return
281
282    def getFormattedDates(self):
283        """Returns a dict with formatted start- and enddate.
284
285        Returns dates of form ``YYYY-MM-DD`` based on the start and
286        enddates of the context container. The result dict has
287        format::
288
289          { 'start': '<YYYY-MM-DD>',
290            'end': '<YYYY-MM-DD>'}
291
292        Each value can also be ``''`` (empty string) if unset.
293        """
294        start = ''
295        if self.context.startdate is not None:
296            start = datetime.strftime(self.context.startdate, '%Y-%m-%d')
297        end = ''
298        if self.context.enddate is not None:
299            end = datetime.strftime(self.context.enddate, '%Y-%m-%d')
300        return {'start' : start, 'end' : end }
301
302
303class ManageApplicantsContainer(WAeUPEditFormPage):
304    grok.context(IApplicantsContainer)
305    grok.name('edit')
306    form_fields = grok.AutoFields(IApplicantsContainer)
307    # Use friendlier date widget...
308    form_fields['startdate'].custom_widget = FriendlyDateWidget
309    form_fields['enddate'].custom_widget = FriendlyDateWidget
310    label = 'Edit container'
311    title = label
312    pnav = 3
313
314    def update(self):
315        datepicker.need()
316        return super(ManageApplicantsContainer, self).update()
317
318    @grok.action('Apply')
319    def apply(self, **data):
320        self.applyData(self.context, **data)
321        self.flash('Data saved.')
322        return
323       
324    @grok.action('Back')
325    def cancel(self, **data):
326        self.redirect(self.url(self.context))
327        return
328   
329#class AddApplicant(WAeUPAddFormPage):
330#    grok.context(IApplicantsContainer)
331#    grok.name('add')
332#    form_fields = grok.AutoFields(IApplicant)
333#    form_fields['fst_sit_results'].custom_widget = list_results_widget
334#    form_fields['passport'].custom_widget = EncodingImageFileWidget
335#    label = 'Add Applicant'
336#    title = 'Add Applicant'
337#    pnav = 1
338#
339#    @grok.action('Add applicant')
340#    def addApplicant(self, **data):
341#        from waeup.sirp.jambtables.applicants import Applicant
342#        applicant = Applicant()
343#        self.applyData(applicant, **data)
344#        # XXX: temporarily disabled.
345#        #self.context[applicant.reg_no] = applicant
346#        try:
347#            self.context[applicant.access_code] = applicant
348#        except KeyError:
349#            self.flash('The given access code is already in use!')
350#            return
351#        self.redirect(self.url(self.context))
352
353class DisplayApplicant(WAeUPDisplayFormPage):
354    grok.context(IApplicant)
355    grok.name('index')
356    form_fields = grok.AutoFields(IApplicant)
357    form_fields['fst_sit_results'].custom_widget = list_results_display_widget
358    #form_fields['passport'].custom_widget = PassportDisplayWidget
359    form_fields['passport'].custom_widget = ThumbnailWidget
360    label = 'Applicant'
361    title = 'Applicant'
362    pnav = 3
363
364class EditApplicant(WAeUPEditFormPage):
365    grok.context(IApplicant)
366    grok.name('edit')
367    form_fields = grok.AutoFields(IApplicantPDEEditData)
368    #form_fields['passport'].custom_widget = FileWidget
369    #form_fields['passport'].custom_widget = PassportWidget
370    form_fields['passport'].custom_widget = EncodingImageFileWidget
371    grok.template('form_edit_pde')
372
373    def update(self):
374        super(EditApplicant, self).update()
375        print self.request.form
376        return
377   
378    @property
379    def label(self):
380        # XXX: Use current/upcoming session
381        return 'Apply for Post UDE Screening Test (2009/2010)'
382    title = 'Edit Application'
383    pnav = 3
384
385    @grok.action('Save')
386    def save(self, **data):
387        self.applyData(self.context, **data)
388        self.context._p_changed = True
389        return
390
391    @grok.action('Final Submit')
392    def finalsubmit(self, **data):
393        self.applyData(self.context, **data)
394        self.context._p_changed = True
395        # XXX: Lock the form for editing...
396        return
Note: See TracBrowser for help on using the repository browser.