source: main/waeup.sirp/trunk/src/waeup/sirp/hostels/browser.py @ 7745

Last change on this file since 7745 was 7718, checked in by Henrik Bettermann, 13 years ago

Internationalize hostels package.

Remove exception catcher in switchReservations and corresponding test.

When testing the hostel configuration manually I found out that the beds_reserved list attribute of halls
only changed during the lifetime of a running instance. After restarting the portal all changes were gone.
Also "hostel._p_changed = True" didn't help. The only solution was to reassign the attribute to ensure persistance.

Unfortunately, the current tests don't catch such a malfunction. This has to be improved.

  • Property svn:keywords set to Id
File size: 11.4 KB
RevLine 
[7195]1## $Id: browser.py 7718 2012-02-28 19:34:51Z henrik $
2##
[6953]3## Copyright (C) 2011 Uli Fouquet & Henrik Bettermann
4## This program is free software; you can redistribute it and/or modify
5## it under the terms of the GNU General Public License as published by
6## the Free Software Foundation; either version 2 of the License, or
7## (at your option) any later version.
8##
9## This program is distributed in the hope that it will be useful,
10## but WITHOUT ANY WARRANTY; without even the implied warranty of
11## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12## GNU General Public License for more details.
13##
14## You should have received a copy of the GNU General Public License
15## along with this program; if not, write to the Free Software
16## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17##
18"""UI components for hostels and related components.
19"""
20import grok
[6973]21import sys
[7718]22from zope.i18n import translate
23from zope.component import getUtility
[6953]24from waeup.sirp.browser import (
[7321]25    SIRPEditFormPage, SIRPAddFormPage, SIRPDisplayFormPage,
[6959]26    NullValidator)
[6953]27from waeup.sirp.browser.breadcrumbs import Breadcrumb
[7332]28from waeup.sirp.browser.resources import datepicker, datatable, tabs, warning
[7243]29from waeup.sirp.browser.layout import default_primary_nav_template
30from waeup.sirp.browser.pages import delSubobjects
[6953]31from waeup.sirp.browser.viewlets import (
[7257]32    ManageActionButton, PrimaryNavTab)
[7459]33from waeup.sirp.browser.layout import jsaction, action
[7718]34from waeup.sirp.interfaces import ISIRPObject, ISIRPUtils
35from waeup.sirp.interfaces import MessageFactory as _
[7068]36from waeup.sirp.hostels.vocabularies import NOT_OCCUPIED
37from waeup.sirp.hostels.hostel import Hostel
38from waeup.sirp.hostels.interfaces import (
39    IHostelsContainer, IHostel, IBed, IBedAllocateStudent)
[6953]40
[6956]41def write_log_message(view, message):
42    ob_class = view.__implemented__.__name__.replace('waeup.sirp.','')
43    view.context.loggerInfo(ob_class, message)
44    return
[6953]45
[6956]46# Save function used for save methods in manager pages
47def msave(view, **data):
48    changed_fields = view.applyData(view.context, **data)
49    # Turn list of lists into single list
50    if changed_fields:
51        changed_fields = reduce(lambda x,y: x+y, changed_fields.values())
52    fields_string = ' + '.join(changed_fields)
53    view.context._p_changed = True
[7718]54    view.flash(_('Form has been saved.'))
[6956]55    if fields_string:
56        write_log_message(view, 'saved: % s' % fields_string)
57    return
58
[6953]59class HostelsTab(PrimaryNavTab):
60    """Hostels tab in primary navigation.
61    """
62
[7321]63    grok.context(ISIRPObject)
[6953]64    grok.order(5)
65    grok.require('waeup.viewHostels')
[7243]66    template = default_primary_nav_template
[6953]67    pnav = 5
[7674]68    tab_title = _(u'Hostels')
[6953]69
70    @property
71    def link_target(self):
72        return self.view.application_url('hostels')
73
74class HostelsBreadcrumb(Breadcrumb):
75    """A breadcrumb for the hostels container.
76    """
77    grok.context(IHostelsContainer)
[7718]78    title = _(u'Hostels')
[6953]79
80class HostelBreadcrumb(Breadcrumb):
81    """A breadcrumb for the hostel container.
82    """
83    grok.context(IHostel)
84
[6959]85    def title(self):
86        return self.context.hostel_name
87
[7068]88class BedBreadcrumb(Breadcrumb):
89    """A breadcrumb for the hostel container.
90    """
91    grok.context(IBed)
92
93    def title(self):
94        co = self.context.getBedCoordinates()
[7718]95        return _('Block ${a}, Room ${b}, Bed ${c}',
96            mapping = {'a':co[1], 'b':co[2], 'c':co[3]})
[7068]97
[7321]98class HostelsContainerPage(SIRPDisplayFormPage):
[6953]99    """The standard view for hostels containers.
100    """
101    grok.context(IHostelsContainer)
102    grok.name('index')
103    grok.require('waeup.viewHostels')
[6959]104    grok.template('containerpage')
[7718]105    label = _('Accommodation Section')
[6953]106    pnav = 5
107
108class HostelsContainerManageActionButton(ManageActionButton):
109    grok.order(1)
110    grok.context(IHostelsContainer)
111    grok.view(HostelsContainerPage)
112    grok.require('waeup.manageHostels')
[7718]113    text = _('Manage accommodation section')
[6953]114
[7321]115class HostelsContainerManagePage(SIRPDisplayFormPage):
[6953]116    """The manage page for hostel containers.
117    """
118    grok.context(IHostelsContainer)
119    grok.name('manage')
120    grok.require('waeup.manageHostels')
[6959]121    grok.template('containermanagepage')
[6953]122    pnav = 5
[7718]123    label = _('Manage accommodation section')
[6953]124
[7332]125    def update(self):
126        warning.need()
127        return super(HostelsContainerManagePage, self).update()
128
[6959]129    # It's quite dangerous to remove entire hostels with its content (beds).
[6966]130    # Thus, this remove method should be combined with an archiving function.
[7718]131    @jsaction(_('Remove selected'))
[6959]132    def delHostels(self, **data):
133        form = self.request.form
134        if form.has_key('val_id'):
135            deleted = []
136            child_id = form['val_id']
[6966]137            if not isinstance(child_id, list):
138                child_id = [child_id]
[6959]139            for id in child_id:
140                deleted.append(id)
141            write_log_message(self, 'deleted: % s' % ', '.join(deleted))
142        delSubobjects(self, redirect='@@manage', tab='2')
143        return
[6953]144
[7718]145    @action(_('Add hostel'), validator=NullValidator)
[6959]146    def addSubunit(self, **data):
147        self.redirect(self.url(self.context, 'addhostel'))
148        return
149
[7321]150class HostelAddFormPage(SIRPAddFormPage):
[6953]151    """Add-form to add a hostel.
152    """
153    grok.context(IHostelsContainer)
154    grok.require('waeup.manageHostels')
155    grok.name('addhostel')
[6970]156    #grok.template('hosteladdpage')
[7718]157    form_fields = grok.AutoFields(IHostel).omit('beds_reserved')
158    label = _('Add hostel')
[6953]159    pnav = 5
160
[7718]161    @action(_('Create hostel'))
[6953]162    def addHostel(self, **data):
[6954]163        hostel = Hostel()
164        self.applyData(hostel, **data)
[6973]165        hostel.hostel_id = data[
166            'hostel_name'].lower().replace(' ','-').replace('_','-')
[6966]167        try:
168            self.context.addHostel(hostel)
169        except KeyError:
[7718]170            self.flash(_('The hostel already exists.'))
[6966]171            return
[7718]172        self.flash(_('Hostel created.'))
[6959]173        write_log_message(self, 'added: % s' % data['hostel_name'])
[6953]174        self.redirect(self.url(self.context[hostel.hostel_id], 'index'))
175        return
176
[7321]177class HostelDisplayFormPage(SIRPDisplayFormPage):
[6953]178    """ Page to display hostel data
179    """
180    grok.context(IHostel)
181    grok.name('index')
182    grok.require('waeup.viewHostels')
183    #grok.template('hostelpage')
184    pnav = 5
185
[6956]186    @property
187    def label(self):
188        return self.context.hostel_name
[6953]189
190class HostelManageActionButton(ManageActionButton):
191    grok.order(1)
192    grok.context(IHostel)
193    grok.view(HostelDisplayFormPage)
194    grok.require('waeup.manageHostels')
[7718]195    text = _('Manage')
[6970]196    target = 'manage'
[6953]197
[7321]198class HostelManageFormPage(SIRPEditFormPage):
[6953]199    """ View to edit hostel data
200    """
201    grok.context(IHostel)
[6970]202    grok.name('manage')
[6953]203    grok.require('waeup.manageHostels')
204    form_fields = grok.AutoFields(IHostel).omit('hostel_id')
[7718]205    form_fields['beds_reserved'].for_display = True
[6970]206    grok.template('hostelmanagepage')
[7718]207    label = _('Manage hostel')
[6953]208    pnav = 5
[7718]209    taboneactions = [_('Save')]
210    tabtwoactions = [_('Update all beds'),
211        _('Switch reservation of selected beds'),
212        _('Release selected beds')]
[6996]213    not_occupied = NOT_OCCUPIED
[6953]214
[6956]215    @property
[6996]216    def students_url(self):
217        return self.url(grok.getSite(),'students')
218
[6953]219    def update(self):
220        datepicker.need() # Enable jQuery datepicker in date fields.
[6970]221        tabs.need()
222        datatable.need()
[7484]223        self.tab1 = self.tab2 = ''
224        qs = self.request.get('QUERY_STRING', '')
225        if not qs:
226            qs = 'tab1'
227        setattr(self, qs, 'active')
[6953]228        super(HostelManageFormPage, self).update()
229        return
230
[7718]231    @action(_('Save'))
[6953]232    def save(self, **data):
233        msave(self, **data)
234        return
[6970]235
[7718]236    @action(_('Update all beds'))
[6970]237    def updateBeds(self, **data):
[6988]238        removed, added, modified, modified_beds = self.context.updateBeds()
239        message = '%d empty beds removed, %d beds added, %d occupied beds modified (%s)' % (
240            removed, added, modified, modified_beds)
[7718]241        flash_message = _(
242            '${a} empty beds removed, ${b} beds added, '
243            + '${c} occupied beds modified (${d})',
244            mapping = {'a':removed, 'b':added, 'c':modified, 'd':modified_beds})
245        self.flash(flash_message)
[6988]246        write_log_message(self, message)
[7484]247        self.redirect(self.url(self.context, '@@manage')+'?tab2')
[6970]248        return
[6973]249
[7718]250    @action(_('Switch reservation of selected beds'))
[6974]251    def switchReservations(self, **data):
[6973]252        form = self.request.form
253        if form.has_key('val_id'):
254            child_id = form['val_id']
255        else:
[7718]256            self.flash(_('No item selected.'))
[7484]257            self.redirect(self.url(self.context, '@@manage')+'?tab2')
[6973]258            return
259        if not isinstance(child_id, list):
260            child_id = [child_id]
[7718]261        switched = [] # for log file
262        switched_translated = [] # for flash message
263        portal_language = getUtility(ISIRPUtils).PORTAL_LANGUAGE
264        preferred_language = self.request.cookies.get(
265            'sirp.language', portal_language)
[6973]266        for bed_id in child_id:
[7718]267            message = self.context[bed_id].switchReservation()
268            switched.append('%s (%s)' % (bed_id,message))
269            m_translated = translate(message, 'waeup.sirp',
270                target_language=preferred_language)
271            switched_translated.append('%s (%s)' % (bed_id,m_translated))
[6973]272        if len(switched):
[6988]273            message = ', '.join(switched)
[7718]274            m_translated = ', '.join(switched_translated)
275            self.flash(_('Successfully switched beds: ${a}',
276                mapping = {'a':m_translated}))
[7042]277            write_log_message(self, 'switched: %s' % message)
[7484]278            self.redirect(self.url(self.context, '@@manage')+'?tab2')
[6973]279        return
280
[7718]281    @action(_('Release selected beds'))
[7042]282    def releaseBeds(self, **data):
283        form = self.request.form
284        if form.has_key('val_id'):
285            child_id = form['val_id']
286        else:
[7718]287            self.flash(_('No item selected.'))
[7484]288            self.redirect(self.url(self.context, '@@manage')+'?tab2')
[7042]289            return
290        if not isinstance(child_id, list):
291            child_id = [child_id]
292        released = []
293        for bed_id in child_id:
[7068]294            message = self.context[bed_id].releaseBed()
[7070]295            if message:
296                released.append('%s (%s)' % (bed_id,message))
[7042]297        if len(released):
298            message = ', '.join(released)
[7718]299            self.flash(_('Successfully released beds: ${a}',
300                mapping = {'a':message}))
[7042]301            write_log_message(self, 'released: %s' % message)
[7484]302            self.redirect(self.url(self.context, '@@manage')+'?tab2')
[7070]303        else:
[7718]304            self.flash(_('No allocated bed selected.'))
[7484]305            self.redirect(self.url(self.context, '@@manage')+'?tab2')
[7042]306        return
[7068]307
[7321]308class BedManageFormPage(SIRPEditFormPage):
[7068]309    """ View to edit bed data
310    """
311    grok.context(IBedAllocateStudent)
312    grok.name('index')
313    grok.require('waeup.manageHostels')
314    form_fields = grok.AutoFields(IBedAllocateStudent).omit(
315        'bed_id').omit('bed_number').omit('bed_type')
[7718]316    label = _('Allocate student')
[7068]317    pnav = 5
318
[7718]319    @action(_('Save'))
[7068]320    def save(self, **data):
321        msave(self, **data)
[7484]322        self.redirect(self.url(self.context.__parent__, '@@manage')+'?tab2')
[7068]323        return
324
325    def update(self):
326        if self.context.owner != NOT_OCCUPIED:
327            # Don't use this form for exchanging students.
328            # Beds must be released first before they can be allocated to
329            # other students.
[7484]330            self.redirect(self.url(self.context.__parent__, '@@manage')+'?tab2')
[7068]331        return
Note: See TracBrowser for help on using the repository browser.