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

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

Remove more trash, reorder imports.

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