source: main/waeup.kofa/trunk/src/waeup/kofa/hostels/browser.py @ 11011

Last change on this file since 11011 was 10771, checked in by Henrik Bettermann, 11 years ago

For customization we need to name the tab viewlets.

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