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

Last change on this file since 13176 was 13170, checked in by Henrik Bettermann, 10 years ago

More docs.

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