source: main/waeup.kofa/branches/uli-zc-async/src/waeup/kofa/hostels/browser.py @ 9168

Last change on this file since 9168 was 9166, checked in by uli, 12 years ago

All remaining changes from last weeks. Sorry for the mess.

  • Property svn:keywords set to Id
File size: 12.2 KB
RevLine 
[7195]1## $Id: browser.py 9166 2012-09-06 16:50:17Z uli $
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
[9166]24from waeup.kofa.browser.layout import (
[7819]25    KofaEditFormPage, KofaAddFormPage, KofaDisplayFormPage,
[6959]26    NullValidator)
[7811]27from waeup.kofa.browser.breadcrumbs import Breadcrumb
28from waeup.kofa.browser.resources import datepicker, datatable, tabs, warning
29from waeup.kofa.browser.layout import default_primary_nav_template
30from waeup.kofa.browser.pages import delSubobjects
31from waeup.kofa.browser.viewlets import (
[7257]32    ManageActionButton, PrimaryNavTab)
[7811]33from waeup.kofa.browser.layout import jsaction, action
[7819]34from waeup.kofa.interfaces import IKofaObject, IKofaUtils
[7811]35from waeup.kofa.interfaces import MessageFactory as _
36from waeup.kofa.hostels.vocabularies import NOT_OCCUPIED
37from waeup.kofa.hostels.hostel import Hostel
38from waeup.kofa.hostels.interfaces import (
[7068]39    IHostelsContainer, IHostel, IBed, IBedAllocateStudent)
[8685]40from waeup.kofa.widgets.datewidget import FriendlyDatetimeDisplayWidget
[6953]41
[6956]42def write_log_message(view, message):
[7811]43    ob_class = view.__implemented__.__name__.replace('waeup.kofa.','')
[6956]44    view.context.loggerInfo(ob_class, message)
45    return
[6953]46
[6956]47# Save function used for save methods in manager pages
48def msave(view, **data):
49    changed_fields = view.applyData(view.context, **data)
50    # Turn list of lists into single list
51    if changed_fields:
52        changed_fields = reduce(lambda x,y: x+y, changed_fields.values())
53    fields_string = ' + '.join(changed_fields)
54    view.context._p_changed = True
[7718]55    view.flash(_('Form has been saved.'))
[6956]56    if fields_string:
57        write_log_message(view, 'saved: % s' % fields_string)
58    return
59
[6953]60class HostelsTab(PrimaryNavTab):
61    """Hostels tab in primary navigation.
62    """
63
[7819]64    grok.context(IKofaObject)
[6953]65    grok.order(5)
66    grok.require('waeup.viewHostels')
[7243]67    template = default_primary_nav_template
[6953]68    pnav = 5
[7674]69    tab_title = _(u'Hostels')
[6953]70
71    @property
72    def link_target(self):
73        return self.view.application_url('hostels')
74
75class HostelsBreadcrumb(Breadcrumb):
76    """A breadcrumb for the hostels container.
77    """
78    grok.context(IHostelsContainer)
[7718]79    title = _(u'Hostels')
[6953]80
81class HostelBreadcrumb(Breadcrumb):
82    """A breadcrumb for the hostel container.
83    """
84    grok.context(IHostel)
85
[6959]86    def title(self):
87        return self.context.hostel_name
88
[7068]89class BedBreadcrumb(Breadcrumb):
90    """A breadcrumb for the hostel container.
91    """
92    grok.context(IBed)
93
94    def title(self):
95        co = self.context.getBedCoordinates()
[7718]96        return _('Block ${a}, Room ${b}, Bed ${c}',
97            mapping = {'a':co[1], 'b':co[2], 'c':co[3]})
[7068]98
[7819]99class HostelsContainerPage(KofaDisplayFormPage):
[6953]100    """The standard view for hostels containers.
101    """
102    grok.context(IHostelsContainer)
103    grok.name('index')
104    grok.require('waeup.viewHostels')
[6959]105    grok.template('containerpage')
[7718]106    label = _('Accommodation Section')
[6953]107    pnav = 5
[8685]108    form_fields = grok.AutoFields(IHostelsContainer)
109    form_fields[
110        'startdate'].custom_widget = FriendlyDatetimeDisplayWidget('le')
111    form_fields[
112        'enddate'].custom_widget = FriendlyDatetimeDisplayWidget('le')
[6953]113
114class HostelsContainerManageActionButton(ManageActionButton):
115    grok.order(1)
116    grok.context(IHostelsContainer)
117    grok.view(HostelsContainerPage)
118    grok.require('waeup.manageHostels')
[7718]119    text = _('Manage accommodation section')
[6953]120
[8685]121class HostelsContainerManagePage(KofaEditFormPage):
[6953]122    """The manage page for hostel containers.
123    """
124    grok.context(IHostelsContainer)
125    grok.name('manage')
126    grok.require('waeup.manageHostels')
[6959]127    grok.template('containermanagepage')
[6953]128    pnav = 5
[7718]129    label = _('Manage accommodation section')
[8685]130    form_fields = grok.AutoFields(IHostelsContainer)
131    taboneactions = [_('Save')]
132    tabtwoactions = [_('Add hostel'), _('Remove selected')]
[6953]133
[7332]134    def update(self):
[8685]135        tabs.need()
136        self.tab1 = self.tab2 = self.tab3 = self.tab4 = ''
137        qs = self.request.get('QUERY_STRING', '')
138        if not qs:
139            qs = 'tab1'
140        setattr(self, qs, 'active')
[7332]141        warning.need()
[8685]142        datatable.need()
[7332]143        return super(HostelsContainerManagePage, self).update()
144
[6959]145    # It's quite dangerous to remove entire hostels with its content (beds).
[6966]146    # Thus, this remove method should be combined with an archiving function.
[7718]147    @jsaction(_('Remove selected'))
[6959]148    def delHostels(self, **data):
149        form = self.request.form
150        if form.has_key('val_id'):
151            deleted = []
152            child_id = form['val_id']
[6966]153            if not isinstance(child_id, list):
154                child_id = [child_id]
[6959]155            for id in child_id:
156                deleted.append(id)
157            write_log_message(self, 'deleted: % s' % ', '.join(deleted))
158        delSubobjects(self, redirect='@@manage', tab='2')
159        return
[6953]160
[7718]161    @action(_('Add hostel'), validator=NullValidator)
[6959]162    def addSubunit(self, **data):
163        self.redirect(self.url(self.context, 'addhostel'))
164        return
165
[8685]166    @action(_('Save'), style='primary')
167    def save(self, **data):
168        self.applyData(self.context, **data)
169        self.flash(_('Settings have been saved.'))
170        return
171
[7819]172class HostelAddFormPage(KofaAddFormPage):
[6953]173    """Add-form to add a hostel.
174    """
175    grok.context(IHostelsContainer)
176    grok.require('waeup.manageHostels')
177    grok.name('addhostel')
[6970]178    #grok.template('hosteladdpage')
[7718]179    form_fields = grok.AutoFields(IHostel).omit('beds_reserved')
180    label = _('Add hostel')
[6953]181    pnav = 5
182
[7718]183    @action(_('Create hostel'))
[6953]184    def addHostel(self, **data):
[6954]185        hostel = Hostel()
186        self.applyData(hostel, **data)
[6973]187        hostel.hostel_id = data[
188            'hostel_name'].lower().replace(' ','-').replace('_','-')
[6966]189        try:
190            self.context.addHostel(hostel)
191        except KeyError:
[7718]192            self.flash(_('The hostel already exists.'))
[6966]193            return
[7718]194        self.flash(_('Hostel created.'))
[6959]195        write_log_message(self, 'added: % s' % data['hostel_name'])
[6953]196        self.redirect(self.url(self.context[hostel.hostel_id], 'index'))
197        return
198
[7819]199class HostelDisplayFormPage(KofaDisplayFormPage):
[6953]200    """ Page to display hostel data
201    """
202    grok.context(IHostel)
203    grok.name('index')
204    grok.require('waeup.viewHostels')
205    #grok.template('hostelpage')
206    pnav = 5
207
[6956]208    @property
209    def label(self):
210        return self.context.hostel_name
[6953]211
212class HostelManageActionButton(ManageActionButton):
213    grok.order(1)
214    grok.context(IHostel)
215    grok.view(HostelDisplayFormPage)
216    grok.require('waeup.manageHostels')
[7718]217    text = _('Manage')
[6970]218    target = 'manage'
[6953]219
[7819]220class HostelManageFormPage(KofaEditFormPage):
[6953]221    """ View to edit hostel data
222    """
223    grok.context(IHostel)
[6970]224    grok.name('manage')
[6953]225    grok.require('waeup.manageHostels')
226    form_fields = grok.AutoFields(IHostel).omit('hostel_id')
[7718]227    form_fields['beds_reserved'].for_display = True
[6970]228    grok.template('hostelmanagepage')
[7718]229    label = _('Manage hostel')
[6953]230    pnav = 5
[7718]231    taboneactions = [_('Save')]
232    tabtwoactions = [_('Update all beds'),
233        _('Switch reservation of selected beds'),
234        _('Release selected beds')]
[6996]235    not_occupied = NOT_OCCUPIED
[6953]236
[6956]237    @property
[6996]238    def students_url(self):
239        return self.url(grok.getSite(),'students')
240
[6953]241    def update(self):
242        datepicker.need() # Enable jQuery datepicker in date fields.
[6970]243        tabs.need()
244        datatable.need()
[7484]245        self.tab1 = self.tab2 = ''
246        qs = self.request.get('QUERY_STRING', '')
247        if not qs:
248            qs = 'tab1'
249        setattr(self, qs, 'active')
[6953]250        super(HostelManageFormPage, self).update()
251        return
252
[7718]253    @action(_('Save'))
[6953]254    def save(self, **data):
255        msave(self, **data)
256        return
[6970]257
[7718]258    @action(_('Update all beds'))
[6970]259    def updateBeds(self, **data):
[6988]260        removed, added, modified, modified_beds = self.context.updateBeds()
261        message = '%d empty beds removed, %d beds added, %d occupied beds modified (%s)' % (
262            removed, added, modified, modified_beds)
[7718]263        flash_message = _(
264            '${a} empty beds removed, ${b} beds added, '
265            + '${c} occupied beds modified (${d})',
266            mapping = {'a':removed, 'b':added, 'c':modified, 'd':modified_beds})
267        self.flash(flash_message)
[6988]268        write_log_message(self, message)
[7484]269        self.redirect(self.url(self.context, '@@manage')+'?tab2')
[6970]270        return
[6973]271
[7718]272    @action(_('Switch reservation of selected beds'))
[6974]273    def switchReservations(self, **data):
[6973]274        form = self.request.form
275        if form.has_key('val_id'):
276            child_id = form['val_id']
277        else:
[7718]278            self.flash(_('No item selected.'))
[7484]279            self.redirect(self.url(self.context, '@@manage')+'?tab2')
[6973]280            return
281        if not isinstance(child_id, list):
282            child_id = [child_id]
[7718]283        switched = [] # for log file
284        switched_translated = [] # for flash message
[7833]285        # Here we know that the cookie has been set
286        preferred_language = self.request.cookies.get('kofa.language')
[6973]287        for bed_id in child_id:
[7718]288            message = self.context[bed_id].switchReservation()
289            switched.append('%s (%s)' % (bed_id,message))
[7811]290            m_translated = translate(message, 'waeup.kofa',
[7718]291                target_language=preferred_language)
292            switched_translated.append('%s (%s)' % (bed_id,m_translated))
[6973]293        if len(switched):
[6988]294            message = ', '.join(switched)
[7718]295            m_translated = ', '.join(switched_translated)
296            self.flash(_('Successfully switched beds: ${a}',
297                mapping = {'a':m_translated}))
[7042]298            write_log_message(self, 'switched: %s' % message)
[7484]299            self.redirect(self.url(self.context, '@@manage')+'?tab2')
[6973]300        return
301
[7718]302    @action(_('Release selected beds'))
[7042]303    def releaseBeds(self, **data):
304        form = self.request.form
305        if form.has_key('val_id'):
306            child_id = form['val_id']
307        else:
[7718]308            self.flash(_('No item selected.'))
[7484]309            self.redirect(self.url(self.context, '@@manage')+'?tab2')
[7042]310            return
311        if not isinstance(child_id, list):
312            child_id = [child_id]
313        released = []
314        for bed_id in child_id:
[7068]315            message = self.context[bed_id].releaseBed()
[7070]316            if message:
317                released.append('%s (%s)' % (bed_id,message))
[7042]318        if len(released):
319            message = ', '.join(released)
[7718]320            self.flash(_('Successfully released beds: ${a}',
321                mapping = {'a':message}))
[7042]322            write_log_message(self, 'released: %s' % message)
[7484]323            self.redirect(self.url(self.context, '@@manage')+'?tab2')
[7070]324        else:
[7718]325            self.flash(_('No allocated bed selected.'))
[7484]326            self.redirect(self.url(self.context, '@@manage')+'?tab2')
[7042]327        return
[7068]328
[7819]329class BedManageFormPage(KofaEditFormPage):
[7068]330    """ View to edit bed data
331    """
332    grok.context(IBedAllocateStudent)
333    grok.name('index')
334    grok.require('waeup.manageHostels')
335    form_fields = grok.AutoFields(IBedAllocateStudent).omit(
336        'bed_id').omit('bed_number').omit('bed_type')
[7718]337    label = _('Allocate student')
[7068]338    pnav = 5
339
[7718]340    @action(_('Save'))
[7068]341    def save(self, **data):
342        msave(self, **data)
[7484]343        self.redirect(self.url(self.context.__parent__, '@@manage')+'?tab2')
[7068]344        return
345
346    def update(self):
347        if self.context.owner != NOT_OCCUPIED:
348            # Don't use this form for exchanging students.
349            # Beds must be released first before they can be allocated to
350            # other students.
[7484]351            self.redirect(self.url(self.context.__parent__, '@@manage')+'?tab2')
[7811]352        return
Note: See TracBrowser for help on using the repository browser.