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

Last change on this file since 13259 was 13177, checked in by Henrik Bettermann, 9 years ago

Add doclinks.

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