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

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

Rename RestWidget? to RestDisplayWidget?.

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 ReSTDisplayWidget
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
146    def update(self):
147        datepicker.need() # Enable jQuery datepicker in date fields.
148        return super(ApplicantsContainerAddFormPage, self).update()
149
150    @grok.action('Add applicants container')
151    def addApplicantsContainer(self, **data):
152        if data['code'] in self.context.keys():
153            self.status = Invalid('The name chosen already exists '
154                                  'in the database')
155            return
156        # Add new applicants container...
157        provider = data['provider'][1]
158        container = provider.factory()
159        self.applyData(container, **data)
160        self.context[data['code']] = container
161        self.flash('Added "%s".' % data['code'])
162        self.redirect(self.url(self.context, u'@@manage')+'#tab-1')
163        return
164
165    @grok.action('Cancel')
166    def cancel(self, **data):
167        self.redirect(self.url(self.context))
168
169class ApplicantsRootBreadcrumb(Breadcrumb):
170    """A breadcrumb for applicantsroot.
171    """
172    grok.context(IApplicantsRoot)
173    title = u'Applicants'
174
175class ApplicantsContainerBreadcrumb(Breadcrumb):
176    """A breadcrumb for applicantscontainers.
177    """
178    grok.context(IApplicantsContainer)
179
180class ApplicantsTab(PrimaryNavTab):
181    """Faculties-tab in primary navigation.
182    """
183
184    grok.context(IWAeUPObject)
185    grok.order(3)
186    grok.require('waeup.manageUniversity')
187    grok.template('primarynavtab')
188
189    pnav = 3
190    tab_title = u'Applicants'
191
192    @property
193    def link_target(self):
194        return self.view.application_url('applicants')
195
196class ApplicantsContainerPage(WAeUPDisplayFormPage):
197    """The standard view for regular applicant containers.
198    """
199    grok.context(IApplicantsContainer)
200    grok.name('index')
201    grok.template('applicantscontainerpage')
202    pnav = 3
203
204    form_fields = grok.AutoFields(IApplicantsContainer)
205    # Use friendlier date widget...
206    form_fields['startdate'].custom_widget = FriendlyDateDisplayWidget('le')
207    form_fields['enddate'].custom_widget = FriendlyDateDisplayWidget('le')
208    form_fields['description'].custom_widget = ReSTDisplayWidget
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
219
220class ManageApplicantsContainerActionButton(ManageActionButton):
221    grok.context(IApplicantsContainer)
222    grok.view(ApplicantsContainerPage)
223    text = 'Manage applicants container'
224
225
226class ManageApplicantsContainer(WAeUPEditFormPage):
227    grok.context(IApplicantsContainer)
228    grok.name('manage')
229    grok.template('form_manage_applicants_container')
230    form_fields = grok.AutoFields(IApplicantsContainer)
231    # Use friendlier date widget...
232    form_fields['startdate'].custom_widget = FriendlyDateWidget('le')
233    form_fields['enddate'].custom_widget = FriendlyDateWidget('le')
234
235    @property
236    def title(self):
237        return "Manage applicants container: %s" % getattr(
238            self.context, '__name__', 'unnamed')
239
240    @property
241    def label(self):
242        return self.title
243
244    pnav = 3
245
246    def update(self):
247        datepicker.need() # Enable jQuery datepicker in date fields.
248        tabs.need()
249        datatable.need()  # Enable jQurey datatables for contents listing
250        return super(ManageApplicantsContainer, self).update()
251
252    @grok.action('Save')
253    def apply(self, **data):
254        self.applyData(self.context, **data)
255        self.flash('Data saved.')
256        return
257
258    @grok.action('Back')
259    def cancel(self, **data):
260        self.redirect(self.url(self.context))
261        return
262
263class LoginApplicant(WAeUPPage):
264    grok.context(IApplicantsContainer)
265    grok.name('login')
266    grok.require('zope.Public')
267
268    title = u'Login'
269
270    @property
271    def label(self):
272        return self.title
273
274    pnav = 3
275    prefix = u'APP'
276
277    def update(self, SUBMIT=None):
278        self.ac_series = self.request.form.get('form.ac_series', None)
279        self.ac_number = self.request.form.get('form.ac_number', None)
280        if SUBMIT is None:
281            return
282
283        if self.request.principal.id == 'zope.anybody':
284            self.flash('Entered credentials are invalid')
285            return
286
287        if not IApplicantPrincipal.providedBy(self.request.principal):
288            # Don't care if user is already authenticated as non-applicant
289            return
290
291        pin = self.request.principal.access_code
292        if pin not in self.context.keys():
293            # Create applicant record
294            applicant = Applicant()
295            applicant.access_code = pin
296            self.context[pin] = applicant
297
298        # Assign current principal the owner role on created applicant
299        # record
300        role_manager = IPrincipalRoleManager(self.context)
301        role_manager.assignRoleToPrincipal(
302            'waeup.local.ApplicationOwner', self.request.principal.id)
303        self.redirect(self.url(self.context[pin], 'edit'))
304        return
305
306class DisplayApplicant(WAeUPDisplayFormPage):
307    grok.context(IApplicant)
308    grok.name('index')
309    grok.require('waeup.viewApplication')
310    form_fields = grok.AutoFields(IApplicant).omit('locked')
311    form_fields['fst_sit_results'].custom_widget = list_results_display_widget
312    form_fields['passport'].custom_widget = ThumbnailWidget
313    form_fields['date_of_birth'].custom_widget = FriendlyDateDisplayWidget('le')
314    label = 'Applicant'
315    title = 'Applicant'
316    pnav = 3
317
318class EditApplicantStudent(WAeUPEditFormPage):
319    """An applicant-centered edit view for applicant data.
320    """
321    grok.context(IApplicant)
322    grok.name('edit')
323    grok.require('waeup.editApplication')
324    form_fields = grok.AutoFields(IApplicantPDEEditData).omit('locked')
325    form_fields['passport'].custom_widget = EncodingImageFileWidget
326    form_fields['date_of_birth'].custom_widget = FriendlyDateWidget('le-year')
327    grok.template('form_edit_pde')
328
329    def emitLockMessage(self):
330        self.flash('The requested form is locked (read-only)')
331        self.redirect(self.url(self.context))
332        return
333
334    def update(self):
335        if self.context.locked:
336            self.emitLockMessage()
337            return
338        datepicker.need() # Enable jQuery datepicker in date fields.
339        super(EditApplicantStudent, self).update()
340        return
341
342    def filteredWidgets(self):
343        for widget in self.widgets:
344            if widget.name == 'form.confirm_passport':
345                continue
346            yield widget
347
348    @property
349    def label(self):
350        # XXX: Use current/upcoming session
351        return 'Apply for Post UDE Screening Test (2009/2010)'
352    title = 'Edit Application'
353    pnav = 3
354
355    @grok.action('Save')
356    def save(self, **data):
357        if self.context.locked:
358            self.emitLockMessage()
359            return
360        self.applyData(self.context, **data)
361        self.context._p_changed = True
362        return
363
364    @grok.action('Final Submit')
365    def finalsubmit(self, **data):
366        if self.context.locked:
367            self.emitLockMessage()
368            return
369        self.applyData(self.context, **data)
370        self.context._p_changed = True
371        if not self.dataComplete():
372            self.flash('Data yet not complete.')
373            return
374        self.context.locked = True
375        return
376
377    def dataComplete(self):
378        if self.context.confirm_passport is not True:
379            return False
380        if len(self.errors) > 0:
381            return False
382        return True
383
384class EditApplicantFull(WAeUPEditFormPage):
385    """A full edit view for applicant data.
386
387    This one is meant to be used by officers only.
388    """
389    grok.context(IApplicant)
390    grok.name('edit_full')
391    grok.require('waeup.editFullApplication')
392    form_fields = grok.AutoFields(IApplicantPDEEditData).omit('locked')
393    form_fields['passport'].custom_widget = EncodingImageFileWidget
394    form_fields['date_of_birth'].custom_widget = FriendlyDateWidget('le-year')
395    grok.template('form_edit_full')
396
397    def update(self):
398        if self.context.locked:
399            self.emitLockMessage()
400            return
401        datepicker.need() # Enable jQuery datepicker in date fields.
402        super(EditApplicantFull, self).update()
403        return
404
405    def filteredWidgets(self):
406        for widget in self.widgets:
407            if widget.name == 'form.confirm_passport':
408                continue
409            yield widget
410
411    @property
412    def label(self):
413        return 'Application for %s' % self.context.access_code
414    title = 'Edit Application'
415    pnav = 3
416
417    @grok.action('Save')
418    def save(self, **data):
419        self.applyData(self.context, **data)
420        self.context._p_changed = True
421        return
Note: See TracBrowser for help on using the repository browser.