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

Last change on this file since 6080 was 6080, checked in by uli, 13 years ago

Remove trash.

File size: 14.4 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 & Henrik Bettermann
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, createObject
30from zope.formlib.widgets import FileWidget, DateWidget
31from zope.securitypolicy.interfaces import IPrincipalRoleManager
32from waeup.sirp.browser import (
33    WAeUPPage, WAeUPEditFormPage, WAeUPAddFormPage,
34    WAeUPDisplayFormPage, NullValidator)
35from waeup.sirp.browser.pages import LoginPage
36from waeup.sirp.interfaces import IWAeUPObject
37from waeup.sirp.browser.resources import datepicker, tabs, datatable
38from waeup.sirp.browser.viewlets import (
39    AddActionButton, ManageActionButton, PrimaryNavTab,
40    )
41from waeup.sirp.browser.breadcrumbs import Breadcrumb
42from waeup.sirp.applicants import get_applicant_data, ResultEntry, Applicant
43from waeup.sirp.applicants.interfaces import (
44    IApplicant, IApplicantPrincipal, IApplicantPDEEditData,
45    IApplicantsRoot, IApplicantsContainer, IApplicantsContainerProvider,
46    IApplicantsContainerAdd
47    )
48from waeup.sirp.widgets.passportwidget import (
49    PassportWidget, PassportDisplayWidget
50    )
51from waeup.sirp.widgets.datewidget import (
52    FriendlyDateWidget, FriendlyDateDisplayWidget)
53
54from waeup.sirp.widgets.restwidget import ReSTWidget
55
56from zope.formlib.sequencewidget import ListSequenceWidget, SequenceDisplayWidget
57from zope.formlib.widget import CustomWidgetFactory
58from waeup.sirp.utils.helpers import ReST2HTML
59from waeup.sirp.widgets.objectwidget import (
60    WAeUPObjectWidget, WAeUPObjectDisplayWidget)
61from waeup.sirp.widgets.multilistwidget import (
62    MultiListWidget, MultiListDisplayWidget)
63from waeup.sirp.image.browser.widget import (
64    ThumbnailWidget, EncodingImageFileWidget,
65    )
66
67results_widget = CustomWidgetFactory(
68    WAeUPObjectWidget, ResultEntry)
69
70results_display_widget = CustomWidgetFactory(
71    WAeUPObjectDisplayWidget, ResultEntry)
72
73list_results_widget = CustomWidgetFactory(
74    MultiListWidget, subwidget=results_widget)
75
76list_results_display_widget = CustomWidgetFactory(
77    MultiListDisplayWidget, subwidget=results_display_widget)
78
79class ApplicantsRootPage(WAeUPPage):
80    grok.context(IApplicantsRoot)
81    grok.name('index')
82    title = 'Applicants'
83    label = 'Application Section'
84    pnav = 3
85
86    def update(self):
87        super(ApplicantsRootPage, self).update()
88        datatable.need()
89        return
90
91    #def getApplications(self):
92    #    """Get a list of all stored applicant containers.
93    #    """
94    #    for key, val in self.context.items():
95    #        url = self.url(val)
96    #        yield(dict(url=url, name=key, container=val))
97
98class ManageApplicantsRootActionButton(ManageActionButton):
99    grok.context(IApplicantsRoot)
100    grok.view(ApplicantsRootPage)
101    grok.require('waeup.manageUniversity')
102    text = 'Manage application section'
103
104class ApplicantsRootManageFormPage(WAeUPEditFormPage):
105    grok.context(IApplicantsRoot)
106    grok.name('manage')
107    grok.template('applicantsrooteditpage')
108    title = 'Applicants'
109    label = 'Manage application section'
110    pnav = 3
111    grok.require('waeup.manageUniversity')
112    taboneactions = ['Add applicants container', 'Remove selected','Cancel']
113    subunits = 'Applicants Containers'
114
115    def update(self):
116        tabs.need()
117        #warning.need()
118        return super(ApplicantsRootManageFormPage, self).update()
119
120    # ToDo: Show warning message before deletion
121    @grok.action('Remove selected')
122    def delApplicantsContainers(self, **data):
123        form = self.request.form
124        child_id = form['val_id']
125        if not isinstance(child_id, list):
126            child_id = [child_id]
127        deleted = []
128        for id in child_id:
129            try:
130                del self.context[id]
131                deleted.append(id)
132            except:
133                self.flash('Could not delete %s: %s: %s' % (
134                        id, sys.exc_info()[0], sys.exc_info()[1]))
135        if len(deleted):
136            self.flash('Successfully removed: %s' % ', '.join(deleted))
137        self.redirect(self.url(self.context, '@@manage')+'#tab-1')
138        return
139
140    @grok.action('Add applicants container', validator=NullValidator)
141    def addApplicantsContainer(self, **data):
142        self.redirect(self.url(self.context, '@@add'))
143        return
144
145    @grok.action('Cancel', validator=NullValidator)
146    def cancel(self, **data):
147        self.redirect(self.url(self.context))
148        return
149
150class ApplicantsContainerAddFormPage(WAeUPAddFormPage):
151    grok.context(IApplicantsRoot)
152    grok.require('waeup.manageUniversity')
153    grok.name('add')
154    grok.template('applicantscontaineraddformpage')
155    title = 'Applicants'
156    label = 'Add applicants container'
157    pnav = 3
158
159    form_fields = grok.AutoFields(IApplicantsContainerAdd)
160    form_fields['startdate'].custom_widget = FriendlyDateDisplayWidget('le')
161    form_fields['enddate'].custom_widget = FriendlyDateDisplayWidget('le')
162    form_fields['description'].custom_widget = ReSTWidget
163
164    @grok.action('Add applicants container')
165    def addApplicantsContainer(self, **data):
166        if data['code'] in self.context.keys():
167            self.status = Invalid('The name chosen already exists '
168                                  'in the database')
169            return
170        # Add new applicants container...
171        provider = getUtility(IApplicantsContainerProvider,
172                              name=getattr(data['provider'],
173                                   'grokcore.component.directive.name'))
174        container = provider.factory()
175        self.applyData(container, **data)
176        self.context[data['code']] = container
177        self.flash('Added "%s".' % data['code'])
178        self.redirect(self.url(self.context, u'@@manage')+'#tab-1')
179        return
180
181    @grok.action('Cancel')
182    def cancel(self, **data):
183        self.redirect(self.url(self.context))
184
185class ApplicantsRootBreadcrumb(Breadcrumb):
186    """A breadcrumb for applicantsroot.
187    """
188    grok.context(IApplicantsRoot)
189    title = u'Applicants'
190
191class ApplicantsContainerBreadcrumb(Breadcrumb):
192    """A breadcrumb for applicantscontainers.
193    """
194    grok.context(IApplicantsContainer)
195
196class ApplicantsTab(PrimaryNavTab):
197    """Faculties-tab in primary navigation.
198    """
199
200    grok.context(IWAeUPObject)
201    grok.order(3)
202    grok.require('waeup.manageUniversity')
203    grok.template('primarynavtab')
204
205    pnav = 3
206    tab_title = u'Applicants'
207
208    @property
209    def link_target(self):
210        return self.view.application_url('applicants')
211
212class ApplicantsContainerPage(WAeUPDisplayFormPage):
213    """The standard view for regular applicant containers.
214    """
215    grok.context(IApplicantsContainer)
216    grok.name('index')
217    grok.template('applicantscontainerpage')
218    pnav = 3
219
220    form_fields = grok.AutoFields(IApplicantsContainer)
221    # Use friendlier date widget...
222    form_fields['startdate'].custom_widget = FriendlyDateDisplayWidget('le')
223    form_fields['enddate'].custom_widget = FriendlyDateDisplayWidget('le')
224    form_fields['description'].custom_widget = ReSTWidget
225
226    @property
227    def title(self):
228        return "Applicants Container: %s" % getattr(
229            self.context, '__name__', 'unnamed')
230
231    @property
232    def label(self):
233        return self.title
234
235    #def descriptionToHTML(self):
236    #    if self.context.description:
237    #        return ReST2HTML(self.context.description)
238    #    else:
239    #        return
240
241
242
243class ManageApplicantsContainerActionButton(ManageActionButton):
244    grok.context(IApplicantsContainer)
245    grok.view(ApplicantsContainerPage)
246    text = 'Manage applicants container'
247
248
249class ManageApplicantsContainer(WAeUPEditFormPage):
250    grok.context(IApplicantsContainer)
251    grok.name('manage')
252    grok.template('form_manage_applicants_container')
253    form_fields = grok.AutoFields(IApplicantsContainer)
254    # Use friendlier date widget...
255    form_fields['startdate'].custom_widget = FriendlyDateWidget('le')
256    form_fields['enddate'].custom_widget = FriendlyDateWidget('le')
257
258    @property
259    def title(self):
260        return "Manage applicants container: %s" % getattr(
261            self.context, '__name__', 'unnamed')
262
263    @property
264    def label(self):
265        return self.title
266
267    pnav = 3
268
269    def update(self):
270        datepicker.need() # Enable jQuery datepicker in date fields.
271        tabs.need()
272        datatable.need()  # Enable jQurey datatables for contents listing
273        return super(ManageApplicantsContainer, self).update()
274
275    @grok.action('Save')
276    def apply(self, **data):
277        self.applyData(self.context, **data)
278        self.flash('Data saved.')
279        return
280
281    @grok.action('Back')
282    def cancel(self, **data):
283        self.redirect(self.url(self.context))
284        return
285
286class LoginApplicant(WAeUPPage):
287    grok.context(IApplicantsContainer)
288    grok.name('login')
289    grok.require('zope.Public')
290
291    title = u'Login'
292
293    @property
294    def label(self):
295        return self.title
296
297    pnav = 3
298    prefix = u'APP'
299
300    def update(self, SUBMIT=None):
301        self.ac_series = self.request.form.get('form.ac_series', None)
302        self.ac_number = self.request.form.get('form.ac_number', None)
303        if SUBMIT is None:
304            return
305
306        if self.request.principal.id == 'zope.anybody':
307            self.flash('Entered credentials are invalid')
308            return
309
310        if not IApplicantPrincipal.providedBy(self.request.principal):
311            # Don't care if user is already authenticated as non-applicant
312            return
313
314        pin = self.request.principal.access_code
315        if pin not in self.context.keys():
316            # Create applicant record
317            applicant = Applicant()
318            applicant.access_code = pin
319            self.context[pin] = applicant
320
321        # Assign current principal the owner role on created applicant
322        # record
323        role_manager = IPrincipalRoleManager(self.context)
324        role_manager.assignRoleToPrincipal(
325            'waeup.local.ApplicationOwner', self.request.principal.id)
326        self.redirect(self.url(self.context[pin], 'edit'))
327        return
328
329class DisplayApplicant(WAeUPDisplayFormPage):
330    grok.context(IApplicant)
331    grok.name('index')
332    grok.require('waeup.viewApplication')
333    form_fields = grok.AutoFields(IApplicant).omit('locked')
334    form_fields['fst_sit_results'].custom_widget = list_results_display_widget
335    form_fields['passport'].custom_widget = ThumbnailWidget
336    form_fields['date_of_birth'].custom_widget = FriendlyDateDisplayWidget('le')
337    label = 'Applicant'
338    title = 'Applicant'
339    pnav = 3
340
341class EditApplicantStudent(WAeUPEditFormPage):
342    """An applicant-centered edit view for applicant data.
343    """
344    grok.context(IApplicant)
345    grok.name('edit')
346    grok.require('waeup.editApplication')
347    form_fields = grok.AutoFields(IApplicantPDEEditData).omit('locked')
348    form_fields['passport'].custom_widget = EncodingImageFileWidget
349    form_fields['date_of_birth'].custom_widget = FriendlyDateWidget('le-year')
350    grok.template('form_edit_pde')
351
352    def emitLockMessage(self):
353        self.flash('The requested form is locked (read-only)')
354        self.redirect(self.url(self.context))
355        return
356
357    def update(self):
358        if self.context.locked:
359            self.emitLockMessage()
360            return
361        datepicker.need() # Enable jQuery datepicker in date fields.
362        super(EditApplicantStudent, self).update()
363        return
364
365    def filteredWidgets(self):
366        for widget in self.widgets:
367            if widget.name == 'form.confirm_passport':
368                continue
369            yield widget
370
371    @property
372    def label(self):
373        # XXX: Use current/upcoming session
374        return 'Apply for Post UDE Screening Test (2009/2010)'
375    title = 'Edit Application'
376    pnav = 3
377
378    @grok.action('Save')
379    def save(self, **data):
380        if self.context.locked:
381            self.emitLockMessage()
382            return
383        self.applyData(self.context, **data)
384        self.context._p_changed = True
385        return
386
387    @grok.action('Final Submit')
388    def finalsubmit(self, **data):
389        if self.context.locked:
390            self.emitLockMessage()
391            return
392        self.applyData(self.context, **data)
393        self.context._p_changed = True
394        if not self.dataComplete():
395            self.flash('Data yet not complete.')
396            return
397        self.context.locked = True
398        return
399
400    def dataComplete(self):
401        if context.confirm_passport is not True:
402            return False
403        if len(self.errors) > 0:
404            return False
405        return True
406
407class EditApplicantFull(WAeUPEditFormPage):
408    """A full edit view for applicant data.
409
410    This one is meant to be used by officers only.
411    """
412    grok.context(IApplicant)
413    grok.name('edit_full')
414    grok.require('waeup.editFullApplication')
415    form_fields = grok.AutoFields(IApplicantPDEEditData).omit('locked')
416    form_fields['passport'].custom_widget = EncodingImageFileWidget
417    form_fields['date_of_birth'].custom_widget = FriendlyDateWidget('le-year')
418    grok.template('form_edit_full')
419
420    def update(self):
421        if self.context.locked:
422            self.emitLockMessage()
423            return
424        datepicker.need() # Enable jQuery datepicker in date fields.
425        super(EditApplicantFull, self).update()
426        return
427
428    def filteredWidgets(self):
429        for widget in self.widgets:
430            if widget.name == 'form.confirm_passport':
431                continue
432            yield widget
433
434    @property
435    def label(self):
436        return 'Application for %s' % self.context.access_code
437    title = 'Edit Application'
438    pnav = 3
439
440    @grok.action('Save')
441    def save(self, **data):
442        self.applyData(self.context, **data)
443        self.context._p_changed = True
444        return
Note: See TracBrowser for help on using the repository browser.