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

Last change on this file since 13158 was 11254, checked in by uli, 11 years ago

Merge changes from uli-diazo-themed back into trunk. If this works, then a miracle happened.

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