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

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

In the morning everything looks easier.

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